From 2fb2813b485f624cef957c68310e47e3597c51bc Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 14 Apr 2021 14:05:59 +0100 Subject: [PATCH 01/96] updating atom mesh component to support non-uniform scale component --- Code/Framework/AzCore/AzCore/Math/Aabb.cpp | 31 ++++++++++++++- Code/Framework/AzCore/AzCore/Math/Aabb.h | 10 ++++- Code/Framework/AzCore/AzCore/Math/Aabb.inl | 8 ++++ .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 4 +- .../Mesh/MeshFeatureProcessorInterface.h | 8 ++-- .../ReflectionProbeFeatureProcessor.h | 2 +- ...ReflectionProbeFeatureProcessorInterface.h | 2 +- .../TransformServiceFeatureProcessor.h | 4 +- ...ransformServiceFeatureProcessorInterface.h | 8 ++-- .../Code/Mocks/MockMeshFeatureProcessor.h | 4 +- .../Code/Source/AuxGeom/AuxGeomDrawQueue.cpp | 2 +- .../DiffuseProbeGridRayTracingPass.cpp | 8 ++-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 18 ++++----- .../RayTracingAccelerationStructurePass.cpp | 2 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 6 +-- .../RayTracing/RayTracingFeatureProcessor.h | 4 +- .../ReflectionProbe/ReflectionProbe.cpp | 8 ++-- .../Source/ReflectionProbe/ReflectionProbe.h | 2 +- .../ReflectionProbeFeatureProcessor.cpp | 8 ++-- .../TransformServiceFeatureProcessor.cpp | 8 ++-- .../RHI/RayTracingAccelerationStructure.h | 6 +-- .../RHI/RayTracingAccelerationStructure.cpp | 6 +-- .../DX12/Code/Source/RHI/RayTracingTlas.cpp | 3 +- .../Vulkan/Code/Source/RHI/RayTracingTlas.cpp | 4 +- .../Include/Atom/RPI.Public/Model/Model.h | 4 +- .../Code/Source/RPI.Public/Model/Model.cpp | 6 +-- .../Code/Source/Mesh/EditorMeshComponent.cpp | 5 ++- .../Source/Mesh/MeshComponentController.cpp | 38 ++++++++++++++++--- .../Source/Mesh/MeshComponentController.h | 10 +++++ .../ReflectionProbeComponentController.cpp | 2 +- .../Code/Source/AtomActorInstance.cpp | 5 ++- .../Editor/EditorBlastMeshDataComponent.cpp | 4 +- .../Code/Source/Family/ActorRenderManager.cpp | 6 +-- .../Code/Tests/ActorRenderManagerTest.cpp | 2 +- .../Rendering/Atom/WhiteBoxAtomRenderMesh.cpp | 2 +- 35 files changed, 166 insertions(+), 84 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp index 94e138d88d..48e51cce48 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp @@ -146,8 +146,8 @@ namespace AZ ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("GetTranslated", &Aabb::GetTranslated) ->Method("GetSurfaceArea", &Aabb::GetSurfaceArea) - ->Method("GetTransformedObb", &Aabb::GetTransformedObb) - ->Method("GetTransformedAabb", &Aabb::GetTransformedAabb) + ->Method("GetTransformedObb", static_cast(&Aabb::GetTransformedObb)) + ->Method("GetTransformedAabb", static_cast(&Aabb::GetTransformedAabb)) ->Method("ApplyTransform", &Aabb::ApplyTransform) ->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All) ->Method("Clone", [](const Aabb& rhs) -> Aabb { return rhs; }) @@ -195,6 +195,20 @@ namespace AZ } + Obb Aabb::GetTransformedObb(const Matrix3x4& matrix3x4) const + { + Matrix3x4 matrixNoScale = matrix3x4; + const AZ::Vector3 scale = matrixNoScale.ExtractScale(); + const AZ::Quaternion rotation = AZ::Quaternion::CreateFromMatrix3x4(matrixNoScale); + + return Obb::CreateFromPositionRotationAndHalfLengths( + matrix3x4 * GetCenter(), + rotation, + 0.5f * scale * GetExtents() + ); + } + + void Aabb::ApplyTransform(const Transform& transform) { Vector3 a, b, axisCoeffs; @@ -224,4 +238,17 @@ namespace AZ m_min = newMin; m_max = newMax; } + + + void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4) + { + const AZ::Vector3 extents = GetExtents(); + const AZ::Vector3 center = GetCenter(); + AZ::Vector3 newHalfExtents( + 0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents), + 0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents), + 0.5f * matrix3x4.GetRowAsVector3(2).GetAbs().Dot(extents)); + m_min = center - newHalfExtents; + m_max = center + newHalfExtents; + } } diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.h b/Code/Framework/AzCore/AzCore/Math/Aabb.h index 0aebd099f4..474ac2e2ee 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.h +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.h @@ -129,12 +129,20 @@ namespace AZ void ApplyTransform(const Transform& transform); + void ApplyMatrix3x4(const Matrix3x4& matrix3x4); + + //! Transforms an Aabb and returns the resulting Obb. + Obb GetTransformedObb(const Transform& transform) const; + //! Transforms an Aabb and returns the resulting Obb. - class Obb GetTransformedObb(const Transform& transform) const; + Obb GetTransformedObb(const Matrix3x4& matrix3x4) const; //! Returns a new AABB containing the transformed AABB. Aabb GetTransformedAabb(const Transform& transform) const; + //! Returns a new AABB containing the transformed AABB. + Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const; + //! Checks if this aabb is equal to another within a floating point tolerance. bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const; diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.inl b/Code/Framework/AzCore/AzCore/Math/Aabb.inl index 5e6a5ae188..94ad3e3e7d 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.inl +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.inl @@ -300,6 +300,14 @@ namespace AZ } + AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Matrix3x4& matrix3x4) const + { + Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max); + aabb.ApplyMatrix3x4(matrix3x4); + return aabb; + } + + AZ_MATH_INLINE bool Aabb::IsClose(const Aabb& rhs, float tolerance) const { return m_min.IsClose(rhs.m_min, tolerance) && m_max.IsClose(rhs.m_max, tolerance); diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index a595471813..cc26ff862a 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -144,8 +144,8 @@ namespace AZ const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override; void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) override; - void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) override; - Transform GetTransform(const MeshHandle& meshHandle) override; + void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) override; + Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) override; void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index 77e3467fb9..ef8084d534 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -61,10 +61,10 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const = 0; //! Connects a handler to any changes to an RPI::Model. Changes include loading and reloading. virtual void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) = 0; - //! Sets the transform for a given mesh handle. - virtual void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) = 0; - //! Gets the transform for a given mesh handle. - virtual Transform GetTransform(const MeshHandle& meshHandle) = 0; + //! Sets the Matrix3x4 for a given mesh handle. + virtual void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) = 0; + //! Gets the Matrix3x4 for a given mesh handle. + virtual Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) = 0; //! Sets the sort key for a given mesh handle. virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h index a89875aaa6..610bb40369 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -37,7 +37,7 @@ namespace AZ void SetProbeOuterExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& outerExtents) override; void SetProbeInnerExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& innerExtents) override; void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance& cubeMapImage) override; - void SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) override; + void SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) override; void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) override; void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) override; bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h index 8b277e97c8..3053d9d44f 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h @@ -48,7 +48,7 @@ namespace AZ virtual void SetProbeOuterExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& outerExtents) = 0; virtual void SetProbeInnerExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& innerExtents) = 0; virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance& cubeMapImage) = 0; - virtual void SetProbeTransform(const ReflectionProbeHandle& handle, const AZ::Transform& transform) = 0; + virtual void SetProbeMatrix3x4(const ReflectionProbeHandle& handle, const AZ::Matrix3x4& matrix3x4) = 0; virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback) = 0; virtual void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) = 0; virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h index 2344f745f8..d6338d6b0c 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h @@ -50,8 +50,8 @@ namespace AZ // TransformServiceFeatureProcessorInterface overrides ... ObjectId ReserveObjectId() override; void ReleaseObjectId(ObjectId& id) override; - void SetTransformForId(ObjectId id, const AZ::Transform& transform) override; - AZ::Transform GetTransformForId(ObjectId id) const override; + void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) override; + AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId id) const override; private: diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h index 0b17a9a5a0..b75257c485 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h @@ -34,10 +34,10 @@ namespace AZ //! Releases an object ID to be used by others. The passed in handle is invalidated. virtual void ReleaseObjectId(ObjectId& id) = 0; - //! Sets the transform for a given id. Id must be one reserved earlier. - virtual void SetTransformForId(ObjectId id, const AZ::Transform& transform) = 0; - //! Gets the transform for a given id. Id must be one reserved earlier. - virtual AZ::Transform GetTransformForId(ObjectId) const = 0; + //! Sets the Matrix3x4 for a given id. Id must be one reserved earlier. + virtual void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& transform) = 0; + //! Gets the Matrix3x4 for a given id. Id must be one reserved earlier. + virtual AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId) const = 0; }; } diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index 6fc1ac0e30..b6428754b5 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -31,11 +31,11 @@ namespace UnitTest MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); - MOCK_METHOD2(SetTransform, void(const MeshHandle&, const AZ::Transform&)); + MOCK_METHOD2(SetMatrix3x4, void(const MeshHandle&, const AZ::Matrix3x4&)); MOCK_METHOD2(SetExcludeFromReflectionCubeMaps, void(const MeshHandle&, bool)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Data::Instance&)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Render::MaterialAssignmentMap&)); - MOCK_METHOD1(GetTransform, AZ::Transform (const MeshHandle&)); + MOCK_METHOD1(GetMatrix3x4, AZ::Matrix3x4 (const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp index fd4b5b28d1..c412746676 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp @@ -504,7 +504,7 @@ namespace AZ box.m_faceCullMode = ConvertRPIFaceCullFlag(faceCull); box.m_color = color; box.m_scale = localMatrix3x4.ExtractScale() * extents; - box.m_position = localMatrix3x4.GetTranslation() + center; + box.m_position = matrix3x4 * center; box.m_rotationMatrix = Matrix3x3::CreateFromMatrix3x4(localMatrix3x4); box.m_pointSize = m_pointSize; box.m_viewProjOverrideIndex = viewProjOverrideIndex; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp index f6eeaf2971..f5e4f29cea 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.cpp @@ -186,10 +186,10 @@ namespace AZ // set irradiance color and worldInverseTranspose constants Vector4 color(subMesh.m_irradianceColor.GetR(), subMesh.m_irradianceColor.GetG(), subMesh.m_irradianceColor.GetB(), 1.0f); - AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); - AZ::Transform noScaleTransform = meshTransform; - noScaleTransform.ExtractScale(); - AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); + AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4; + noScaleMatrix3x4.ExtractScale(); + AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4); rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose(); m_closestHitData[m_meshCount].m_materialColor = color; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 1f5b8ecc65..40873ccea0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -256,7 +256,7 @@ namespace AZ } } - void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform) + void MeshFeatureProcessor::SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) { if (meshHandle.IsValid()) { @@ -264,26 +264,26 @@ namespace AZ meshData.m_cullBoundsNeedsUpdate = true; meshData.m_objectSrgNeedsUpdate = true; - m_transformService->SetTransformForId(meshHandle->m_objectId, transform); + m_transformService->SetMatrix3x4ForId(meshHandle->m_objectId, matrix3x4); // ray tracing data needs to be updated with the new transform if (m_rayTracingFeatureProcessor) { - m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform); + m_rayTracingFeatureProcessor->SetMeshMatrix3x4(meshHandle->m_objectId, matrix3x4); } } } - Transform MeshFeatureProcessor::GetTransform(const MeshHandle& meshHandle) + Matrix3x4 MeshFeatureProcessor::GetMatrix3x4(const MeshHandle& meshHandle) { if (meshHandle.IsValid()) { - return m_transformService->GetTransformForId(meshHandle->m_objectId); + return m_transformService->GetMatrix3x4ForId(meshHandle->m_objectId); } else { AZ_Assert(false, "Invalid mesh handle"); - return Transform::CreateIdentity(); + return Matrix3x4::CreateIdentity(); } } @@ -841,7 +841,7 @@ namespace AZ AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt"); AZ_Assert(m_model, "The model has not finished loading yet"); - Transform localToWorld = transformService->GetTransformForId(m_objectId); + Matrix3x4 localToWorld = transformService->GetMatrix3x4ForId(m_objectId); Vector3 center; float radius; @@ -919,11 +919,11 @@ namespace AZ // retrieve the list of probes that contain the centerpoint of the mesh TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor(); - Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId); + Matrix3x4 matrix3x4 = transformServiceFeatureProcessor->GetMatrix3x4ForId(m_objectId); ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor(); ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes; - reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes); + reflectionProbeFeatureProcessor->FindReflectionProbes(matrix3x4.GetTranslation(), reflectionProbes); if (!reflectionProbes.empty() && reflectionProbes[0]) { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp index f874f87b4a..7e39f968fd 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp @@ -83,7 +83,7 @@ namespace AZ ->InstanceID(blasIndex) ->HitGroupIndex(blasIndex) ->Blas(rayTracingSubMesh.m_blas) - ->Transform(rayTracingMesh.second.m_transform) + ->Matrix3x4(rayTracingMesh.second.m_matrix3x4) ; } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index abced377a0..1e7fc464df 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -97,7 +97,7 @@ namespace AZ } // set initial transform - mesh.m_transform = m_transformServiceFeatureProcessor->GetTransformForId(objectId); + mesh.m_matrix3x4 = m_transformServiceFeatureProcessor->GetMatrix3x4ForId(objectId); m_revision++; m_subMeshCount += aznumeric_cast(subMeshes.size()); @@ -119,7 +119,7 @@ namespace AZ } } - void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, AZ::Transform transform) + void RayTracingFeatureProcessor::SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4) { if (!m_rayTracingEnabled) { @@ -129,7 +129,7 @@ namespace AZ MeshMap::iterator itMesh = m_meshes.find(objectId.GetIndex()); if (itMesh != m_meshes.end()) { - itMesh->second.m_transform = transform; + itMesh->second.m_matrix3x4 = matrix3x4; m_revision++; } } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 09a4a6f63c..af5bfd0d51 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -66,7 +66,7 @@ namespace AZ SubMeshVector m_subMeshes; // mesh transform - AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); // flag indicating if the Blas objects in the sub-meshes are built bool m_blasBuilt = false; @@ -85,7 +85,7 @@ namespace AZ //! Sets the ray tracing mesh transform //! This will cause an update to the RayTracing acceleration structure on the next frame - void SetMeshTransform(const ObjectId objectId, const AZ::Transform transform); + void SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4); //! Retrieves ray tracing data for all meshes in the scene const MeshMap& GetMeshes() const { return m_meshes; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 51303436ee..f56902ebde 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -70,7 +70,7 @@ namespace AZ m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true); m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity()); + m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, AZ::Matrix3x4::CreateIdentity()); // We have to pre-load this asset before creating a Material instance because the InstanceDatabase will attempt a blocking load which could deadlock, // particularly when slices are involved. @@ -206,10 +206,10 @@ namespace AZ } - void ReflectionProbe::SetTransform(const AZ::Transform& transform) + void ReflectionProbe::SetMatrix3x4(const AZ::Matrix3x4& matrix3x4) { - m_position = transform.GetTranslation(); - m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); + m_position = matrix3x4.GetTranslation(); + m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, matrix3x4); m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); m_updateSrg = true; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 22645a4ed3..6b23afb1fc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -76,7 +76,7 @@ namespace AZ void Simulate(uint32_t probeIndex); const Vector3& GetPosition() const { return m_position; } - void SetTransform(const AZ::Transform& transform); + void SetMatrix3x4(const AZ::Matrix3x4& matrix3x4); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } void SetOuterExtents(const AZ::Vector3& outerExtents); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 80719564b1..8631e334b4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -223,7 +223,7 @@ namespace AZ { AZStd::shared_ptr reflectionProbe = AZStd::make_shared(); reflectionProbe->Init(GetParentScene(), &m_reflectionRenderData); - reflectionProbe->SetTransform(transform); + reflectionProbe->SetMatrix3x4(AZ::Matrix3x4::CreateFromTransform(transform)); reflectionProbe->SetUseParallaxCorrection(useParallaxCorrection); m_reflectionProbes.push_back(reflectionProbe); m_probeSortRequired = true; @@ -264,10 +264,10 @@ namespace AZ probe->SetCubeMapImage(cubeMapImage); } - void ReflectionProbeFeatureProcessor::SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) + void ReflectionProbeFeatureProcessor::SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) { - AZ_Assert(probe.get(), "SetProbeTransform called with an invalid handle"); - probe->SetTransform(transform); + AZ_Assert(probe.get(), "SetProbeMatrix3x4 called with an invalid handle"); + probe->SetMatrix3x4(matrix3x4); m_probeSortRequired = true; } diff --git a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp index a4f255185a..a3a91ca620 100644 --- a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp @@ -210,14 +210,12 @@ namespace AZ } } - void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform) + void TransformServiceFeatureProcessor::SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) { AZ_Error("TransformServiceFeatureProcessor", m_isWriteable, "Transform data cannot be written to during this phase"); AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); if (id.IsValid()) { - AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform); - matrix3x4.StoreToRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); // Inverse transpose to take the non-uniform scale out of the transform for usage with normals. @@ -226,10 +224,10 @@ namespace AZ } } - AZ::Transform TransformServiceFeatureProcessor::GetTransformForId(ObjectId id) const + AZ::Matrix3x4 TransformServiceFeatureProcessor::GetMatrix3x4ForId(ObjectId id) const { AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); - return AZ::Transform::CreateFromMatrix3x4( Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform) ); + return AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); } } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index 09ba2b1d59..0225673efd 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -12,7 +12,7 @@ #pragma once #include -#include +#include #include #include #include @@ -110,7 +110,7 @@ namespace AZ { uint32_t m_instanceID = 0; uint32_t m_hitGroupIndex = 0; - AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); RHI::Ptr m_blas; }; using RayTracingTlasInstanceVector = AZStd::vector; @@ -153,7 +153,7 @@ namespace AZ RayTracingTlasDescriptor* Instance(); RayTracingTlasDescriptor* InstanceID(uint32_t instanceID); RayTracingTlasDescriptor* HitGroupIndex(uint32_t hitGroupIndex); - RayTracingTlasDescriptor* Transform(const AZ::Transform& transform); + RayTracingTlasDescriptor* Matrix3x4(const AZ::Matrix3x4& matrix3x4); RayTracingTlasDescriptor* Blas(RHI::Ptr& blas); RayTracingTlasDescriptor* InstancesBuffer(RHI::Ptr& tlasInstances); RayTracingTlasDescriptor* NumInstances(uint32_t numInstancesInBuffer); diff --git a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp index 37e5b316d6..dadaeee5d4 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp @@ -78,10 +78,10 @@ namespace AZ return this; } - RayTracingTlasDescriptor* RayTracingTlasDescriptor::Transform(const AZ::Transform& transform) + RayTracingTlasDescriptor* RayTracingTlasDescriptor::Matrix3x4(const AZ::Matrix3x4& matrix3x4) { - AZ_Assert(m_buildContext, "Transform property can only be added to an Instance entry"); - m_buildContext->m_transform = transform; + AZ_Assert(m_buildContext, "Matrix3x4 property can only be added to an Instance entry"); + m_buildContext->m_matrix3x4 = matrix3x4; return this; } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index 77d8d38e42..8c01b798a6 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -89,8 +89,7 @@ namespace AZ mappedData[i].InstanceID = instance.m_instanceID; mappedData[i].InstanceContributionToHitGroupIndex = instance.m_hitGroupIndex; // convert transform to row-major 3x4 - AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); - matrix34.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); + instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); mappedData[i].AccelerationStructure = static_cast(blas->GetBuffers().m_blasBuffer.get())->GetMemoryView().GetGpuAddress(); // [GFX TODO][ATOM-5270] Add ray tracing TLAS instance mask support mappedData[i].InstanceMask = 0x1; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp index 9720fecb6d..161104060e 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp @@ -92,9 +92,7 @@ namespace AZ mappedData[i].instanceCustomIndex = instance.m_instanceID; mappedData[i].instanceShaderBindingTableRecordOffset = instance.m_hitGroupIndex; - // convert transform to row-major 3x4 - AZ::Matrix3x4 matrix34 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); - matrix34.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); + instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); RayTracingBlas* blas = static_cast(instance.m_blas.get()); VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {}; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h index 5cd464962b..ada429ee05 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Model/Model.h @@ -72,11 +72,13 @@ namespace AZ //! [GFX TODO][ATOM-4343 Bake mesh spatial during AP processing] //! //! @param modelTransform a transform that puts the model into the ray's coordinate space + //! @param nonUniformScale Non-uniform scale applied in the model's local frame. //! @param rayStart position where the ray starts //! @param dir direction where the ray ends (does not have to be unit length) //! @param distanceFactor if an intersection is detected, this will be set such that distanceFactor * dir.length == distance to intersection //! @return true if the ray intersects the mesh - bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const; + bool RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, + const AZ::Vector3& dir, float& distanceFactor) const; //! Get available UV names from the model and its lods. const AZStd::unordered_set& GetUvNames() const; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp index 84c10cb272..ad56b6e33a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp @@ -164,15 +164,15 @@ namespace AZ return false; } - bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const + bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor) const { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); const AZ::Transform inverseTM = modelTransform.GetInverse(); - const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart); + const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / nonUniformScale; // Instead of just rotating 'dir' we need it to be scaled too, so that 'distanceFactor' will be in the target units rather than object local units. const AZ::Vector3 rayDest = rayStart + dir; - const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest); + const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / nonUniformScale; const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal; return LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 0afe96588f..86a3c12557 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -137,7 +137,10 @@ namespace AZ AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); - return m_controller.GetModel()->RayIntersection(transform, src, dir, distance); + AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne(); + AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale); + + return m_controller.GetModel()->RayIntersection(transform, nonUniformScale, src, dir, distance); } bool EditorMeshComponent::SupportsEditorRayIntersect() diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index db64d26a54..1404db717f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -180,6 +180,11 @@ namespace AZ m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(m_entityId); AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId."); + m_cachedNonUniformScale = AZ::Vector3::CreateOne(); + AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); + AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, + m_nonUniformScaleChangedHandler); + MeshComponentRequestBus::Handler::BusConnect(m_entityId); TransformNotificationBus::Handler::BusConnect(m_entityId); MaterialReceiverRequestBus::Handler::BusConnect(m_entityId); @@ -216,11 +221,24 @@ namespace AZ return m_configuration; } - void MeshComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) + void MeshComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world) + { + UpdateOverallMatrix(); + } + + void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3 & nonUniformScale) + { + m_cachedNonUniformScale = nonUniformScale; + UpdateOverallMatrix(); + } + + void MeshComponentController::UpdateOverallMatrix() { if (m_meshFeatureProcessor) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, world); + Matrix3x4 world = Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()); + world.MultiplyByScale(m_cachedNonUniformScale); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, world); } } @@ -266,8 +284,8 @@ namespace AZ m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); - const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : Transform::Identity(); - m_meshFeatureProcessor->SetTransform(m_meshHandle, transform); + const AZ::Matrix3x4& matrix3x4 = m_transformInterface ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) : Matrix3x4::Identity(); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps); @@ -403,7 +421,17 @@ namespace AZ Aabb MeshComponentController::GetLocalBounds() { const Data::Instance model = GetModel(); - return model ? model->GetAabb() : Aabb::CreateNull(); + if (model) + { + Aabb aabb = model->GetAabb(); + aabb.SetMin(aabb.GetMin() * m_cachedNonUniformScale); + aabb.SetMax(aabb.GetMax() * m_cachedNonUniformScale); + return aabb; + } + else + { + return Aabb::CreateNull(); + } } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 184756d931..68c7ed8063 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -14,6 +14,7 @@ #include #include +#include #include @@ -120,17 +121,26 @@ namespace AZ void UnregisterModel(); void RefreshModelRegistration(); + void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale); + void UpdateOverallMatrix(); + Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle; TransformInterface* m_transformInterface = nullptr; AZ::EntityId m_entityId; bool m_isVisible = true; MeshComponentConfig m_configuration; + AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne(); MeshFeatureProcessorInterface::ModelChangedEvent::Handler m_changeEventHandler { [&](Data::Instance model) { HandleModelChange(model); } }; + + AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler + { + [&](const AZ::Vector3& nonUniformScale) { HandleNonUniformScaleChange(nonUniformScale); } + }; }; } // namespace Render diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index 005e9a6ff5..57aaa6a83f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -199,7 +199,7 @@ namespace AZ return; } - m_featureProcessor->SetProbeTransform(m_handle, world); + m_featureProcessor->SetProbeMatrix3x4(m_handle, Matrix3x4::CreateFromTransform(world)); } void ReflectionProbeComponentController::OnShapeChanged(ShapeChangeReasons changeReason) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index b0d52e0776..fd98dfe666 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -187,8 +187,9 @@ namespace AZ void AtomActorInstance::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) { - // The mesh transform is used to determine where the actor instance is actually rendered - m_meshFeatureProcessor->SetTransform(*m_meshHandle, world); // handle validity is checked internally. + // The mesh Matrix3x4 is used to determine where the actor instance is actually rendered + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(world); + m_meshFeatureProcessor->SetMatrix3x4(*m_meshHandle, matrix3x4); // handle validity is checked internally. if (m_skinnedMeshRenderProxy.IsValid()) { diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index d2aa81900b..5fd9c678dc 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -193,7 +193,7 @@ namespace Blast AZ::Transform transform = AZ::Transform::Identity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM); - m_meshFeatureProcessor->SetTransform(m_meshHandle, transform); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(transform)); } } @@ -232,7 +232,7 @@ namespace Blast { if (m_meshFeatureProcessor) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, world); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(world)); } } } // namespace Blast diff --git a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp index deb6362ee3..d057e5a619 100644 --- a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp +++ b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp @@ -74,10 +74,10 @@ namespace Blast { if (m_chunkActors[chunkId]) { - auto transform = m_chunkActors[chunkId]->GetWorldBody()->GetTransform(); + auto matrix3x4 = AZ::Matrix3x4::CreateFromTransform(m_chunkActors[chunkId]->GetWorldBody()->GetTransform()); // Multiply by scale because the transform on the world body does not store scale - transform.MultiplyByScale(m_scale); - m_meshFeatureProcessor->SetTransform(m_chunkMeshHandles[chunkId], transform); + matrix3x4.MultiplyByScale(m_scale); + m_meshFeatureProcessor->SetMatrix3x4(m_chunkMeshHandles[chunkId], matrix3x4); } } } diff --git a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp index 4036023397..0a7cd229a3 100644 --- a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp +++ b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp @@ -114,7 +114,7 @@ namespace Blast // ActorRenderManager::SyncMeshes { - EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _)) + EXPECT_CALL(*m_mockMeshFeatureProcessor, SetMatrix3x4(_, _)) .Times(aznumeric_cast(m_actorFactory->m_mockActors[0]->GetChunkIndices().size())); actorRenderManager->SyncMeshes(); } diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp index 9aa29cb288..9c3428ad63 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp @@ -248,7 +248,7 @@ namespace WhiteBox void AtomRenderMesh::UpdateTransform(const AZ::Transform& worldFromLocal) { - m_meshFeatureProcessor->SetTransform(m_meshHandle, worldFromLocal); + m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(worldFromLocal)); } void AtomRenderMesh::UpdateMaterial([[maybe_unused]] const WhiteBoxMaterial& material) From 217009de2b8752da208a1c53eaf1062d722f7000 Mon Sep 17 00:00:00 2001 From: greerdv Date: Wed, 14 Apr 2021 18:25:38 +0100 Subject: [PATCH 02/96] adding tests for transforming Aabb with Matrix3x4 and fixing bug in implementation --- Code/Framework/AzCore/AzCore/Math/Aabb.cpp | 2 +- .../Framework/AzCore/Tests/Math/AabbTests.cpp | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp index 48e51cce48..3f7cb4ecf5 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.cpp @@ -243,7 +243,7 @@ namespace AZ void Aabb::ApplyMatrix3x4(const Matrix3x4& matrix3x4) { const AZ::Vector3 extents = GetExtents(); - const AZ::Vector3 center = GetCenter(); + const AZ::Vector3 center = matrix3x4 * GetCenter(); AZ::Vector3 newHalfExtents( 0.5f * matrix3x4.GetRowAsVector3(0).GetAbs().Dot(extents), 0.5f * matrix3x4.GetRowAsVector3(1).GetAbs().Dot(extents), diff --git a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp index 20a4d2ed85..6b7317f5b3 100644 --- a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp @@ -15,6 +15,7 @@ #include #include #include +#include using namespace AZ; @@ -385,4 +386,64 @@ namespace UnitTest EXPECT_TRUE(aabb.GetMin().IsClose(transAabb.GetMin())); EXPECT_TRUE(aabb.GetMax().IsClose(transAabb.GetMax())); } + + TEST(MATH_AabbTransform, GetTransformedObbMatrix3x4) + { + Vector3 min(-1.0f, -2.0f, -3.0f); + Vector3 max(4.0f, 3.0f, 2.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.46f, 0.26f, 0.58f, 0.62f); + Vector3 translation(5.0f, 7.0f, 9.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(0.5f, 1.5f, 2.0f)); + + Obb obb = aabb.GetTransformedObb(matrix3x4); + + EXPECT_THAT(obb.GetRotation(), IsClose(rotation)); + EXPECT_THAT(obb.GetHalfLengths(), IsClose(Vector3(1.25f, 3.75f, 5.0f))); + EXPECT_THAT(obb.GetPosition(), IsClose(Vector3(3.928f, 7.9156f, 9.3708f))); + } + + TEST(MATH_AabbTransform, GetTransformedAabbMatrix3x4) + { + Vector3 min(2.0f, 3.0f, 5.0f); + Vector3 max(6.0f, 5.0f, 11.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.34f, 0.46f, 0.58f, 0.58f); + Vector3 translation(-3.0f, -4.0f, -5.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(1.2f, 0.8f, 2.0f)); + + Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4); + + EXPECT_THAT(transformedAabb.GetMin(), IsClose(Vector3(4.1488f, -0.01216f, -0.31904f))); + EXPECT_THAT(transformedAabb.GetMax(), IsClose(Vector3(16.3216f, 6.54272f, 5.98112f))); + } + + TEST(MATH_AabbTransform, GetTransformedObbFitsInsideTransformedAabb) + { + Vector3 min(4.0f, 3.0f, 1.0f); + Vector3 max(7.0f, 6.0f, 8.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Quaternion rotation(0.40f, 0.40f, 0.64f, 0.52f); + Vector3 translation(-2.0f, 4.0f, -3.0f); + + Matrix3x4 matrix3x4 = Matrix3x4::CreateFromQuaternionAndTranslation(rotation, translation); + + matrix3x4.MultiplyByScale(Vector3(2.2f, 0.6f, 1.4f)); + + Aabb transformedAabb = aabb.GetTransformedAabb(matrix3x4); + Obb transformedObb = aabb.GetTransformedObb(matrix3x4); + Aabb aabbContainingTransformedObb = Aabb::CreateFromObb(transformedObb); + + EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin())); + EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax())); + } } From 79a34f87b03aebcdd10a02dbb7424b629a0fe9f0 Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 08:28:50 +0100 Subject: [PATCH 03/96] fixing merge conflicts --- .../temp/128x128_RGBA8.tga.streamingimage | Bin 0 -> 28066 bytes .../RayTracingAccelerationStructurePass.cpp | 2 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 8 ++++---- 3 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/temp/128x128_RGBA8.tga.streamingimage new file mode 100644 index 0000000000000000000000000000000000000000..b867b7cfb19ea2f70157e69cd9534fd8bfb04002 GIT binary patch literal 28066 zcmeHw3tUvy+Www_jG0lKM3T}r0q0=BDqi7`=Dv~mQ43nCrM-=cf zB48sNjRQ{PWiZ4M%QDSUw7?RRDKCtmj)o%_9p?YMdpYVsJ$?PNb2{G_zkWZ@Gi%T6 zz1H)-&-<>m-n9?Mah%ipf+1`2d!%I!bJ^sa^oYLfy(uHV%TVEczi2)X?Y zdpzG13{KTgS=#*4mR*gV*1q=r7fBJz9v$H`?0DLYWXsF>+O&6{Z}V-_LR_!mBCMm% zw7+{xb6%I|yR-;6F8qh&xb*Y7?M|OJzO;Dt^>?PHI?oKkV}-vUI1zEj=WV!%lRM{B zXMCM>ZH#P0(?4F>UbpMJcR#`Hhj9D<@ym)R!MwQdzu#N+LhlXo!#^GE>!uBVBtsE@ z$M4|x=Wmrr@A#bKMn0DMqRQv{qIS`76GyFCyS{AZqqB$Xe?BPEPq6IZd%d6DJ92H| z`cI$gwE2loCM-Mg@WMGILF2j7nEUHT?ii}S#^f(M z`M>BpTttN546nNgB7`i$?Xmigjw#}&D~CVdbLHQE+#hi@D;A$W$VI&Ryid;EzqG&l zZ(RoplJ_i~8UEOdeYQ0F&wQvfRuyi#vMKj28W(<|Df3$E&+T?D{ITf2ooxL%ZXMoj z+V=Nae~#-TYT{!?-$jej39&x^$-9IbwA`~35z{|)PMts8H#_>xmlqfLt{#_uBC*tt zKQ1Er_{XVt?>ILyV%93t%!bvAp4v7s<-IG4`gezZyE>foy7dE7NB;U8!S())12?kf ziY@4&8MecH(;^=J_`7v09ynyvjHFSXXxcs^DP+W>>GpS=`n_SB9)9xD5%0TE5-~I6L|MKr((2%9k3ts*}lcqYbch>GI z$HmArxQG{jX*qcpGZJzmzwWf^v({g|M}8IVQJ!-8E)N|3-sbXNcYH43Mh=suPWXKW zifrYshAX_s=T7(d-1#1#KX8xF@1LRE{rUg+-{(fYvwXvYvz#tBr0$Pgz1AiA#pUxR zhVcga;F}9a6rUdY-iB>K2|w)|@{j$|vmSrxkIr@@Hv5dadKVMy%0&pjy?*x279q@b z4A;HOoh?DI==;!-pnIn6Xt{UVey@&5@6{1F;5|Aby+0l4de4ra<+pdlO4FogH$ z2wHx7M=;E+5x)hoIe>N;&&qvuY|K~(_iLspnKL~t%-e6HTkR+Ge3fgkP zzu4#biJm8HE#n>%0LKg#Od)J9;M|13Gi6*9aw56CkaH6RN7-W}K@1n%xLy+ExV{}X z=4bm`l4$<-l+BzAem^j#T`G^|DQ0JSp5>|fu6Q81Tv^MWcfp@_JpZKpI_RYF&GxTR`duy_ISWh;|B=?v^WP_);BZob>Ao{@jK8XcxLH|9^7KzT;KxEuS;-L)rmITCf_`do4Cs5CLZ|6n4`x#i-H{2 z_wA5!w6e2kX8`M~>)4_p8-;J}@TA-dz%X%A+f%wAXSTf|Mxx=5~7i zc~hEoVlMb+uM6$B@b;omHwwvKf)@<9*glkJyR@lCO)l2;z1otF045-K(xtsfz(=7C>;J|Q;ZhaWvFwv3h+PL`#{W& z(>+ANAtQQO%L=&h1IQkF2$qH}_9YxPq>0Cc;Wd85cX&{6RB2Tk?qIn2d4|FFZFs_S zj92yD3b3XTiXUkr~^gN1|0?pt~geB2m`Yn(uTWWPr zyQn{F27U_mqJTX-Ca|BfZ(gw_5B94_X)%kSFJ9Xh9$|W-Z2WK64`$yP9Ub=V${qNi zI^~=z^{>MEoTP{I0bA)a$G~q_&T1=?`E@9%TXW`f#;;K(4(U+>ev84UXE*RI4jaJu zF2ML(i+T&E4R4Cs0sh-gbr}kNg)_&1|1$#wqh>^hpq-nmVEiwSD-0)o6C)4ID)sad z98Rj^@%$;lQ9Ho5C8_OHYM&nkJ-7`gMS|}tmms=ciT3yju#fJdksrk!lbdZ1-*b9lQ{=WZMabI`eQV~z%%Z(qsBBc-~Lk9YGH+_rR0`tj${3&!`l zn|!;0@3NF8S9<;mtI@~%!IC8H#m_}g_3GwgH5N&RJq8TE&Cl=kAbwwcmhsR0RVIF8 zL<#)=bCLIqp5V7o94{w4K=e^uK`8P6?o`IVbkWmONe@=cV*JN0inckU@tqz^{x6xH zvFf8Z1@wRMYrMZt@3Y8z2Kd$_D!_MVNzCD-gW-ylTHTD1SNFpIQ^`IR>So=90amhy z)WUGmlUm)2Pg?gjKiV$UW#}o7lxDN;S&?;EGukP>fPUShf|R3yn^#njKH~c(R{|>w> zm*;<^u9s>T+-gfGjezvkAS^PNgd*M6L;UxI8u}GF0&G>$0*{B)B_Xah?ZaJ1D zBm8}9TFDI30~&9uu~586NA@s4rWK_33sj`{;fZ;{BM0j7arH2_Mwl#;h zKjPf28|*=45_9UKUa$w^OQDQV{hFS)Zf`x`_7EJ%$x4ZLBfYU2y?y*1iskuUjQN$p z+eaezjcu9(z6+3VgKt^vXl4&Fh<8RGnK(6?*~2S{&twmq7A7>!fj*F4!hFQLbBOQn zc)kfA-3t4Fzptw-HjqA?-dA#s^1~rDgZ7bqTs~GZW96CcJil;%Vbkf7x{MS3M7tY? z)KGq4ySU^+#tBc(Zcnx#KJ;#}HvKrK%2Q;w?`{C!VtZro$*oyEcwAvw%Gn#o94*dj zGm_esz%ACReT$E_3A%B;#%5_5R(#wgn0_y%r9gM>>{aA%qG-Aw(s{1_2kS88b1`Hu z3bk2NbHKWn^qRL1*h6J8@heHC{t#cE>A)}inb!+^Q20Lh1SWeRf6kc6_@#UXP!~Ur z;pK5lL)DFD)5L+B`(6!ix8)%62YlTe@Cdc1Zu!zLSE^1lo1PF@w*?feu+sckspj*? zpFLmtpX&kqecjq6THfC)Dy;o`K9CSU&N59*`KhtUM;824Y<%3sX|AM4M)3W{aN>KK z>(j`8fhF%w;rVx^{EX~jgPPex$Bm@tg|gC2hRGicFc9z!efaJs-!%uAK6HV9QT|~4 zv7~7Z_$U9R_+Yz`P&emHKY@c^dqeDmnJYbkcQ+ViLe75uaxv{d+U?c$A~F7LAw(FZ zK>WWffBqk1TZ~Y5`}dnp=cT7H`#`woS}a%kRvvYk&f5p{ywP-pkJq~!I#(0lwO?Q0 z@gz&;A&TFX#XO&Shdq?72Zq1%`p{_BZCc3qCjTHlm%h&ME6bjqN_@W+!s8>OW(0?* z6B|vVWrd^Lu^B+Wt!_^%)gD^-m+Kw17DmhrhHuwy`MLpw+~m!X9%y3ONftyy^x-f zJ#0;5_OZs0v5M^F>&;9*NY4qM{(|8y@NcrOt3Q%Hj29E%M!ihZV)1=rbWRZX&9RU^ z*soo#Z0E%I)f3sNbq-L3*po)WDk+*=EfbXHxr**D1QK*rgbXfv)z$zvkxZ`zw^ThuQ)>U3$?1z z6fwB4`&IBw@fO$|@Ms~mSCAfnesdSWmA-)m?VEGKr&^_=^{1nrx8(=OAG4<|(LycQ zUstCDtzuwod(sccz0c5YzH`S}CW~plruX)dMGcFE9++GyKQZEig;9j3@%|1h%UwWt zvTMhU(nZAY9v$=o?G46`8(}|^%)()w?rcRkMsR&_H&y(Trxo)F6DJc{sw!4r z4f!bi)%?XK^5+#t2JIWak@(JkpJ5gs5*wFJXZ%vWtOmi+BYDj00r`8dR~~O4J+U68 zQkhL&ZR)!FuUlcI^|Z)Hm8uQ*@@HO2!oY5nA1D-&ZMY@cu#$8)!WF9xhTbAS_i^Vg zxzhFhy}i9(miev@1)sFurT6ysd25s}&p*v)$sST?`gS6Fpm;@Cznrzx^8(7g(o_3n zSBJl!{fhMAv@6-a0bgi5<=YT?cC47S1(56wS2UFIbD zqz5LGMuUi-XC2#4Uu_>!lh|Bqu0727i@ z-9K!FmGqVTJ8m3nC;d%?e}_Jc?}x3ZAbo~?sQR?a&9jEBxJ>atg?0&dWm`b)!WN1L zkr5H|C0vPCk+7Pd&-L%$-@8wH;`@>-T@Si_Li;gH>z^Bl8k(l@=2kI(tRa0 z`>%B;=C7d3T)IBDdo%d1#CXCSOxek~JpbQjTau_fabj*>6WVFL5_GF3_~ZKU71n~# zFZ}>b13R(nX+Hy4^^l-0FTlKz&j(bh*|S{*39A(e>3qINeD!#y>qT{8w^px39GW+NnQimtC$R z{x7*wf9dyZSI*6L-DKkZ-JsX&k*^_A{f>O?-_7rDylFQ=)R6{KFPnX+0ZIHR*Y@uU%n1816EZ z@ZiVMzILJCmzbXueppyb{0Go{Za%P70P^wQ6zBo*G2jv3huWV@1OK@^|6u`_rGyKx zUPtYTlY#Ny;iU6XgtHegOzWkDcjft}yTX2G{fzMOz4$#`LhC7n>rK9^UGaOEe^={) zTN=)#iT^PhI={Pt+W+hI{@3iGX|2=ca@PygU$e<%x_V~q!v0|k`&0ZQeyaC_EZ}P= zCmbUD**|pDZpCVpo^am#xqN%ajjt>t{Lbq-;-1{Ga3bE(ophYX^RQmH)qk+{;q8Tl_QoxXFJtoF6|){1e|T z4IfIy8`A#o@ZT(T@*V5cpXCE4^VKsT8_=-?E~G%-OT@XST2no=pIM;AM8PYp`r%gUp;OT=6m$}wu_r)k3QFN z9OZvLMS7$Cx>FzS@iff$|Ci){HjdMA;;xSV*e;igzmXP!{~U|iT$_0LxJRlrystmy zL(^5Nupf+JK38)C{mEazJXB`|L3bCvEG*+wnUpv{2L6`irymT&s0wXdY*gf z>9f2))BF#7>0?G+BpgTcKN&t)G4tZ3(Z25SH2)*4U%_7=Py2Cz#)Ep`f$s4%|C9OX z^=A*BC3}dc`Ja!s-q3Vo~ z8k6aoSt>aa?gM|1r~y>fmV4-}xn=%CYBCR*pa(~`g{2Z+SGmT}*qo@|zB&x;+x%(% z2YX0d{Wjq;f0}O*jvG(c_w^@#1iy))eHo_tA7Nit;y=*;HTW~}FX2o@Ew#hEh;LOy zM5Gh9BwZDp{drfYu3>dWMK>qQY&XOMTK|E38;5mc{L%h2_|;Dx2EM@`t^W|ei>5L@ zDgL0{n7iOC@fqI_`Xuw#8$Z>ZHH{wFDW2B5ee^~{m62gu|A9RiFCW`Dc{Hx4`Jeog_1wNJurXo=kWKI%jG?{ga`VQzw6-dS5A}{9LX&U zp!FYfV`60WXVSt7@Jaherbd-|-zE=zMP8Xdb|>|qH!^<-Zyy1)o`UAcrP0h@X#K~m zN>oRO5Z>lb>%q8Q9nzERW1D|4*5~p2i9Oqd6*c8<3!wEJWQSPqnf#r#@azxKsQ`us_0U z-X^S#-wOMbfZuKD^nI=*PJztNu|d(bA39>|J}XZGbxCQR$Ugs+~=hCOJtG(KYB zmP^^?!Dl;aY5WM=uXBhG(ph8=oKT|wkLL&1;W&F1!!GeWoX%{oPwSET=yTwEeS^;2 ztZw?bJpahl!|?YZH74+V?jZP{dN_dekMPm09)%Tohk1WD!{0yAO2Pl(fMSf72?S;( z0K-0L{TEQ39M0^+g7sg*lZHt3)~GVX`x-ykPhvo4W*@ZvOW*GzTR_1}Bf54j*8NIH=9Iq5@xLq$dJHjGcQA4GRU@KYO2? zad8y!tJRVo5dXO;xE`3+gJnKO!>)AMF#w%y@>zuP|e zd~|{5&EIS0oJT%+Fo3@wm*3oSDXmBP)E|N2-}%kz#-Gabw@e*1nDRLdaNQx|e@x&c zOTr;@ZF9=89q@nfzZ3Zo*~h0Jz#a<61U4Ama&+cK^@odq!9VGz3GIJ-gJIs^VJ|a7 zJY4JG*J^3MAMR_- zU&OE+`~9+_GGkdz4%tU3*#r6aciV{X%+kz5#RkG>z6747EhT*bw*B%0;mpz;%kfHK z?;>OK*_Gv^=4Doqe{td>tId+JXVf#9)np&yf--B%RbiiC@5~d#m$1Mtw>JrOF+DQD zC+wx5&~9(yK92Ep-~xLK-d+>!IWdrL&$laVmo=U--D7~kZ$Wd)HM3?@>RUesQvBvL zwdyNXY57~GO#;4l5_Buf2f_ba%0RMTojFnY{f_dUTQ@5M9enT21^;=URz4>f%wdbA-&gTQNBnx|6Sg{OUWL37na#} zWdX-$-mr%<>!FW;=Vg{s{z&|vC|gPG)s#QL-EHQtSB{-IFSDA)TiCnIYB| zic8;X{+{~Qg+R*Bxq=k=xkG82(%*{V`Gxx{t3NH@v}JQlAg$NwYSoG(TgpG#vUyS< z~<58&TpUww9dZA;4LCBWdH;Y%jp6GZKs&O&sYAczqjVQHEx|B zNV$RO+9g>hC_c3JHdH+GAmjfj+#m994erkKs|^l0)A|$PANPU(d0C#s7xDk&myCZ0KCxG`Jza0}qWQN5 z?Zv_2U7$LW8+Ek3w&&s>f#$*QLNLk=o@MT~Ew8my;qO%M(7UM2s+|je2j7%WLho%G z-{t+iitK~@{p0kNLFE6ueH7X&O0o!N*^9CM#Pu$+?#}B#_&Tkh5Z`+~r`pH9#FnU z_OSE~#y7=p=z}tTJj0}iWDiq=%JU82zwK1`x4AiGR8O?S{~de}XbTMf!MD@|f;$Vs zjLp_lUNqi>ow%^yrSGl%{kLKv7oF}Lyzb_CCwIZcOWLNK(++#^aX~&0e`q4!x)NM|kmT;2*dT@=M}BJr@2yFRMCZ z)$%wo_|HsYeAD^}>HYe5z&H4(`flP|x0u@#Q=H{V_Ct8Xd*Ht~=O+GO0r-diJFZ_h zAN<2U==X5Fa%CLjpYEqAXi+YCBaQ4Kknw9*%nv6$u<-g#`tVi=@jWY$=4Yh$69*BV z6iD@3I^=`U^ZYIFck+*X;J#wuY05x{e|Hgteba2Uc;yn`@ONi!?Y17jBcA_Oet+xr zqz|{xC#4*-2Z|RGA8SPq=WG+jZ>k>^7nRutcLd)vGfOF-6hhx$>dE|_<`>WlYxp4E z->Z4OD700){sQ5wYSKsOfpzvPJpb33e%R#k6Bz$gKgsnjlP4<~K8*b_;#)n9_|NgQ zBt7lGAIBJO;pE9Y|7d5|Crsr1-;?$`xqQ2PPAKD>?x(4>E2fWR*qitTju=e-e*ye{ z>8FAJkCqXh6iD@1qz3_y5dSfOG(RJMm$fPXw^!2Ut2N&+*?9u}tcv3#;W0lLh2+qvbmgQV0`xY13tWQ74`}+xsACUWs z!4LENSJ8PH_`mf9Pp0>D-bz?dRx!p0{Laj(4i0&(7wP@0gBahmUQPMm#K4T8ImKDm zX?{%nM+`;$hyT<1IFE;+q+g$N6Hg3ceBZcUq3~z=Px~Kq{VTqR|1lT9=VD(jzePT> zM;h{j3xU00uf+dzkH8*~FMbGqNgsSfz~GnqqpM9(JRvOK*?hI$i`Lgbze3E79c5Sl z!sly^kqSBH=YMGY{!iOO>-$suxILc`ac5^|9mw${z3{PB$UV4h)0(mzJH->&hurgl zm1F0WWu2z^hq%aI;Vof&Q+$Em%lma?_;u(B@inM3^uIXk^d{_Q16K@wf(x1n|EK*B zY9IVK>;e2cuwNI%1Ly&r52f}2?o9t_{fn?qTi~~BUc{#c^Mf93z^}pXN%hyd<`j8n zLHYjUSM9uB>zeIK2`4?++_IAIk4deN!=F!)K0^MuNVy#6x&i)+{riu8egP-=r}ar^ z?qu30w~d#GJ281j(+B+c%ItD^dv2wv*v>FlXp?soGR)hL-7bGvC@iP;DA*J6=`Q5< z5TqyuoL_TK<2|e;?rOcYPy9@B?vKUudZ8Jm17&|lT_IDdrmC?CbS z45j|7hK|AcLzf^2p3|S5KcegDyxEk;*m;xlQF}db{zUhplbX&GhEGiIUR!y%axo zKF5;ur5~NoTR)NYzdpMz9Oo~DTi@o-V+rQ!>HJ=AZs#JL$3p)r4X-St{_lL3KYtf= z%*gPzdG>GVy!{#j&con5^@d5T|86=1S@O zj5p5DdetqoGW&`A&Eo-n*PmFD*@@@3!q8tKLH#<;t5AP&yiM}Aq3nFZE6ajI=zL1? zEY|wk^~J3Q$BFJDmq+u*!W z7?0}=)L+qbx}MIL|FDjoAKh75pH1flOXAr1l48T*BsyQT;zgV%!TF)Bt9pgd`GN>3 zt2bX7x#H`rpU~c*?;d>vr)YrdF68Mo&S+1zC~GyG?Xb0P<#BOz zwS8SB@q2a?@!d{;?PR}==&r8hZB|cT40{1KEec>*y2xcH>g&zH&gc93qrS4|P&zNC zYNYpfcqT94^DVhtF}^c*ASZi?wlnD!j<@xn^awleP#B(vdUtPGPB_)GPjju$J{V5* z>J@9KUVWN)C-|lF3fB(e`m^PtlMR`N==__#e#3BqQ&+x!-je%pKH;i|Q$Byb0QG`< zXgp9q>>){|@u2e|$FtaZft{6ZIq04#Z!)VV?zpk-RH`4J)|KJ9@Y7vUFKBv_Oa9Dj z&Vm54Zv_f~WvKsF_@%o&1wA$x`ad_zm(}Zznz5L#_x(7|*Gl!kz><+dTrEm z52;y0<=Zm5`P?+|`mw0jh^Rq*{vThjeSWOd1&#Q9vJcf{ljg!Fe7*CLNtRRCyT z34gMH;bH?$c;oNVUeqsQJd)wRgzXL8E(so=%%49JiJY8%_kPo_)(>igW=&fS`Ols` zdo)+}=b}Dvg>`)cs~6n8gy9Bb>@sZktLDFedcm~|Q6JnZgs`9U&rbfR2gB@zum3~; z)6sv_``qY%5MS>%?q>fNq8{X&beyCAm-nLcz_#2S% zqDCnBH`FJb*SO@Dw?#ckvW4nLE`EagA=Gz}{iA#&aYrKhkNP39e_+*IKf>KnAHvsz ztDfa_P60n}3wRCvRjDE(J7d3Bbs+Nu>0f^ofJ8ou{$YRjAoP#=mot&?Z#>0wU}L3r z6ZU&L#Zx?zVSo4f*I4hhbc`pxm&m*g_A6Xh&Rxpab7Ft~_t$G+KQ2ha>SwUgKHFAa z?s5e66xCSa$99OiDu?ZtAFu4Vk@iFKCS!jb`{ks6wEsD+8}`GoKTi5*!uUMNnY()> z9rZee{-XRv@c?%K^Uw936#v{;%jLs`XD@}uYPA&qB&bi)__O^i%5SipX)KOqnDQC) z*LXUQt#=QpK|KT3H?M!=Ha6rLZE3YV;SlXt;gvvr1V2*!0`?1qy^Z!p+-T)0yqX;Q zkDSnk{YQ?=c%AJxa&YVOcvt7qudtt-Y{CAb(pIkNp`SV_ko2C`i)-@P{$b~8>^EQo zpmZMF51{x*_}xH;rHg9(%)lYeY=4O2AGU`hMcnM8v>!<8FXLambN<ofKH*nV7&Wx^qvZ`JerFE%d+zOV!9D_B2?sHrs2di(KgwqAA|@r~Bc zcFrZN40QB2JsA5Vz!|HSVt-VvoYaBsuNQ>odB8p*dvK<{fyuvkQvRdD`bz8kr!{W9 zUe%jxNQ*y^bDGxYu-zq}&<_1YeFEiIV)XwVf7XA>M``_97s1vm>$A^CVL!^cJ>HGq zf1vn@^(yPG#jO97?^6GFy~po2csZ~^#jiJD|HzW0!TLh(WLiJE5J>h+{eL%r_7|0b zl;6;P!lZ{V9#fTp)L+^^>cfSV1)#qp5Z|c3zjr^V^>}o{c$C6l$UeLca`_8R*<h`7iqpYj;%Kh0N&|2h5n^%#51j1T$sv&7;2dW`4cq@MixTjFrG-s-?_4`l0Y z%j0PM&aRx=mG!?a{FDdw)0Dx^)PIW?*)!H#6i;zsV**n$Zu0wk``g+cehs%l{5Xw} zNApn(hx~DFxjR^{{SbhPe$4-zn<2M=zf31`cVgd{z9V2U77w%~mOMY6ANyboy5KD^%v^UJyv_I|gB8a7|7 zdk6EyDwmN%YGV2MD6|e-!tnp<-z=XHMmN+0s&IeY9FK78{>XPwpWmg1<-7JvxcLK8{`|F2=!AbU ze)!LhKXez*)e6^h&XYM8@r$!zOYck?-vt>UdzjG?DrAhq|b{4Qd#BZ zab9G96rVge)z373xwv11;?DTn5%su^=jjiJd6mnVt;Kpc`IE$0A&+%}o?`!E)QqmY zUc@?)Ugq4yVO;tCW_1Rx@5<47vj;c(mz(#)@3r>7*T^3ZWOZB~$NOLZ6M_RN^ggw! zlX%~utx)_U-am!)CcOU!?@vsr)x1g9&ld(@cMSgeYS?iu0q1)!xh5Q1fcJr5KJ?j! zARKpuU3lyh(ZBnoP8yEp^Mm$H)^J?40Oyfm66-3Xq&SYOs^aiv-_`N-eSF6&pfSr{K=saWO8=NRT8;?Zx`_yW={G?_ z>3M}%|2-+7{aU*h-A_}SB7ciB?e&75(({KQ|FPqJMsXir60C3N=2D>-N$i~ZS$}E! zuXi`#eSL|OO?K{y*InstanceID(blasIndex) ->HitGroupIndex(blasIndex) ->Blas(rayTracingSubMesh.m_blas) - ->Transform(rayTracingMesh.second.m_transform) + ->Matrix3x4(rayTracingMesh.second.m_matrix3x4) ; } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 99748677d9..d5c9bedf80 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -295,10 +295,10 @@ namespace AZ for (const auto& mesh : m_meshes) { - AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); - AZ::Transform noScaleTransform = meshTransform; - noScaleTransform.ExtractScale(); - AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); + AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); + AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4; + noScaleMatrix3x4.ExtractScale(); + AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4); rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose(); const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes; From 2bfb93e5e1fec303714a50df7fc7f03fac862c8d Mon Sep 17 00:00:00 2001 From: greerdv Date: Thu, 15 Apr 2021 12:34:35 +0100 Subject: [PATCH 04/96] fixing non-uniform scale for mesh on activation --- .../Code/Source/Mesh/MeshComponentController.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 17ee56f36e..59f4a8a92a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -293,7 +293,9 @@ namespace AZ m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); - const AZ::Matrix3x4& matrix3x4 = m_transformInterface ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) : Matrix3x4::Identity(); + const AZ::Matrix3x4& matrix3x4 = m_transformInterface + ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) * Matrix3x4::CreateScale(m_cachedNonUniformScale) + : Matrix3x4::Identity(); m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); From a5fdbddedaba651f097982dfa0facfacd404b9be Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 15 Apr 2021 20:24:50 +0100 Subject: [PATCH 05/96] Merged MultiplayerPipeline from CodeCommit --- .../Serialization/ISerializer.inl | 18 ++ Gems/Multiplayer/Code/CMakeLists.txt | 21 ++ .../Code/Source/MultiplayerGem.cpp | 4 + .../Code/Source/MultiplayerToolsModule.cpp | 65 +++++++ .../Code/Source/MultiplayerToolsModule.h | 33 ++++ .../Code/Source/MultiplayerTypes.h | 47 ++++- .../EntityReplicationManager.cpp | 2 +- .../NetworkEntity/INetworkEntityManager.h | 6 +- .../NetworkEntity/NetworkEntityManager.cpp | 110 ++++++++++- .../NetworkEntity/NetworkEntityManager.h | 31 ++- .../NetworkEntity/NetworkSpawnableLibrary.cpp | 81 ++++++++ .../NetworkEntity/NetworkSpawnableLibrary.h | 43 ++++ .../Pipeline/NetBindMarkerComponent.cpp | 35 ++++ .../Source/Pipeline/NetBindMarkerComponent.h | 39 ++++ .../Pipeline/NetworkPrefabProcessor.cpp | 184 ++++++++++++++++++ .../Source/Pipeline/NetworkPrefabProcessor.h | 43 ++++ .../NetworkSpawnableHolderComponent.cpp | 42 ++++ .../NetworkSpawnableHolderComponent.h | 44 +++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 6 + .../Code/multiplayer_tools_files.cmake | 19 ++ Gems/Multiplayer/Registry/prefab.tools.setreg | 26 +++ 21 files changed, 890 insertions(+), 9 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp create mode 100644 Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h create mode 100644 Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp create mode 100644 Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h create mode 100644 Gems/Multiplayer/Code/multiplayer_tools_files.cmake create mode 100644 Gems/Multiplayer/Registry/prefab.tools.setreg diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl index 2d983c2061..2720f09f4b 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl @@ -18,6 +18,8 @@ #include #include #include +#include "AzCore/Name/Name.h" +#include "AzCore/Name/NameDictionary.h" namespace AzNetworking { @@ -173,6 +175,22 @@ namespace AzNetworking return true; } }; + + template<> + struct SerializeObjectHelper + { + static bool SerializeObject(ISerializer& serializer, AZ::Name& value) + { + AZ::Name::Hash nameHash = value.GetHash(); + bool result = serializer.Serialize(nameHash, "NameHash"); + + if (result && serializer.GetSerializerMode() == SerializerMode::WriteToObject) + { + value = AZ::NameDictionary::Instance().FindName(nameHash); + } + return result; + } + }; } #include diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index dde5e387f6..d395938e8c 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -56,6 +56,27 @@ ly_add_target( Gem::CertificateManager ) + +if (PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME Multiplayer.Tools MODULE + NAMESPACE Gem + OUTPUT_NAME Gem.Multiplayer.Tools + FILES_CMAKE + multiplayer_tools_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + . + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AzToolsFramework + Gem::Multiplayer.Static + ) +endif() + ################################################################################ # Tests ################################################################################ diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 9fa1413be5..15d4e2f6f0 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include namespace Multiplayer { @@ -26,6 +28,8 @@ namespace Multiplayer AzNetworking::NetworkingSystemComponent::CreateDescriptor(), MultiplayerSystemComponent::CreateDescriptor(), NetBindComponent::CreateDescriptor(), + NetBindMarkerComponent::CreateDescriptor(), + NetworkSpawnableHolderComponent::CreateDescriptor(), }); CreateComponentDescriptors(m_descriptors); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp new file mode 100644 index 0000000000..16f13f9ee8 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -0,0 +1,65 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include "Pipeline/NetworkPrefabProcessor.h" +#include "AzCore/Serialization/Json/RegistrationContext.h" +#include "Prefab/Instance/InstanceSerializer.h" + +namespace Multiplayer +{ + //! Multiplayer system component wraps the bridging logic between the game and transport layer. + class MultiplayerToolsSystemComponent final + : public AZ::Component + { + public: + AZ_COMPONENT(MultiplayerToolsSystemComponent, "{65AF5342-0ECE-423B-B646-AF55A122F72B}"); + + static void Reflect(AZ::ReflectContext* context) + { + NetworkPrefabProcessor::Reflect(context); + } + + MultiplayerToolsSystemComponent() = default; + ~MultiplayerToolsSystemComponent() override = default; + + /// AZ::Component overrides. + void Activate() override + { + + } + + void Deactivate() override + { + + } + }; + + MultiplayerToolsModule::MultiplayerToolsModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + MultiplayerToolsSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList MultiplayerToolsModule::GetRequiredSystemComponents() const + { + return AZ::ComponentTypeList + { + azrtti_typeid(), + }; + } +} // namespace Multiplayer + +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer2_Tools, Multiplayer::MultiplayerToolsModule); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h new file mode 100644 index 0000000000..823bd63a1d --- /dev/null +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.h @@ -0,0 +1,33 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace Multiplayer +{ + class MultiplayerToolsModule + : public AZ::Module + { + public: + + AZ_RTTI(MultiplayerToolsModule, "{3F726172-21FC-48FA-8CFA-7D87EBA07E55}", AZ::Module); + AZ_CLASS_ALLOCATOR(MultiplayerToolsModule, AZ::SystemAllocator, 0); + + MultiplayerToolsModule(); + ~MultiplayerToolsModule() override = default; + + AZ::ComponentTypeList GetRequiredSystemComponents() const override; + }; +} // namespace Multiplayer + diff --git a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h index b387602843..ad491f4016 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace Multiplayer { @@ -69,14 +70,54 @@ namespace Multiplayer True }; + template + bool Serialize(TYPE& value, const char* name); + + inline NetEntityId MakeEntityId(uint8_t a_ServerId, int32_t a_NextId) + { + constexpr int32_t MAX_ENTITYID = 0x00FFFFFF; + + AZ_Assert((a_NextId < MAX_ENTITYID) && (a_NextId > 0), "Requested Id out of range"); + + NetEntityId ret = NetEntityId(((static_cast(a_ServerId) << 24) & 0xFF000000) | (a_NextId & MAX_ENTITYID)); + return ret; + } + // This is just a placeholder // The level/prefab cooking will devise the actual solution for identifying a dynamically spawnable entity within a prefab struct PrefabEntityId { AZ_TYPE_INFO(PrefabEntityId, "{EFD37465-CCAC-4E87-A825-41B4010A2C75}"); - bool operator==(const PrefabEntityId&) const { return true; } - bool operator!=(const PrefabEntityId& rhs) const { return !(*this == rhs); } - bool Serialize(AzNetworking::ISerializer&) { return true; } + + static constexpr uint32_t AllIndices = AZStd::numeric_limits::max(); + + AZ::Name m_prefabName; + uint32_t m_entityOffset = AllIndices; + + PrefabEntityId() = default; + + explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices) + : m_prefabName(name) + , m_entityOffset(entityOffset) + { + } + + bool operator==(const PrefabEntityId& rhs) const + { + return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset; + } + + bool operator!=(const PrefabEntityId& rhs) const + { + return !(*this == rhs); + } + + bool Serialize(AzNetworking::ISerializer& serializer) + { + serializer.Serialize(m_prefabName, "prefabName"); + serializer.Serialize(m_entityOffset, "entityOffset"); + return serializer.IsValid(); + } }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e58b7fde9d..e19bc7685b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -544,7 +544,7 @@ namespace Multiplayer if (createEntity) { //replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity()); - AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString()); + AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr()); if (replicatorEntity == nullptr) { return false; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h index 2262cccd19..be4f32752d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h @@ -16,6 +16,7 @@ #include #include #include +#include namespace Multiplayer { @@ -35,6 +36,7 @@ namespace Multiplayer AZ_RTTI(INetworkEntityManager, "{109759DE-9492-439C-A0B1-AE46E6FD029C}"); using OwnedEntitySet = AZStd::unordered_set; + using EntityList = AZStd::vector; virtual ~INetworkEntityManager() = default; @@ -50,7 +52,9 @@ namespace Multiplayer //! @return the HostId for this INetworkEntityManager instance virtual HostId GetHostId() const = 0; - // TODO: Spawn methods for entities within slices/prefabs/levels + //! Creates new entities of the given archetype + //! @param prefabEntryId the name of the spawnable to spawn + virtual void CreateEntitiesImmediate(const PrefabEntityId& prefabEntryId) = 0; //! Returns an ConstEntityPtr for the provided entityId. //! @param netEntityId the netEntityId to get an ConstEntityPtr for diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 46d1617760..d92becfb97 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -32,12 +32,15 @@ namespace Multiplayer , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) , m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); }) , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) + , m_rootSpawnableMonitor(*this) { AZ::Interface::Register(this); + AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); } NetworkEntityManager::~NetworkEntityManager() { + AzFramework::RootSpawnableNotificationBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); } @@ -147,7 +150,6 @@ namespace Multiplayer //{ // rootSlice->RemoveEntity(entity); //} - m_nonNetworkedEntities.clear(); m_networkEntityTracker.clear(); } @@ -282,7 +284,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - const NetEntityId netEntityId = m_nextEntityId++; + const NetEntityId netEntityId = NextId(); netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); } } @@ -334,4 +336,108 @@ namespace Multiplayer m_networkEntityTracker.erase(entityId); } } + + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable) + { + INetworkEntityManager::EntityList returnList; + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + const AzFramework::Spawnable::EntityList& entities = spawnable.GetEntities(); + size_t entitiesSize = entities.size(); + + for (size_t i = 0; i < entitiesSize; ++i) + { + AZ::Entity* clone = serializeContext->CloneObject(entities[i].get()); + AZ_Assert(clone != nullptr, "Failed to clone spawnable entity."); + clone->SetId(AZ::Entity::MakeId()); + + NetBindComponent* netBindComponent = clone->FindComponent(); + if (netBindComponent != nullptr) + { + PrefabEntityId prefabEntityId; + prefabEntityId.m_prefabName = m_networkPrefabLibrary.GetPrefabNameFromAssetId(spawnable.GetId()); + prefabEntityId.m_entityOffset = aznumeric_cast(i); + + const NetEntityId netEntityId = NextId(); + netBindComponent->PreInit(clone, prefabEntityId, netEntityId, NetEntityRole::Authority); + + AzFramework::GameEntityContextRequestBus::Broadcast( + &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); + + returnList.push_back(netBindComponent->GetEntityHandle()); + + } + else + { + delete clone; + } + } + + return returnList; + } + + void NetworkEntityManager::CreateEntitiesImmediate([[maybe_unused]] const PrefabEntityId& a_SliceEntryId) + { + } + + Multiplayer::NetEntityId NetworkEntityManager::NextId() + { + const NetEntityId netEntityId = m_nextEntityId++; + return netEntityId; + } + + void NetworkEntityManager::OnRootSpawnableAssigned( + [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + { + AZStd::string hint = rootSpawnable.GetHint(); + + size_t extensionPos = hint.find(".spawnable"); + if (extensionPos == AZStd::string::npos) + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable hint doesn't have .spawnable extension"); + return; + } + + AZStd::string newhint = hint.replace(extensionPos, 0, ".network"); + auto rootSpawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(AZ::Name(newhint)); + if (!rootSpawnableAssetId.IsValid()) + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Network spawnable asset ID is invalid"); + return; + } + + m_rootSpawnableAsset = AZ::Data::Asset( + rootSpawnableAssetId, azrtti_typeid(), newhint); + if (m_rootSpawnableAsset.QueueLoad()) + { + m_rootSpawnableMonitor.Connect(rootSpawnableAssetId); + } + else + { + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Unable to queue networked root spawnable '%s' for loading.", + m_rootSpawnableAsset.GetHint().c_str()); + } + } + + void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) + { + m_rootSpawnableMonitor.Disconnect(); + } + + + NetworkEntityManager::NetworkSpawnableMonitor::NetworkSpawnableMonitor( + NetworkEntityManager& entityManager) + : m_entityManager(entityManager) + { + } + + void NetworkEntityManager::NetworkSpawnableMonitor::OnAssetReady(AZ::Data::Asset asset) + { + AzFramework::Spawnable* spawnable = asset.GetAs(); + AZ_Assert(spawnable, "NetworkSpawnableMonitor: Loaded asset data didn't contain a Spawanble."); + + m_entityManager.CreateEntitiesImmediate(*spawnable); + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index b154983f4c..20c67a74fd 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -14,11 +14,15 @@ #include #include +#include +#include #include #include #include #include #include +#include + namespace Multiplayer { @@ -26,6 +30,7 @@ namespace Multiplayer //! This class creates and manages all networked entities. class NetworkEntityManager final : public INetworkEntityManager + , public AzFramework::RootSpawnableNotificationBus::Handler { public: NetworkEntityManager(); @@ -40,6 +45,11 @@ namespace Multiplayer NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override; HostId GetHostId() const override; ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override; + + EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable); + + void CreateEntitiesImmediate(const PrefabEntityId& a_SliceEntryId) override; + uint32_t GetEntityCount() const override; NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override; void MarkForRemoval(const ConstNetworkEntityHandle& entityHandle) override; @@ -61,19 +71,32 @@ namespace Multiplayer void DispatchLocalDeferredRpcMessages(); void UpdateEntityDomain(); void OnEntityExitDomain(NetEntityId entityId); + //! RootSpawnableNotificationBus + //! @{ + void OnRootSpawnableAssigned(AZ::Data::Asset rootSpawnable, uint32_t generation) override; + void OnRootSpawnableReleased(uint32_t generation) override; + //! @} private: + class NetworkSpawnableMonitor final : public AzFramework::SpawnableMonitor + { + public: + explicit NetworkSpawnableMonitor(NetworkEntityManager& entityManager); + void OnAssetReady(AZ::Data::Asset asset) override; + + NetworkEntityManager& m_entityManager; + }; void OnEntityAdded(AZ::Entity* entity); void OnEntityRemoved(AZ::Entity* entity); void RemoveEntities(); + NetEntityId NextId(); + NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; AZ::ScheduledEvent m_removeEntitiesEvent; AZStd::vector m_removeList; - AZStd::vector m_nonNetworkedEntities; // Contains entities that we've instantiated, but are not networked entities - AZStd::unique_ptr m_entityDomain; AZ::ScheduledEvent m_updateEntityDomainEvent; @@ -95,5 +118,9 @@ namespace Multiplayer // This is done to prevent local and network sent RPC's from having different dispatch behaviours typedef AZStd::deque DeferredRpcMessages; DeferredRpcMessages m_localDeferredRpcMessages; + + NetworkSpawnableLibrary m_networkPrefabLibrary; + NetworkSpawnableMonitor m_rootSpawnableMonitor; + AZ::Data::Asset m_rootSpawnableAsset; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp new file mode 100644 index 0000000000..ad2e18e222 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -0,0 +1,81 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include +#include +#include + +namespace Multiplayer +{ + NetworkSpawnableLibrary::NetworkSpawnableLibrary() + { + AzFramework::AssetCatalogEventBus::Handler::BusConnect(); + } + + NetworkSpawnableLibrary::~NetworkSpawnableLibrary() + { + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + } + + void NetworkSpawnableLibrary::BuildPrefabsList() + { + auto enumerateCallback = [this](const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info) + { + if (info.m_assetType == AZ::AzTypeInfo::Uuid()) + { + ProcessSpawnableAsset(info.m_relativePath, id); + } + }; + + AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::EnumerateAssets, nullptr, + enumerateCallback, nullptr); + } + + void NetworkSpawnableLibrary::ProcessSpawnableAsset(const AZStd::string& relativePath, const AZ::Data::AssetId id) + { + const AZ::Name name = AZ::Name(relativePath); + m_spawnables[name] = id; + m_spawnablesReverseLookup[id] = name; + + } + + void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) + { + BuildPrefabsList(); + } + + AZ::Name NetworkSpawnableLibrary::GetPrefabNameFromAssetId(AZ::Data::AssetId assetId) + { + if (assetId.IsValid()) + { + auto it = m_spawnablesReverseLookup.find(assetId); + if (it != m_spawnablesReverseLookup.end()) + { + return it->second; + } + } + + return {}; + } + + AZ::Data::AssetId NetworkSpawnableLibrary::GetAssetIdByName(AZ::Name name) + { + auto it = m_spawnables.find(name); + if (it != m_spawnables.end()) + { + return it->second; + } + + return {}; + } +} diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h new file mode 100644 index 0000000000..a2c3d4ae56 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.h @@ -0,0 +1,43 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include +#include + +namespace Multiplayer +{ + /// Implementation of the network prefab library interface. + class NetworkSpawnableLibrary final + : private AzFramework::AssetCatalogEventBus::Handler + { + public: + NetworkSpawnableLibrary(); + ~NetworkSpawnableLibrary(); + + void BuildPrefabsList(); + void ProcessSpawnableAsset(const AZStd::string& relativePath, AZ::Data::AssetId id); + + /// AssetCatalogEventBus overrides. + void OnCatalogLoaded(const char* catalogFile) override; + + AZ::Name GetPrefabNameFromAssetId(AZ::Data::AssetId assetId); + AZ::Data::AssetId GetAssetIdByName(AZ::Name name); + + private: + AZStd::unordered_map m_spawnables; + AZStd::unordered_map m_spawnablesReverseLookup; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp new file mode 100644 index 0000000000..84983b700e --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp @@ -0,0 +1,35 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +namespace Multiplayer +{ + void NetBindMarkerComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + } + } + + void NetBindMarkerComponent::Activate() + { + } + + void NetBindMarkerComponent::Deactivate() + { + } +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h new file mode 100644 index 0000000000..ebafead73c --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h @@ -0,0 +1,39 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace Multiplayer +{ + //! @class NetBindMarkerComponent + //! @brief Component for tracking net entities in the original non-networked spawnable. + class NetBindMarkerComponent final : public AZ::Component + { + public: + AZ_COMPONENT(NetBindMarkerComponent, "{40612C1B-427D-45C6-A2F0-04E16DF5B718}"); + + static void Reflect(AZ::ReflectContext* context); + + NetBindMarkerComponent() = default; + ~NetBindMarkerComponent() override = default; + + //! AZ::Component overrides. + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + + private: + }; +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp new file mode 100644 index 0000000000..0995ec29d8 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -0,0 +1,184 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; + using AzToolsFramework::Prefab::PrefabConversionUtils::ProcessedObjectStore; + + void NetworkPrefabProcessor::Process(PrefabProcessorContext& context) + { + context.ListPrefabs([&context](AZStd::string_view prefabName, PrefabDom& prefab) { + ProcessPrefab(context, prefabName, prefab); + }); + } + + void NetworkPrefabProcessor::Reflect(AZ::ReflectContext* context) + { + if (auto* serializeContext = azrtti_cast(context); serializeContext != nullptr) + { + serializeContext->Class()->Version(1); + } + } + + static AZStd::vector GetEntitiesFromInstance(AZStd::unique_ptr& instance) + { + AZStd::vector result; + + instance->GetNestedEntities([&result](const AZStd::unique_ptr& entity) { + result.emplace_back(entity.get()); + return true; + }); + + if (instance->HasContainerEntity()) + { + auto containerEntityReference = instance->GetContainerEntity(); + result.emplace_back(&containerEntityReference->get()); + } + + return result; + } + void NetworkPrefabProcessor::ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab) + { + using namespace AzToolsFramework::Prefab; + + // convert Prefab DOM into Prefab Instance. + AZStd::unique_ptr sourceInstance(aznew Instance()); + if (!PrefabDomUtils::LoadInstanceFromPrefabDom(*sourceInstance, prefab, + PrefabDomUtils::LoadInstanceFlags::AssignRandomEntityId)) + { + PrefabDomValueReference sourceReference = PrefabDomUtils::FindPrefabDomValue(prefab, PrefabDomUtils::SourceName); + + AZStd::string errorMessage("NetworkPrefabProcessor: Failed to Load Prefab Instance from given Prefab Dom."); + if (sourceReference.has_value() && sourceReference->get().IsString() && sourceReference->get().GetStringLength() != 0) + { + AZStd::string_view source(sourceReference->get().GetString(), sourceReference->get().GetStringLength()); + errorMessage += AZStd::string::format("Prefab Source: %.*s", AZ_STRING_ARG(source)); + } + AZ_Error("NetworkPrefabProcessor", false, errorMessage.c_str()); + return; + } + + AZStd::string uniqueName = prefabName; + uniqueName += ".network.spawnable"; + + auto serializer = [](AZStd::vector& output, const ProcessedObjectStore& object) -> bool { + AZ::IO::ByteContainerStream stream(&output); + auto& asset = object.GetAsset(); + return AZ::Utils::SaveObjectToStream(stream, AZ::DataStream::ST_JSON, &asset, asset.GetType()); + }; + + auto&& [object, networkSpawnable] = + ProcessedObjectStore::Create(uniqueName, context.GetSourceUuid(), AZStd::move(serializer)); + + // grab all nested entities from the Instance as source entities. + AZStd::vector sourceEntities = GetEntitiesFromInstance(sourceInstance); + AZStd::vector networkedEntityIds; + networkedEntityIds.reserve(sourceEntities.size()); + + for (auto* sourceEntity : sourceEntities) + { + if (sourceEntity->FindComponent()) + { + networkedEntityIds.push_back(sourceEntity->GetId()); + } + } + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + AZStd::unique_ptr networkInstance(aznew Instance()); + + for (auto entityId : networkedEntityIds) + { + AZ::Entity* netEntity = sourceInstance->DetachEntity(entityId).release(); + + networkInstance->AddEntity(*netEntity); + + AZ::Entity* breadcrumbEntity = aznew AZ::Entity(netEntity->GetName()); + breadcrumbEntity->SetRuntimeActiveByDefault(netEntity->IsRuntimeActiveByDefault()); + breadcrumbEntity->CreateComponent(); + AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); + breadcrumbEntity->CreateComponent(*transformComponent); + + // TODO: Add NetBindMarkerComponent here referring to the net entity + sourceInstance->AddEntity(*breadcrumbEntity); + } + + // Add net spawnable asset holder + { + AZ::Data::AssetId assetId = networkSpawnable->GetId(); + AZ::Data::Asset networkSpawnableAsset; + networkSpawnableAsset.Create(assetId); + + EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity(); + if (containerEntityRef.has_value()) + { + auto* networkSpawnableHolderComponent = containerEntityRef.value().get().CreateComponent(); + networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); + } + else + { + AZ::Entity* networkSpawnableHolderEntity = aznew AZ::Entity(uniqueName); + auto* networkSpawnableHolderComponent = networkSpawnableHolderEntity->CreateComponent(); + networkSpawnableHolderComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); + sourceInstance->AddEntity(*networkSpawnableHolderEntity); + } + } + + // save the final result in the target Prefab DOM. + PrefabDom networkPrefab; + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*networkInstance, networkPrefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + if (!PrefabDomUtils::StoreInstanceInPrefabDom(*sourceInstance, prefab)) + { + AZ_Error("NetworkPrefabProcessor", false, "Saving exported Prefab Instance within a Prefab Dom failed."); + return; + } + + + bool result = SpawnableUtils::CreateSpawnable(*networkSpawnable, networkPrefab); + if (result) + { + AzFramework::Spawnable::EntityList& entities = networkSpawnable->GetEntities(); + for (auto it = entities.begin(); it != entities.end(); ++it) + { + (*it)->InvalidateDependencies(); + (*it)->EvaluateDependencies(); + } + context.GetProcessedObjects().push_back(AZStd::move(object)); + } + else + { + AZ_Error("Prefabs", false, "Failed to convert prefab '%.*s' to a spawnable.", AZ_STRING_ARG(prefabName)); + context.ErrorEncountered(); + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h new file mode 100644 index 0000000000..ea927a1453 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.h @@ -0,0 +1,43 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#include + +namespace AzToolsFramework::Prefab::PrefabConversionUtils +{ + class PrefabProcessorContext; +} + +namespace Multiplayer +{ + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessor; + using AzToolsFramework::Prefab::PrefabConversionUtils::PrefabProcessorContext; + using AzToolsFramework::Prefab::PrefabDom; + + class NetworkPrefabProcessor : public PrefabProcessor + { + public: + AZ_CLASS_ALLOCATOR(NetworkPrefabProcessor, AZ::SystemAllocator, 0); + AZ_RTTI(NetworkPrefabProcessor, "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}", PrefabProcessor); + + ~NetworkPrefabProcessor() override = default; + + void Process(PrefabProcessorContext& context) override; + + static void Reflect(AZ::ReflectContext* context); + + protected: + static void ProcessPrefab(PrefabProcessorContext& context, AZStd::string_view prefabName, PrefabDom& prefab); + }; +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp new file mode 100644 index 0000000000..26592fb935 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -0,0 +1,42 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include +#include + +namespace Multiplayer +{ + void NetworkSpawnableHolderComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1) + ->Field("AssetRef", &NetworkSpawnableHolderComponent::m_networkSpawnableAsset); + } + } + + void NetworkSpawnableHolderComponent::Activate() + { + } + + void NetworkSpawnableHolderComponent::Deactivate() + { + } + + void NetworkSpawnableHolderComponent::SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset) + { + m_networkSpawnableAsset = networkSpawnableAsset; + } + +} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h new file mode 100644 index 0000000000..81f0959c74 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -0,0 +1,44 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include +#include + +namespace Multiplayer +{ + //! @class NetworkSpawnableHolderComponent + //! @brief Component for holding a reference to the network spawnable to make sure it is loaded with the original one. + class NetworkSpawnableHolderComponent final : public AZ::Component + { + public: + AZ_COMPONENT(NetworkSpawnableHolderComponent, "{B0E3ADEE-FCB4-4A32-8D4F-6920F1CB08E4}"); + + static void Reflect(AZ::ReflectContext* context); + + NetworkSpawnableHolderComponent() = default; + ~NetworkSpawnableHolderComponent() override = default; + + //! AZ::Component overrides. + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + + void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); + + private: + AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; + }; +} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index eea9379df9..9a7dd52cb8 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -60,6 +60,8 @@ set(FILES Source/NetworkEntity/NetworkEntityHandle.inl Source/NetworkEntity/NetworkEntityManager.cpp Source/NetworkEntity/NetworkEntityManager.h + Source/NetworkEntity/NetworkSpawnableLibrary.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkEntity/NetworkEntityRpcMessage.cpp Source/NetworkEntity/NetworkEntityRpcMessage.h Source/NetworkEntity/NetworkEntityTracker.cpp @@ -81,6 +83,10 @@ set(FILES Source/NetworkTime/NetworkTime.h Source/NetworkTime/RewindableObject.h Source/NetworkTime/RewindableObject.inl + Source/Pipeline/NetBindMarkerComponent.cpp + Source/Pipeline/NetBindMarkerComponent.h + Source/Pipeline/NetworkSpawnableHolderComponent.cpp + Source/Pipeline/NetworkSpawnableHolderComponent.h Source/ReplicationWindows/IReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp Source/ReplicationWindows/ServerToClientReplicationWindow.h diff --git a/Gems/Multiplayer/Code/multiplayer_tools_files.cmake b/Gems/Multiplayer/Code/multiplayer_tools_files.cmake new file mode 100644 index 0000000000..1be02fd999 --- /dev/null +++ b/Gems/Multiplayer/Code/multiplayer_tools_files.cmake @@ -0,0 +1,19 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Source/Multiplayer_precompiled.cpp + Source/Multiplayer_precompiled.h + Source/Pipeline/NetworkPrefabProcessor.cpp + Source/Pipeline/NetworkPrefabProcessor.h + Source/MultiplayerToolsModule.h + Source/MultiplayerToolsModule.cpp +) diff --git a/Gems/Multiplayer/Registry/prefab.tools.setreg b/Gems/Multiplayer/Registry/prefab.tools.setreg new file mode 100644 index 0000000000..4f20f88df9 --- /dev/null +++ b/Gems/Multiplayer/Registry/prefab.tools.setreg @@ -0,0 +1,26 @@ +{ + "Amazon": + { + "Tools": + { + "Prefab": + { + "Processing": + { + "Stack": + { + "GameObjectCreation": + [ + { "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::EditorInfoRemover" }, + { "$type": "{AF6C36DA-CBB9-4DF4-AE2D-7BC6CCE65176}" }, + { + "$type": "AzToolsFramework::Prefab::PrefabConversionUtils::PrefabCatchmentProcessor", + "SerializationFormat": "Text" // Options are "Binary" (default) or "Text". Prefer "Binary" for performance. + } + ] + } + } + } + } + } +} \ No newline at end of file From 4962218d2932517b23a72beff1e4e2bce8e2f0cc Mon Sep 17 00:00:00 2001 From: pereslav Date: Fri, 16 Apr 2021 00:19:43 +0100 Subject: [PATCH 06/96] Refactored root spawnable instantiation, added selective instantiation of root spawnable entities --- .../Serialization/ISerializer.inl | 4 +- .../Code/Source/MultiplayerGem.cpp | 2 +- .../Code/Source/MultiplayerToolsModule.cpp | 8 +- .../Code/Source/MultiplayerTypes.h | 15 +- .../EntityReplicationManager.cpp | 12 +- .../NetworkEntity/INetworkEntityManager.h | 3 +- .../NetworkEntity/NetworkEntityManager.cpp | 133 +++++++++++++----- .../NetworkEntity/NetworkEntityManager.h | 17 +-- .../Pipeline/NetworkPrefabProcessor.cpp | 3 +- .../NetworkSpawnableHolderComponent.cpp | 9 ++ .../NetworkSpawnableHolderComponent.h | 3 +- 11 files changed, 134 insertions(+), 75 deletions(-) diff --git a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl index 2720f09f4b..df3b08f798 100644 --- a/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl +++ b/Code/Framework/AzNetworking/AzNetworking/Serialization/ISerializer.inl @@ -18,8 +18,8 @@ #include #include #include -#include "AzCore/Name/Name.h" -#include "AzCore/Name/NameDictionary.h" +#include +#include namespace AzNetworking { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 15d4e2f6f0..596a1b40fa 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -15,9 +15,9 @@ #include #include #include -#include #include #include +#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 16f13f9ee8..71b04585ad 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -12,13 +12,13 @@ #include #include -#include "Pipeline/NetworkPrefabProcessor.h" -#include "AzCore/Serialization/Json/RegistrationContext.h" -#include "Prefab/Instance/InstanceSerializer.h" +#include +#include +#include namespace Multiplayer { - //! Multiplayer system component wraps the bridging logic between the game and transport layer. + //! Multiplayer Tools system component provides serialize context reflection for tools-only systems. class MultiplayerToolsSystemComponent final : public AZ::Component { diff --git a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h index ad491f4016..7ffaa8a56e 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerTypes.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerTypes.h @@ -13,11 +13,11 @@ #pragma once #include +#include #include #include #include #include -#include namespace Multiplayer { @@ -70,19 +70,6 @@ namespace Multiplayer True }; - template - bool Serialize(TYPE& value, const char* name); - - inline NetEntityId MakeEntityId(uint8_t a_ServerId, int32_t a_NextId) - { - constexpr int32_t MAX_ENTITYID = 0x00FFFFFF; - - AZ_Assert((a_NextId < MAX_ENTITYID) && (a_NextId > 0), "Requested Id out of range"); - - NetEntityId ret = NetEntityId(((static_cast(a_ServerId) << 24) & 0xFF000000) | (a_NextId & MAX_ENTITYID)); - return ret; - } - // This is just a placeholder // The level/prefab cooking will devise the actual solution for identifying a dynamically spawnable entity within a prefab struct PrefabEntityId diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index e19bc7685b..3295f9e45e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace Multiplayer { @@ -532,7 +533,7 @@ namespace Multiplayer NetEntityId netEntityId, NetEntityRole localNetworkRole, AzNetworking::ISerializer& serializer, - [[maybe_unused]] const PrefabEntityId& prefabEntityId + const PrefabEntityId& prefabEntityId ) { ConstNetworkEntityHandle replicatorEntity = GetNetworkEntityManager()->GetEntity(netEntityId); @@ -544,6 +545,15 @@ namespace Multiplayer if (createEntity) { //replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity()); + INetworkEntityManager::EntityList entityList = GetNetworkEntityManager()->CreateEntitiesImmediate( + prefabEntityId, netEntityId, localNetworkRole, + AZ::Transform::Identity()); + + if (entityList.size() == 1) + { + replicatorEntity = entityList[0]; + } + AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab %s", prefabEntityId.m_prefabName.GetCStr()); if (replicatorEntity == nullptr) { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h index be4f32752d..557a912a31 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/INetworkEntityManager.h @@ -54,7 +54,8 @@ namespace Multiplayer //! Creates new entities of the given archetype //! @param prefabEntryId the name of the spawnable to spawn - virtual void CreateEntitiesImmediate(const PrefabEntityId& prefabEntryId) = 0; + virtual EntityList CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, const AZ::Transform& transform) = 0; //! Returns an ConstEntityPtr for the provided entityId. //! @param netEntityId the netEntityId to get an ConstEntityPtr for diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index d92becfb97..80ad654cae 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include namespace Multiplayer { @@ -32,7 +35,6 @@ namespace Multiplayer , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) , m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); }) , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) - , m_rootSpawnableMonitor(*this) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); @@ -284,8 +286,8 @@ namespace Multiplayer NetBindComponent* netBindComponent = entity->FindComponent(); if (netBindComponent != nullptr) { - const NetEntityId netEntityId = NextId(); - netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); + //const NetEntityId netEntityId = NextId(); + //netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority); } } @@ -337,7 +339,8 @@ namespace Multiplayer } } - INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable) + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate( + const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole) { INetworkEntityManager::EntityList returnList; @@ -361,7 +364,7 @@ namespace Multiplayer prefabEntityId.m_entityOffset = aznumeric_cast(i); const NetEntityId netEntityId = NextId(); - netBindComponent->PreInit(clone, prefabEntityId, netEntityId, NetEntityRole::Authority); + netBindComponent->PreInit(clone, prefabEntityId, netEntityId, netEntityRole); AzFramework::GameEntityContextRequestBus::Broadcast( &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); @@ -378,8 +381,62 @@ namespace Multiplayer return returnList; } - void NetworkEntityManager::CreateEntitiesImmediate([[maybe_unused]] const PrefabEntityId& a_SliceEntryId) + INetworkEntityManager::EntityList NetworkEntityManager::CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, + const AZ::Transform& transform) { + INetworkEntityManager::EntityList returnList; + + // TODO: Implement for non-root spawnables + auto spawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(prefabEntryId.m_prefabName); + if (spawnableAssetId == m_rootSpawnableAsset.GetId()) + { + AzFramework::Spawnable* netSpawnable = m_rootSpawnableAsset.GetAs(); + if (!netSpawnable) + { + return returnList; + } + + const uint32_t entityIndex = prefabEntryId.m_entityOffset; + + if (entityIndex == PrefabEntityId::AllIndices) + { + return CreateEntitiesImmediate(*netSpawnable, netEntityRole); + } + + const AzFramework::Spawnable::EntityList& entities = netSpawnable->GetEntities(); + size_t entitiesSize = entities.size(); + if (entityIndex >= entitiesSize) + { + return returnList; + } + + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + AZ::Entity* clone = serializeContext->CloneObject(entities[entityIndex].get()); + AZ_Assert(clone != nullptr, "Failed to clone spawnable entity."); + clone->SetId(AZ::Entity::MakeId()); + + NetBindComponent* netBindComponent = clone->FindComponent(); + if (netBindComponent) + { + netBindComponent->PreInit(clone, prefabEntryId, netEntityId, netEntityRole); + + auto* transformComponent = clone->FindComponent(); + if (transformComponent) + { + transformComponent->SetWorldTM(transform); + } + + AzFramework::GameEntityContextRequestBus::Broadcast( + &AzFramework::GameEntityContextRequestBus::Events::AddGameEntity, clone); + + returnList.push_back(netBindComponent->GetEntityHandle()); + } + } + + return returnList; } Multiplayer::NetEntityId NetworkEntityManager::NextId() @@ -389,55 +446,57 @@ namespace Multiplayer } void NetworkEntityManager::OnRootSpawnableAssigned( - [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) { - AZStd::string hint = rootSpawnable.GetHint(); - - size_t extensionPos = hint.find(".spawnable"); - if (extensionPos == AZStd::string::npos) + AzFramework::Spawnable* rootSpawnableData = rootSpawnable.GetAs(); + const auto& entityList = rootSpawnableData->GetEntities(); + if (entityList.size() == 0) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable hint doesn't have .spawnable extension"); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root spawnable doesn't have any entities."); return; } - AZStd::string newhint = hint.replace(extensionPos, 0, ".network"); - auto rootSpawnableAssetId = m_networkPrefabLibrary.GetAssetIdByName(AZ::Name(newhint)); - if (!rootSpawnableAssetId.IsValid()) + const auto& rootEntity = entityList[0]; + auto* spawnableHolder = rootEntity->FindComponent(); + if (!spawnableHolder) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Network spawnable asset ID is invalid"); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Root entity doesn't have NetworkSpawnableHolderComponent."); return; } - m_rootSpawnableAsset = AZ::Data::Asset( - rootSpawnableAssetId, azrtti_typeid(), newhint); - if (m_rootSpawnableAsset.QueueLoad()) + AZ::Data::Asset netSpawnableAsset = spawnableHolder->GetNetworkSpawnableAsset(); + AzFramework::Spawnable* netSpawnable = netSpawnableAsset.GetAs(); + if (!netSpawnable) { - m_rootSpawnableMonitor.Connect(rootSpawnableAssetId); + // TODO: Temp sync load until JsonSerialization of loadBehavior is fixed. + netSpawnableAsset = AZ::Data::AssetManager::Instance().GetAsset( + netSpawnableAsset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad); + AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(netSpawnableAsset); + + netSpawnable = netSpawnableAsset.GetAs(); } - else + + if (!netSpawnable) { - AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Unable to queue networked root spawnable '%s' for loading.", - m_rootSpawnableAsset.GetHint().c_str()); + AZ_Error("NetworkEntityManager", false, "OnRootSpawnableAssigned: Net spawnable doesn't have any data."); + return; } - } - void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) - { - m_rootSpawnableMonitor.Disconnect(); - } + m_rootSpawnableAsset = netSpawnableAsset; + const auto agentType = AZ::Interface::Get()->GetAgentType(); + const bool spawnImmediately = + (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); - NetworkEntityManager::NetworkSpawnableMonitor::NetworkSpawnableMonitor( - NetworkEntityManager& entityManager) - : m_entityManager(entityManager) - { + if (spawnImmediately) + { + CreateEntitiesImmediate(*netSpawnable, NetEntityRole::Authority); + } } - void NetworkEntityManager::NetworkSpawnableMonitor::OnAssetReady(AZ::Data::Asset asset) + void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) { - AzFramework::Spawnable* spawnable = asset.GetAs(); - AZ_Assert(spawnable, "NetworkSpawnableMonitor: Loaded asset data didn't contain a Spawanble."); - - m_entityManager.CreateEntitiesImmediate(*spawnable); + // TODO: Do we need to clear all entities here? + m_rootSpawnableAsset.Release(); } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 20c67a74fd..d9d21d6b7b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -46,9 +45,11 @@ namespace Multiplayer HostId GetHostId() const override; ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override; - EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable); + EntityList CreateEntitiesImmediate(const AzFramework::Spawnable& spawnable, NetEntityRole netEntityRole); - void CreateEntitiesImmediate(const PrefabEntityId& a_SliceEntryId) override; + EntityList CreateEntitiesImmediate( + const PrefabEntityId& prefabEntryId, NetEntityId netEntityId, NetEntityRole netEntityRole, + const AZ::Transform& transform) override; uint32_t GetEntityCount() const override; NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override; @@ -78,15 +79,6 @@ namespace Multiplayer //! @} private: - class NetworkSpawnableMonitor final : public AzFramework::SpawnableMonitor - { - public: - explicit NetworkSpawnableMonitor(NetworkEntityManager& entityManager); - void OnAssetReady(AZ::Data::Asset asset) override; - - NetworkEntityManager& m_entityManager; - }; - void OnEntityAdded(AZ::Entity* entity); void OnEntityRemoved(AZ::Entity* entity); void RemoveEntities(); @@ -120,7 +112,6 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; - NetworkSpawnableMonitor m_rootSpawnableMonitor; AZ::Data::Asset m_rootSpawnableAsset; }; } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index 0995ec29d8..2006272135 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -124,7 +124,7 @@ namespace Multiplayer AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); breadcrumbEntity->CreateComponent(*transformComponent); - // TODO: Add NetBindMarkerComponent here referring to the net entity + // TODO: Configure NetBindMarkerComponent to refer to the net entity sourceInstance->AddEntity(*breadcrumbEntity); } @@ -133,6 +133,7 @@ namespace Multiplayer AZ::Data::AssetId assetId = networkSpawnable->GetId(); AZ::Data::Asset networkSpawnableAsset; networkSpawnableAsset.Create(assetId); + networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); EntityOptionalReference containerEntityRef = sourceInstance->GetContainerEntity(); if (containerEntityRef.has_value()) diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index 26592fb935..3c3d1f079d 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -39,4 +39,13 @@ namespace Multiplayer m_networkSpawnableAsset = networkSpawnableAsset; } + AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() + { + return m_networkSpawnableAsset; + } + + NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() + { + } + } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h index 81f0959c74..54a9a4e42f 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -27,7 +27,7 @@ namespace Multiplayer static void Reflect(AZ::ReflectContext* context); - NetworkSpawnableHolderComponent() = default; + NetworkSpawnableHolderComponent();; ~NetworkSpawnableHolderComponent() override = default; //! AZ::Component overrides. @@ -37,6 +37,7 @@ namespace Multiplayer //! @} void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); + AZ::Data::Asset GetNetworkSpawnableAsset(); private: AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; From beafc80939e882ed9cc1d94e33c71e1d00ccb4f8 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Fri, 16 Apr 2021 18:34:28 +0100 Subject: [PATCH 07/96] Fixed entities not being deselected when entering game mode in editor. added protections around physx AZ::Events handlers that are connected/disconnected on selection events. jira: LYN-2998 --- .../Entity/EditorEntityContextComponent.cpp | 10 ++++++++-- .../PhysX/Code/Source/EditorShapeColliderComponent.cpp | 10 ++++++++-- .../Components/EditorCharacterControllerComponent.cpp | 5 ++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp index ad458b0434..44c8487272 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityContextComponent.cpp @@ -491,6 +491,14 @@ namespace AzToolsFramework EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditorBegin); + //cache the current selected entities. + ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities); + //deselect entities if selected when entering game mode before deactivating the entities in StartPlayInEditor(...) + if (!m_selectedBeforeStartingGame.empty()) + { + ToolsApplicationRequests::Bus::Broadcast(&ToolsApplicationRequests::MarkEntitiesDeselected, m_selectedBeforeStartingGame); + } + if (m_isLegacySliceService) { SliceEditorEntityOwnershipService* editorEntityOwnershipService = @@ -507,8 +515,6 @@ namespace AzToolsFramework m_isRunningGame = true; - ToolsApplicationRequests::Bus::BroadcastResult(m_selectedBeforeStartingGame, &ToolsApplicationRequests::GetSelectedEntities); - EditorEntityContextNotificationBus::Broadcast(&EditorEntityContextNotification::OnStartPlayInEditor); } diff --git a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp index a1b8516150..4ee41d2be4 100644 --- a/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorShapeColliderComponent.cpp @@ -686,8 +686,14 @@ namespace PhysX { if (auto* physXSystem = GetPhysXSystem()) { - physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); - physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler); + if (!m_physXConfigChangedHandler.IsConnected()) + { + physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + } + if (!m_onDefaultMaterialLibraryChangedEventHandler.IsConnected()) + { + physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler); + } } } diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp index 3f76b269e7..9a85274910 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/EditorCharacterControllerComponent.cpp @@ -149,7 +149,10 @@ namespace PhysX { if (auto* physXSystem = GetPhysXSystem()) { - physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + if (!m_physXConfigChangedHandler.IsConnected()) + { + physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler); + } } } From db9b0f141fbeacc24606d5d109766559d4912b62 Mon Sep 17 00:00:00 2001 From: mnaumov Date: Fri, 16 Apr 2021 16:13:39 -0700 Subject: [PATCH 08/96] Double click launches Material Editor --- .../Window/MaterialBrowserInteractions.cpp | 356 ----------------- .../MaterialEditorBrowserInteractions.cpp | 358 ++++++++++++++++++ ....h => MaterialEditorBrowserInteractions.h} | 8 +- .../Window/MaterialEditorWindowComponent.cpp | 2 +- .../Window/MaterialEditorWindowComponent.h | 4 +- .../Code/materialeditorwindow_files.cmake | 4 +- .../EditorMaterialSystemComponent.cpp | 2 + .../Material/EditorMaterialSystemComponent.h | 4 + .../Material/MaterialBrowserInteractions.cpp | 54 +++ .../Material/MaterialBrowserInteractions.h | 52 +++ ...egration_commonfeatures_editor_files.cmake | 2 + 11 files changed, 481 insertions(+), 365 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp create mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp rename Gems/Atom/Tools/MaterialEditor/Code/Source/Window/{MaterialBrowserInteractions.h => MaterialEditorBrowserInteractions.h} (91%) create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp deleted file mode 100644 index b0412c001c..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -namespace MaterialEditor -{ - MaterialBrowserInteractions::MaterialBrowserInteractions() - { - using namespace AzToolsFramework::AssetBrowser; - - AssetBrowserInteractionNotificationBus::Handler::BusConnect(); - } - - MaterialBrowserInteractions::~MaterialBrowserInteractions() - { - AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); - } - - void MaterialBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) - { - AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); - if (!entry) - { - return; - } - - m_caller = caller; - QObject::connect(m_caller, &QObject::destroyed, [this]() - { - m_caller = nullptr; - }); - - AddGenericContextMenuActions(caller, menu, entry); - - if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) - { - const auto source = azalias_cast(entry); - if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) - { - AddContextMenuActionsForMaterialSource(caller, menu, source); - } - else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) - { - AddContextMenuActionsForMaterialTypeSource(caller, menu, source); - } - else - { - AddContextMenuActionsForOtherSource(caller, menu, source); - } - } - else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) - { - const auto folder = azalias_cast(entry); - AddContextMenuActionsForFolder(caller, menu, folder); - } - } - - void MaterialBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) - { - menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() - { - QApplication::clipboard()->setText(entry->GetName().c_str()); - }); - menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() - { - QApplication::clipboard()->setText(entry->GetFullPath().c_str()); - }); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) - { - menu->addAction("Open", [entry]() - { - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); - }); - - menu->addAction("Duplicate...", [entry, caller]() - { - const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); - if (!duplicateFileInfo.absoluteFilePath().isEmpty()) - { - if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) - { - QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); - - // Auto add file to source control - AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, - duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); - } - } - }); - - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - menu->addSeparator(); - - menu->addAction("Create Child Material...", [entry]() - { - const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( - QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + - AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + - AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); - - MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, - entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); - }); - - menu->addSeparator(); - - QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() - { - AZ_UNUSED(entry); - // ToDo - }); - openParentAction->setEnabled(false); - - AddPerforceMenuActions(caller, menu, entry); - } - - void MaterialBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) - { - menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() - { - AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); - }); - - QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); - QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() - { - bool ok; - QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); - if (ok) - { - if (newFolderName.isEmpty()) - { - QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); - msgBox.exec(); - } - else - { - AZStd::string newFolderPath; - AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); - QDir dir(newFolderPath.c_str()); - if (dir.exists()) - { - QMessageBox::critical(caller, "Error", "Folder with this name already exists"); - return; - } - auto result = dir.mkdir(newFolderPath.c_str()); - if (!result) - { - AZ_Error("MaterialBrowser", false, "Failed to make new folder"); - return; - } - } - } - }); - } - - void MaterialBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) - { - using namespace AzToolsFramework; - - bool isActive = false; - SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); - - if (isActive) - { - menu->addSeparator(); - - AZStd::string path = entry->GetFullPath(); - AzFramework::StringFunc::Path::Normalize(path); - - QMenu* sourceControlMenu = menu->addMenu("Source Control"); - - // Update the enabled state of source control menu actions only if menu is shown - QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), - [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); - }); - - // add get latest action - m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), - [](bool, const SourceControlFileInfo&) {}); - }); - QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() - { - m_getLatestAction = nullptr; - }); - m_getLatestAction->setEnabled(false); - - // add add action - m_addAction = sourceControlMenu->addAction("Add", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_addAction, &QObject::destroyed, [this]() - { - m_addAction = nullptr; - }); - m_addAction->setEnabled(false); - - // add checkout action - m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() - { - m_checkOutAction = nullptr; - }); - m_checkOutAction->setEnabled(false); - - // add undo checkout action - m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() - { - SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), - [path](bool, const SourceControlFileInfo&) - { - SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); - }); - }); - QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() - { - m_undoCheckOutAction = nullptr; - }); - m_undoCheckOutAction->setEnabled(false); - } - } - - void MaterialBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) - { - if (!success && m_caller) - { - QMessageBox::critical(m_caller, "Error", "Source control operation failed."); - } - if (m_getLatestAction) - { - m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); - } - if (m_addAction) - { - m_addAction->setEnabled(!info.IsManaged()); - } - if (m_checkOutAction) - { - m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); - } - if (m_undoCheckOutAction) - { - m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); - } - } -} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp new file mode 100644 index 0000000000..92e02d5b42 --- /dev/null +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.cpp @@ -0,0 +1,358 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +namespace MaterialEditor +{ + MaterialEditorBrowserInteractions::MaterialEditorBrowserInteractions() + { + using namespace AzToolsFramework::AssetBrowser; + + AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialEditorBrowserInteractions::~MaterialEditorBrowserInteractions() + { + AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActions(QWidget* caller, QMenu* menu, const AZStd::vector& entries) + { + AssetBrowserEntry* entry = entries.empty() ? nullptr : entries.front(); + if (!entry) + { + return; + } + + m_caller = caller; + QObject::connect(m_caller, &QObject::destroyed, [this]() + { + m_caller = nullptr; + }); + + AddGenericContextMenuActions(caller, menu, entry); + + if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source) + { + const auto source = azalias_cast(entry); + if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialExtension)) + { + AddContextMenuActionsForMaterialSource(caller, menu, source); + } + else if (AzFramework::StringFunc::Path::IsExtension(entry->GetFullPath().c_str(), MaterialTypeExtension)) + { + AddContextMenuActionsForMaterialTypeSource(caller, menu, source); + } + else + { + AddContextMenuActionsForOtherSource(caller, menu, source); + } + } + else if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder) + { + const auto folder = azalias_cast(entry); + AddContextMenuActionsForFolder(caller, menu, folder); + } + } + + void MaterialEditorBrowserInteractions::AddGenericContextMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + menu->addAction(QObject::tr("Copy Name To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetName().c_str()); + }); + menu->addAction(QObject::tr("Copy Path To Clipboard"), [=]() + { + QApplication::clipboard()->setText(entry->GetFullPath().c_str()); + }); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialTypeSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForOtherSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + QDesktopServices::openUrl(QUrl::fromLocalFile(entry->GetFullPath().c_str())); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForMaterialSource(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::SourceAssetBrowserEntry* entry) + { + menu->addAction("Open", [entry]() + { + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::OpenDocument, entry->GetFullPath()); + }); + + menu->addAction("Duplicate...", [entry, caller]() + { + const QFileInfo duplicateFileInfo(AtomToolsFramework::GetDuplicationFileInfo(entry->GetFullPath().c_str())); + if (!duplicateFileInfo.absoluteFilePath().isEmpty()) + { + if (QFile::copy(entry->GetFullPath().c_str(), duplicateFileInfo.absoluteFilePath())) + { + QFile::setPermissions(duplicateFileInfo.absoluteFilePath(), QFile::ReadOther | QFile::WriteOther); + + // Auto add file to source control + AzToolsFramework::SourceControlCommandBus::Broadcast(&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, + duplicateFileInfo.absoluteFilePath().toUtf8().constData(), true, [](bool, const AzToolsFramework::SourceControlFileInfo&) {}); + } + } + }); + + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + menu->addSeparator(); + + menu->addAction("Create Child Material...", [entry]() + { + const QString defaultPath = AtomToolsFramework::GetUniqueFileInfo( + QString(AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@")) + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "Materials" + + AZ_CORRECT_FILESYSTEM_SEPARATOR + "untitled." + + AZ::RPI::MaterialSourceData::Extension).absoluteFilePath(); + + MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CreateDocumentFromFile, + entry->GetFullPath(), AtomToolsFramework::GetSaveFileInfo(defaultPath).absoluteFilePath().toUtf8().constData()); + }); + + menu->addSeparator(); + + QAction* openParentAction = menu->addAction("Open Parent Material", [entry]() + { + AZ_UNUSED(entry); + // ToDo + }); + openParentAction->setEnabled(false); + + AddPerforceMenuActions(caller, menu, entry); + } + + void MaterialEditorBrowserInteractions::AddContextMenuActionsForFolder(QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::FolderAssetBrowserEntry* entry) + { + menu->addAction(AzQtComponents::fileBrowserActionName(), [entry]() + { + AzQtComponents::ShowFileOnDesktop(entry->GetFullPath().c_str()); + }); + + QAction* createFolderAction = menu->addAction(QObject::tr("Create new sub folder...")); + QObject::connect(createFolderAction, &QAction::triggered, caller, [caller, entry]() + { + bool ok; + QString newFolderName = QInputDialog::getText(caller, "Enter new folder name", "name:", QLineEdit::Normal, "NewFolder", &ok); + if (ok) + { + if (newFolderName.isEmpty()) + { + QMessageBox msgBox(QMessageBox::Icon::Critical, "Error", "Folder name can't be empty", QMessageBox::Ok, caller); + msgBox.exec(); + } + else + { + AZStd::string newFolderPath; + AzFramework::StringFunc::Path::Join(entry->GetFullPath().c_str(), newFolderName.toUtf8().constData(), newFolderPath); + QDir dir(newFolderPath.c_str()); + if (dir.exists()) + { + QMessageBox::critical(caller, "Error", "Folder with this name already exists"); + return; + } + auto result = dir.mkdir(newFolderPath.c_str()); + if (!result) + { + AZ_Error("MaterialBrowser", false, "Failed to make new folder"); + return; + } + } + } + }); + } + + void MaterialEditorBrowserInteractions::AddPerforceMenuActions([[maybe_unused]] QWidget* caller, QMenu* menu, const AzToolsFramework::AssetBrowser::AssetBrowserEntry* entry) + { + using namespace AzToolsFramework; + + bool isActive = false; + SourceControlConnectionRequestBus::BroadcastResult(isActive, &SourceControlConnectionRequests::IsActive); + + if (isActive) + { + menu->addSeparator(); + + AZStd::string path = entry->GetFullPath(); + AzFramework::StringFunc::Path::Normalize(path); + + QMenu* sourceControlMenu = menu->addMenu("Source Control"); + + // Update the enabled state of source control menu actions only if menu is shown + QMenu::connect(sourceControlMenu, &QMenu::aboutToShow, [this, path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::GetFileInfo, path.c_str(), + [this](bool success, const SourceControlFileInfo& info) { UpdateSourceControlActions(success, info); }); + }); + + // add get latest action + m_getLatestAction = sourceControlMenu->addAction("Get Latest", [path, this]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestLatest, path.c_str(), + [](bool, const SourceControlFileInfo&) {}); + }); + QObject::connect(m_getLatestAction, &QObject::destroyed, [this]() + { + m_getLatestAction = nullptr; + }); + m_getLatestAction->setEnabled(false); + + // add add action + m_addAction = sourceControlMenu->addAction("Add", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_addAction, &QObject::destroyed, [this]() + { + m_addAction = nullptr; + }); + m_addAction->setEnabled(false); + + // add checkout action + m_checkOutAction = sourceControlMenu->addAction("Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestEdit, path.c_str(), true, + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_checkOutAction, &QObject::destroyed, [this]() + { + m_checkOutAction = nullptr; + }); + m_checkOutAction->setEnabled(false); + + // add undo checkout action + m_undoCheckOutAction = sourceControlMenu->addAction("Undo Check Out", [path]() + { + SourceControlCommandBus::Broadcast(&SourceControlCommandBus::Events::RequestRevert, path.c_str(), + [path](bool, const SourceControlFileInfo&) + { + SourceControlThumbnailRequestBus::Broadcast(&SourceControlThumbnailRequests::FileStatusChanged, path.c_str()); + }); + }); + QObject::connect(m_undoCheckOutAction, &QObject::destroyed, [this]() + { + m_undoCheckOutAction = nullptr; + }); + m_undoCheckOutAction->setEnabled(false); + } + } + + void MaterialEditorBrowserInteractions::UpdateSourceControlActions(bool success, AzToolsFramework::SourceControlFileInfo info) + { + if (!success && m_caller) + { + QMessageBox::critical(m_caller, "Error", "Source control operation failed."); + } + if (m_getLatestAction) + { + m_getLatestAction->setEnabled(info.IsManaged() && info.HasFlag(AzToolsFramework::SCF_OutOfDate)); + } + if (m_addAction) + { + m_addAction->setEnabled(!info.IsManaged()); + } + if (m_checkOutAction) + { + m_checkOutAction->setEnabled(info.IsManaged() && info.IsReadOnly() && !info.IsLockedByOther()); + } + if (m_undoCheckOutAction) + { + m_undoCheckOutAction->setEnabled(info.IsManaged() && !info.IsReadOnly()); + } + } +} // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h similarity index 91% rename from Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h rename to Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h index 2806cee6d4..7ee3ec833d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialBrowserInteractions.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorBrowserInteractions.h @@ -31,14 +31,14 @@ namespace AzToolsFramework namespace MaterialEditor { - class MaterialBrowserInteractions + class MaterialEditorBrowserInteractions : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler { public: - AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + AZ_CLASS_ALLOCATOR(MaterialEditorBrowserInteractions, AZ::SystemAllocator, 0); - MaterialBrowserInteractions(); - ~MaterialBrowserInteractions(); + MaterialEditorBrowserInteractions(); + ~MaterialEditorBrowserInteractions(); private: //! AssetBrowserInteractionNotificationBus::Handler overrides... diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp index 6f03510301..a1ff8da635 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.cpp @@ -98,7 +98,7 @@ namespace MaterialEditor void MaterialEditorWindowComponent::CreateMaterialEditorWindow() { - m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); + m_materialEditorBrowserInteractions.reset(aznew MaterialEditorBrowserInteractions); m_window.reset(aznew MaterialEditorWindow); m_window->show(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h index f727fcc97c..1ea05d6530 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialEditorWindowComponent.h @@ -16,7 +16,7 @@ #include #include -#include +#include #include namespace MaterialEditor @@ -57,6 +57,6 @@ namespace MaterialEditor //////////////////////////////////////////////////////////////////////// AZStd::unique_ptr m_window; - AZStd::unique_ptr m_materialBrowserInteractions; + AZStd::unique_ptr m_materialEditorBrowserInteractions; }; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake index fef3aeefb7..1547dbf48f 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditorwindow_files.cmake @@ -14,8 +14,8 @@ set(FILES Include/Atom/Window/MaterialEditorWindowNotificationBus.h Include/Atom/Window/MaterialEditorWindowRequestBus.h Include/Atom/Window/MaterialEditorWindowFactoryRequestBus.h - Source/Window/MaterialBrowserInteractions.h - Source/Window/MaterialBrowserInteractions.cpp + Source/Window/MaterialEditorBrowserInteractions.h + Source/Window/MaterialEditorBrowserInteractions.cpp Source/Window/MaterialEditorWindow.h Source/Window/MaterialEditorWindow.cpp Source/Window/MaterialEditorWindowModule.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp index 82f65b205d..94dfb39419 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.cpp @@ -100,6 +100,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusConnect(); SetupThumbnails(); + m_materialBrowserInteractions.reset(aznew MaterialBrowserInteractions); } void EditorMaterialSystemComponent::Deactivate() @@ -111,6 +112,7 @@ namespace AZ AzToolsFramework::EditorMenuNotificationBus::Handler::BusDisconnect(); TeardownThumbnails(); + m_materialBrowserInteractions.reset(); if (m_openMaterialEditorAction) { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h index de065f679e..09ad1c1b9c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialSystemComponent.h @@ -22,6 +22,8 @@ #include +#include + namespace AZ { namespace Render @@ -76,6 +78,8 @@ namespace AZ AzFramework::TargetInfo m_materialEditorTarget; QAction* m_openMaterialEditorAction = nullptr; + + AZStd::unique_ptr m_materialBrowserInteractions; }; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp new file mode 100644 index 0000000000..82fa47a810 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.cpp @@ -0,0 +1,54 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + MaterialBrowserInteractions::MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusConnect(); + } + + MaterialBrowserInteractions::~MaterialBrowserInteractions() + { + AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler::BusDisconnect(); + } + + void MaterialBrowserInteractions::AddSourceFileOpeners(const char* fullSourceFileName, [[maybe_unused]] const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) + { + if (HandlesSource(fullSourceFileName)) + { + openers.push_back( + { + "Material_Editor", + "Open in Material Editor...", + QIcon(), + [&](const char* fullSourceFileNameInCallback, [[maybe_unused]] const AZ::Uuid& sourceUUID) + { + EditorMaterialSystemComponentRequestBus::Broadcast(&EditorMaterialSystemComponentRequestBus::Events::OpenInMaterialEditor, fullSourceFileNameInCallback); + } + }); + } + } + + bool MaterialBrowserInteractions::HandlesSource(AZStd::string_view fileName) const + { + return AZStd::wildcard_match("*.material", fileName.data()); + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h new file mode 100644 index 0000000000..bd9791d3a5 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialBrowserInteractions.h @@ -0,0 +1,52 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include +#include + +class QWidget; +class QMenu; +class QAction; + +namespace AzToolsFramework +{ + namespace AssetBrowser + { + class AssetBrowserEntry; + class SourceAssetBrowserEntry; + class FolderAssetBrowserEntry; + } +} + +namespace AZ +{ + namespace Render + { + class MaterialBrowserInteractions + : public AzToolsFramework::AssetBrowser::AssetBrowserInteractionNotificationBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(MaterialBrowserInteractions, AZ::SystemAllocator, 0); + + MaterialBrowserInteractions(); + ~MaterialBrowserInteractions(); + + private: + //! AssetBrowserInteractionNotificationBus::Handler overrides... + void AddSourceFileOpeners(const char* fullSourceFileName, const AZ::Uuid& sourceUUID, AzToolsFramework::AssetBrowser::SourceFileOpenerList& openers) override; + + bool HandlesSource(AZStd::string_view fileName) const; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index f77b175cd7..fe475da189 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -41,6 +41,8 @@ set(FILES Source/Material/EditorMaterialModelUvNameMapInspector.h Source/Material/EditorMaterialSystemComponent.cpp Source/Material/EditorMaterialSystemComponent.h + Source/Material/MaterialBrowserInteractions.h + Source/Material/MaterialBrowserInteractions.cpp Source/Material/MaterialThumbnail.cpp Source/Material/MaterialThumbnail.h Source/Mesh/EditorMeshComponent.h From 0c10e769c5bd9c0058a51226782e687590a61e37 Mon Sep 17 00:00:00 2001 From: Chris Santora Date: Sat, 17 Apr 2021 00:13:14 -0700 Subject: [PATCH 09/96] ATOM-14040 Add Support for Cavity Maps Before working on adding cavity map support, I am replacing the 010_SpecularOcclusion test case with maps that make it easier to distinguish what's going on. The brick map was just too noisy. This simpler tile map will make it easier to see if there are artifacts like banding that get introduced somewhere along the way. There are corresponding changes in AtomSampleViewer for the baseline screenshot. --- .../010_AmbientOcclusion.material | 14 ++++++++++---- .../Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg | 3 +++ .../TestData/Textures/cc0/Tiles009_1K_Color.jpg | 3 +++ .../Textures/cc0/Tiles009_1K_Displacement.jpg | 3 +++ .../TestData/Textures/cc0/Tiles009_1K_Normal.jpg | 3 +++ .../Textures/cc0/Tiles009_1K_Roughness.jpg | 3 +++ 6 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg create mode 100644 Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material index 66843b3a2c..2c0b6767f3 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material @@ -1,15 +1,21 @@ { "description": "", - "materialType": "Materials\\Types\\StandardPBR.materialtype", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { "ambientOcclusion": { "enable": true, - "factor": 1.25, - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_ao.png" + "factor": 2.0, + "textureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" }, "baseColor": { - "textureMap": "TestData/Textures/TextureHaven/4k_castle_brick_02_red/4k_castle_brick_02_red_bc.png" + "color": [ + 1.0, + 1.0, + 0.21223773062229157, + 1.0 + ] } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg new file mode 100644 index 0000000000..3494ef8a6c --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de6b49c1c4965896a190ed5f40c7d91f9deb942d859fd96264828df768098a83 +size 45257 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg new file mode 100644 index 0000000000..bf62c26631 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Color.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0172df6b91bb42bf6c41d18a6fdb7088397663d71f0c2d3ee504a4e91a7e5e98 +size 426462 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg new file mode 100644 index 0000000000..49efd77e18 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Displacement.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9de0bb2f58936658e8bd3599e487cbd6af3394c772d3132cd77a73774cfb5994 +size 230692 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg new file mode 100644 index 0000000000..c61e7f316b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Normal.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48a8690b74141da4e7e06cd10b47f0eb787b5333a915cd1e048ab24bec485ad0 +size 759052 diff --git a/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg new file mode 100644 index 0000000000..bef45f0995 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Textures/cc0/Tiles009_1K_Roughness.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddd79ef9962100cd5a9eec686bdcfb98db19ab410329e50df53d6781f9d8b441 +size 421004 From 4e75a099b8e4a1658f04109d03df2068feeeaf5d Mon Sep 17 00:00:00 2001 From: karlberg Date: Sat, 17 Apr 2021 19:06:28 -0700 Subject: [PATCH 10/96] Initial Imgui debug display for stats, some hookup between entity replication and the spawnable code to make testing possible --- Gems/Multiplayer/Code/CMakeLists.txt | 38 ++++-- .../Source/AutoGen/AutoComponent_Source.jinja | 6 + .../Source/Imgui/MultiplayerImguiModule.cpp | 36 +++++ .../Source/Imgui/MultiplayerImguiModule.h | 31 +++++ .../Imgui/MultiplayerImguiSystemComponent.cpp | 123 ++++++++++++++++++ .../Imgui/MultiplayerImguiSystemComponent.h | 56 ++++++++ .../Source/MultiplayerSystemComponent.cpp | 18 ++- .../Code/Source/MultiplayerToolsModule.cpp | 2 +- .../EntityReplicationManager.cpp | 4 +- .../NetworkEntity/NetworkEntityManager.cpp | 12 +- .../NetworkSpawnableHolderComponent.cpp | 9 +- .../Code/multiplayer_imgui_files.cmake | 19 +++ 12 files changed, 328 insertions(+), 26 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h create mode 100644 Gems/Multiplayer/Code/multiplayer_imgui_files.cmake diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index d395938e8c..8cde5e01e2 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -18,16 +18,16 @@ ly_add_target( INCLUDE_DIRECTORIES PRIVATE ${pal_source_dir} - Source AZ::AzNetworking + Source . + PUBLIC + Include BUILD_DEPENDENCIES PUBLIC AZ::AzCore AZ::AzFramework AZ::AzNetworking - Gem::CertificateManager - 3rdParty::AWSNativeSDK::Core AUTOGEN_RULES *.AutoPackets.xml,AutoPackets_Header.jinja,$path/$fileprefix.AutoPackets.h *.AutoPackets.xml,AutoPackets_Inline.jinja,$path/$fileprefix.AutoPackets.inl @@ -49,6 +49,8 @@ ly_add_target( PRIVATE Source . + PUBLIC + Include BUILD_DEPENDENCIES PRIVATE Gem::Multiplayer.Static @@ -56,7 +58,6 @@ ly_add_target( Gem::CertificateManager ) - if (PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_target( NAME Multiplayer.Tools MODULE @@ -77,10 +78,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) ) endif() -################################################################################ -# Tests -################################################################################ -if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) +if (PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_target( NAME Multiplayer.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} NAMESPACE Gem @@ -92,6 +90,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ${pal_source_dir} Source . + PUBLIC + Include BUILD_DEPENDENCIES PRIVATE AZ::AzTest @@ -101,3 +101,25 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) NAME Gem::Multiplayer.Tests ) endif() + +ly_add_target( + NAME Multiplayer.Imgui ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAMESPACE Gem + FILES_CMAKE + multiplayer_imgui_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Source + . + PUBLIC + Include + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AtomCore + AZ::AzFramework + AZ::AzNetworking + Gem::Atom_Feature_Common.Static + Gem::Multiplayer.Static + Gem::ImGui.Static +) diff --git a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja index aee15bc190..d6907876e1 100644 --- a/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja +++ b/Gems/Multiplayer/Code/Source/AutoGen/AutoComponent_Source.jinja @@ -1168,6 +1168,12 @@ namespace {{ Component.attrib['Namespace'] }} void {{ ComponentBaseName }}::Init() { + if (m_netBindComponent == nullptr) + { + AZLOG_ERROR("NetBindComponent is null, ensure NetworkAttach is called prior to activating a networked entity"); + return; + } + {{ DefineComponentServiceProxyGrabs(Component, ClassType, ComponentName)|indent(8) }} {% if ComponentDerived %} OnInit(); diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp new file mode 100644 index 0000000000..1b59a704dc --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp @@ -0,0 +1,36 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include + +namespace Multiplayer +{ + MultiplayerImguiModule::MultiplayerImguiModule() + : AZ::Module() + { + m_descriptors.insert(m_descriptors.end(), { + MultiplayerImguiSystemComponent::CreateDescriptor(), + }); + } + + AZ::ComponentTypeList MultiplayerImguiModule::GetRequiredSystemComponents() const + { + return AZ::ComponentTypeList + { + azrtti_typeid(), + }; + } +} + +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerImguiModule); diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h new file mode 100644 index 0000000000..ce0ed244be --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h @@ -0,0 +1,31 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +namespace Multiplayer +{ + class MultiplayerImguiModule + : public AZ::Module + { + public: + AZ_RTTI(MultiplayerImguiModule, "{9E1460FA-4513-4B5E-86B4-9DD8ADEFA714}", AZ::Module); + AZ_CLASS_ALLOCATOR(MultiplayerImguiModule, AZ::SystemAllocator, 0); + + MultiplayerImguiModule(); + ~MultiplayerImguiModule() override = default; + + AZ::ComponentTypeList GetRequiredSystemComponents() const override; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp new file mode 100644 index 0000000000..a53dd2800f --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp @@ -0,0 +1,123 @@ +/* +* All or portions of this file Copyright(c) Amazon.com, Inc.or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution(the "License").All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file.Do not +* remove or modify any license notices.This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include +#include +#include +#include + +namespace Multiplayer +{ + void MultiplayerImguiSystemComponent::Reflect(AZ::ReflectContext* context) + { + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(1); + } + } + + void MultiplayerImguiSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + } + + void MultiplayerImguiSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + ; + } + + void MultiplayerImguiSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile) + { + incompatbile.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + } + + void MultiplayerImguiSystemComponent::Activate() + { +#ifdef IMGUI_ENABLED + ImGui::ImGuiUpdateListenerBus::Handler::BusConnect(); +#endif + } + + void MultiplayerImguiSystemComponent::Deactivate() + { +#ifdef IMGUI_ENABLED + ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect(); +#endif + } + +#ifdef IMGUI_ENABLED + void MultiplayerImguiSystemComponent::OnImGuiMainMenuUpdate() + { + if (ImGui::BeginMenu("Multiplayer")) + { + //{ + // static int lossPercent{ 0 }; + // lossPercent = static_cast(net_UdpDebugLossPercent); + // if (ImGui::SliderInt("UDP Loss Percent", &lossPercent, 0, 100)) + // { + // net_UdpDebugLossPercent = lossPercent; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLossPercent); + // } + //} + // + //{ + // static int latency{ 0 }; + // latency = static_cast(net_UdpDebugLatencyMs); + // if (ImGui::SliderInt("UDP Latency Ms", &latency, 0, 3000)) + // { + // net_UdpDebugLatencyMs = latency; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugLatencyMs); + // } + //} + // + //{ + // static int variance{ 0 }; + // variance = static_cast(net_UdpDebugVarianceMs); + // if (ImGui::SliderInt("UDP Variance Ms", &variance, 0, 1000)) + // { + // net_UdpDebugVarianceMs = variance; + // m_ClientAgent.UpdateConnectionCvars(net_UdpDebugVarianceMs); + // } + //} + + ImGui::Checkbox("Multiplayer Stats", &m_displayStats); + ImGui::EndMenu(); + } + } + + void MultiplayerImguiSystemComponent::OnImGuiUpdate() + { + if (m_displayStats) + { + if (ImGui::Begin("Multiplayer Stats", &m_displayStats, ImGuiWindowFlags_HorizontalScrollbar)) + { + IMultiplayer* multiplayer = AZ::Interface::Get(); + Multiplayer::MultiplayerStats& stats = multiplayer->GetStats(); + ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType())); + ImGui::Text("Total networked entities: %llu", aznumeric_cast(stats.m_entityCount)); + ImGui::Text("Total client connections: %llu", aznumeric_cast(stats.m_clientConnectionCount)); + ImGui::Text("Total server connections: %llu", aznumeric_cast(stats.m_serverConnectionCount)); + ImGui::Text("Total property updates sent: %llu", aznumeric_cast(stats.m_propertyUpdatesSent)); + ImGui::Text("Total property updates sent bytes: %llu", aznumeric_cast(stats.m_propertyUpdatesSentBytes)); + ImGui::Text("Total property updates received: %llu", aznumeric_cast(stats.m_propertyUpdatesRecv)); + ImGui::Text("Total property updates received bytes: %llu", aznumeric_cast(stats.m_propertyUpdatesRecvBytes)); + ImGui::Text("Total RPCs sent: %llu", aznumeric_cast(stats.m_rpcsSent)); + ImGui::Text("Total RPCs sent bytes: %llu", aznumeric_cast(stats.m_rpcsSentBytes)); + ImGui::Text("Total RPCs received: %llu", aznumeric_cast(stats.m_rpcsRecv)); + ImGui::Text("Total RPCs received bytes: %llu", aznumeric_cast(stats.m_rpcsRecvBytes)); + } + ImGui::End(); + } + } +#endif +} diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h new file mode 100644 index 0000000000..1650d62264 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h @@ -0,0 +1,56 @@ +/* +* All or portions of this file Copyright(c) Amazon.com, Inc.or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution(the "License").All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file.Do not +* remove or modify any license notices.This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#pragma once + +#include + +#ifdef IMGUI_ENABLED +# include +# include +#endif + +namespace Multiplayer +{ + class MultiplayerImguiSystemComponent final + : public AZ::Component +#ifdef IMGUI_ENABLED + , public ImGui::ImGuiUpdateListenerBus::Handler +#endif + { + public: + AZ_COMPONENT(MultiplayerImguiSystemComponent, "{060BF3F1-0BFE-4FCE-9C3C-EE991F0DA581}"); + + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile); + + ~MultiplayerImguiSystemComponent() override = default; + + //! AZ::Component overrides + //! @{ + void Activate() override; + void Deactivate() override; + //! @} + +#ifdef IMGUI_ENABLED + //! ImGui::ImGuiUpdateListenerBus overrides + //! @{ + void OnImGuiMainMenuUpdate() override; + void OnImGuiUpdate() override; + //! @} +#endif + private: + bool m_displayStats = false; + }; +} diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 70323d7de3..e40e9e9d66 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -133,23 +133,33 @@ namespace Multiplayer // Let the network system know the frame is done and we can collect dirty bits m_networkEntityManager.NotifyEntitiesDirtied(); + MultiplayerStats& stats = GetStats(); + stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); + stats.m_serverConnectionCount = 0; + stats.m_clientConnectionCount = 0; + // Send out the game state update to all connections { - auto sendNetworkUpdates = [serverGameTimeMs](IConnection& connection) + auto sendNetworkUpdates = [serverGameTimeMs, &stats](IConnection& connection) { if (connection.GetUserData() != nullptr) { IConnectionData* connectionData = reinterpret_cast(connection.GetUserData()); connectionData->Update(serverGameTimeMs); + if (connectionData->GetConnectionDataType() == ConnectionDataType::ServerToClient) + { + stats.m_clientConnectionCount++; + } + else + { + stats.m_serverConnectionCount++; + } } }; m_networkInterface->GetConnectionSet().VisitConnections(sendNetworkUpdates); } - MultiplayerStats& stats = GetStats(); - stats.m_entityCount = GetNetworkEntityManager()->GetEntityCount(); - MultiplayerPackets::SyncConsole packet; AZ::ThreadSafeDeque::DequeType cvarUpdates; m_cvarCommands.Swap(cvarUpdates); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 71b04585ad..4c57924eb4 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -62,4 +62,4 @@ namespace Multiplayer } } // namespace Multiplayer -AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer2_Tools, Multiplayer::MultiplayerToolsModule); +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Tools, Multiplayer::MultiplayerToolsModule); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index a3bb2029d2..2d2c668497 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ - +#pragma optimize("", off) #include #include #include @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index c06d7bc8f9..257173b347 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -39,12 +39,6 @@ namespace Multiplayer { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); - if (AZ::Interface::Get() != nullptr) - { - // Null guard needed for unit tests - AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); - AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); - } } NetworkEntityManager::~NetworkEntityManager() @@ -58,6 +52,12 @@ namespace Multiplayer m_hostId = hostId; m_entityDomain = AZStd::move(entityDomain); m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); + if (AZ::Interface::Get() != nullptr) + { + // Null guard needed for unit tests + AZ::Interface::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); + AZ::Interface::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); + } } NetworkEntityTracker* NetworkEntityManager::GetNetworkEntityTracker() diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index 3c3d1f079d..6087376b30 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -26,6 +26,10 @@ namespace Multiplayer } } + NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() + { + } + void NetworkSpawnableHolderComponent::Activate() { } @@ -43,9 +47,4 @@ namespace Multiplayer { return m_networkSpawnableAsset; } - - NetworkSpawnableHolderComponent::NetworkSpawnableHolderComponent() - { - } - } diff --git a/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake b/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake new file mode 100644 index 0000000000..57623772d2 --- /dev/null +++ b/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake @@ -0,0 +1,19 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + Source/Multiplayer_precompiled.cpp + Source/Multiplayer_precompiled.h + Source/Imgui/MultiplayerImguiModule.cpp + Source/Imgui/MultiplayerImguiModule.h + Source/Imgui/MultiplayerImguiSystemComponent.cpp + Source/Imgui/MultiplayerImguiSystemComponent.h +) From 08ed726faa3d29c863423cfa92224adfce9a9413 Mon Sep 17 00:00:00 2001 From: Olex Lozitskiy Date: Mon, 19 Apr 2021 15:52:13 -0400 Subject: [PATCH 11/96] Deleted CrySCompileServer --- Code/Tools/CMakeLists.txt | 1 - Code/Tools/CrySCompileServer/CMakeLists.txt | 12 - .../CrySCompileServer/CMakeLists.txt | 63 - .../CrySCompileServer/Core/Common.h | 39 - .../CrySCompileServer/Core/Error.cpp | 73 - .../CrySCompileServer/Core/Error.hpp | 95 - .../CrySCompileServer/Core/MD5.hpp | 334 --- .../CrySCompileServer/Core/Mailer.cpp | 420 ---- .../CrySCompileServer/Core/Mailer.h | 72 - .../CrySCompileServer/Core/STLHelper.cpp | 343 --- .../CrySCompileServer/Core/STLHelper.hpp | 112 - .../Core/Server/CrySimpleCache.cpp | 311 --- .../Core/Server/CrySimpleCache.hpp | 68 - .../Core/Server/CrySimpleErrorLog.cpp | 274 --- .../Core/Server/CrySimpleErrorLog.hpp | 42 - .../Core/Server/CrySimpleFileGuard.hpp | 33 - .../Core/Server/CrySimpleHTTP.cpp | 228 -- .../Core/Server/CrySimpleHTTP.hpp | 36 - .../Core/Server/CrySimpleJob.cpp | 211 -- .../Core/Server/CrySimpleJob.hpp | 74 - .../Core/Server/CrySimpleJobCache.cpp | 36 - .../Core/Server/CrySimpleJobCache.hpp | 35 - .../Core/Server/CrySimpleJobCompile.cpp | 969 --------- .../Core/Server/CrySimpleJobCompile.hpp | 92 - .../Core/Server/CrySimpleJobCompile1.cpp | 31 - .../Core/Server/CrySimpleJobCompile1.hpp | 29 - .../Core/Server/CrySimpleJobCompile2.cpp | 34 - .../Core/Server/CrySimpleJobCompile2.hpp | 29 - .../Core/Server/CrySimpleJobGetShaderList.cpp | 86 - .../Core/Server/CrySimpleJobGetShaderList.hpp | 29 - .../Core/Server/CrySimpleJobRequest.cpp | 90 - .../Core/Server/CrySimpleJobRequest.hpp | 33 - .../Core/Server/CrySimpleMutex.cpp | 57 - .../Core/Server/CrySimpleMutex.hpp | 53 - .../Core/Server/CrySimpleServer.cpp | 722 ------- .../Core/Server/CrySimpleServer.hpp | 119 -- .../Core/Server/CrySimpleSock.cpp | 760 ------- .../Core/Server/CrySimpleSock.hpp | 104 - .../Core/Server/ShaderList.cpp | 521 ----- .../Core/Server/ShaderList.hpp | 95 - .../CrySCompileServer/Core/StdTypes.hpp | 41 - .../Core/WindowsAPIImplementation.cpp | 80 - .../Core/WindowsAPIImplementation.h | 78 - .../CrySCompileServer/CrySCompileServer.cpp | 424 ---- .../External/tinyxml/readme.txt | 530 ----- .../External/tinyxml/tinystr.cpp | 116 - .../External/tinyxml/tinystr.h | 309 --- .../External/tinyxml/tinyxml.cpp | 1889 ----------------- .../External/tinyxml/tinyxml.h | 1785 ---------------- .../External/tinyxml/tinyxmlerror.cpp | 53 - .../External/tinyxml/tinyxmlparser.cpp | 1638 -------------- .../External/tinyxml/xmltest.cpp | 1336 ------------ .../CrySCompileServer/ListCache.bat | 16 - .../Platform/Android/PAL_android.cmake | 12 - .../Platform/Android/platform_android.cmake | 10 - .../Clang/cryscompileserver_clang.cmake | 15 - .../Common/MSVC/cryscompileserver_msvc.cmake | 15 - .../Platform/Linux/PAL_linux.cmake | 12 - .../Platform/Linux/platform_linux.cmake | 10 - .../Platform/Mac/PAL_mac.cmake | 12 - .../Platform/Mac/platform_mac.cmake | 15 - .../Platform/Windows/PAL_windows.cmake | 12 - .../Platform/Windows/platform_windows.cmake | 44 - .../Platform/iOS/PAL_ios.cmake | 12 - .../Platform/iOS/platform_ios.cmake | 10 - .../cryscompileserver_files.cmake | 60 - .../3rdParty/FindDirectXShaderCompiler.cmake | 22 - .../Mac/DirectXShaderCompiler_mac.cmake | 16 - .../Platform/Mac/cmake_mac_files.cmake | 1 - .../DirectXShaderCompiler_windows.cmake | 16 - .../Windows/cmake_windows_files.cmake | 1 - cmake/3rdParty/cmake_files.cmake | 1 - 72 files changed, 15356 deletions(-) delete mode 100644 Code/Tools/CrySCompileServer/CMakeLists.txt delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxmlerror.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxmlparser.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/xmltest.cpp delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake delete mode 100644 Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake delete mode 100644 cmake/3rdParty/FindDirectXShaderCompiler.cmake delete mode 100644 cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake delete mode 100644 cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index b96ebae1ac..d2500dfd04 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -14,7 +14,6 @@ add_subdirectory(AssetProcessor) add_subdirectory(AWSNativeSDKInit) add_subdirectory(AzTestRunner) add_subdirectory(CryCommonTools) -add_subdirectory(CrySCompileServer) add_subdirectory(CryXML) add_subdirectory(HLSLCrossCompiler) add_subdirectory(HLSLCrossCompilerMETAL) diff --git a/Code/Tools/CrySCompileServer/CMakeLists.txt b/Code/Tools/CrySCompileServer/CMakeLists.txt deleted file mode 100644 index 84725a9d13..0000000000 --- a/Code/Tools/CrySCompileServer/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -add_subdirectory(CrySCompileServer) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt b/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt deleted file mode 100644 index ca22619c92..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/CMakeLists.txt +++ /dev/null @@ -1,63 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) -ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common) -ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform) -ly_get_pal_tool_dirs(pal_tool_core_server_dirs ${CMAKE_CURRENT_LIST_DIR}/Core/Server/Platform) - -include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) - -if(NOT PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED OR NOT PAL_TRAIT_BUILD_HOST_TOOLS) - return() -endif() - -set(platform_tools_files) -foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED}) - string(TOLOWER ${enabled_platform} enabled_platform_lowercase) - ly_get_list_relative_pal_filename(pal_tool_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${enabled_platform}) - list(APPEND platform_tools_files ${pal_tool_dir}/pal_tools_${enabled_platform_lowercase}.cmake) -endforeach() - -ly_add_target( - NAME CrySCompileServer EXECUTABLE - NAMESPACE Legacy - FILES_CMAKE - cryscompileserver_files.cmake - PLATFORM_INCLUDE_FILES - Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - ${platform_tools_files} - ${common_dir}/${PAL_TRAIT_COMPILER_ID}/cryscompileserver_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake - INCLUDE_DIRECTORIES - PUBLIC - . - External - PRIVATE - ${pal_tool_dirs} - ${pal_tool_core_server_dirs} - BUILD_DEPENDENCIES - PRIVATE - 3rdParty::zlib - AZ::AzCore - AZ::AzFramework -) -ly_add_source_properties( - SOURCES - Core/Server/CrySimpleJobCompile.cpp - CrySCompileServer.cpp - PROPERTY COMPILE_DEFINITIONS - VALUES ${LY_PAL_TOOLS_DEFINES} -) -ly_add_source_properties( - SOURCES Core/Server/CrySimpleServer.cpp - PROPERTY COMPILE_DEFINITIONS - VALUES ${LY_PAL_TOOLS_DEFINES} -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h deleted file mode 100644 index d228fc1dc3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Common.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H -#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H -#pragma once - -#include -#include -#include - -#if defined(AZ_PLATFORM_WINDOWS) -# if !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0501 -# endif - -// Windows platform requires either a long or an unsigned long/uint64 for the -// Interlock instructions. -typedef long AtomicCountType; - -#else - -// Linux/Mac platforms don't support a long for the atomic types, only int32 or -// int64 (no unsigned support). -typedef int32_t AtomicCountType; - -#endif - -#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp deleted file mode 100644 index edbdcc6997..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "StdTypes.hpp" -#include "Error.hpp" -#include -#include "Server/CrySimpleErrorLog.hpp" -#include "Server/CrySimpleJob.hpp" - -#include -#include -#include - -ICryError::ICryError(EErrorType t) - : m_eType(t) - , m_numDupes(0) -{ -} - -void logmessage(const char* text, ...) -{ - va_list arg; - va_start(arg, text); - - char szBuffer[256]; - char* error = szBuffer; - int bufferlen = sizeof(szBuffer) - 1; - memset(szBuffer, 0, sizeof(szBuffer)); - - long req = CCrySimpleJob::GlobalRequestNumber(); - - int ret = azsnprintf(error, bufferlen, "%8ld | ", req); - - if (ret <= 0) - { - return; - } - error += ret; - bufferlen -= ret; - - time_t ltime; - time(<ime); - tm today; -#if defined(AZ_PLATFORM_WINDOWS) - localtime_s(&today, <ime); -#else - localtime_r(<ime, &today); -#endif - ret = (int)strftime(error, bufferlen, "%d/%m %H:%M:%S | ", &today); - - if (ret <= 0) - { - return; - } - error += ret; - bufferlen -= ret; - - vsnprintf(error, bufferlen, text, arg); - - AZ_TracePrintf(0, szBuffer); - - va_end(arg); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp deleted file mode 100644 index 8e432ce29a..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Error.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __DXPSERROR__ -#define __DXPSERROR__ - -#include -#include -#include "STLHelper.hpp" - -// printf wrapper to format things nicely -void logmessage(const char* text, ...); - -class ICryError -{ -public: - enum EErrorType - { - SIMPLE_ERROR = 0, - COMPILE_ERROR, - }; - - enum EOutputFormatType - { - OUTPUT_EMAIL = 0, - OUTPUT_TTY, - OUTPUT_HASH, - }; - - ICryError(EErrorType t); - virtual ~ICryError() {}; - - EErrorType GetType() const { return m_eType; } - - tdHash Hash() const { return CSTLHelper::Hash(GetErrorName() + GetErrorDetails(OUTPUT_HASH)); }; - - virtual bool Compare(const ICryError* err) const - { - if (GetType() != err->GetType()) - { - return GetType() < err->GetType(); - } - return Hash() < err->Hash(); - }; - virtual bool CanMerge([[maybe_unused]] const ICryError* err) const { return true; } - - virtual void AddDuplicate([[maybe_unused]] ICryError* err) { m_numDupes++; } - uint32_t NumDuplicates() const { return m_numDupes; } - - virtual void SetUniqueID([[maybe_unused]] int uniqueID) {} - - virtual bool HasFile() const { return false; }; - - virtual void AddCCs([[maybe_unused]] std::set& ccs) const {} - - virtual std::string GetErrorName() const = 0; - virtual std::string GetErrorDetails(EOutputFormatType outputType) const = 0; - virtual std::string GetFilename() const { return "NoFile"; } - virtual std::string GetFileContents() const { return ""; } -private: - EErrorType m_eType; - uint32_t m_numDupes; -}; - -class CSimpleError - : public ICryError -{ -public: - CSimpleError(const std::string& in_text) - : ICryError(SIMPLE_ERROR) - , m_text(in_text) {} - virtual ~CSimpleError() {} - - virtual std::string GetErrorName() const { return m_text; }; - virtual std::string GetErrorDetails([[maybe_unused]] EOutputFormatType outputType) const { return m_text; }; -private: - std::string m_text; -}; - - -#define CrySimple_ERROR(X) throw new CSimpleError(X) -#define CrySimple_SECURE_START try{ -#define CrySimple_SECURE_END }catch (const ICryError* err) {printf(err->GetErrorName().c_str()); delete err; } - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp deleted file mode 100644 index f79725f9af..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/MD5.hpp +++ /dev/null @@ -1,334 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CSCMD5__ -#define __CSCMD5__ - -/* -* This code implements the MD5 message-digest algorithm. -* The algorithm is due to Ron Rivest. This code was -* written by Colin Plumb in 1993, no copyright is claimed. -* This code is in the public domain; do with it what you wish. -* -* Equivalent code is available from RSA Data Security, Inc. -* This code has been tested against that, and is equivalent, -* except that you don't need to include two pages of legalese -* with every copy. -* -* To compute the message digest of a chunk of bytes, declare an -* MD5Context structure, pass it to MD5Init, call MD5Update as -* needed on buffers full of bytes, and then call MD5Final, which -* will fill a supplied 16-byte array with the digest. -*/ - -/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to -not require an integer type which is exactly 32 bits. This work -draws on the changes for the same purpose by Tatu Ylonen - as part of SSH, but since I didn't actually use -that code, there is no copyright issue. I hereby disclaim -copyright in any changes I have made; this code remains in the -public domain. */ - -/* Note regarding cvs_* namespace: this avoids potential conflicts -with libraries such as some versions of Kerberos. No particular -need to worry about whether the system supplies an MD5 library, as -this file is only about 3k of object code. */ - - -struct cvs_MD5Context -{ - uint32_t buf[4]; - uint32_t bits[2]; - unsigned char in[64]; -}; - -void cvs_MD5Init(struct cvs_MD5Context* context); -void cvs_MD5Update(struct cvs_MD5Context* context, unsigned char const* buf, unsigned len); -void cvs_MD5Final(unsigned char digest[16], struct cvs_MD5Context* context); -void cvs_MD5Transform(uint32_t buf[4], const unsigned char in[64]); - -/* Little-endian byte-swapping routines. Note that these do not -depend on the size of datatypes such as uint32_t, nor do they require -us to detect the endianness of the machine we are running on. It -is possible they should be macros for speed, but I would be -surprised if they were a performance bottleneck for MD5. */ - -uint32_t getu32 (const unsigned char* addr) -{ - return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; -} - -void putu32(uint32_t data, unsigned char* addr) -{ - addr[0] = (unsigned char)data; - addr[1] = (unsigned char)(data >> 8); - addr[2] = (unsigned char)(data >> 16); - addr[3] = (unsigned char)(data >> 24); -} - -/* -* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious -* initialization constants. -*/ -void cvs_MD5Init(cvs_MD5Context& rCtx) -{ - rCtx.buf[0] = 0x67452301; - rCtx.buf[1] = 0xefcdab89; - rCtx.buf[2] = 0x98badcfe; - rCtx.buf[3] = 0x10325476; - rCtx.bits[0] = 0; - rCtx.bits[1] = 0; -} - -/* -* Update context to reflect the concatenation of another buffer full -* of bytes. -*/ -void cvs_MD5Update(cvs_MD5Context& rCtx, unsigned char const* buf, uint32_t len) -{ - uint32_t t; - - /* Update bitcount */ - - t = rCtx.bits[0]; - if ((rCtx.bits[0] = (t + ((uint32_t)len << 3)) & 0xffffffff) < t) - { - rCtx.bits[1]++; /* Carry from low to high */ - } - rCtx.bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) - { - unsigned char* p = rCtx.in + t; - - t = 64 - t; - if (len < t) - { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - cvs_MD5Transform (rCtx.buf, rCtx.in); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) - { - memcpy(rCtx.in, buf, 64); - cvs_MD5Transform (rCtx.buf, rCtx.in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(rCtx.in, buf, len); -} - -/* -* Final wrapup - pad to 64-byte boundary with the bit pattern -* 1 0* (64-bit count of bits processed, MSB-first) -*/ -void cvs_MD5Final(unsigned char digest[16], cvs_MD5Context& rCtx) -{ - unsigned count; - uint8_t* p; - - /* Compute number of bytes mod 64 */ - count = (rCtx.bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = rCtx.in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) - { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - cvs_MD5Transform (rCtx.buf, rCtx.in); - - /* Now fill the next block with 56 bytes */ - memset(rCtx.in, 0, 56); - } - else - { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - - /* Append length in bits and transform */ - putu32(rCtx.bits[0], rCtx.in + 56); - putu32(rCtx.bits[1], rCtx.in + 60); - - cvs_MD5Transform (rCtx.buf, rCtx.in); - putu32(rCtx.buf[0], digest); - putu32(rCtx.buf[1], digest + 4); - putu32(rCtx.buf[2], digest + 8); - putu32(rCtx.buf[3], digest + 12); - //memset(&rCtx,0,sizeof(rCtx)); // In case it's sensitive -} - - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - (w += f(x, y, z) + data, w &= 0xffffffff, w = w << s | w >> (32 - s), w += x) - -/* -* The core of the MD5 algorithm, this alters an existing MD5 hash to -* reflect the addition of 16 longwords of new data. MD5Update blocks -* the data and converts bytes into longwords for this routine. -*/ -void cvs_MD5Transform(uint32_t buf[4], const unsigned char inraw[64]) -{ - uint32_t a, b, c, d; - uint32_t in[16]; - int i; - - for (i = 0; i < 16; ++i) - { - in[i] = getu32 (inraw + 4 * i); - } - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -/* -#include - -int -main (int argc, char **argv) -{ - struct cvs_MD5Context context; - unsigned char checksum[16]; - int i; - int j; - - if (argc < 2) - { - fprintf (stderr, "usage: %s string-to-hash\n", argv[0]); - exit (1); - } - for (j = 1; j < argc; ++j) - { - printf ("MD5 (\"%s\") = ", argv[j]); - cvs_MD5Init (&context); - cvs_MD5Update (&context, argv[j], strlen (argv[j])); - cvs_MD5Final (checksum, &context); - for (i = 0; i < 16; i++) - { - printf ("%02x", (unsigned int) checksum[i]); - } - printf ("\n"); - } - return 0; -} -*/ - -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp deleted file mode 100644 index 390fc3f8c9..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "Mailer.h" -#include "WindowsAPIImplementation.h" - -#include -#include - -#if defined(AZ_PLATFORM_MAC) -#include -#include -#elif defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include -#include - -#pragma comment(lib,"ws2_32.lib") - - -namespace // helpers -{ - static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - - void Base64EncodeBlock(const unsigned char* in, unsigned char* out) - { - out[0] = cb64[in[0] >> 2]; - out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; - out[2] = cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)]; - out[3] = cb64[in[2] & 0x3f]; - } - - - void Base64EncodeBlock(const unsigned char* in, unsigned char* out, int len) - { - out[0] = cb64[in[0] >> 2]; - out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; - out[2] = (unsigned char) (len > 1 ? cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)] : '='); - out[3] = (unsigned char) (len > 2 ? cb64[in[2] & 0x3f] : '='); - } - - - void Base64Encode(const unsigned char* pSrc, const size_t srcLen, unsigned char* pDst, [[maybe_unused]] const size_t dstLen) - { - assert(dstLen >= 4 * ((srcLen + 2) / 3)); - - size_t len = srcLen; - for (; len > 2; len -= 3, pSrc += 3, pDst += 4) - { - Base64EncodeBlock(pSrc, pDst); - } - - if (len > 0) - { - unsigned char in[3]; - in[0] = pSrc[0]; - in[1] = len > 1 ? pSrc[1] : 0; - in[2] = 0; - Base64EncodeBlock(in, pDst, (int) len); - } - } - - - std::string Base64EncodeString(const std::string& in) - { - const size_t srcLen = in.size(); - const size_t dstLen = 4 * ((srcLen + 2) / 3); - std::string out(dstLen, 0); - - Base64Encode((const unsigned char*) in.c_str(), srcLen, (unsigned char*) out.c_str(), dstLen); - - return out; - } - - - const char* ExtractFileName(const char* filepath) - { - for (const char* p = filepath + strlen(filepath) - 1; p >= filepath; --p) - { - if (*p == '\\' || *p == '/') - { - return p + 1; - } - } - return filepath; - } -} - -AZStd::atomic_long CSMTPMailer::ms_OpenSockets = {0}; - -CSMTPMailer::CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port) - : m_server(server) - , m_username(username) - , m_password(password) - , m_port(port) - , m_winSockAvail(false) - , m_response() -{ -#if defined(AZ_PLATFORM_WINDOWS) - WSADATA wd; - m_winSockAvail = WSAStartup(MAKEWORD(1, 1), &wd) == 0; - if (!m_winSockAvail) - { - m_response += "Error: Unable to initialize WinSock 1.1\n"; - } -#endif -} - - -CSMTPMailer::~CSMTPMailer() -{ -#if defined(AZ_PLATFORM_WINDOWS) - if (m_winSockAvail) - { - WSACleanup(); - } -#endif -} - - -void CSMTPMailer::ReceiveLine(SOCKET connection) -{ - char buf[1025]; - int ret = recv(connection, buf, sizeof(buf) - 1, 0); - if (ret == SOCKET_ERROR) - { - ret = azsnprintf(buf, sizeof(buf), "Error: WinSock error %d during recv()\n", WSAGetLastError()); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - } - else - { - buf[ret] = 0; - } - m_response += buf; -} - - -void CSMTPMailer::SendLine(SOCKET connection, const char* format, ...) const -{ - char buf[2049]; - va_list args; - va_start(args, format); - int len = azvsnprintf(buf, sizeof(buf), format, args); - if (len == sizeof(buf) || len < 0) - { - buf[sizeof(buf) - 1] = '\0'; - len = sizeof(buf) - 1; - } - va_end(args); - send(connection, buf, len, 0); -} - - -void CSMTPMailer::SendRaw(SOCKET connection, const char* data, size_t dataLen) const -{ - send(connection, data, (int) dataLen, 0); -} - - -void CSMTPMailer::SendFile(SOCKET connection, const tattachment& filepath, const char* boundary) const -{ - AZ::IO::SystemFile inputFile; - const bool wasSuccessful = inputFile.Open(filepath.second.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - if (wasSuccessful) - { - SendLine(connection, "--%s\r\n", boundary); - SendLine(connection, "Content-Type: application/octet-stream\r\n"); - SendLine(connection, "Content-Transfer-Encoding: base64\r\n"); - SendLine(connection, "Content-Disposition: attachment; filename=\"%s\"\r\n", filepath.first.c_str()); - SendLine(connection, "\r\n"); - - AZ::IO::SystemFile::SizeType fileSize = inputFile.Length(); - while (fileSize) - { - const int DEF_BLOCK_SIZE = 128; // 72 - char in[3 * DEF_BLOCK_SIZE]; - size_t blockSize = fileSize > sizeof(in) ? sizeof(in) : fileSize; - inputFile.Read(blockSize, in); - - char out[4 * DEF_BLOCK_SIZE]; - Base64Encode((unsigned char*) in, blockSize, (unsigned char*) out, sizeof(out)); - SendRaw(connection, out, 4 * ((blockSize + 2) / 3)); - - SendLine(connection, "\r\n"); // seems to get sent faster if you split up the data lines - - fileSize -= blockSize; - } - } -} - - -SOCKET CSMTPMailer::Open(const char* host, unsigned short port, sockaddr_in& serverAddress) -{ - SOCKET connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (connection == INVALID_SOCKET) - { - m_response += "Error: Failed to create socket\n"; - return 0; - } - - struct addrinfo* addressInfo{}; - char portBuffer[16]; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - azsnprintf(portBuffer, AZStd::size(portBuffer), "%hu", port); - int addrInfoReturnCode = getaddrinfo(host, portBuffer, &hints, &addressInfo); - if(addrInfoReturnCode != 0) - { - char buf[1025]; - int ret = azsnprintf(buf, sizeof(buf), "Error: Host %s not found\n", host); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - m_response += buf; - closesocket(connection); - return 0; - } - - if (addressInfo) - { - ++ms_OpenSockets; - - serverAddress = *reinterpret_cast(addressInfo->ai_addr); - } - - return connection; -} - - -void CSMTPMailer::AddReceivers(SOCKET connection, const tstrcol& receivers) -{ - for (tstrcol::const_iterator it = receivers.begin(), itEnd = receivers.end(); it != itEnd; ++it) - { - if (!(*it).empty()) - { - SendLine(connection, "rcpt to: %s\r\n", (*it).c_str()); - ReceiveLine(connection); - } - } -} - - -void CSMTPMailer::AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers) -{ - tstrcol::const_iterator it = receivers.begin(); - tstrcol::const_iterator itEnd = receivers.end(); - - while (it != itEnd && (*it).empty()) - { - ++it; - } - - if (it != itEnd) - { - tstr out(receiverTag); - out += *it; - ++it; - for (; it != itEnd; ++it) - { - if (!(*it).empty()) - { - out += "; "; - out += *it; - } - } - out += "\r\n"; - SendLine(connection, out.c_str()); - } -} - - -void CSMTPMailer::SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary) -{ - for (tattachlist::const_iterator it = attachments.begin(), itEnd = attachments.end(); it != itEnd; ++it) - { - if (!(*it).first.empty() && !(*it).second.empty()) - { - SendFile(connection, *it, boundary); - } - } -} - - -bool CSMTPMailer::IsEmpty(const tstrcol& col) const -{ - if (!col.empty()) - { - for (tstrcol::const_iterator it = col.begin(), itEnd = col.end(); it != itEnd; ++it) - { - if (!(*it).empty()) - { - return false; - } - } - } - - return true; -} - - -bool CSMTPMailer::Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments) -{ - if (!m_winSockAvail) - { - return false; - } - - if (from.empty() || IsEmpty(to)) - { - return false; - } - - sockaddr_in serverAddress; - SOCKET connection = Open(m_server.c_str(), m_port, serverAddress); // SMTP telnet (usually port 25) - if (connection == INVALID_SOCKET) - { - return false; - } - - if (connect(connection, (sockaddr*) &serverAddress, sizeof(serverAddress)) != SOCKET_ERROR) - { - ReceiveLine(connection); - - SendLine(connection, "helo localhost\r\n"); - ReceiveLine(connection); - - if (!m_username.empty() && !m_password.empty()) - { - SendLine(connection, "auth login\r\n"); // most servers should implement this (todo: otherwise fall back to PLAIN or CRAM-MD5 (requiring EHLO)) - ReceiveLine(connection); - SendLine(connection, "%s\r\n", Base64EncodeString(m_username).c_str()); - ReceiveLine(connection); - SendLine(connection, "%s\r\n", Base64EncodeString(m_password).c_str()); - ReceiveLine(connection); - } - - SendLine(connection, "mail from: %s\r\n", from.c_str()); - ReceiveLine(connection); - - AddReceivers(connection, to); - AddReceivers(connection, cc); - AddReceivers(connection, bcc); - - SendLine(connection, "data\r\n"); - ReceiveLine(connection); - - SendLine(connection, "From: %s\r\n", from.c_str()); - AssignReceivers(connection, "To: ", to); - AssignReceivers(connection, "Cc: ", cc); - AssignReceivers(connection, "Bcc: ", bcc); - - SendLine(connection, "Subject: %s\r\n", subject.c_str()); - - static const char boundary[] = "------a95ed0b485e4a9b0fd4ff93f50ad06ca"; // beware, boundary should not clash with text content of message body! - - SendLine(connection, "MIME-Version: 1.0\r\n"); - SendLine(connection, "Content-Type: multipart/mixed; boundary=\"%s\"\r\n", boundary); - SendLine(connection, "\r\n"); - SendLine(connection, "This is a multi-part message in MIME format.\r\n"); - - SendLine(connection, "--%s\r\n", boundary); - SendLine(connection, "Content-Type: text/plain; charset=iso-8859-1; format=flowed\r\n"); // the used charset should support the commonly used special characters of western languages - SendLine(connection, "Content-Transfer-Encoding: 7bit\r\n"); - SendLine(connection, "\r\n"); - SendRaw(connection, body.c_str(), body.size()); - SendLine(connection, "\r\n"); - - SendAttachments(connection, attachments, boundary); - - SendLine(connection, "--%s--\r\n", boundary); - - SendLine(connection, "\r\n.\r\n"); - ReceiveLine(connection); - - SendLine(connection, "quit\r\n"); - ReceiveLine(connection); - } - else - { - char buf[1025]; - int ret = azsnprintf(buf, sizeof(buf), "Error: Failed to connect to %s:%d\n", m_server.c_str(), m_port); - if (ret == sizeof(buf) || ret < 0) - { - buf[sizeof(buf) - 1] = '\0'; - } - m_response += buf; - return false; - } - - closesocket(connection); - --ms_OpenSockets; - - return true; -} - - -const char* CSMTPMailer::GetResponse() const -{ - return m_response.c_str(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h deleted file mode 100644 index 29d8815056..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Mailer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H -#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H -#pragma once - -#include "Common.h" -#include "Server/CrySimpleSock.hpp" -#include -#include -#include -#include -#include - -class CSMTPMailer -{ -public: - typedef std::string tstr; - typedef std::set tstrcol; - typedef std::pair tattachment; - typedef std::list tattachlist; - - static const int DEFAULT_PORT = 25; - static AZStd::atomic_long ms_OpenSockets; - -public: - CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port = DEFAULT_PORT); - ~CSMTPMailer(); - - bool Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments); - const char* GetResponse() const; - - static long GetOpenSockets() { return ms_OpenSockets; } - -private: - void ReceiveLine(SOCKET connection); - void SendLine(SOCKET connection, const char* format, ...) const; - void SendRaw(SOCKET connection, const char* data, size_t dataLen) const; - void SendFile(SOCKET connection, const tattachment& file, const char* boundary) const; - - SOCKET Open(const char* host, unsigned short port, sockaddr_in& serverAddress); - - void AddReceivers(SOCKET connection, const tstrcol& receivers); - void AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers); - void SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary); - - bool IsEmpty(const tstrcol& col) const; - -private: - - std::unique_ptr m_socket; - tstr m_server; - tstr m_username; - tstr m_password; - int m_port; - - bool m_winSockAvail; - tstr m_response; -}; - -#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp deleted file mode 100644 index 3f7d2390db..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "StdTypes.hpp" -#include "Error.hpp" -#include "STLHelper.hpp" - -#include -#include -#include -#include -#include - -#if defined(AZ_PLATFORM_WINDOWS) -#include -#endif - -#include "MD5.hpp" -#include -#include - -#include -#include -#include -#include - -void CSTLHelper::Log(const std::string& rLog) -{ - const std::string Output = rLog + "\n"; - logmessage(Output.c_str()); -} - -void CSTLHelper::Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator) -{ - rRet.clear(); - std::string::size_type Pt; - std::string::size_type Start = 0; - std::string::size_type SSize = Separator.size(); - - while ((Pt = Tokens.find(Separator, Start)) != std::string::npos) - { - std::string SubStr = Tokens.substr(Start, Pt - Start); - rRet.push_back(SubStr); - Start = Pt + SSize; - } - - rRet.push_back(Tokens.substr(Start)); -} - - -void CSTLHelper::Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement) -{ - std::vector Out; - std::vector In(rSrc.c_str(), rSrc.c_str() + rSrc.size() + 1); - Replace(Out, In, rToReplace, rReplacement); - rRet = std::string(reinterpret_cast(&Out[0])); -} - -void CSTLHelper::Replace(std::vector& rRet, const std::vector& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement) -{ - rRet.clear(); - size_t SSize = rToReplace.size(); - for (size_t a = 0, Size = rTokenSrc.size(); a < Size; a++) - { - if (a + SSize < Size && strncmp((const char*)&rTokenSrc[a], rToReplace.c_str(), SSize) == 0) - { - for (size_t b = 0, RSize = rReplacement.size(); b < RSize; b++) - { - rRet.push_back(rReplacement.c_str()[b]); - } - a += SSize - 1; - } - else - { - rRet.push_back(rTokenSrc[a]); - } - } -} - -tdToken CSTLHelper::SplitToken(const std::string& rToken, const std::string& rSeparator) -{ -#undef min - using namespace std; - string Token; - Remove(Token, rToken, ' '); - - string::size_type Pt = Token.find(rSeparator); - return tdToken(Token.substr(0, Pt), Token.substr(std::min(Pt + 1, Token.size()))); -} - -void CSTLHelper::Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator) -{ - rTokenList.clear(); - for (size_t a = 0, Size = rFilter.size(); a < Size; a++) - { - rTokenList.push_back(SplitToken(rFilter[a], rSeparator)); - } -} - -void CSTLHelper::Trim(std::string& rStr, const std::string& charsToTrim) -{ - std::string::size_type Pt1 = rStr.find_first_not_of(charsToTrim); - if (Pt1 == std::string::npos) - { - // At this point the string could be empty or it could only contain 'charsToTrim' characters. - // In case it's the later then trim should be applied by leaving the string empty. - rStr = ""; - return; - } - - std::string::size_type Pt2 = rStr.find_last_not_of(charsToTrim) + 1; - - Pt2 = Pt2 - Pt1; - rStr = rStr.substr(Pt1, Pt2); -} - -void CSTLHelper::Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C) -{ - using namespace std; - AZ_PUSH_DISABLE_WARNING(4996, "-Wdeprecated-declarations") - remove_copy_if(rTokenSrc.begin(), rTokenSrc.end(), back_inserter(rTokenDst), [C](char token) { return token == C; }); - AZ_POP_DISABLE_WARNING -} - - -bool CSTLHelper::ToFile(const std::string& rFileName, const std::vector& rOut) -{ - if (rOut.size() == 0) - { - return false; - } - - AZ::IO::SystemFile outputFile; - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE); - - if (wasSuccessful == false) - { - AZ_Error("ShaderCompiler", wasSuccessful, "CSTLHelper::ToFile Could not create file: %s", rFileName.c_str()); - return false; - } - - outputFile.Write(&rOut[0], rOut.size()); - - return true; -} - -bool CSTLHelper::FromFile(const std::string& rFileName, std::vector& rIn) -{ - AZ::IO::SystemFile inputFile; - bool wasSuccess = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_WRITE); - if (!wasSuccess) - { - return false; - } - - AZ::IO::SystemFile::SizeType fileSize = inputFile.Length(); - if (fileSize <= 0) - { - return false; - } - - rIn.resize(fileSize); - AZ::IO::SystemFile::SizeType actualReadAmount = inputFile.Read(fileSize, &rIn[0]); - - return actualReadAmount == fileSize; -} - -bool CSTLHelper::ToFileCompressed(const std::string& rFileName, const std::vector& rOut) -{ - std::vector buf; - - unsigned long sourceLen = (unsigned long)rOut.size(); - unsigned long destLen = compressBound(sourceLen) + 16; - - buf.resize(destLen); - compress(buf.data(), &destLen, &rOut[0], sourceLen); - - if (destLen > 0) - { - AZ::IO::SystemFile outputFile; - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not create compressed file: %s", rFileName.c_str()); - - if (wasSuccessful == false) - { - return false; - } - - AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(&sourceLen, sizeof(sourceLen)); - AZ_Error("ShaderCompiler", bytesWritten == sizeof(sourceLen), "Could not save out size of compressed data to %s", rFileName.c_str()); - - if (bytesWritten != sizeof(sourceLen)) - { - return false; - } - - bytesWritten = outputFile.Write(buf.data(), destLen); - AZ_Error("ShaderCompiler", bytesWritten == destLen, "Could not save out compressed data to %s", rFileName.c_str()); - - if (bytesWritten != destLen) - { - return false; - } - - return true; - } - else - { - return false; - } -} - -bool CSTLHelper::FromFileCompressed(const std::string& rFileName, std::vector& rIn) -{ - std::vector buf; - AZ::IO::SystemFile inputFile; - const bool wasSuccessful = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not read: ", rFileName.c_str()); - - if (!wasSuccessful) - { - return false; - } - - AZ::IO::SystemFile::SizeType FileLen = inputFile.Length(); - AZ_Error("ShaderCompiler", FileLen > 0, "Error getting file-size of ", rFileName.c_str()); - - if (FileLen <= 0) - { - return false; - } - - unsigned long uncompressedLen = 0; - // Possible, expected, loss of data from u64 to u32. Zlib supports only unsigned long - unsigned long sourceLen = azlossy_caster((FileLen - 4)); - - buf.resize(sourceLen); - - AZ::IO::SystemFile::SizeType bytesReadIn = inputFile.Read(sizeof(uncompressedLen), &uncompressedLen); - AZ_Warning("ShaderCompiler", bytesReadIn == sizeof(uncompressedLen), "Expected to read in %d but read in %d from file %s", sizeof(uncompressedLen), bytesReadIn, rFileName.c_str()); - - bytesReadIn = inputFile.Read(buf.size(), buf.data()); - AZ_Warning("ShaderCompiler", bytesReadIn == buf.size(), "Expected to read in %d but read in %d from file %s", buf.size(), bytesReadIn, rFileName.c_str()); - - unsigned long nUncompressedBytes = uncompressedLen; - rIn.resize(uncompressedLen); - int nRes = uncompress(rIn.data(), &nUncompressedBytes, buf.data(), sourceLen); - - return nRes == Z_OK && nUncompressedBytes == uncompressedLen; -} - -////////////////////////////////////////////////////////////////////////// -bool CSTLHelper::AppendToFile(const std::string& rFileName, const std::vector& rOut) -{ - AZ::IO::SystemFile outputFile; - int openMode = AZ::IO::SystemFile::SF_OPEN_APPEND; - if (!AZ::IO::SystemFile::Exists(rFileName.c_str())) - { - openMode = AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; - } - const bool wasSuccessful = outputFile.Open(rFileName.c_str(), openMode); - AZ_Error("ShaderCompiler", wasSuccessful, "Could not open file for appending: %s", rFileName.c_str()); - if (wasSuccessful == false) - { - return false; - } - - [[maybe_unused]] AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(rOut.data(), rOut.size()); - AZ_Warning("ShaderCompiler", bytesWritten == rOut.size(), "Did not write out all the data to the file: %s", rFileName.c_str()); - return true; -} - -////////////////////////////////////////////////////////////////////////// -tdHash CSTLHelper::Hash(const uint8_t* pData, const size_t Size) -{ - tdHash CheckSum; - cvs_MD5Context MD5Context; - cvs_MD5Init(MD5Context); - cvs_MD5Update(MD5Context, pData, static_cast(Size)); - cvs_MD5Final(CheckSum.hash, MD5Context); - return CheckSum; -} - -static char C2A[17] = "0123456789ABCDEF"; - -std::string CSTLHelper::Hash2String(const tdHash& rHash) -{ - std::string Ret; - for (size_t a = 0, Size = std::min(sizeof(rHash.hash), 16u); a < Size; a++) - { - const uint8_t C1 = rHash[a] & 0xf; - const uint8_t C2 = rHash[a] >> 4; - Ret += C2A[C1]; - Ret += C2A[C2]; - } - return Ret; -} - -tdHash CSTLHelper::String2Hash(const std::string& rStr) -{ - assert(rStr.size() == 32); - tdHash Ret; - for (size_t a = 0, Size = std::min(rStr.size(), 32u); a < Size; a += 2) - { - const uint8_t C1 = rStr.c_str()[a]; - const uint8_t C2 = rStr.c_str()[a + 1]; - Ret[a >> 1] = C1 - (C1 >= '0' && C1 <= '9' ? '0' : 'A' - 10); - Ret[a >> 1] |= (C2 - (C2 >= '0' && C2 <= '9' ? '0' : 'A' - 10)) << 4; - } - return Ret; -} - -////////////////////////////////////////////////////////////////////////// -bool CSTLHelper::Compress(const std::vector& rIn, std::vector& rOut) -{ - unsigned long destLen, sourceLen = (unsigned long)rIn.size(); - destLen = compressBound(sourceLen) + 16; - rOut.resize(destLen + 4); - compress(&rOut[4], &destLen, &rIn[0], sourceLen); - rOut.resize(destLen + 4); - *(uint32_t*)(&rOut[0]) = sourceLen; - return true; -} - -bool CSTLHelper::Uncompress(const std::vector& rIn, std::vector& rOut) -{ - unsigned long sourceLen = (unsigned long)rIn.size() - 4; - unsigned long nUncompressed = *(uint32_t*)(&rIn[0]); - unsigned long nUncompressedBytes = nUncompressed; - rOut.resize(nUncompressed); - int nRes = uncompress(&rOut[0], &nUncompressedBytes, &rIn[4], sourceLen); - return nRes == Z_OK && nUncompressed == nUncompressedBytes; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp deleted file mode 100644 index a7f4228d3c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/STLHelper.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __STLHELPER__ -#define __STLHELPER__ - -#include -#include - -typedef std::vector tdEntryVec; -typedef std::pair tdToken; -typedef std::vector tdTokenList; -typedef std::vector tdDataVector; -//typedef std::vector tdHash; - -struct tdHash -{ - uint8_t hash[16]; - - inline bool operator<(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) < 0; } - inline bool operator>(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) > 0; } - inline bool operator==(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) == 0; } - inline uint8_t& operator[](size_t nIndex) { return hash[nIndex]; } - inline const uint8_t& operator[](size_t nIndex) const { return hash[nIndex]; } -}; - -class CSTLHelper -{ - static tdHash Hash(const uint8_t* pData, const size_t Size); -public: - static void Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator); - static tdToken SplitToken(const std::string& rToken, const std::string& rSeparator); - static void Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator); - static void Trim(std::string& rStr, const std::string& charsToTrim); - static void Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C); - static void Replace(std::vector& rRet, const std::vector& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement); - static void Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement); - - - static bool ToFile(const std::string& rFileName, const std::vector& rOut); - static bool FromFile(const std::string& rFileName, std::vector& rIn); - - static bool AppendToFile(const std::string& rFileName, const std::vector& rOut); - - static bool ToFileCompressed(const std::string& rFileName, const std::vector& rOut); - static bool FromFileCompressed(const std::string& rFileName, std::vector& rIn); - - static bool Compress(const std::vector& rIn, std::vector& rOut); - static bool Uncompress(const std::vector& rIn, std::vector& rOut); - - - static void EndianSwizzleU64(uint64_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[7]; - pT[7] = T; - T = pT[1]; - pT[1] = pT[6]; - pT[6] = T; - T = pT[2]; - pT[2] = pT[5]; - pT[5] = T; - T = pT[3]; - pT[3] = pT[4]; - pT[4] = T; - } - static void EndianSwizzleU32(uint32_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[3]; - pT[3] = T; - T = pT[1]; - pT[1] = pT[2]; - pT[2] = T; - } - static void EndianSwizzleU16(uint16_t& S) - { - uint8_t* pT = reinterpret_cast(&S); - uint8_t T; - T = pT[0]; - pT[0] = pT[1]; - pT[1] = T; - } - - - static void Log(const std::string& rLog); - - static tdHash Hash(const std::string& rStr) { return Hash(reinterpret_cast(rStr.c_str()), rStr.size()); } - static tdHash Hash(const std::vector& rData) { return Hash(&rData[0], rData.size()); } - static tdHash Hash(const std::vector& rData, size_t Size) { return Hash(&rData[0], Size); } - - static std::string Hash2String(const tdHash& rHash); - static tdHash String2Hash(const std::string& rStr); -}; - -#define CRYSIMPLE_LOG(X) CSTLHelper::Log(X) -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp deleted file mode 100644 index 9ceb6be6e2..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleCache.hpp" -#include "CrySimpleServer.hpp" - -#include -#include -#include - -#include -#include -#include - -enum EFileEntryHeaderFlags -{ - EFEHF_NONE = (0 << 0), - EFEHF_REFERENCE = (1 << 0), -}; - -#pragma pack(push, 1) -struct SFileEntryHeader -{ - char signature[4]; // entry signature. - uint32_t dataSize; // Size of entry data. - uint32_t flags; // Flags - uint8_t hash[16]; // Hash code for the data. -}; -#pragma pack(pop) - -static const int MAX_DATA_SIZE = 1024 * 1024; - -CCrySimpleCache& CCrySimpleCache::Instance() -{ - static CCrySimpleCache g_Cache; - return g_Cache; -} - -void CCrySimpleCache::Init() -{ - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_CachingEnabled = false; - m_Hit = 0; - m_Miss = 0; -} - -std::string CCrySimpleCache::CreateFileName(const tdHash& rHash) const -{ - AZStd::string Name; - Name = CSTLHelper::Hash2String(rHash).c_str(); - char Tmp[4] = "012"; - Tmp[0] = Name.c_str()[0]; - Tmp[1] = Name.c_str()[1]; - Tmp[2] = Name.c_str()[2]; - - AZ::IO::Path resultFileName = SEnviropment::Instance().m_CachePath / Tmp / Name; - return std::string{ resultFileName.c_str(), resultFileName.Native().size() }; -} - - -bool CCrySimpleCache::Find(const tdHash& rHash, tdDataVector& rData) -{ - if (!m_CachingEnabled) - { - return false; - } - - CCrySimpleMutexAutoLock Lock(m_Mutex); - tdEntries::iterator it = m_Entries.find(rHash); - if (it != m_Entries.end()) - { - tdData::iterator dataIt = m_Data.find(it->second); - if (dataIt == m_Data.end()) - { - m_Miss++; - return false; - } - m_Hit++; - rData = dataIt->second; - return true; - } - m_Miss++; - return false; -} - -void CCrySimpleCache::Add(const tdHash& rHash, const tdDataVector& rData) -{ - if (!m_CachingEnabled) - { - return; - } - if (rData.size() > 0) - { - SFileEntryHeader hdr; - memcpy(hdr.signature, "SHDR", 4); - hdr.dataSize = (uint32_t)rData.size(); - hdr.flags = EFEHF_NONE; - memcpy(hdr.hash, &rHash, sizeof(hdr.hash)); - const uint8_t* pData = &rData[0]; - - tdHash DataHash = CSTLHelper::Hash(rData); - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_Entries[rHash] = DataHash; - if (m_Data.find(DataHash) == m_Data.end()) - { - m_Data[DataHash] = rData; - } - else - { - hdr.flags |= EFEHF_REFERENCE; - hdr.dataSize = sizeof(tdHash); - pData = reinterpret_cast(&DataHash); - } - } - - - - tdDataVector buf; - buf.resize(sizeof(hdr) + hdr.dataSize); - memcpy(&buf[0], &hdr, sizeof(hdr)); - memcpy(&buf[sizeof(hdr)], pData, hdr.dataSize); - - tdDataVector* pPendingCacheEntry = new tdDataVector(buf); - { - CCrySimpleMutexAutoLock LockFile(m_FileMutex); - m_PendingCacheEntries.push_back(pPendingCacheEntry); - if (m_PendingCacheEntries.size() > 10000) - { - printf("Warning: Too many pending entries not saved to disk!!!"); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -bool CCrySimpleCache::LoadCacheFile(const std::string& filename) -{ - AZ::u64 startTimeInMillis = AZStd::GetTimeUTCMilliSecond(); - - printf("Loading shader cache from %s\n", filename.c_str()); - - tdDataVector rData; - - tdHash hash; - - bool bLoadedOK = true; - - uint32_t Loaded = 0; - uint32_t num = 0; - - uint64_t nFilePos = 0; - - ////////////////////////////////////////////////////////////////////////// - AZ::IO::SystemFile cacheFile; - const bool wasSuccessful = cacheFile.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - if (!wasSuccessful) - { - return false; - } - - AZ::IO::SystemFile::SizeType fileSize = cacheFile.Length(); - - uint64_t SizeAdded = 0; - uint64_t SizeAddedCount = 0; - uint64_t SizeSaved = 0; - uint64_t SizeSavedCount = 0; - - while (nFilePos < fileSize) - { - SFileEntryHeader hdr; - AZ::IO::SystemFile::SizeType bytesReadIn = cacheFile.Read(sizeof(hdr), &hdr); - if (bytesReadIn != sizeof(hdr)) - { - break; - } - - if (memcmp(hdr.signature, "SHDR", 4) != 0) - { - // Bad Entry! - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu because signature is bad", num, nFilePos); - break; - } - - if (hdr.dataSize > MAX_DATA_SIZE || hdr.dataSize == 0) - { - // Too big entry, probably invalid. - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu because data size is too big", num, nFilePos); - break; - } - - rData.resize(hdr.dataSize); - bytesReadIn = cacheFile.Read(hdr.dataSize, rData.data()); - if (bytesReadIn != hdr.dataSize) - { - break; - } - memcpy(&hash, hdr.hash, sizeof(hdr.hash)); - - if (hdr.flags & EFEHF_REFERENCE) - { - if (hdr.dataSize != sizeof(tdHash)) - { - // Too big entry, probably invalid. - bLoadedOK = false; - printf("\nSkipping Invalid cache entry %d\n at file position: %llu, was flagged as cache reference but size was %d", num, nFilePos, hdr.dataSize); - break; - } - - bool bSkip = false; - - tdHash DataHash = *reinterpret_cast(&rData[0]); - tdData::iterator it = m_Data.find(DataHash); - if (it == m_Data.end()) - { - // Too big entry, probably invalid. - bSkip = true; // don't abort reading whole file just yet - skip only this entry - printf("\nSkipping Invalid cache entry %d\n at file position: %llu, data-hash references to not existing data ", num, nFilePos); - } - - if (!bSkip) - { - m_Entries[hash] = DataHash; - SizeSaved += it->second.size(); - SizeSavedCount++; - } - } - else - { - tdHash DataHash = CSTLHelper::Hash(rData); - m_Entries[hash] = DataHash; - if (m_Data.find(DataHash) == m_Data.end()) - { - SizeAdded += rData.size(); - m_Data[DataHash] = rData; - SizeAddedCount++; - } - else - { - SizeSaved += rData.size(); - SizeSavedCount++; - } - } - - if (num % 1000 == 0) - { - AZ::u64 endTimeInMillis = AZStd::GetTimeUTCMilliSecond(); - - Loaded = static_cast(nFilePos * 100 / fileSize); - printf("\rLoad:%3u%% %6uk t=%llus Compress: (Count)%llu%% %lluk:%lluk (MB)%llu%% %lluMB:%lluMB", Loaded, num / 1000u, (endTimeInMillis - startTimeInMillis), - SizeAddedCount / AZStd::GetMax((SizeAddedCount + SizeSavedCount) / 100ull, 1ull), - SizeAddedCount / 1000, SizeSavedCount / 1000, - SizeAdded / AZStd::GetMax((SizeAdded + SizeSaved) / 100ull, 1ull), - SizeAdded / (MAX_DATA_SIZE), SizeSaved / (MAX_DATA_SIZE)); - } - - num++; - nFilePos += hdr.dataSize + sizeof(SFileEntryHeader); - } - - printf("\n%d shaders loaded from cache\n", num); - - return bLoadedOK; -} - -void CCrySimpleCache::Finalize() -{ - m_CachingEnabled = true; - printf("\n caching enabled\n"); -} - -////////////////////////////////////////////////////////////////////////// -void CCrySimpleCache::ThreadFunc_SavePendingCacheEntries() -{ - // Check pending entries and save them to disk. - bool bListEmpty = false; - do - { - tdDataVector* pPendingCacheEntry = 0; - - { - CCrySimpleMutexAutoLock LockFile(m_FileMutex); - if (!m_PendingCacheEntries.empty()) - { - pPendingCacheEntry = m_PendingCacheEntries.front(); - m_PendingCacheEntries.pop_front(); - } - //CSTLHelper::AppendToFile( SEnviropment::Instance().m_CachePath+"Cache.dat",buf ); - bListEmpty = m_PendingCacheEntries.empty(); - } - - if (pPendingCacheEntry) - { - AZ::IO::Path cacheDatPath = SEnviropment::Instance().m_CachePath / "Cache.dat"; - CSTLHelper::AppendToFile(std::string{ cacheDatPath.c_str(), cacheDatPath.Native().size() }, *pPendingCacheEntry); - delete pPendingCacheEntry; - } - } while (!bListEmpty); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp deleted file mode 100644 index 5f8feab64c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleCache.hpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLECACHE__ -#define __CRYSIMPLECACHE__ - -#include "CrySimpleMutex.hpp" - -#include - -#include -#include -#include - -/*class CCrySimpleCacheEntry -{ - tdCache -public: -protected: -private: -};*/ - -typedef std::map tdEntries; -typedef std::map tdData; - -class CCrySimpleCache -{ - volatile bool m_CachingEnabled; - int m_Hit; - int m_Miss; - tdEntries m_Entries; - tdData m_Data; - CCrySimpleMutex m_Mutex; - CCrySimpleMutex m_FileMutex; - - std::list m_PendingCacheEntries; - std::string CreateFileName(const tdHash& rHash) const; - -public: - void Init(); - bool Find(const tdHash& rHash, tdDataVector& rData); - void Add(const tdHash& rHash, const tdDataVector& rData); - - bool LoadCacheFile(const std::string& filename); - void Finalize(); - - void ThreadFunc_SavePendingCacheEntries(); - - static CCrySimpleCache& Instance(); - - - std::list& PendingCacheEntries(){return m_PendingCacheEntries; } - int Hit() const{return m_Hit; } - int Miss() const{return m_Miss; } - int EntryCount() const{return static_cast(m_Entries.size()); } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp deleted file mode 100644 index 6fe019da53..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleErrorLog.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleJob.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#ifdef _MSC_VER -#include -#include -#endif -#ifdef UNIX -#include -#endif - -static unsigned int volatile g_bSendingMail = false; -static unsigned int volatile g_nMailNum = 0; - -CCrySimpleErrorLog& CCrySimpleErrorLog::Instance() -{ - static CCrySimpleErrorLog g_Cache; - return g_Cache; -} - -CCrySimpleErrorLog::CCrySimpleErrorLog() -{ - m_lastErrorTime = 0; -} - -void CCrySimpleErrorLog::Init() -{ -} - -bool CCrySimpleErrorLog::Add(ICryError* err) -{ - CCrySimpleMutexAutoLock Lock(m_LogMutex); - - if (m_Log.size() > 150) - { - // too many, just throw this error away - return false; // no ownership of this error - } - - m_Log.push_back(err); - - m_lastErrorTime = AZStd::GetTimeUTCMilliSecond(); - - return true; // take ownership of this error -} - -inline bool CmpError(ICryError* a, ICryError* b) -{ - return a->Compare(b); -} - -void CCrySimpleErrorLog::SendMail() -{ - CSMTPMailer::tstrcol Rcpt; - - std::string mailBody; - - tdEntryVec RcptVec; - CSTLHelper::Tokenize(RcptVec, SEnviropment::Instance().m_FailEMail, ";"); - - for (size_t i = 0; i < RcptVec.size(); i++) - { - Rcpt.insert(RcptVec[i]); - } - - tdErrorList tempLog; - { - CCrySimpleMutexAutoLock Lock(m_LogMutex); - m_Log.swap(tempLog); - } -#if defined(_MSC_VER) - { - char compName[256]; - DWORD size = ARRAYSIZE(compName); - - typedef BOOL (WINAPI * FP_GetComputerNameExA)(COMPUTER_NAME_FORMAT, LPSTR, LPDWORD); - FP_GetComputerNameExA pGetComputerNameExA = (FP_GetComputerNameExA) GetProcAddress(LoadLibrary("kernel32.dll"), "GetComputerNameExA"); - - if (pGetComputerNameExA) - { - pGetComputerNameExA(ComputerNamePhysicalDnsFullyQualified, compName, &size); - } - else - { - GetComputerName(compName, &size); - } - - mailBody += std::string("Report sent from ") + compName + "...\n\n"; - } -#endif - { - bool dedupe = SEnviropment::Instance().m_DedupeErrors; - - std::vector errors; - - if (!dedupe) - { - for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it) - { - errors.push_back(*it); - } - } - else - { - std::map uniqErrors; - for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it) - { - ICryError* err = *it; - - tdHash hash = err->Hash(); - - std::map::iterator uniq = uniqErrors.find(hash); - if (uniq != uniqErrors.end()) - { - uniq->second->AddDuplicate(err); - delete err; - } - else - { - uniqErrors[hash] = err; - } - } - - for (std::map::iterator it = uniqErrors.begin(); it != uniqErrors.end(); ++it) - { - errors.push_back(it->second); - } - } - - std::string body = mailBody; - CSMTPMailer::tstrcol cc; - CSMTPMailer::tattachlist Attachment; - - std::sort(errors.begin(), errors.end(), CmpError); - - int a = 0; - for (uint32_t i = 0; i < errors.size(); i++) - { - ICryError* err = errors[i]; - - err->SetUniqueID(a + 1); - - // doesn't have to be related to any job/error, - // we just use it to differentiate "1-IlluminationPS.txt" from "1-IlluminationPS.txt" - long req = CCrySimpleJob::GlobalRequestNumber(); - - if (err->HasFile()) - { - char Filename[1024]; - azsprintf(Filename, "%d-req%ld-%s", a + 1, req, err->GetFilename().c_str()); - - char DispFilename[1024]; - azsprintf(DispFilename, "%d-%s", a + 1, err->GetFilename().c_str()); - - std::string sErrorFile = (SEnviropment::Instance().m_ErrorPath / Filename).c_str(); - - std::vector bytes; - std::string text = err->GetFileContents(); - bytes.resize(text.size() + 1); - std::copy(text.begin(), text.end(), bytes.begin()); - while (bytes.size() && bytes[bytes.size() - 1] == 0) - { - bytes.pop_back(); - } - - CrySimple_SECURE_START - - CSTLHelper::ToFile(sErrorFile, bytes); - - Attachment.push_back(CSMTPMailer::tattachment(DispFilename, sErrorFile)); - - CrySimple_SECURE_END - } - - body += std::string("=============================================================\n"); - body += err->GetErrorDetails(ICryError::OUTPUT_EMAIL) + "\n"; - - err->AddCCs(cc); - a++; - - if (i == errors.size() - 1 || !err->CanMerge(errors[i + 1])) - { - CSMTPMailer::tstrcol bcc; - - CSMTPMailer mail("", "", SEnviropment::Instance().m_MailServer); - mail.Send(SEnviropment::Instance().m_FailEMail, Rcpt, cc, bcc, err->GetErrorName(), body, Attachment); - - a = 0; - body = mailBody; - cc.clear(); - - for (CSMTPMailer::tattachlist::iterator attach = Attachment.begin(); attach != Attachment.end(); ++attach) - { - AZ::IO::SystemFile::Delete(attach->second.c_str()); - } - - Attachment.clear(); - } - - delete err; - } - } - - g_bSendingMail = false; -} - -////////////////////////////////////////////////////////////////////////// -void CCrySimpleErrorLog::Tick() -{ - if (SEnviropment::Instance().m_MailInterval == 0) - { - return; - } - - AZ::u64 lastError = 0; - bool forceFlush = false; - - { - CCrySimpleMutexAutoLock Lock(m_LogMutex); - - if (m_Log.size() == 0) - { - return; - } - - // log has gotten pretty big, force a flush to avoid losing any errors - if (m_Log.size() > 100) - { - forceFlush = true; - } - - lastError = m_lastErrorTime; - } - - AZ::u64 t = AZStd::GetTimeUTCMilliSecond(); - if (forceFlush || t < lastError || (t - lastError) > SEnviropment::Instance().m_MailInterval * 1000) - { - if (!g_bSendingMail) - { - g_bSendingMail = true; - g_nMailNum++; - logmessage("Sending Errors Mail %d\n", g_nMailNum); - CCrySimpleErrorLog::Instance().SendMail(); - } - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp deleted file mode 100644 index 96e417f143..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleErrorLog.hpp +++ /dev/null @@ -1,42 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEERRORLOG__ -#define __CRYSIMPLEERRORLOG__ - -#include "CrySimpleMutex.hpp" - -#include -#include - -class ICryError; -typedef std::list tdErrorList; - -class CCrySimpleErrorLog -{ - CCrySimpleMutex m_LogMutex; // protects both below variables - tdErrorList m_Log; // error log - AZ::u64 m_lastErrorTime; // last time an error came in (we mail out a little after we've stopped receiving errors) - - void Init(); - void SendMail(); - CCrySimpleErrorLog(); -public: - - bool Add(ICryError* err); - void Tick(); - - static CCrySimpleErrorLog& Instance(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp deleted file mode 100644 index 58bd88d57b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleFileGuard.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEFILEGUARD__ -#define __CRYSIMPLEFILEGUARD__ - -#include -#include - -class CCrySimpleFileGuard -{ - std::string m_FileName; -public: - CCrySimpleFileGuard(const std::string& rFileName) - : m_FileName(rFileName) - { - } - ~CCrySimpleFileGuard() - { - remove(m_FileName.c_str()); - } -}; -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp deleted file mode 100644 index 624bfd5b80..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleHTTP.hpp" -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleCache.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -////////////////////////////////////////////////////////////////////////// -class CHTTPRequest -{ - CCrySimpleSock* m_pSock; -public: - CHTTPRequest(CCrySimpleSock* pSock) - : m_pSock(pSock){} - - ~CHTTPRequest(){delete m_pSock; } - - CCrySimpleSock* Socket(){return m_pSock; } -}; - -#define HTML_HEADER "HTTP/1.1 200 OK\n\ -Server: Shader compile server %s\n\ -Content-Length: %zu\n\ -Content-Language: de (nach RFC 3282 sowie RFC 1766)\n\ -Content-Type: text/html\n\ -Connection: close\n\ -\n\ -shader compile server %s" - -#define TABLE_START "\n\ -\n\ -\n" -#define TABLE_INFO "\n\ -\n" -#define TABLE_BAR "\n\ -\n" -#define TABLE_END "
DescriptionValueMax %
%s %s \n\ -
%s %d%d \n\ -\n\ -\n\ -
%d%%
" - -std::string CreateBar(const std::string& rName, int Value, int Max, int Percentage) -{ - AZStd::string formattedString = AZStd::string::format(TABLE_BAR, rName.c_str(), Value, Max, Percentage, Percentage); - return formattedString.c_str(); -} - -std::string CreateInfoText(const std::string& rName, const std::string& rValue) -{ - AZStd::string formattedString = AZStd::string::format(TABLE_INFO, rName.c_str(), rValue.c_str()); - return formattedString.c_str(); -} - -std::string CreateInfoText(const std::string& rName, int Value) -{ - char Text[64]; - azsprintf(Text, "%d", Value); - return CreateInfoText(rName, Text); -} - -class HttpProcessRequestJob - : public AZ::Job -{ -public: - HttpProcessRequestJob(CHTTPRequest* request) - : AZ::Job(true, nullptr) - , m_request(request) { } - -protected: - void Process() override - { -#if defined(AZ_PLATFORM_WINDOWS) - FILETIME IdleTime0, IdleTime1; - FILETIME KernelTime0, KernelTime1; - FILETIME UserTime0, UserTime1; - - int Ret0 = GetSystemTimes(&IdleTime0, &KernelTime0, &UserTime0); - Sleep(100); - int Ret1 = GetSystemTimes(&IdleTime1, &KernelTime1, &UserTime1); - const int Idle = IdleTime1.dwLowDateTime - IdleTime0.dwLowDateTime; - const int Kernel = KernelTime1.dwLowDateTime - KernelTime0.dwLowDateTime; - const int User = UserTime1.dwLowDateTime - UserTime0.dwLowDateTime; - //const int Idle = IdleTime1.dwHighDateTime-IdleTime0.dwHighDateTime; - //const int Kernel = KernelTime1.dwHighDateTime-KernelTime0.dwHighDateTime; - //const int User = UserTime1.dwHighDateTime-UserTime0.dwHighDateTime; - const int Total = Kernel + User; -#else - int Ret0 = 0; - int Ret1 = 0; - int Total = 0; - int Idle = 0; -#endif - - std::string Ret = TABLE_START; - - Ret += CreateInfoText("Load:", ""); - if (Ret0 && Ret1 && Total) - { - Ret += CreateBar("CPU-Usage", Total - Idle, Total, 100 - Idle * 100 / Total); - } - - Ret += CreateBar("CompileTasks", CCrySimpleJobCompile::GlobalCompileTasks(), - CCrySimpleJobCompile::GlobalCompileTasksMax(), - CCrySimpleJobCompile::GlobalCompileTasksMax() ? - CCrySimpleJobCompile::GlobalCompileTasks() * 100 / - CCrySimpleJobCompile::GlobalCompileTasksMax() : 0); - - - Ret += CreateInfoText("Setup:", ""); - Ret += CreateInfoText("Root", SEnviropment::Instance().m_Root.c_str()); - Ret += CreateInfoText("CompilerPath", SEnviropment::Instance().m_CompilerPath.c_str()); - Ret += CreateInfoText("CachePath", SEnviropment::Instance().m_CachePath.c_str()); - Ret += CreateInfoText("TempPath", SEnviropment::Instance().m_TempPath.c_str()); - Ret += CreateInfoText("ErrorPath", SEnviropment::Instance().m_ErrorPath.c_str()); - Ret += CreateInfoText("ShaderPath", SEnviropment::Instance().m_ShaderPath.c_str()); - Ret += CreateInfoText("FailEMail", SEnviropment::Instance().m_FailEMail); - Ret += CreateInfoText("MailServer", SEnviropment::Instance().m_MailServer); - Ret += CreateInfoText("port", SEnviropment::Instance().m_port); - Ret += CreateInfoText("MailInterval", SEnviropment::Instance().m_MailInterval); - Ret += CreateInfoText("Caching", SEnviropment::Instance().m_Caching ? "Enabled" : "Disabled"); - Ret += CreateInfoText("FallbackServer", SEnviropment::Instance().m_FallbackServer == "" ? "None" : SEnviropment::Instance().m_FallbackServer); - Ret += CreateInfoText("FallbackTreshold", static_cast(SEnviropment::Instance().m_FallbackTreshold)); - Ret += CreateInfoText("DumpShaders", static_cast(SEnviropment::Instance().m_DumpShaders)); - - Ret += CreateInfoText("Cache:", ""); - Ret += CreateInfoText("Entries", CCrySimpleCache::Instance().EntryCount()); - Ret += CreateBar("Hits", CCrySimpleCache::Instance().Hit(), - CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss(), - CCrySimpleCache::Instance().Hit() * 100 / AZStd::GetMax(1, (CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss()))); - Ret += CreateInfoText("Pending Entries", static_cast(CCrySimpleCache::Instance().PendingCacheEntries().size())); - - - - Ret += TABLE_END; - - Ret += ""; - char Text[sizeof(HTML_HEADER) + 1024]; - azsprintf(Text, HTML_HEADER, __DATE__, Ret.size(), __DATE__); - Ret = std::string(Text) + Ret; - m_request->Socket()->Send(Ret); - } - -private: - std::unique_ptr m_request; -}; - -class HttpServerJob - : public AZ::Job -{ -public: - HttpServerJob(CCrySimpleHTTP* simpleHttp) - : AZ::Job(true, nullptr) - , m_simpleHttp(simpleHttp) { } - -protected: - void Process() - { - m_simpleHttp->Run(); - } -private: - CCrySimpleHTTP* m_simpleHttp; -}; - -////////////////////////////////////////////////////////////////////////// -CCrySimpleHTTP::CCrySimpleHTTP() - : m_pServerSocket(0) -{ - CrySimple_SECURE_START - - Init(); - - CrySimple_SECURE_END -} - -void CCrySimpleHTTP::Init() -{ - m_pServerSocket = new CCrySimpleSock(61480, SEnviropment::Instance().m_WhitelistAddresses); //http - m_pServerSocket->Listen(); - HttpServerJob* serverJob = new HttpServerJob(this); - serverJob->Start(); -} - -void CCrySimpleHTTP::Run() -{ - while (1) - { - // New client message, receive new client socket connection. - CCrySimpleSock* newClientSocket = m_pServerSocket->Accept(); - if(!newClientSocket) - { - continue; - } - - // HTTP Request Data for new job - CHTTPRequest* pData = new CHTTPRequest(newClientSocket); - - HttpProcessRequestJob* requestJob = new HttpProcessRequestJob(pData); - requestJob->Start(); - } -} - - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp deleted file mode 100644 index e78d6ef41d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleHTTP.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CrySimpleHTTP__ -#define __CrySimpleHTTP__ - -#include -#include -#include - -extern bool g_Success; - -class CCrySimpleSock; - -class CCrySimpleHTTP -{ - static AZStd::atomic_long ms_ExceptionCount; - CCrySimpleSock* m_pServerSocket; - void Init(); -public: - CCrySimpleHTTP(); - - void Run(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp deleted file mode 100644 index 1e7423dc69..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJob.hpp" -#include "CrySimpleFileGuard.hpp" -#include "CrySimpleServer.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -AZStd::atomic_long CCrySimpleJob::m_GlobalRequestNumber = {0}; - -CCrySimpleJob::CCrySimpleJob(uint32_t requestIP) - : m_State(ECSJS_NONE) - , m_RequestIP(requestIP) -{ - ++m_GlobalRequestNumber; -} - -CCrySimpleJob::~CCrySimpleJob() -{ -} - - -bool CCrySimpleJob::ExecuteCommand(const std::string& rCmd, std::string& outError) -{ - const bool showStdOuput = false; // For Debug: Set to true if you want the compiler's standard ouput printed out as well. - const bool showStdErrorOuput = SEnviropment::Instance().m_PrintWarnings; - -#ifdef _MSC_VER - bool Ret = false; - DWORD ExitCode = 0; - - STARTUPINFO StartupInfo; - PROCESS_INFORMATION ProcessInfo; - memset(&StartupInfo, 0, sizeof(StartupInfo)); - memset(&ProcessInfo, 0, sizeof(ProcessInfo)); - StartupInfo.cb = sizeof(StartupInfo); - - - std::string Path = ""; - std::string::size_type Pt = rCmd.find_first_of(' '); - if (Pt != std::string::npos) - { - std::string First = std::string(rCmd.c_str(), Pt); - std::string::size_type Pt2 = First.find_last_of('/'); - if (Pt2 != std::string::npos) - { - Path = std::string(First.c_str(), Pt2); - } - else - { - Pt = std::string::npos; - } - } - - HANDLE hReadErr, hWriteErr; - - { - CreatePipe(&hReadErr, &hWriteErr, NULL, 0); - SetHandleInformation(hWriteErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - - StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - StartupInfo.hStdOutput = (showStdOuput) ? GetStdHandle(STD_OUTPUT_HANDLE) : NULL; - StartupInfo.hStdError = hWriteErr; - StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - - BOOL processCreated = CreateProcess(NULL, (char*)rCmd.c_str(), 0, 0, TRUE, CREATE_DEFAULT_ERROR_MODE, 0, Pt != std::string::npos ? Path.c_str() : 0, &StartupInfo, &ProcessInfo) != false; - - if (!processCreated) - { - outError = "Couldn't create process - missing compiler for cmd?: '" + rCmd + "'"; - } - else - { - std::string error; - - DWORD waitResult = 0; - HANDLE waitHandles[] = { ProcessInfo.hProcess, hReadErr }; - while (true) - { - //waitResult = WaitForMultipleObjects(sizeof(waitHandles) / sizeof(waitHandles[0]), waitHandles, FALSE, 1000 ); - waitResult = WaitForSingleObject(ProcessInfo.hProcess, 1000); - if (waitResult == WAIT_FAILED) - { - break; - } - - DWORD bytesRead, bytesAvailable; - while (PeekNamedPipe(hReadErr, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable) - { - char buff[4096]; - ReadFile(hReadErr, buff, sizeof(buff) - 1, &bytesRead, 0); - buff[bytesRead] = '\0'; - error += buff; - } - CSTLHelper::Trim(error," \t\r\n"); - - //if (waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT) - //break; - - if (waitResult == WAIT_OBJECT_0) - { - break; - } - } - - //if (waitResult != WAIT_TIMEOUT) - { - GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode); - if (ExitCode) - { - Ret = false; - outError = error; - } - else - { - if (showStdErrorOuput && !error.empty()) - { - AZ_Printf(0, "\n%s\n", error.c_str()); - } - Ret = true; - } - } - /* - else - { - Ret = false; - outError = std::string("Timed out executing compiler: ") + rCmd; - TerminateProcess(ProcessInfo.hProcess, 1); - } - */ - - CloseHandle(ProcessInfo.hProcess); - CloseHandle(ProcessInfo.hThread); - } - - CloseHandle(hReadErr); - if (hWriteErr) - { - CloseHandle(hWriteErr); - } - } - - return Ret; -#endif - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - std::thread::id threadId = std::this_thread::get_id(); - std::stringstream threadIdStream; - threadIdStream << threadId; - - // Multiple threads could execute a command, therefore the temporary file has to be unique per thread. - AZ::IO::Path errorTempFilePath = SEnviropment::Instance().m_TempPath / AZStd::string::format("stderr_%s.log", threadIdStream.str().c_str()); - std::string stdErrorTempFilename{ errorTempFilePath.c_str(), errorTempFilePath.Native().size() }; - - CCrySimpleFileGuard FGTmpOutput(stdErrorTempFilename); // Delete file at the end of this function - - std::string systemCmd = rCmd; - if(!showStdOuput) - { - // Standard output redirected to null to disable it - systemCmd += " > /dev/null"; - } - // Standard error ouput redirected to the temporary file - systemCmd += " 2> \"" + stdErrorTempFilename + "\""; - - int ret = system(systemCmd.c_str()); - - // Obtain standard error output - std::ifstream fileStream(stdErrorTempFilename.c_str()); - std::stringstream stdErrorStream; - stdErrorStream << fileStream.rdbuf(); - std::string stdErrorString = stdErrorStream.str(); - CSTLHelper::Trim(stdErrorString," \t\r\n"); - - if (ret != 0) - { - outError = stdErrorString; - return false; - } - else - { - if (showStdErrorOuput && !stdErrorString.empty()) - { - AZ_Printf(0, "\n%s\n", stdErrorString.c_str()); - } - return true; - } -#endif -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp deleted file mode 100644 index 839fdb1543..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJob.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOB__ -#define __CRYSIMPLEJOB__ - -#include -#include -#include -#include -#include - -class TiXmlElement; - -enum ECrySimpleJobState -{ - ECSJS_NONE, - ECSJS_DONE = 1, //this is checked on client side, don't change! - ECSJS_JOBNOTFOUND, - ECSJS_CACHEHIT, - ECSJS_ERROR, - ECSJS_ERROR_COMPILE = 5, //this is checked on client side, don't change! - ECSJS_ERROR_COMPRESS, - ECSJS_ERROR_FILEIO, - ECSJS_ERROR_INVALID_PROFILE, - ECSJS_ERROR_INVALID_PROJECT, - ECSJS_ERROR_INVALID_PLATFORM, - ECSJS_ERROR_INVALID_PROGRAM, - ECSJS_ERROR_INVALID_ENTRY, - ECSJS_ERROR_INVALID_COMPILEFLAGS, - ECSJS_ERROR_INVALID_COMPILER, - ECSJS_ERROR_INVALID_LANGUAGE, - ECSJS_ERROR_INVALID_SHADERREQUESTLINE, - ECSJS_ERROR_INVALID_SHADERLIST, -}; - -class CCrySimpleJob -{ - ECrySimpleJobState m_State; - uint32_t m_RequestIP; - static AZStd::atomic_long m_GlobalRequestNumber; - - -protected: - virtual bool ExecuteCommand(const std::string& rCmd, std::string& outError); -public: - CCrySimpleJob(uint32_t requestIP); - virtual ~CCrySimpleJob(); - - virtual bool Execute(const TiXmlElement* pElement) = 0; - - void State(ECrySimpleJobState S) - { - if (m_State < ECSJS_ERROR || S >= ECSJS_ERROR) - { - m_State = S; - } - } - ECrySimpleJobState State() const { return m_State; } - const uint32_t& RequestIP() const { return m_RequestIP; } - static long GlobalRequestNumber() { return m_GlobalRequestNumber; } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp deleted file mode 100644 index dd2bac8db2..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJobCache.hpp" -#include "CrySimpleCache.hpp" - -#include -#include -#include -#include -#include - -CCrySimpleJobCache::CCrySimpleJobCache(uint32_t requestIP) - : CCrySimpleJob(requestIP) -{ -} - -void CCrySimpleJobCache::CheckHashID(std::vector& rVec, size_t Size) -{ - m_HashID = CSTLHelper::Hash(rVec, Size); - if (CCrySimpleCache::Instance().Find(m_HashID, rVec)) - { - State(ECSJS_CACHEHIT); - logmessage("\r"); // Just update cache hit number - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp deleted file mode 100644 index 834a3c687a..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCache.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCACHE__ -#define __CRYSIMPLEJOBCACHE__ - -#include "CrySimpleJob.hpp" -#include - -class CCrySimpleJobCache - : public CCrySimpleJob -{ - tdHash m_HashID; - -protected: - - void CheckHashID(std::vector& rVec, size_t Size); - -public: - CCrySimpleJobCache(uint32_t requestIP); - - tdHash HashID() const{return m_HashID; } -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp deleted file mode 100644 index 5acc0bc2c8..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - - -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile.hpp" -#include "CrySimpleFileGuard.hpp" -#include "CrySimpleServer.hpp" -#include "CrySimpleCache.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#undef AZ_RESTRICTED_SECTION -#define CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 1 -#endif - -#define MAX_COMPILER_WAIT_TIME (60 * 1000) - -AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasks = {0}; -AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasksMax = {0}; -volatile int32_t CCrySimpleJobCompile::m_RemoteServerID = 0; -volatile int64_t CCrySimpleJobCompile::m_GlobalCompileTime = 0; - -struct STimer -{ - int64_t m_freq; - STimer() - { - QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq); - } - int64_t GetTime() const - { - int64_t t; - QueryPerformanceCounter((LARGE_INTEGER*)&t); - return t; - } - - double TimeToSeconds(int64_t t) - { - return ((double)t) / m_freq; - } -}; - - -STimer g_Timer; - -// This function validates executables up to version 21 -// because it's received within the compilation flags. -bool ValidateExecutableStringLegacy(const AZStd::string& executableString) -{ - AZStd::string::size_type endOfCommand = executableString.find(" "); - - // Game always sends some type of options after the command. If we don't - // have a space then that implies that there are no options. Reject the - // command as someone being malicious - if (endOfCommand == AZStd::string::npos) - { - return false; - } - - AZStd::string commandString = executableString.substr(0, endOfCommand); - - // The game never sends a parent directory in the compiler flags so lets - // reject any commands that have .. in it - if (commandString.find("..") != AZStd::string::npos) - { - return false; - } - - // Though the code later down would fail gracefully reject any absolute paths here - if (commandString.find("\\\\") != AZStd::string::npos || - commandString.find(":") != AZStd::string::npos) - { - return false; - } - - // Only allow a subset of executables to be accepted... - if (commandString.find("fxc.exe") == AZStd::string::npos && - commandString.find("FXC.exe") == AZStd::string::npos && - commandString.find("HLSLcc.exe") == AZStd::string::npos && - commandString.find("HLSLcc_dedicated.exe") == AZStd::string::npos && - commandString.find("DXProvoShaderCompiler.exe") == AZStd::string::npos && - commandString.find("dxcGL") == AZStd::string::npos && - commandString.find("dxcMetal") == AZStd::string::npos) - { - return false; - } - - return true; -} - -CCrySimpleJobCompile::CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector* pRVec) - : CCrySimpleJobCache(requestIP) - , m_Version(Version) - , m_pRVec(pRVec) -{ - ++m_GlobalCompileTasks; - if (m_GlobalCompileTasksMax < m_GlobalCompileTasks) - { - //Need this cast as the copy assignment operator is implicitly deleted - m_GlobalCompileTasksMax = static_cast(m_GlobalCompileTasks); - } -} - -CCrySimpleJobCompile::~CCrySimpleJobCompile() -{ - --m_GlobalCompileTasks; -} - -bool CCrySimpleJobCompile::Execute(const TiXmlElement* pElement) -{ - std::vector& rVec = *m_pRVec; - - size_t Size = SizeOf(rVec); - - CheckHashID(rVec, Size); - - if (State() == ECSJS_CACHEHIT) - { - State(ECSJS_DONE); - return true; - } - - if (!SEnviropment::Instance().m_FallbackServer.empty() && m_GlobalCompileTasks > SEnviropment::Instance().m_FallbackTreshold) - { - tdEntryVec ServerVec; - CSTLHelper::Tokenize(ServerVec, SEnviropment::Instance().m_FallbackServer, ";"); - uint32_t Idx = m_RemoteServerID++; - uint32_t Count = (uint32_t)ServerVec.size(); - std::string Server = ServerVec[Idx % Count]; - printf(" Remote Compile on %s ...\n", Server.c_str()); - CCrySimpleSock Sock(Server, SEnviropment::Instance().m_port); - if (Sock.Valid()) - { - Sock.Forward(rVec); - std::vector Tmp; - if (Sock.Backward(Tmp)) - { - rVec = Tmp; - if (Tmp.size() <= 4 || (m_Version == EPV_V002 && Tmp[4] != ECSJS_DONE)) - { - State(ECSJS_ERROR_COMPILE); - CrySimple_ERROR("failed to compile request"); - return false; - } - State(ECSJS_DONE); - //printf("done\n"); - } - else - { - printf("failed, fallback to local\n"); - } - } - else - { - printf("failed, fallback to local\n"); - } - } - if (State() == ECSJS_NONE) - { - if (!Compile(pElement, rVec) || rVec.size() == 0) - { - State(ECSJS_ERROR_COMPILE); - CrySimple_ERROR("failed to compile request"); - return false; - } - - tdDataVector rDataRaw; - rDataRaw.swap(rVec); - if (!CSTLHelper::Compress(rDataRaw, rVec)) - { - State(ECSJS_ERROR_COMPRESS); - CrySimple_ERROR("failed to compress request"); - return false; - } - State(ECSJS_DONE); - } - - // Cache compiled data - const char* pCaching = pElement->Attribute("Caching"); - if (State() != ECSJS_ERROR && (!pCaching || std::string(pCaching) == "1")) - { - CCrySimpleCache::Instance().Add(HashID(), rVec); - } - - return true; -} - -bool CCrySimpleJobCompile::Compile(const TiXmlElement* pElement, std::vector& rVec) -{ - AZStd::string platform; - AZStd::string compiler; - AZStd::string language; - AZStd::string shaderPath; - - if (m_Version >= EPV_V0023) - { - // NOTE: These attributes were alredy validated. - platform = pElement->Attribute("Platform"); - compiler = pElement->Attribute("Compiler"); - language = pElement->Attribute("Language"); - - shaderPath = AZStd::string::format("%s%s-%s-%s/", SEnviropment::Instance().m_ShaderPath.c_str(), platform.c_str(), compiler.c_str(), language.c_str()); - } - else - { - // In previous versions Platform attribute is the language - platform = "N/A"; - language = pElement->Attribute("Platform"); - - // Map shader language to shader compiler key - const AZStd::unordered_map languageToCompilerMap - { - { - "GL4", SEnviropment::m_GLSL_HLSLcc - },{ - "GLES3_0", SEnviropment::m_GLSL_HLSLcc - },{ - "GLES3_1", SEnviropment::m_GLSL_HLSLcc - },{ - "DX11", SEnviropment::m_D3D11_FXC - },{ - "METAL", SEnviropment::m_METAL_HLSLcc - },{ - "ORBIS", SEnviropment::m_Orbis_DXC - },{ - "JASPER", SEnviropment::m_Jasper_FXC - } - }; - - auto foundShaderLanguage = languageToCompilerMap.find(language); - if (foundShaderLanguage == languageToCompilerMap.end()) - { - State(ECSJS_ERROR_INVALID_LANGUAGE); - CrySimple_ERROR("Trying to compile with invalid shader language"); - return false; - } - - if (m_Version < EPV_V0022) - { - compiler = "N/A"; // Compiler exe will be specified inside 'compile flags', this variable won't be used - } - else - { - compiler = foundShaderLanguage->second; - - if (!SEnviropment::Instance().IsShaderCompilerValid(compiler)) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("Trying to compile with invalid shader compiler"); - return false; - } - } - - shaderPath = AZStd::string::format("%s%s/", SEnviropment::Instance().m_ShaderPath.c_str(), language.c_str()); - } - - shaderPath = AZ::IO::PathView(shaderPath).LexicallyNormal().Native(); - if (!IsPathValid(shaderPath)) - { - State(ECSJS_ERROR); - CrySimple_ERROR("Shaders output path is invalid"); - return false; - } - - // Create shaders directory - AZ::IO::SystemFile::CreateDir( shaderPath.c_str() ); - - const char* pProfile = pElement->Attribute("Profile"); - const char* pProgram = pElement->Attribute("Program"); - const char* pEntry = pElement->Attribute("Entry"); - const char* pCompileFlags = pElement->Attribute("CompileFlags"); - const char* pShaderRequestLine = pElement->Attribute("ShaderRequest"); - - if (!pProfile) - { - State(ECSJS_ERROR_INVALID_PROFILE); - CrySimple_ERROR("failed to extract Profile of the request"); - return false; - } - if (!pProgram) - { - State(ECSJS_ERROR_INVALID_PROGRAM); - CrySimple_ERROR("failed to extract Program of the request"); - return false; - } - if (!pEntry) - { - State(ECSJS_ERROR_INVALID_ENTRY); - CrySimple_ERROR("failed to extract Entry of the request"); - return false; - } - if (!pShaderRequestLine) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("failed to extract ShaderRequest of the request"); - return false; - } - if (!pCompileFlags) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("failed to extract CompileFlags of the request"); - return false; - } - - // Validate that the shader request line has a set of open/close parens as - // the code below this expects at least the open paren to be in the string. - // Without the open paren the code below will crash the compiler - std::string strippedShaderRequestLine(pShaderRequestLine); - const size_t locationOfOpenParen = strippedShaderRequestLine.find("("); - const size_t locationOfCloseParen = strippedShaderRequestLine.find(")"); - if (locationOfOpenParen == std::string::npos || - locationOfCloseParen == std::string::npos || locationOfCloseParen < locationOfOpenParen) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("invalid ShaderRequest attribute"); - return false; - } - - static AZStd::atomic_long nTmpCounter = { 0 }; - ++nTmpCounter; - - const auto tmpIndex = AZStd::string::format("%ld", static_cast(nTmpCounter)); - const AZ::IO::Path TmpIn = SEnviropment::Instance().m_TempPath / (tmpIndex + ".In"); - const AZ::IO::Path TmpOut = SEnviropment::Instance().m_TempPath / (tmpIndex + ".Out"); - CCrySimpleFileGuard FGTmpIn(TmpIn.c_str()); - CCrySimpleFileGuard FGTmpOut(TmpOut.c_str()); - CSTLHelper::ToFile(TmpIn.c_str(), std::vector(pProgram, &pProgram[strlen(pProgram)])); - - AZ::IO::Path compilerPath = SEnviropment::Instance().m_CompilerPath; - AZStd::string command; - if (m_Version >= EPV_V0022) - { - AZStd::string compilerExecutable; - bool validCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(compiler, compilerExecutable); - if (!validCompiler) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("Trying to compile with unknown compiler"); - return false; - } - - AZStd::string commandStringToFormat = (compilerPath / compilerExecutable).Native(); - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - // Surrounding compiler path+executable with quotes to support spaces in the path. - // NOTE: Executable has a space at the end on purpose, inserting quote before. - commandStringToFormat.insert(0, "\""); - commandStringToFormat.insert(commandStringToFormat.length()-1, "\""); -#endif - - commandStringToFormat.append(pCompileFlags); - - if (strstr(pCompileFlags, "-fxc") != nullptr) - { - AZStd::string fxcCompilerExecutable; - bool validFXCCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(SEnviropment::m_D3D11_FXC, fxcCompilerExecutable); - if (!validFXCCompiler) - { - State(ECSJS_ERROR_INVALID_COMPILER); - CrySimple_ERROR("FXC compiler executable cannot be found"); - return false; - } - - AZ::IO::Path fxcLocation = compilerPath / fxcCompilerExecutable; - - // Handle an extra string parameter to specify the base directory where the fxc compiler is located - command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), fxcLocation.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - else - { - command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - } - else - { - if (!ValidateExecutableStringLegacy(pCompileFlags)) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("CompileFlags failed validation"); - return false; - } - - if (strstr(pCompileFlags, "-fxc=\"%s") != nullptr) - { - // Check that the string after the %s is a valid shader compiler - // executable - AZStd::string tempString(pCompileFlags); - const AZStd::string::size_type fxcOffset = tempString.find("%s") + 2; - const AZStd::string::size_type endOfFxcString = tempString.find(" ", fxcOffset); - tempString = tempString.substr(fxcOffset, endOfFxcString); - if (!ValidateExecutableStringLegacy(tempString)) - { - State(ECSJS_ERROR_INVALID_COMPILEFLAGS); - CrySimple_ERROR("CompileFlags failed validation"); - return false; - } - - // Handle an extra string parameter to specify the base directory where the fxc compiler is located - command = AZStd::move(AZStd::string::format(pCompileFlags, compilerPath.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - - // Need to add the string for escaped quotes around the path to the compiler. This is in case the path has spaces. - // Adding just quotes (escaped) doesn't work because this cmd line is used to execute another process. - AZStd::string insertPattern = "\\\""; - - // Search for the next space until that path exists. Then we assume that's the path to the executable. - size_t startPos = command.find(compilerPath.Native()); - for (size_t pos = command.find(" ", startPos); pos != AZStd::string::npos; pos = command.find(" ", pos + 1)) - { - if (AZ::IO::SystemFile::Exists(command.substr(startPos, pos - startPos).c_str())) - { - command.insert(pos, insertPattern); - command.insert(startPos, insertPattern); - } - } - } - else - { - command = AZStd::move(AZStd::string::format(pCompileFlags, pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str())); - } - - command = compilerPath.Native() + command; - } - - AZStd::string hardwareTarget; - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) - #if defined(TOOLS_SUPPORT_JASPER) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, jasper) - #endif - #if defined(TOOLS_SUPPORT_PROVO) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, provo) - #endif - #if defined(TOOLS_SUPPORT_SALEM) - #define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, salem) - #endif -#endif - - int64_t t0 = g_Timer.GetTime(); - - std::string outError; - - std::string shaderName; - std::stringstream crcStringStream; - - - // Dump source shader - if (SEnviropment::Instance().m_DumpShaders) - { - unsigned long crc = crc32(0l, Z_NULL, 0); - // shader permutations start with '(' - size_t position = strippedShaderRequestLine.find('('); - // split the string into shader name - shaderName = strippedShaderRequestLine.substr(0, position); - // split the string into permutation - std::string permutation = strippedShaderRequestLine.substr(position, strippedShaderRequestLine.length() - position); - // replace illegal filename characters with valid ones - AZStd::replace(shaderName.begin(), shaderName.end(), '<', '('); - AZStd::replace(shaderName.begin(), shaderName.end(), '>', ')'); - AZStd::replace(shaderName.begin(), shaderName.end(), '/', '_'); - AZStd::replace(shaderName.begin(), shaderName.end(), '|', '+'); - AZStd::replace(shaderName.begin(), shaderName.end(), '*', '^'); - AZStd::replace(shaderName.begin(), shaderName.end(), ':', ';'); - AZStd::replace(shaderName.begin(), shaderName.end(), '?', '!'); - AZStd::replace(shaderName.begin(), shaderName.end(), '%', '$'); - - crc = crc32(crc, reinterpret_cast(permutation.c_str()), static_cast(permutation.length())); - crcStringStream << crc; - const std::string HlslDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".hlsl"; - CSTLHelper::ToFile(HlslDump, std::vector(pProgram, &pProgram[strlen(pProgram)])); - std::ofstream crcFile; - - std::string crcFileName = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".txt"; - - crcFile.open(crcFileName, std::ios_base::trunc); - - if (!crcFile.fail()) - { - // store permutation - crcFile << permutation; - } - else - { - std::cout << "Error opening file " + crcFileName << std::endl; - } - - crcFile.close(); - } - - if (SEnviropment::Instance().m_PrintCommands) - { - AZ_Printf(0, "Compiler Command:\n%s\n\n", command.c_str()); - } - - if (!ExecuteCommand(command.c_str(), outError)) - { - unsigned char* nIP = (unsigned char*) &RequestIP(); - char sIP[128]; - azsprintf(sIP, "%d.%d.%d.%d", nIP[0], nIP[1], nIP[2], nIP[3]); - - const char* pProject = pElement->Attribute("Project"); - const char* pTags = pElement->Attribute("Tags"); - const char* pEmailCCs = pElement->Attribute("EmailCCs"); - - std::string project = pProject ? pProject : "Unk/"; - std::string ccs = pEmailCCs ? pEmailCCs : ""; - std::string tags = pTags ? pTags : ""; - - std::string filteredError; - AZ::IO::Path patchFilePath = TmpIn; - patchFilePath.ReplaceFilename(AZ::IO::PathView{ AZStd::string{ TmpIn.Filename().Native() } + ".patched" }); - CSTLHelper::Replace(filteredError, outError, patchFilePath.c_str(), "%filename%"); // DXPS does its own patching - CSTLHelper::Replace(filteredError, filteredError, TmpIn.c_str(), "%filename%"); - // replace any that don't have the full path - CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In.patched").c_str(), "%filename%"); // DXPS does its own patching - CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In").c_str(), "%filename%"); - - CSTLHelper::Replace(filteredError, filteredError, "\r\n", "\n"); - - State(ECSJS_ERROR_COMPILE); - throw new CCompilerError(pEntry, filteredError, ccs, sIP, pShaderRequestLine, pProgram, project, platform.c_str(), compiler.c_str(), language.c_str(), tags, pProfile); - } - - if (!CSTLHelper::FromFile(TmpOut.c_str(), rVec)) - { - State(ECSJS_ERROR_FILEIO); - std::string errorString("Could not read: "); - errorString += std::string(TmpOut.c_str(), TmpOut.Native().size()); - CrySimple_ERROR(errorString.c_str()); - return false; - } - - // Dump cross-compiled shader - if (SEnviropment::Instance().m_DumpShaders) - { - AZStd::string fileExtension = language; - AZStd::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), tolower); - - std::string shaderDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + "." + fileExtension.c_str(); - CSTLHelper::ToFile(shaderDump, rVec); - } - - - int64_t t1 = g_Timer.GetTime(); - int64_t dt = t1 - t0; - m_GlobalCompileTime += dt; - - int millis = (int)(g_Timer.TimeToSeconds(dt) * 1000.0); - int secondsTotal = (int)g_Timer.TimeToSeconds(m_GlobalCompileTime); - logmessage("Compiled [%5dms|%8ds] (%s - %s - %s - %s) %s\n", millis, secondsTotal, platform.c_str(), compiler.c_str(), language.c_str(), pProfile, pEntry); - - if (hardwareTarget.empty()) - { - logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry); - } - else - { - logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry, hardwareTarget.c_str()); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -inline bool SortByLinenum(const std::pair& f1, const std::pair& f2) -{ - return f1.first < f2.first; -} - -CCompilerError::CCompilerError(const std::string& entry, const std::string& errortext, const std::string& ccs, const std::string& IP, - const std::string& requestLine, const std::string& program, const std::string& project, - const std::string& platform, const std::string& compiler, const std::string& language, const std::string& tags, const std::string& profile) - : ICryError(COMPILE_ERROR) - , m_entry(entry) - , m_errortext(errortext) - , m_IP(IP) - , m_program(program) - , m_project(project) - , m_platform(platform) - , m_compiler(compiler) - , m_language(language) - , m_tags(tags) - , m_profile(profile) - , m_uniqueID(0) -{ - m_requests.push_back(requestLine); - Init(); - - CSTLHelper::Tokenize(m_CCs, ccs, ";"); -} - -void CCompilerError::Init() -{ - while (!m_errortext.empty() && (m_errortext.back() == '\r' || m_errortext.back() == '\n')) - { - m_errortext.pop_back(); - } - - if (m_requests[0].size()) - { - m_shader = m_requests[0]; - size_t offs = m_shader.find('>'); - if (offs != std::string::npos) - { - m_shader.erase(0, m_shader.find('>') + 1); // remove <2> version - } - offs = m_shader.find('@'); - if (offs != std::string::npos) - { - m_shader.erase(m_shader.find('@')); // remove everything after @ - } - offs = m_shader.find('/'); - if (offs != std::string::npos) - { - m_shader.erase(m_shader.find('/')); // remove everything after / (used on xenon) - } - } - else - { - // default to entry function - m_shader = m_entry; - size_t len = m_shader.length(); - - // if it ends in ?S then trim those two characters - if (m_shader[len - 1] == 'S') - { - m_shader.pop_back(); - m_shader.pop_back(); - } - } - - std::vector lines; - CSTLHelper::Tokenize(lines, m_errortext, "\n"); - - for (uint32_t i = 0; i < lines.size(); i++) - { - std::string& line = lines[i]; - - if (line.substr(0, 5) == "error") - { - m_errors.push_back(std::pair(-1, line)); - m_hasherrors += line; - - continue; - } - - if (line.find(": error") == std::string::npos) - { - continue; - } - - if (line.substr(0, 10) != "%filename%") - { - continue; - } - - if (line[10] != '(') - { - continue; - } - - uint32_t c = 11; - - int linenum = 0; - { - bool ln = true; - while (c < line.length() && - ((line[c] >= '0' && line[c] <= '9') || line[c] == ',' || line[c] == '-') - ) - { - if (line[c] == ',') - { - ln = false; // reached column, don't save the value - just keep reading to the end - } - if (ln) - { - linenum *= 10; - linenum += line[c] - '0'; - } - c++; - } - - if (c >= line.length()) - { - continue; - } - - if (line[c] != ')') - { - continue; - } - - c++; - } - - while (c < line.length() && (line[c] == ' ' || line[c] == ':')) - { - c++; - } - - if (line.substr(c, 5) != "error") - { - continue; - } - - m_errors.push_back(std::pair(linenum, line)); - m_hasherrors += line.substr(c); - } - - AZStd::sort(m_errors.begin(), m_errors.end(), SortByLinenum); -} - -std::string CCompilerError::GetErrorLines() const -{ - std::string ret = ""; - - for (uint32_t i = 0; i < m_errors.size(); i++) - { - if (m_errors[i].first < 0) - { - ret += m_errors[i].second + "\n"; - } - else if (i > 0 && m_errors[i - 1].first < 0) - { - ret += "\n" + GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n"; - } - else if (i > 0 && m_errors[i - 1].first == m_errors[i].first) - { - ret.pop_back(); // pop extra newline - ret += m_errors[i].second + "\n\n"; - } - else - { - ret += GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n"; - } - } - - return ret; -} - -std::string CCompilerError::GetContext(int linenum, int context, std::string prefix) const -{ - std::vector lines; - CSTLHelper::Tokenize(lines, m_program, "\n"); - - std::string ret = ""; - - linenum--; // line numbers start at one - - char sLineNum[16]; - - for (uint32_t i = AZStd::GetMax(0U, (uint32_t)(linenum - context)); i <= AZStd::GetMin((uint32_t)lines.size() - 1U, (uint32_t)(linenum + context)); i++) - { - azsprintf(sLineNum, "% 3d", i + 1); - - ret += sLineNum; - ret += " "; - - if (prefix.size()) - { - if (i == linenum) - { - ret += "*"; - } - else - { - ret += " "; - } - - ret += prefix; - - ret += " "; - } - - ret += lines[i] + "\n"; - } - - return ret; -} - -void CCompilerError::AddDuplicate(ICryError* err) -{ - ICryError::AddDuplicate(err); - - if (err->GetType() == COMPILE_ERROR) - { - CCompilerError* comperr = (CCompilerError*)err; - m_requests.insert(m_requests.end(), comperr->m_requests.begin(), comperr->m_requests.end()); - } -} - -bool CCompilerError::Compare(const ICryError* err) const -{ - if (GetType() != err->GetType()) - { - return GetType() < err->GetType(); - } - - CCompilerError* e = (CCompilerError*)err; - - if (m_platform != e->m_platform) - { - return m_platform < e->m_platform; - } - - if (m_compiler != e->m_compiler) - { - return m_compiler < e->m_compiler; - } - - if (m_language != e->m_language) - { - return m_language < e->m_language; - } - - if (m_shader != e->m_shader) - { - return m_shader < e->m_shader; - } - - if (m_entry != e->m_entry) - { - return m_entry < e->m_entry; - } - - return Hash() < err->Hash(); -} - -bool CCompilerError::CanMerge(const ICryError* err) const -{ - if (GetType() != err->GetType()) // don't merge with non compile errors - { - return false; - } - - CCompilerError* e = (CCompilerError*)err; - - if (m_platform != e->m_platform || m_compiler != e->m_compiler || m_language != e->m_language || m_shader != e->m_shader) - { - return false; - } - - if (m_CCs.size() != e->m_CCs.size()) - { - return false; - } - - for (size_t a = 0, S = m_CCs.size(); a < S; a++) - { - if (m_CCs[a] != e->m_CCs[a]) - { - return false; - } - } - - return true; -} - -void CCompilerError::AddCCs(std::set& ccs) const -{ - for (size_t a = 0, S = m_CCs.size(); a < S; a++) - { - ccs.insert(m_CCs[a]); - } -} - -std::string CCompilerError::GetErrorName() const -{ - return std::string("[") + m_tags + "] Shader Compile Errors in " + m_shader + " on " + m_language + " for " + m_platform + " " + m_compiler; -} - -std::string CCompilerError::GetErrorDetails(EOutputFormatType outputType) const -{ - std::string errorString(""); - - char sUniqueID[16], sNumDuplicates[16]; - azsprintf(sUniqueID, "%d", m_uniqueID); - azsprintf(sNumDuplicates, "%d", NumDuplicates()); - - std::string errorOutput; - CSTLHelper::Replace(errorOutput, GetErrorLines(), "%filename%", std::string(sUniqueID) + "-" + GetFilename()); - - std::string fullOutput; - CSTLHelper::Replace(fullOutput, m_errortext, "%filename%", std::string(sUniqueID) + "-" + GetFilename()); - - if (outputType == OUTPUT_HASH) - { - errorString = GetFilename() + m_IP + m_platform + m_compiler + m_language + m_project + m_entry + m_tags + m_profile + m_hasherrors /*+ m_requestline*/; - } - else if (outputType == OUTPUT_EMAIL) - { - errorString = std::string("=== Shader compile error in ") + m_entry + " (" + sNumDuplicates + " duplicates)\n\n"; - - ///// - errorString += std::string("* From: ") + m_IP + " on " + m_language + " for " + m_platform + " " + m_compiler + " " + m_project; - if (m_tags != "") - { - errorString += std::string(" (Tags: ") + m_tags + ")"; - } - errorString += "\n"; - - ///// - errorString += std::string("* Target profile: ") + m_profile + "\n"; - - ///// - bool hasrequests = false; - for (uint32_t i = 0; i < m_requests.size(); i++) - { - if (m_requests[i].size()) - { - errorString += std::string("* Shader request line: ") + m_requests[i] + "\n"; - hasrequests = true; - } - } - - errorString += "\n"; - - if (hasrequests) - { - errorString += "* Shader source from first listed request\n"; - } - - errorString += std::string("* Reported error(s) from ") + sUniqueID + "-" + GetFilename() + "\n\n"; - errorString += errorOutput + "\n\n"; - - errorString += std::string("* Full compiler output:\n\n"); - errorString += fullOutput + "\n"; - } - else if (outputType == OUTPUT_TTY) - { - errorString = std::string("=== Shader compile error in ") + m_entry + " { " + m_requests[0] + " }\n"; - // errors only - errorString += std::string("* Reported error(s):\n\n"); - errorString += errorOutput; - errorString += m_errortext; - } - - return errorString; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp deleted file mode 100644 index 7f097cbd7c..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE__ -#define __CRYSIMPLEJOBCOMPILE__ - -#include "CrySimpleJobCache.hpp" -#include -#include - - -class CCrySimpleJobCompile - : public CCrySimpleJobCache -{ -public: - CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector* pRVec); - virtual ~CCrySimpleJobCompile(); - - virtual bool Execute(const TiXmlElement* pElement); - - static long GlobalCompileTasks(){return m_GlobalCompileTasks; } - static long GlobalCompileTasksMax(){return m_GlobalCompileTasksMax; } - -private: - static AZStd::atomic_long m_GlobalCompileTasks; - static AZStd::atomic_long m_GlobalCompileTasksMax; - static volatile int32_t m_RemoteServerID; - static volatile int64_t m_GlobalCompileTime; - - EProtocolVersion m_Version; - std::vector* m_pRVec; - - virtual size_t SizeOf(std::vector& rVec) = 0; - - bool Compile(const TiXmlElement* pElement, std::vector& rVec); -}; - -class CCompilerError - : public ICryError -{ -public: - CCompilerError(const std::string& entry, const std::string& errortext, const std::string& ccs, const std::string& IP, - const std::string& requestLine, const std::string& program, const std::string& project, - const std::string& platform, const std::string& compiler, const std::string& language, const std::string& tags, const std::string& profile); - - virtual ~CCompilerError() {} - - virtual void AddDuplicate(ICryError* err); - - virtual void SetUniqueID(int uniqueID) { m_uniqueID = uniqueID; } - - virtual bool Compare(const ICryError* err) const; - virtual bool CanMerge(const ICryError* err) const; - - virtual bool HasFile() const { return true; } - - virtual void AddCCs(std::set& ccs) const; - - virtual std::string GetErrorName() const; - virtual std::string GetErrorDetails(EOutputFormatType outputType) const; - virtual std::string GetFilename() const { return m_entry + ".txt"; } - virtual std::string GetFileContents() const { return m_program; } - - std::vector m_requests; -private: - void Init(); - std::string GetErrorLines() const; - std::string GetContext(int linenum, int context = 2, std::string prefix = ">") const; - - std::vector< std::pair > m_errors; - - tdEntryVec m_CCs; - - std::string m_entry, m_errortext, m_hasherrors, m_IP, - m_program, m_project, m_shader, - m_platform, m_compiler, m_language, m_tags, m_profile; - int m_uniqueID; - - friend CCompilerError; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp deleted file mode 100644 index 35582a64cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include -#include -#include -#include -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile1.hpp" - - - -CCrySimpleJobCompile1::CCrySimpleJobCompile1(uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJobCompile(requestIP, EPV_V001, pRVec) -{ -} - -size_t CCrySimpleJobCompile1::SizeOf(std::vector& rVec) -{ - return rVec.size(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp deleted file mode 100644 index 839ab2f393..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile1.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE1__ -#define __CRYSIMPLEJOBCOMPILE1__ - -#include "CrySimpleJobCompile.hpp" - - -class CCrySimpleJobCompile1 - : public CCrySimpleJobCompile -{ - virtual size_t SizeOf(std::vector& rVec); - -public: - CCrySimpleJobCompile1(uint32_t requestIP, std::vector* pRVec); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp deleted file mode 100644 index 4946f7146b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleSock.hpp" -#include "CrySimpleJobCompile2.hpp" - -#include -#include -#include -#include - - - -CCrySimpleJobCompile2::CCrySimpleJobCompile2(EProtocolVersion version, uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJobCompile(requestIP, version, pRVec) -{ -} - -size_t CCrySimpleJobCompile2::SizeOf(std::vector& rVec) -{ - const char* pXML = reinterpret_cast(&rVec[0]); - const char* pFirst = strstr(pXML, "HashStop"); - return pFirst ? pFirst - pXML : rVec.size(); -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp deleted file mode 100644 index 6d52d9a822..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobCompile2.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBCOMPILE2__ -#define __CRYSIMPLEJOBCOMPILE2__ - -#include "CrySimpleJobCompile.hpp" - - -class CCrySimpleJobCompile2 - : public CCrySimpleJobCompile -{ - virtual size_t SizeOf(std::vector& rVec); - -public: - CCrySimpleJobCompile2(EProtocolVersion version, uint32_t requestIP, std::vector* pRVec); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp deleted file mode 100644 index b0c87edf90..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "CrySimpleJobGetShaderList.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - - -CCrySimpleJobGetShaderList::CCrySimpleJobGetShaderList(uint32_t requestIP, std::vector* pRVec) - : CCrySimpleJob(requestIP) - , m_pRVec(pRVec) -{ -} - -bool CCrySimpleJobGetShaderList::Execute(const TiXmlElement* pElement) -{ - AZ::IO::Path shaderListFilename; - - const char* project = pElement->Attribute("Project"); - const char* shaderList = pElement->Attribute("ShaderList"); - const char* platform = pElement->Attribute("Platform"); - const char* compiler = pElement->Attribute("Compiler"); - const char* language = pElement->Attribute("Language"); - - shaderListFilename = project; - shaderListFilename /= "Cache"; - shaderListFilename /= AZStd::string::format("%s-%s-%s", platform, compiler, language); - shaderListFilename /= shaderList; - - //open the file and read into the rVec - - FILE* pFile = nullptr; - azfopen(&pFile, shaderListFilename.c_str(), "rb"); - if (!pFile) - { - // Fake a good result. We can't be sure if this file name is bad or if it doesn't exist *yet*, so we'll just assume the latter. - m_pRVec->resize(4, '\0'); - State(ECSJS_DONE); - return true; - } - - fseek(pFile, 0, SEEK_END); - size_t fileSize = ftell(pFile); - m_pRVec->resize(fileSize); - fseek(pFile, 0, SEEK_SET); - - size_t remaining = fileSize; - size_t read = 0; - while (remaining) - { - read += fread(m_pRVec->data() + read, 1, remaining, pFile); - remaining -= read; - } - - fclose(pFile); - - //compress before sending - tdDataVector rDataRaw; - rDataRaw.swap(*m_pRVec); - if (!CSTLHelper::Compress(rDataRaw, *m_pRVec)) - { - State(ECSJS_ERROR_COMPRESS); - CrySimple_ERROR("failed to compress request"); - return false; - } - State(ECSJS_DONE); - - return true; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp deleted file mode 100644 index 58f2ac16c7..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobGetShaderList.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#ifndef __CRYSIMPLEJOBGETSHADERLIST__ -#define __CRYSIMPLEJOBGETSHADERLIST__ - -#include "CrySimpleJob.hpp" - - -class CCrySimpleJobGetShaderList - : public CCrySimpleJob -{ -public: - CCrySimpleJobGetShaderList(uint32_t requestIP, std::vector* pRVec); - - virtual bool Execute(const TiXmlElement* pElement); - std::vector* m_pRVec = nullptr; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp deleted file mode 100644 index 878d8921dd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleJobRequest.hpp" -#include "CrySimpleServer.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -CCrySimpleJobRequest::CCrySimpleJobRequest(EProtocolVersion Version, uint32_t requestIP) - : CCrySimpleJob(requestIP) - , m_Version(Version) -{ -} - -bool CCrySimpleJobRequest::Execute(const TiXmlElement* pElement) -{ - const char* shaderRequest = pElement->Attribute("ShaderRequest"); - if (!shaderRequest) - { - State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE); - CrySimple_ERROR("Missing shader request line"); - return false; - } - - AZ::IO::Path shaderListFilename; - if (m_Version >= EPV_V0023) - { - const char* project = pElement->Attribute("Project"); - const char* shaderList = pElement->Attribute("ShaderList"); - if (!project) - { - State(ECSJS_ERROR_INVALID_PROJECT); - CrySimple_ERROR("Missing Project for shader request"); - return false; - } - if (!shaderList) - { - State(ECSJS_ERROR_INVALID_SHADERLIST); - CrySimple_ERROR("Missing Shader List for shader request"); - return false; - } - - // NOTE: These attributes were alredy validated. - AZStd::string platform = pElement->Attribute("Platform"); - AZStd::string compiler = pElement->Attribute("Compiler"); - AZStd::string language = pElement->Attribute("Language"); - - shaderListFilename = project; - shaderListFilename /= "Cache"; - shaderListFilename /= AZStd::string::format("%s-%s-%s", platform.c_str(), compiler.c_str(), language.c_str()); - shaderListFilename /= shaderList; - } - else - { - // In previous versions Platform attribute is the shader list filename directly - shaderListFilename = pElement->Attribute("Platform"); - } - - std::string shaderRequestLine(shaderRequest); - tdEntryVec toks; - CSTLHelper::Tokenize(toks, shaderRequestLine, ";"); - for (size_t a = 0, s = toks.size(); a < s; a++) - { - CShaderList::Instance().Add(shaderListFilename.c_str(), toks[a].c_str()); - } - - State(ECSJS_DONE); - - return true; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp deleted file mode 100644 index f55334a1da..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleJobRequest.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEJOBREQUEST__ -#define __CRYSIMPLEJOBREQUEST__ - -#include "CrySimpleJob.hpp" -#include "CrySimpleSock.hpp" - - -class CCrySimpleJobRequest - : public CCrySimpleJob -{ -public: - CCrySimpleJobRequest(EProtocolVersion Version, uint32_t requestIP); - - virtual bool Execute(const TiXmlElement* pElement); - -private: - EProtocolVersion m_Version; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp deleted file mode 100644 index 997d2fe9b0..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleMutex.hpp" - -#include -#include -#include - - -CCrySimpleMutex::CCrySimpleMutex() -{ -#if defined(AZ_PLATFORM_WINDOWS) - InitializeCriticalSectionAndSpinCount(&cs, 10000); -#else - pthread_mutex_init(&m_Mutex, nullptr); -#endif -} - -CCrySimpleMutex::~CCrySimpleMutex() -{ -#if defined(AZ_PLATFORM_WINDOWS) - DeleteCriticalSection(&cs); -#else - pthread_mutex_destroy(&m_Mutex); -#endif -} - - -void CCrySimpleMutex::Lock() -{ -#if defined(AZ_PLATFORM_WINDOWS) - EnterCriticalSection(&cs); -#else - pthread_mutex_lock(&m_Mutex); -#endif -} - -void CCrySimpleMutex::Unlock() -{ -#if defined(AZ_PLATFORM_WINDOWS) - LeaveCriticalSection(&cs); -#else - pthread_mutex_unlock(&m_Mutex); -#endif -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp deleted file mode 100644 index 09aa08349d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleMutex.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLEMUTEX__ -#define __CRYSIMPLEMUTEX__ - -#include - -#if !defined(AZ_PLATFORM_WINDOWS) -#include "pthread.h" -#endif - -class CCrySimpleMutex -{ -#if defined(AZ_PLATFORM_WINDOWS) - CRITICAL_SECTION cs; -#else - // Use posix thread support - pthread_mutex_t m_Mutex; -#endif -public: - CCrySimpleMutex(); - ~CCrySimpleMutex(); - - void Lock(); - void Unlock(); -}; - -class CCrySimpleMutexAutoLock -{ - CCrySimpleMutex& m_rMutex; -public: - CCrySimpleMutexAutoLock(CCrySimpleMutex& rMutex) - : m_rMutex(rMutex) - { - rMutex.Lock(); - } - ~CCrySimpleMutexAutoLock() - { - m_rMutex.Unlock(); - } -}; -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp deleted file mode 100644 index ede23c97fc..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.cpp +++ /dev/null @@ -1,722 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include -#include -#include - -#include "CrySimpleServer.hpp" -#include "CrySimpleSock.hpp" -#include "CrySimpleJob.hpp" -#include "CrySimpleJobCompile1.hpp" -#include "CrySimpleJobCompile2.hpp" -#include "CrySimpleJobRequest.hpp" -#include "CrySimpleJobGetShaderList.hpp" -#include "CrySimpleCache.hpp" -#include "CrySimpleErrorLog.hpp" -#include "ShaderList.hpp" - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#undef AZ_RESTRICTED_SECTION -#define CRYSIMPLESERVER_CPP_SECTION_1 1 -#define CRYSIMPLESERVER_CPP_SECTION_2 2 -#endif - -#if defined(AZ_PLATFORM_MAC) -#include -#include -#endif - -#include -#include -#include -#include - - -#ifdef WIN32 - #define EXTENSION ".exe" -#else - #define EXTENSION "" -#endif - -AZStd::atomic_long CCrySimpleServer::ms_ExceptionCount = {0}; - -static const bool autoDeleteJobWhenDone = true; -static const int sleepTimeWhenWaiting = 10; - -static AZStd::atomic_long g_ConnectionCount = {0}; - -SEnviropment* SEnviropment::m_instance=nullptr; - -void SEnviropment::Create() -{ - if (!m_instance) - { - m_instance = new SEnviropment; - } -} - -void SEnviropment::Destroy() -{ - if (m_instance) - { - delete m_instance; - m_instance = nullptr; - } -} - -SEnviropment& SEnviropment::Instance() -{ - AZ_Assert(m_instance, "Using SEnviropment::Instance() before calling SEnviropment::Create()"); - return *m_instance; -} - -// Shader Compilers ID -// NOTE: Values must be in sync with CShaderSrv::GetShaderCompilerName() function in the engine side. -const char* SEnviropment::m_Orbis_DXC = "Orbis_DXC"; -const char* SEnviropment::m_Jasper_FXC = "Jasper_FXC"; -const char* SEnviropment::m_D3D11_FXC = "D3D11_FXC"; -const char* SEnviropment::m_GLSL_HLSLcc = "GLSL_HLSLcc"; -const char* SEnviropment::m_METAL_HLSLcc = "METAL_HLSLcc"; -const char* SEnviropment::m_GLSL_LLVM_DXC = "GLSL_LLVM_DXC"; -const char* SEnviropment::m_METAL_LLVM_DXC = "METAL_LLVM_DXC"; - -void SEnviropment::InitializePlatformAttributes() -{ - // Initialize valid Plaforms - // NOTE: Values must be in sync with CShaderSrv::GetPlatformName() function in the engine side. - m_Platforms.insert("Orbis"); - m_Platforms.insert("Nx"); - m_Platforms.insert("PC"); - m_Platforms.insert("Mac"); - m_Platforms.insert("iOS"); - m_Platforms.insert("Android"); - m_Platforms.insert("Linux"); - m_Platforms.insert("Jasper"); - - // Initialize valid Shader Languages - // NOTE: Values must be in sync with GetShaderLanguageName() function in the engine side. - m_ShaderLanguages.insert("Orbis"); - m_ShaderLanguages.insert("D3D11"); - m_ShaderLanguages.insert("METAL"); - m_ShaderLanguages.insert("GL4"); - m_ShaderLanguages.insert("GLES3"); - m_ShaderLanguages.insert("Jasper"); - // These are added for legacy support (GLES3_0 and GLES3_1 are combined into just GLES3) - m_ShaderLanguages.insert("GL4_1"); - m_ShaderLanguages.insert("GL4_4"); - m_ShaderLanguages.insert("GLES3_0"); - m_ShaderLanguages.insert("GLES3_1"); - - // Initialize valid Shader Compilers ID and Executables. - // Intentionally put a space after the executable name so that attackers can't try to change the executable name that we are going to run. -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) -#if defined(TOOLS_SUPPORT_JASPER) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, jasper) -#endif -#if defined(TOOLS_SUPPORT_PROVO) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, provo) -#endif -#if defined(TOOLS_SUPPORT_SALEM) -#define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_2 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, salem) -#endif -#endif - - m_ShaderCompilersMap[m_D3D11_FXC] = "PCD3D11/v006/fxc.exe "; - m_ShaderCompilersMap[m_GLSL_HLSLcc] = "PCGL/V006/HLSLcc "; - m_ShaderCompilersMap[m_METAL_HLSLcc] = "PCGMETAL/HLSLcc/HLSLcc "; -#if defined(_DEBUG) - m_ShaderCompilersMap[m_GLSL_LLVM_DXC] = "LLVMGL/debug/dxcGL "; - m_ShaderCompilersMap[m_METAL_LLVM_DXC] = "LLVMMETAL/debug/dxcMetal "; -#else - m_ShaderCompilersMap[m_GLSL_LLVM_DXC] = "LLVMGL/release/dxcGL "; - m_ShaderCompilersMap[m_METAL_LLVM_DXC] = "LLVMMETAL/release/dxcMetal "; -#endif -} - -bool SEnviropment::IsPlatformValid( const AZStd::string& platform ) const -{ - return m_Platforms.find(platform) != m_Platforms.end(); -} - -bool SEnviropment::IsShaderLanguageValid( const AZStd::string& shaderLanguage ) const -{ - return m_ShaderLanguages.find(shaderLanguage) != m_ShaderLanguages.end(); -} - -bool SEnviropment::IsShaderCompilerValid( const AZStd::string& shaderCompilerID ) const -{ - bool validCompiler = (m_ShaderCompilersMap.find(shaderCompilerID) != m_ShaderCompilersMap.end()); - - // Extra check for Mac: Only GL_LLVM_DXC and METAL_LLVM_DXC compilers are supported. - #if defined(AZ_PLATFORM_MAC) - if (validCompiler && - shaderCompilerID != m_GLSL_LLVM_DXC && - shaderCompilerID != m_METAL_LLVM_DXC) - { - printf("error: trying to use an unsupported compiler on Mac.\n"); - return false; - } - #endif - - return validCompiler; -} - -bool SEnviropment::GetShaderCompilerExecutable( const AZStd::string& shaderCompilerID, AZStd::string& shaderCompilerExecutable ) const -{ - auto it = m_ShaderCompilersMap.find(shaderCompilerID); - if (it != m_ShaderCompilersMap.end()) - { - shaderCompilerExecutable = it->second; - return true; - } - else - { - return false; - } -} - -class CThreadData -{ - uint32_t m_Counter; - CCrySimpleSock* m_pSock; -public: - CThreadData(uint32_t Counter, CCrySimpleSock* pSock) - : m_Counter(Counter) - , m_pSock(pSock){} - - ~CThreadData(){delete m_pSock; } - - CCrySimpleSock* Socket(){return m_pSock; } - uint32_t ID() const{return m_Counter; } -}; - -////////////////////////////////////////////////////////////////////////// - -bool CopyFileOnPlatform(const char* nameOfFileToCopy, const char* copiedFileName, bool failIfFileExists) -{ - if (AZ::IO::SystemFile::Exists(copiedFileName) && failIfFileExists) - { - AZ_Warning("CrySimpleServer", false, ("File to copy to, %s, already exists."), copiedFileName); - return false; - } - - AZ::IO::SystemFile fileToCopy; - if (!fileToCopy.Open(nameOfFileToCopy, AZ::IO::SystemFile::SF_OPEN_READ_ONLY)) - { - AZ_Warning("CrySimpleServer", false, ("Unable to open file: %s for copying."), nameOfFileToCopy); - return false; - } - - AZ::IO::SystemFile::SizeType fileLength = fileToCopy.Length(); - - AZ::IO::SystemFile newFile; - if (!newFile.Open(copiedFileName, AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE)) - { - AZ_Warning("CrySimpleServer", false, ("Unable to open new file: %s for copying."), copiedFileName); - return false; - } - - char* fileContents = new char[fileLength]; - fileToCopy.Read(fileLength, fileContents); - newFile.Write(fileContents, fileLength); - delete[] fileContents; - - return true; -} - -void MakeErrorVec(const std::string& errorText, tdDataVector& Vec) -{ - Vec.resize(errorText.size() + 1); - for (size_t i = 0; i < errorText.size(); i++) - { - Vec[i] = errorText[i]; - } - Vec[errorText.size()] = 0; - - // Compress output data - tdDataVector rDataRaw; - rDataRaw.swap(Vec); - if (!CSTLHelper::Compress(rDataRaw, Vec)) - { - Vec.resize(0); - } -} - -////////////////////////////////////////////////////////////////////////// -class CompileJob - : public AZ::Job -{ -public: - CompileJob() - : Job(autoDeleteJobWhenDone, nullptr) { } - void SetThreadData(CThreadData* threadData) { m_pThreadData.reset(threadData); } -protected: - void Process() override; - bool ValidatePlatformAttributes(EProtocolVersion Version, const TiXmlElement* pElement); -private: - std::unique_ptr m_pThreadData; -}; - -void CompileJob::Process() -{ - std::vector Vec; - std::unique_ptr Job; - EProtocolVersion Version = EPV_V001; - ECrySimpleJobState State = ECSJS_JOBNOTFOUND; - try - { - if (m_pThreadData->Socket()->Recv(Vec)) - { - std::string Request(reinterpret_cast(&Vec[0]), Vec.size()); - TiXmlDocument ReqParsed("Request.xml"); - ReqParsed.Parse(Request.c_str()); - - if (ReqParsed.Error()) - { - CrySimple_ERROR("failed to parse request XML"); - return; - } - const TiXmlElement* pElement = ReqParsed.FirstChildElement(); - if (!pElement) - { - CrySimple_ERROR("failed to extract First Element of the request"); - return; - } - - const char* pPing = pElement->Attribute("Identify"); - if (pPing) - { - const std::string& rData("ShaderCompilerServer"); - m_pThreadData->Socket()->Send(rData); - return; - } - - const char* pVersion = pElement->Attribute("Version"); - const char* pHardwareTarget = nullptr; - - //new request type? - if (pVersion) - { - if (std::string(pVersion) == "2.3") - { - Version = EPV_V0023; - } - else if (std::string(pVersion) == "2.2") - { - Version = EPV_V0022; - } - else if (std::string(pVersion) == "2.1") - { - Version = EPV_V0021; - } - else if (std::string(pVersion) == "2.0") - { - Version = EPV_V002; - } - } - - - // If the job type is 'GetShaderList', then we dont need to perform a validation on the platform - // attributes, since the command doesnt use them, and the incoming request will not have 'compiler' or 'language' - // attributes. - const char* pJobType = pElement->Attribute("JobType"); - if ((!pJobType) || (azstricmp(pJobType,"GetShaderList")!=0)) - { - if (!ValidatePlatformAttributes(Version, pElement)) - { - return; - } - } - - if (Version >= EPV_V002) - { - const std::string JobType(pJobType); - - if (Version >= EPV_V0023) - { - pHardwareTarget = pElement->Attribute("HardwareTarget"); - } - - if (Version >= EPV_V0021) - { - m_pThreadData->Socket()->WaitForShutDownEvent(true); - } - -#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS) - #if defined(TOOLS_SUPPORT_JASPER) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, jasper) - #endif - #if defined(TOOLS_SUPPORT_PROVO) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, provo) - #endif - #if defined(TOOLS_SUPPORT_SALEM) - #define AZ_RESTRICTED_SECTION CRYSIMPLESERVER_CPP_SECTION_1 -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleServer_cpp, salem) - #endif -#endif - - if (pJobType) - { - if (JobType == "RequestLine") - { - Job = std::make_unique(Version, m_pThreadData->Socket()->PeerIP()); - Job->Execute(pElement); - State = Job->State(); - Vec.resize(0); - } - else - if (JobType == "Compile") - { - Job = std::make_unique(Version, m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - State = Job->State(); - } - else - if (JobType == "GetShaderList") - { - Job = std::make_unique(m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - State = Job->State(); - } - else - { - printf("\nRequested unkown job %s\n", pJobType); - } - } - else - { - printf("\nVersion 2.0 or higher but has no JobType tag\n"); - } - } - else - { - //legacy request - Version = EPV_V001; - Job = std::make_unique(m_pThreadData->Socket()->PeerIP(), &Vec); - Job->Execute(pElement); - } - m_pThreadData->Socket()->Send(Vec, State, Version); - - if (Version >= EPV_V0021) - { - /* - // wait until message has been succesfully delived before shutting down the connection - if(!m_pThreadData->Socket()->RecvResult()) - { - printf("\nInvalid result from client\n"); - } - */ - } - } - } - catch (const ICryError* err) - { - CCrySimpleServer::IncrementExceptionCount(); - - CRYSIMPLE_LOG(" " + err->GetErrorName()); - - std::string returnStr = err->GetErrorDetails(ICryError::OUTPUT_TTY); - - // Send error back - MakeErrorVec(returnStr, Vec); - - if (Job.get()) - { - State = Job->State(); - - if (State == ECSJS_ERROR_COMPILE && SEnviropment::Instance().m_PrintErrors) - { - printf("\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); - printf("%s\n", err->GetErrorName().c_str()); - printf("%s\n", returnStr.c_str()); - printf("\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n\n"); - } - } - - bool added = CCrySimpleErrorLog::Instance().Add((ICryError*)err); - - // error log hasn't taken ownership, delete this error. - if (!added) - { - delete err; - } - - m_pThreadData->Socket()->Send(Vec, State, Version); - } - --g_ConnectionCount; -} - - -bool CompileJob::ValidatePlatformAttributes(EProtocolVersion Version, const TiXmlElement* pElement) -{ - if (Version >= EPV_V0023) - { - const char* platform = pElement->Attribute("Platform"); // eg. PC, Mac... - const char* compiler = pElement->Attribute("Compiler"); // key to shader compiler executable - const char* language = pElement->Attribute("Language"); // eg. D3D11, GL4_1, GL3_1, METAL... - - if (!platform || !SEnviropment::Instance().IsPlatformValid(platform)) - { - CrySimple_ERROR("invalid Platform attribute from request."); - return false; - } - if (!compiler || !SEnviropment::Instance().IsShaderCompilerValid(compiler)) - { - CrySimple_ERROR("invalid Compiler attribute from request."); - return false; - } - if (!language || !SEnviropment::Instance().IsShaderLanguageValid(language)) - { - CrySimple_ERROR("invalid Language attribute from request."); - return false; - } - } - else - { - // In older versions the attribute Platform was used differently depending on the JobType - // - JobType Compile: Platform is the shader language - // - JobType RequestLine: Platform is the shader list filename - const char* platformLegacy = pElement->Attribute("Platform"); - - // The only check we can do here is if the attribute exists. Each JobType will check it has a valid value. - if (!platformLegacy) - { - CrySimple_ERROR("failed to extract required platform attribute from request."); - return false; - } - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void TickThread() -{ - AZ::u64 t0 = AZStd::GetTimeUTCMilliSecond(); - - while (true) - { - CrySimple_SECURE_START - - AZ::u64 t1 = AZStd::GetTimeUTCMilliSecond(); - if ((t1 < t0) || (t1 - t0 > 100)) - { - t0 = t1; - const int maxStringSize = 512; - char str[maxStringSize] = { 0 }; - azsnprintf(str, maxStringSize, "Amazon Shader Compiler Server (%ld compile tasks | %ld open sockets | %ld exceptions)", - CCrySimpleJobCompile::GlobalCompileTasks(), CCrySimpleSock::GetOpenSockets() + CSMTPMailer::GetOpenSockets(), - CCrySimpleServer::GetExceptionCount()); -#if defined(AZ_PLATFORM_WINDOWS) - SetConsoleTitle(str); -#endif - } - - const AZ::u64 T1 = AZStd::GetTimeUTCMilliSecond(); - CCrySimpleErrorLog::Instance().Tick(); - CShaderList::Instance().Tick(); - CCrySimpleCache::Instance().ThreadFunc_SavePendingCacheEntries(); - const AZ::u64 T2 = AZStd::GetTimeUTCMilliSecond(); - if (T2 - T1 < 100) - { - Sleep(static_cast(100 - T2 + T1)); - } - - CrySimple_SECURE_END - } -} - -////////////////////////////////////////////////////////////////////////// -void LoadCache() -{ - AZ::IO::Path cacheDatFile{ SEnviropment::Instance().m_CachePath }; - AZ::IO::Path cacheBakFile = cacheDatFile; - cacheDatFile /= "Cache.dat"; - cacheBakFile /= "Cache.bak"; - if (CCrySimpleCache::Instance().LoadCacheFile(cacheDatFile.c_str())) - { - AZ::IO::Path cacheBakFile2 = cacheBakFile; - cacheBakFile2.ReplaceFilename("Cache.bak2"); - - printf("Creating cache backup...\n"); - AZ::IO::SystemFile::Delete(cacheBakFile2.c_str()); - printf("Move %s to %s\n", cacheBakFile.c_str(), cacheBakFile2.c_str()); - AZ::IO::SystemFile::Rename(cacheBakFile.c_str(), cacheBakFile2.c_str()); - printf("Copy %s to %s\n", cacheDatFile.c_str(), cacheBakFile.c_str()); - CopyFileOnPlatform(cacheDatFile.c_str(), cacheBakFile.c_str(), false); - printf("Cache backup done.\n"); - } - else - { - // Restoring backup cache! - if (AZ::IO::SystemFile::Exists(cacheDatFile.c_str())) - { - printf("Cache file corrupted!!!\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - - printf("Restoring backup cache...\n"); - printf("Copy %s to %s\n", cacheBakFile.c_str(), cacheDatFile.c_str()); - CopyFileOnPlatform(cacheBakFile.c_str(), cacheDatFile.c_str(), false); - if (!CCrySimpleCache::Instance().LoadCacheFile(cacheDatFile.c_str())) - { - // Backup file corrupted too! - if (AZ::IO::SystemFile::Exists(cacheDatFile.c_str())) - { - printf("Backup file corrupted too!!!\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - printf("Deleting cache completely\n"); - AZ::IO::SystemFile::Delete(cacheDatFile.c_str()); - } - } - - CCrySimpleCache::Instance().Finalize(); - printf("Ready\n"); -} - - -////////////////////////////////////////////////////////////////////////// -CCrySimpleServer::CCrySimpleServer([[maybe_unused]] const char* pShaderModel, [[maybe_unused]] const char* pDst, [[maybe_unused]] const char* pSrc, [[maybe_unused]] const char* pEntryFunction) - : m_pServerSocket(nullptr) -{ - Init(); -} - -CCrySimpleServer::CCrySimpleServer() - : m_pServerSocket(nullptr) -{ - CrySimple_SECURE_START - - uint32_t Port = SEnviropment::Instance().m_port; - - m_pServerSocket = new CCrySimpleSock(Port, SEnviropment::Instance().m_WhitelistAddresses); - Init(); - m_pServerSocket->Listen(); - - AZ::Job* tickThreadJob = AZ::CreateJobFunction(&TickThread, autoDeleteJobWhenDone); - tickThreadJob->Start(); - - uint32_t JobCounter = 0; - while (1) - { - // New client message, receive new client socket connection. - CCrySimpleSock* newClientSocket = m_pServerSocket->Accept(); - if(!newClientSocket) - { - continue; - } - - // Thread Data for new job - CThreadData* pData = new CThreadData(JobCounter++, newClientSocket); - - // Increase connection count and start new job. - // NOTE: CompileJob will be auto deleted when done, deleting thread data and client socket as well. - ++g_ConnectionCount; - CompileJob* compileJob = new CompileJob(); - compileJob->SetThreadData(pData); - compileJob->Start(); - - bool printedMessage = false; - while (g_ConnectionCount >= SEnviropment::Instance().m_MaxConnections) - { - if (!printedMessage) - { - logmessage("Waiting for a request to finish before accepting another connection...\n"); - printedMessage = true; - } - - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(sleepTimeWhenWaiting)); - }; - } - CrySimple_SECURE_END -} - -bool IsPathValid(const AZStd::string& path) -{ - return AZ::IO::PathView(path).IsRelativeTo(AZ::IO::PathView(SEnviropment::Instance().m_Root)); -} - -bool IsPathValid(const std::string& path) -{ - const AZStd::string tempString = path.c_str(); - return IsPathValid(tempString); -} - -void CCrySimpleServer::Init() -{ - SEnviropment::Instance().m_Root = AZ::Utils::GetExecutableDirectory(); - SEnviropment::Instance().m_CompilerPath = SEnviropment::Instance().m_Root / "Compiler"; - SEnviropment::Instance().m_CachePath = SEnviropment::Instance().m_Root / "Cache"; - - if (SEnviropment::Instance().m_TempPath.empty()) - { - SEnviropment::Instance().m_TempPath = SEnviropment::Instance().m_Root / "Temp"; - } - if (SEnviropment::Instance().m_ErrorPath.empty()) - { - SEnviropment::Instance().m_ErrorPath = SEnviropment::Instance().m_Root / "Error"; - } - if (SEnviropment::Instance().m_ShaderPath.empty()) - { - SEnviropment::Instance().m_ShaderPath = SEnviropment::Instance().m_Root / "Shaders"; - } - - SEnviropment::Instance().m_Root = SEnviropment::Instance().m_Root.LexicallyNormal(); - SEnviropment::Instance().m_CompilerPath = SEnviropment::Instance().m_CompilerPath.LexicallyNormal(); - SEnviropment::Instance().m_CachePath = SEnviropment::Instance().m_CachePath.LexicallyNormal(); - SEnviropment::Instance().m_ErrorPath = SEnviropment::Instance().m_ErrorPath.LexicallyNormal(); - SEnviropment::Instance().m_TempPath = SEnviropment::Instance().m_TempPath.LexicallyNormal(); - SEnviropment::Instance().m_ShaderPath = SEnviropment::Instance().m_ShaderPath.LexicallyNormal(); - - if (SEnviropment::Instance().m_Caching) - { - AZ::Job* loadCacheJob = AZ::CreateJobFunction(&LoadCache, autoDeleteJobWhenDone); - loadCacheJob->Start(); - } - else - { - printf("\nNO CACHING, disabled by config\n"); - } -} - -void CCrySimpleServer::IncrementExceptionCount() -{ - ++ms_ExceptionCount; -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp deleted file mode 100644 index a7dcdb42ee..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleServer.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLESERVER__ -#define __CRYSIMPLESERVER__ - -#include -#include -#include -#include -#include -#include -#include -#include - -extern bool g_Success; - - -bool IsPathValid(const AZStd::string& path); -bool IsPathValid(const std::string& path); - -namespace AZ { - class JobManager; -} - -class CCrySimpleSock; - -class SEnviropment -{ -public: - AZ::IO::Path m_Root; - AZ::IO::Path m_CompilerPath; - AZ::IO::Path m_CachePath; - AZ::IO::Path m_TempPath; - AZ::IO::Path m_ErrorPath; - AZ::IO::Path m_ShaderPath; - - std::string m_FailEMail; - std::string m_MailServer; - uint32_t m_port; - uint32_t m_MailInterval; // seconds since last error to flush error mails - - bool m_Caching; - bool m_PrintErrors = 1; - bool m_PrintWarnings; - bool m_PrintCommands; - bool m_PrintListUpdates; - bool m_DedupeErrors; - bool m_DumpShaders = false; - bool m_RunAsRoot = false; - std::string m_FallbackServer; - int32_t m_FallbackTreshold; - int32_t m_MaxConnections; - std::vector m_WhitelistAddresses; - - // Shader Compilers ID - static const char* m_Orbis_DXC; - static const char* m_Jasper_FXC; - static const char* m_D3D11_FXC; - static const char* m_GLSL_HLSLcc; - static const char* m_METAL_HLSLcc; - static const char* m_GLSL_LLVM_DXC; - static const char* m_METAL_LLVM_DXC; - - int m_hardwareTarget = -1; - - static void Create(); - static void Destroy(); - static SEnviropment& Instance(); - - void InitializePlatformAttributes(); - - bool IsPlatformValid( const AZStd::string& platform ) const; - bool IsShaderLanguageValid( const AZStd::string& shaderLanguage ) const; - bool IsShaderCompilerValid( const AZStd::string& shaderCompilerID ) const; - - bool GetShaderCompilerExecutable( const AZStd::string& shaderCompilerID, AZStd::string& shaderCompilerExecutable ) const; - -private: - SEnviropment() = default; - - // The single instance of the environment - static SEnviropment* m_instance; - - // Platforms - AZStd::unordered_set m_Platforms; - - // Shader Languages - AZStd::unordered_set m_ShaderLanguages; - - // Shader Compilers ID to Executable map - AZStd::unordered_map m_ShaderCompilersMap; -}; - -class CCrySimpleServer -{ - static AZStd::atomic_long ms_ExceptionCount; - CCrySimpleSock* m_pServerSocket; - void Init(); -public: - CCrySimpleServer(const char* pShaderModel, const char* pDst, const char* pSrc, const char* pEntryFunction); - CCrySimpleServer(); - - - static long GetExceptionCount() { return ms_ExceptionCount; } - static void IncrementExceptionCount(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp deleted file mode 100644 index e0cbd8d733..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "CrySimpleSock.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -#include -#include -#include -#include -#include -#else -#include -typedef int socklen_t; -#endif - -namespace -{ - enum ECrySimpleS_TYPE - { - ECrySimpleST_ROOT, - ECrySimpleST_SERVER, - ECrySimpleST_CLIENT, - ECrySimpleST_INVALID, - }; - - static AZStd::atomic_long numberOfOpenSockets = {0}; - const int MAX_DATA_SIZE = 1024 * 1024; // Only allow 1 MB of data to come through. Open 3D Engine has the same size constraint - const size_t BLOCKSIZE = 4 * 1024; - const size_t MAX_ERROR_MESSAGE_SIZE = 1024; - const size_t MAX_HOSTNAME_BUFFER_SIZE = 1024; - - struct Ip4WhitelistAddress - { - Ip4WhitelistAddress() : m_address(0), m_mask(-1) { } - // IP Address in network order to whitelist - uint32_t m_address; - // Mask in network order to apply to connecting IP addresses - uint32_t m_mask; - }; -} - -struct CCrySimpleSock::Implementation -{ - - Implementation(ECrySimpleS_TYPE type) - : m_Type(type) { } - - void SetWhitelist(const std::vector& whiteList) - { - // Add in our local address so that we always allow connections from the local machine - char hostNameBuffer[MAX_HOSTNAME_BUFFER_SIZE] = { 0 }; - gethostname(hostNameBuffer, MAX_HOSTNAME_BUFFER_SIZE); - struct addrinfo* addressInfos{}; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - int addressInfoResultCode = getaddrinfo(hostNameBuffer, nullptr, &hints, &addressInfos); - - if (addressInfoResultCode == 0) - { - int i = 0; - for (auto addressInfoIter = addressInfos; addressInfoIter != nullptr; addressInfoIter = addressInfoIter->ai_next) - { - Ip4WhitelistAddress whitelistAddress; - whitelistAddress.m_address = static_cast(reinterpret_cast(addressInfoIter->ai_addr)->sin_addr.s_addr); - m_ipWhiteList.push_back(whitelistAddress); - ++i; - } - } - else - { - printf("Network error trying to get host computer local address. The host computer's local IP addresses will not be automatically whitelisted."); - } - - for (const auto& address : whiteList) - { - Ip4WhitelistAddress whitelistAddress; - AZStd::string::size_type maskLocation = address.rfind("/"); - if (maskLocation != AZStd::string::npos) - { - //x.x.x.x/0 is all addresses - // For CIDR that specify the network mask, mask out the address that is - // supplied here once instead of everytime we check the address during - // accept calls. - int mask = atoi(address.substr(maskLocation+1).c_str()); - if (mask == 0) - { - whitelistAddress.m_mask = 0; - whitelistAddress.m_address = 0; - - static bool warnOnce = true; - if (warnOnce) - { - warnOnce = false; - printf("\nWARNING: Attempting to run the CrySCompileServer authorizing every IP. This is a security risk and not recommended.\nPlease use a more restrictive whitelist in the config.ini file by not using netmask 0.\n\n"); - } - } - else - { - whitelistAddress.m_mask ^= (1 << (32 - mask)) - 1; - whitelistAddress.m_mask = htonl(whitelistAddress.m_mask); - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, address.substr(0, maskLocation).c_str(), &ipv4Address) == 1) - { - whitelistAddress.m_address = static_cast(ipv4Address.s_addr); - } - } - } - else - { - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, address.c_str(), &ipv4Address) == 1) - { - whitelistAddress.m_address = static_cast(ipv4Address.s_addr); - } - } - - m_ipWhiteList.push_back(whitelistAddress); - } - } - - CCrySimpleSock* m_pInstance; - - const ECrySimpleS_TYPE m_Type; - SOCKET m_Socket; - uint16_t m_Port; -#ifdef USE_WSAEVENTS - WSAEVENT m_Event; -#endif - bool m_WaitForShutdownEvent; - bool m_SwapEndian; - - bool m_bHasReceivedData; - bool m_bHasSendData; - - tdDataVector m_tempSendBuffer; - - std::vector m_ipWhiteList; -}; - -#if defined(AZ_PLATFORM_WINDOWS) -typedef BOOL (WINAPI * LPFN_DISCONNECTEX)(SOCKET, LPOVERLAPPED, DWORD, DWORD); -#define WSAID_DISCONNECTEX {0x7fda2e11, 0x8630, 0x436f, {0xa0, 0x31, 0xf5, 0x36, 0xa6, 0xee, 0xc1, 0x57} \ -} -#endif - -#ifdef USE_WSAEVENTS -CCrySimpleSock::CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance, WSAEVENT wsaEvent) -#else -CCrySimpleSock::CCrySimpleSock(SOCKET Sock, CCrySimpleSock * pInstance) -#endif - : m_pImpl(new Implementation(ECrySimpleST_SERVER)) -{ - #ifdef USE_WSAEVENTS - m_pImpl->m_Event = wsaEvent; - #endif - - m_pImpl->m_pInstance = pInstance; - m_pImpl->m_Socket = Sock; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = ~0; - - ++numberOfOpenSockets; - - InitClient(); -} - - -CCrySimpleSock::CCrySimpleSock(const std::string& rServerName, uint16_t Port) - : m_pImpl(new Implementation(ECrySimpleST_CLIENT)) -{ - m_pImpl->m_pInstance = nullptr; - m_pImpl->m_Socket = INVALID_SOCKET; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = Port; - - struct sockaddr_in addr; - memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - addr.sin_port = htons(Port); - const char* pHostName = rServerName.c_str(); - bool IP = true; - for (size_t a = 0, size = strlen(pHostName); a < size; a++) - { - IP &= (pHostName[a] >= '0' && pHostName[a] <= '9') || pHostName[a] == '.'; - } - if (IP) - { - struct in_addr ipv4Address{}; - if (inet_pton(AF_INET, pHostName, &ipv4Address) == 1) - { - addr.sin_addr = ipv4Address; - } - } - else - { - struct addrinfo* addressInfo{}; - struct addrinfo hints{}; - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - int addressInfoResultCode = getaddrinfo(pHostName, nullptr, &hints, &addressInfo); - if (addressInfoResultCode != 9) - { - return; - } - addr = *reinterpret_cast(addressInfo->ai_addr); - } - - m_pImpl->m_Socket = socket(AF_INET, SOCK_STREAM, 0); - - ++numberOfOpenSockets; - - int Err = connect(m_pImpl->m_Socket, (struct sockaddr*)&addr, sizeof addr); - if (Err < 0) - { - m_pImpl->m_Socket = INVALID_SOCKET; - } -} - -CCrySimpleSock::~CCrySimpleSock() -{ - Release(); -} - -CCrySimpleSock::CCrySimpleSock(uint16_t Port, const std::vector& ipWhiteList) - : m_pImpl(new Implementation(ECrySimpleST_ROOT)) -{ - m_pImpl->m_pInstance = nullptr; - m_pImpl->m_WaitForShutdownEvent = false; - m_pImpl->m_bHasReceivedData = false; - m_pImpl->m_bHasSendData = false; - m_pImpl->m_Port = Port; - -#ifdef _MSC_VER - WSADATA Data; - m_pImpl->m_Socket = INVALID_SOCKET; - if (WSAStartup(MAKEWORD(2, 0), &Data)) - { - CrySimple_ERROR("Could not init root socket"); - return; - } -#endif - m_pImpl->SetWhitelist(ipWhiteList); - - m_pImpl->m_Socket = socket(AF_INET, SOCK_STREAM, 0); - if (INVALID_SOCKET == m_pImpl->m_Socket) - { - CrySimple_ERROR("Could not initialize basic server due to invalid socket"); - return; - } - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) - int arg = 1; - setsockopt(m_pImpl->m_Socket, SOL_SOCKET, SO_KEEPALIVE, &arg, sizeof arg); - arg = 1; - setsockopt(m_pImpl->m_Socket, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof arg); -#endif - - sockaddr_in SockAddr; - memset(&SockAddr, 0, sizeof(sockaddr_in)); - SockAddr.sin_family = PF_INET; - SockAddr.sin_port = htons(Port); - if (bind(m_pImpl->m_Socket, (sockaddr*)&SockAddr, sizeof(sockaddr_in)) == SOCKET_ERROR) - { -#if defined(AZ_PLATFORM_WINDOWS) - AZ_Warning(0, false, "bind failed with error = %d", WSAGetLastError()); -#else - shutdown(m_pImpl->m_Socket, SHUT_RDWR); -#endif - closesocket(m_pImpl->m_Socket); - CrySimple_ERROR("Could not bind server socket. This can happen if there is another process running already that is using this port or antivirus software/firewall is blocking the port.\n"); - return; - } - - ++numberOfOpenSockets; -} - -void CCrySimpleSock::Listen() -{ - listen(m_pImpl->m_Socket, SOMAXCONN); -} - -void CCrySimpleSock::InitClient() -{ -} - -void CCrySimpleSock::Release() -{ - if (m_pImpl->m_Socket != INVALID_SOCKET) - { - // check if we have received and sended data but ignore that for the HTTP server - if ((!m_pImpl->m_bHasSendData || !m_pImpl->m_bHasReceivedData) && (!m_pImpl->m_pInstance || m_pImpl->m_pInstance->m_pImpl->m_Port != 80)) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "ERROR : closing socket without both receiving and sending data: receive: %d send: %d", - m_pImpl->m_bHasReceivedData, m_pImpl->m_bHasSendData); - CRYSIMPLE_LOG(acTmp); - } - -#ifdef USE_WSAEVENTS - if (m_pImpl->m_WaitForShutdownEvent) - { - // wait until client has shutdown its socket - DWORD nReturnCode = WSAWaitForMultipleEvents(1, &m_pImpl->m_Event, - FALSE, INFINITE, FALSE); - if ((nReturnCode != WSA_WAIT_FAILED) && (nReturnCode != WSA_WAIT_TIMEOUT)) - { - WSANETWORKEVENTS NetworkEvents; - WSAEnumNetworkEvents(m_pImpl->m_Socket, m_pImpl->m_Event, &NetworkEvents); - if (NetworkEvents.lNetworkEvents & FD_CLOSE) - { - int iErrorCode = NetworkEvents.iErrorCode[FD_CLOSE_BIT]; - if (iErrorCode != 0) - { - // error shutting down - } - } - } - } - - // shutdown the server side of the connection since no more data will be sent - shutdown(m_pImpl->m_Socket, SHUT_RDWR); - closesocket(m_pImpl->m_Socket); -#endif - -#if defined(AZ_PLATFORM_WINDOWS) - LPFN_DISCONNECTEX pDisconnectEx = NULL; - DWORD Bytes; - GUID guidDisconnectEx = WSAID_DISCONNECTEX; - WSAIoctl(m_pImpl->m_Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidDisconnectEx, - sizeof(GUID), &pDisconnectEx, sizeof(pDisconnectEx), &Bytes, NULL, NULL); - pDisconnectEx(m_pImpl->m_Socket, NULL, 0, 0); // retrieve this function pointer with WSAIoctl(WSAID_DISCONNECTEX). -#else - shutdown(m_pImpl->m_Socket, SHUT_RDWR); -#endif - closesocket(m_pImpl->m_Socket); - m_pImpl->m_Socket = INVALID_SOCKET; - --numberOfOpenSockets; - } - -#if defined(AZ_PLATFORM_WINDOWS) - switch (m_pImpl->m_Type) - { - case ECrySimpleST_ROOT: - WSACleanup(); - break; - case ECrySimpleST_SERVER: // Intentionally fall through - case ECrySimpleST_CLIENT: - break; - default: - CrySimple_ERROR("unknown SocketType Released"); - } -#endif -} - -CCrySimpleSock* CCrySimpleSock::Accept() -{ - if (m_pImpl->m_Type != ECrySimpleST_ROOT) - { - CrySimple_ERROR("called Accept on non root socket"); - return nullptr; - } - - while (true) - { - sockaddr_in connectingAddress; - int addressSize = sizeof(connectingAddress); - SOCKET Sock = accept(m_pImpl->m_Socket, reinterpret_cast(&connectingAddress), reinterpret_cast(&addressSize)); - if (Sock == INVALID_SOCKET) - { -#if defined(AZ_PLATFORM_MAC) - switch (errno) - { - case EINTR: - // OS X tends to get interupt calls on every other accept call - // so just ignore this particular error and try the accept call - // again. - continue; - default: - // Do nothing - all other errors are "real" and we should exit - break; - } -#endif - AZ_Warning(0, false, "Errno = %d", WSAGetLastError()); - CrySimple_ERROR("Accept recived invalid socket"); - return nullptr; - } - - bool allowConnection = false; - - for (const auto& ip4WhitelistAddress : m_pImpl->m_ipWhiteList) - { - if ((connectingAddress.sin_addr.s_addr & ip4WhitelistAddress.m_mask) == (ip4WhitelistAddress.m_address)) - { - allowConnection = true; - break; - } - } - - if (!allowConnection) - { - constexpr size_t ipAddressBufferSize = 17; - char ipAddressBuffer[ipAddressBufferSize]{}; - inet_ntop(AF_INET, &connectingAddress.sin_addr, ipAddressBuffer, ipAddressBufferSize); - printf("Warning: unauthorized IP %s trying to connect. If this IP is authorized please add it to the whitelist in the config.ini file\n", ipAddressBuffer); - closesocket(Sock); - continue; - } - - int arg = 1; - setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, sizeof arg); - - /* - // keep socket open for another 2 seconds until data has been fully send - LINGER linger; - int len = sizeof(LINGER); - linger.l_onoff = 1; - linger.l_linger = 2; - setsockopt(Sock, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof linger); - */ - -#ifdef USE_WSAEVENTS - WSAEVENT wsaEvent = WSACreateEvent(); - if (wsaEvent == WSA_INVALID_EVENT) - { - closesocket(Sock); - int Error = WSAGetLastError(); - CrySimple_ERROR("Couldn't create wsa event"); - return nullptr; - } - - int Status = WSAEventSelect(Sock, wsaEvent, FD_CLOSE); - if (Status == SOCKET_ERROR) - { - closesocket(Sock); - int Error = WSAGetLastError(); - CrySimple_ERROR("Couldn't create wsa event"); - return nullptr; - } - - return new CCrySimpleSock(Sock, this, wsaEvent); -#else - return new CCrySimpleSock(Sock, this); -#endif - } - - return nullptr; -} - -union CrySimpleRecvSize -{ - uint8_t m_Data8[8]; - uint64_t m_Data64; -}; - -static const int MAX_TIME_TO_WAIT = 10000; - -int CCrySimpleSock::Recv(char* acData, int len, int flags) -{ - int recived = SOCKET_ERROR; - int waitingtime = 0; - while (recived < 0) - { - recived = recv(m_pImpl->m_Socket, acData, len, flags); - if (recived == SOCKET_ERROR) - { - int WSAError = WSAGetLastError(); -#if defined(AZ_PLATFORM_WINDOWS) - if (WSAError == WSAEWOULDBLOCK) - { - // are we out of time - if (waitingtime > MAX_TIME_TO_WAIT) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Timeout on blocking. (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return recived; - } - - waitingtime += 5; - - // sleep a bit and try again - Sleep(5); - } - else -#endif - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Network error. (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return recived; - } - } - } - - return recived; -} - -bool CCrySimpleSock::Recv(std::vector& rVec) -{ - CrySimpleRecvSize size; - - int received = Recv(reinterpret_cast(&size.m_Data8[0]), 8, 0); - if (received != 8) - { -#if defined(AZ_PLATFORM_WINDOWS) - int WSAError = WSAGetLastError(); -#else - int WSAError = errno; -#endif - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Invalid size (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - return false; - } - - if (size.m_Data64 == 0) - { - int WSAError = WSAGetLastError(); - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Size of zero (Error Code: %i)", WSAError); - CrySimple_ERROR(acTmp); - - return false; - } - - if (size.m_Data64 > MAX_DATA_SIZE) - { - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving size of data - Size is greater than max support data size."); - CrySimple_ERROR(acTmp); - - return false; - } - - m_pImpl->m_SwapEndian = (size.m_Data64 >> 32) != 0; - if (m_pImpl->m_SwapEndian) - { - CSTLHelper::EndianSwizzleU64(size.m_Data64); - } - - rVec.clear(); - rVec.resize(static_cast(size.m_Data64)); - - for (uint32_t a = 0; a < size.m_Data64; ) - { - int read = Recv(reinterpret_cast(&rVec[a]), static_cast(size.m_Data64) - a, 0); - if (read <= 0) - { - int WSAError = WSAGetLastError(); - char acTmp[MAX_ERROR_MESSAGE_SIZE]; - azsprintf(acTmp, "Error while receiving tcp-data (size: %d - Error Code: %i)", static_cast(size.m_Data64), WSAError); - CrySimple_ERROR(acTmp); - return false; - } - a += read; - } - - m_pImpl->m_bHasReceivedData = true; - - return true; -} - -bool CCrySimpleSock::RecvResult() -{ - CrySimpleRecvSize size; - if (recv(m_pImpl->m_Socket, reinterpret_cast(&size.m_Data8[0]), 8, 0) != 8) - { - CrySimple_ERROR("Error while receiving result"); - return false; - } - - return size.m_Data64 > 0; -} - - -void CCrySimpleSock::Forward(const std::vector& rVecIn) -{ - tdDataVector& rVec = m_pImpl->m_tempSendBuffer; - rVec.resize(rVecIn.size() + 8); - CrySimpleRecvSize& rHeader = *(CrySimpleRecvSize*)(&rVec[0]); - rHeader.m_Data64 = (uint32_t)rVecIn.size(); - memcpy(&rVec[8], &rVecIn[0], rVecIn.size()); - - CrySimpleRecvSize size; - size.m_Data64 = static_cast(rVec.size()); - for (uint64_t a = 0; a < size.m_Data64; a += BLOCKSIZE) - { - char* pData = reinterpret_cast(&rVec[(size_t)a]); - int nSendRes = send(m_pImpl->m_Socket, pData, std::min(static_cast(size.m_Data64 - a), BLOCKSIZE), 0); - if (nSendRes == SOCKET_ERROR) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send(forward) error: %d", nLastSendError); - } - } -} - - -bool CCrySimpleSock::Backward(std::vector& rVec) -{ - uint32_t size; - if (recv(m_pImpl->m_Socket, reinterpret_cast(&size), 4, 0) != 4) - { - CrySimple_ERROR("Error while receiving size of data"); - return false; - } - - rVec.clear(); - rVec.resize(static_cast(size)); - - for (uint32_t a = 0; a < size; ) - { - int read = recv(m_pImpl->m_Socket, reinterpret_cast(&rVec[a]), size - a, 0); - if (read <= 0) - { - CrySimple_ERROR("Error while receiving tcp-data"); - return false; - } - a += read; - } - return true; -} - -void CCrySimpleSock::Send(const std::vector& rVecIn, size_t state, EProtocolVersion version) -{ - const size_t offset = version == EPV_V001 ? 4 : 5; - tdDataVector& rVec = m_pImpl->m_tempSendBuffer; - rVec.resize(rVecIn.size() + offset); - if (rVecIn.size()) - { - *(uint32_t*)(&rVec[0]) = (uint32_t)rVecIn.size(); - memcpy(&rVec[offset], &rVecIn[0], rVecIn.size()); - } - - if (version >= EPV_V002) - { - rVec[4] = static_cast(state); - } - - if (m_pImpl->m_SwapEndian) - { - CSTLHelper::EndianSwizzleU32(*(uint32_t*)&rVec[0]); - } - - // send can fail, you must retry unsent parts. - size_t remainingBytes = rVec.size(); - const char* pData = reinterpret_cast(rVec.data()); - - while (remainingBytes != 0) - { - size_t sendThisRound = remainingBytes; - if (sendThisRound > BLOCKSIZE) - { - sendThisRound = BLOCKSIZE; - } - - int bytesActuallySent = send(m_pImpl->m_Socket, pData, static_cast(sendThisRound), 0); - if (bytesActuallySent < 0) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send error: %d", nLastSendError); - m_pImpl->m_bHasSendData = true; - return; - } - size_t actuallySent = static_cast(bytesActuallySent); - - remainingBytes -= actuallySent; - pData += actuallySent; - } - - m_pImpl->m_bHasSendData = true; -} - - -void CCrySimpleSock::Send(const std::string& rData) -{ - const size_t S = rData.size(); - - for (uint64_t a = 0; a < S; a += BLOCKSIZE) - { - const char* pData = &rData.c_str()[a]; - const int nSendRes = send(m_pImpl->m_Socket, pData, std::min(static_cast(S - a), BLOCKSIZE), 0); - if (nSendRes == SOCKET_ERROR) - { - int nLastSendError = WSAGetLastError(); - logmessage("Socket send error: %d", nLastSendError); - } - else - { - m_pImpl->m_bHasSendData = true; - } - } -} - -uint32_t CCrySimpleSock::PeerIP() -{ - struct sockaddr_in addr; -#if defined(AZ_PLATFORM_WINDOWS) - int addr_size = sizeof(sockaddr_in); -#else - socklen_t addr_size = sizeof(sockaddr_in); -#endif - int nRes = getpeername(m_pImpl->m_Socket, (sockaddr*) &addr, &addr_size); - if (nRes == SOCKET_ERROR) - { - int nError = WSAGetLastError(); - logmessage("Socket getpeername error: %d", nError); - return 0; - } -#if defined(AZ_PLATFORM_WINDOWS) - return addr.sin_addr.S_un.S_addr; -#else - return addr.sin_addr.s_addr; -#endif -} - -bool CCrySimpleSock::Valid() const -{ - return m_pImpl->m_Socket != INVALID_SOCKET; -} - -void CCrySimpleSock::WaitForShutDownEvent(bool bValue) -{ - m_pImpl->m_WaitForShutdownEvent = bValue; -} - -long CCrySimpleSock::GetOpenSockets() -{ - return numberOfOpenSockets; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp deleted file mode 100644 index ef35f03c03..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/CrySimpleSock.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __CRYSIMPLESOCK__ -#define __CRYSIMPLESOCK__ - -#include -#include - -#include -#include - -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -typedef int SOCKET; -#define INVALID_SOCKET (-1) -#define SOCKET_ERROR (-1) -#include -#include -#include -#include -#define closesocket close -#else -#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS -#define _WINSOCK_DEPRECATED_NO_WARNINGS // till we swtich to in inet_pton and getaddrinfo -#endif -#include -#endif - -#include -#include - -//#define USE_WSAEVENTS - -enum EProtocolVersion -{ - EPV_V001, - EPV_V002, - EPV_V0021, - EPV_V0022, - EPV_V0023, -}; - -class CCrySimpleSock -{ -public: - - -#ifdef USE_WSAEVENTS - CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance, WSAEVENT wsaEvent); -#else - CCrySimpleSock(SOCKET Sock, CCrySimpleSock* pInstance); -#endif - CCrySimpleSock(const CCrySimpleSock&); - - CCrySimpleSock(const std::string& rServerName, uint16_t Port); - CCrySimpleSock(uint16_t Port, const std::vector& ipWhiteList); - - ~CCrySimpleSock(); - - void InitClient(); - void Release(); - - int Recv(char* acData, int len, int flags); - - void Listen(); - - - CCrySimpleSock* Accept(); - - bool Recv(std::vector& rVec); - bool RecvResult(); - - bool Backward(std::vector& rVec); - void Send(const std::vector& rVec, size_t State, EProtocolVersion Version); - void Forward(const std::vector& rVec); - - //used for HTML - void Send(const std::string& rData); - - uint32_t PeerIP(); - - bool Valid() const; - - void WaitForShutDownEvent(bool bValue); - - static long GetOpenSockets(); - - -private: - struct Implementation; - std::unique_ptr m_pImpl; -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp deleted file mode 100644 index 5de6e64ae8..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "ShaderList.hpp" -#include -#include - -#include "CrySimpleServer.hpp" - -#include - -#include -#ifdef _MSC_VER -#include -#include -#endif -#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC) -#include -#include -#include -#include -#endif - -static bool g_bSaveThread = false; - -CShaderList& CShaderList::Instance() -{ - static CShaderList g_Cache; - return g_Cache; -} - -////////////////////////////////////////////////////////////////////////// -CShaderList::CShaderList() -{ - m_lastTime = 0; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Tick() -{ -#if defined(AZ_PLATFORM_WINDOWS) - DWORD t = GetTickCount(); -#else - unsigned long t = time(nullptr)*1000; // Current time in milliseconds -#endif - if (t < m_lastTime || (t - m_lastTime) > 1000) //check every second - { - m_lastTime = t; - - Save(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Add(const std::string& rShaderListName, const char* pLine) -{ - tdShaderLists::iterator it; - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - it = m_ShaderLists.find(rShaderListName); - //not existing yet? - if (it == m_ShaderLists.end()) - { - CCrySimpleMutexAutoLock Lock2(m_Mutex2); //load/save mutex - m_ShaderLists[rShaderListName] = new CShaderListFile(rShaderListName); - it = m_ShaderLists.find(rShaderListName); - it->second->Load((SEnviropment::Instance().m_CachePath / AZStd::string_view{ rShaderListName.c_str(), rShaderListName.size() }).c_str()); - } - } - it->second->InsertLine(pLine); -} - - -////////////////////////////////////////////////////////////////////////// -void CShaderList::Save() -{ - CCrySimpleMutexAutoLock Lock(m_Mutex2); //load/save mutex - for (tdShaderLists::iterator it = m_ShaderLists.begin(); it != m_ShaderLists.end(); ++it) - { - it->second->MergeNewLinesAndSave(); - } -} - -////////////////////////////////////////////////////////////////////////// -CShaderListFile::CShaderListFile(std::string ListName) -{ - m_bModified = false; - - m_listname = ListName; - - // some test cases - SMetaData MD; - assert(CheckSyntax("<1>watervolume@WaterVolumeOutofPS()()(0)(0)(0)(ps_2_0)", MD) == true); - assert(CheckSyntax("<1>Blurcloak@BlurCloakPS(%BUMP_MAP)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)(0)(0)(1)(ps_2_0)", MD) == true); - assert(CheckSyntax("<1>Burninglayer@BurnPS()(%_RT_ADDBLEND|%_RT_)HDR_MODE|%_RT_BUMP|%_RT_3DC)(0)(0)(0)(ps_2_0)", MD) == false); - assert(CheckSyntax("<1>Illum@IlluminationVS(%DIFFUSE|%SPECULAR|%BUMP_MAP|%VERTCOLORS|%STAT_BRANCHING)(%_RT_RAE_GEOMTERM)(101)(0)(0)(vs_2_0)", MD) == true); - - assert(CheckSyntax("<660><2>Cloth@Common_SG_VS()(%_RT_QUALITY|%_RT_SHAPEDEFORM|%_RT_SKELETON_SSD|%_RT_HW_PCF_COMPARE)(0)(0)(0)(VS)", MD) == true); - assert(CheckSyntax("<6452><2>ShadowMaskGen@FrustumClipVolumeVS()()(0)(0)(0)(VS)", MD) == true); - assert(CheckSyntax("<5604><2>ParticlesNoMat@ParticlePS()(%_RT_FOG|%_RT_AMBIENT|%_RT_ALPHABLEND|%_RT_QUALITY1)(0)(0)(0)(PS)", MD) == true); -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Reload() -{ - return Load(m_filename.c_str()); -} - -void CShaderListFile::CreatePath(const std::string& rPath) -{ - std::string Path = rPath; - CSTLHelper::Replace(Path, rPath, "\\", "/"); - tdEntryVec rToks; - CSTLHelper::Tokenize(rToks, Path, "/"); - - Path = ""; - for (size_t a = 0; a + 1 < rToks.size(); a++) - { - Path += rToks[a] + "/"; -#if defined(AZ_PLATFORM_WINDOWS) - _mkdir(Path.c_str()); -#else - mkdir(Path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); -#endif - } -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Load(const char* filename) -{ - CreatePath(filename); - printf("Loading ShaderList file: %s\n", filename); - m_filename = filename; - m_filenametmp = filename; - m_filenametmp += ".tmp"; - FILE* f = nullptr; - azfopen(&f, filename, "rt"); - if (!f) - { - return false; - } - - int nNumLines = 0; - m_entries.clear(); - char str[65535]; - while (fgets(str, sizeof(str), f) != NULL) - { - if (*str && InsertLineInternal(str)) - { - ++nNumLines; - } - } - fclose(f); - if (nNumLines == m_entries.size()) - { - m_bModified = false; - } - else - { - m_bModified = true; - } - - printf("Loaded %d combination for %s\n", nNumLines, filename); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::Save() -{ - //not needed regarding timur, m_entries is just accessed by one thread - //CCrySimpleMutexAutoLock Lock(m_Mutex); - - CreatePath(m_filename); - if (m_filename.empty()) - { - return false; - } - - // write to tmp file - FILE* f = nullptr; - azfopen(&f, m_filenametmp.c_str(), "wt"); - if (!f) - { - return false; - } - for (Entries::iterator it = m_entries.begin(); it != m_entries.end(); ++it) - { - const char* str = it->first.c_str(); - if (it->second.m_Count == -1) - { - fprintf(f, "<%d>%s\n", it->second.m_Version, str); - } - else - { - fprintf(f, "<%d><%d>%s\n", it->second.m_Count, it->second.m_Version, str); - } - } - fclose(f); - - // first check if original file excists - f = nullptr; - azfopen(&f, m_filename.c_str(), "rt"); - if (f) - { - fclose(f); - - // remove original file (keep on trying until success - shadercompiler could currently be copying it for example) - int sleeptime = 0; - while (remove(m_filename.c_str())) - { - Sleep(100); - - sleeptime += 100; - if (sleeptime > 5000) - { - break; - } - } - } - - { - int sleeptime = 0; - while (rename(m_filenametmp.c_str(), m_filename.c_str())) - { - Sleep(100); - - sleeptime += 100; - if (sleeptime > 5000) - { - break; - } - } - } - - m_bModified = false; - return true; -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsHexNumberCharacter(const char c) -{ - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsDecNumberCharacter(const char c) -{ - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -////////////////////////////////////////////////////////////////////////// -inline bool IsNameCharacter(const char c) -{ - return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || c == '@' || c == '/' || c == '%' || c == '_'; -} - -int shGetHex(const char* buf) -{ - if (!buf) - { - return 0; - } - int i = 0; - - azsscanf(buf, "%x", &i); - - return i; -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::CheckSyntax(const char* szLine, SMetaData& rMD, const char** sOutStr) -{ - assert(szLine); - if (!szLine) - { - return false; - } - - if (sOutStr) - { - *sOutStr = 0; - } - - // e.g. Blurcloak@BlurCloakPS(%BUMP_MAP|%SPECULAR)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)(0)(0)(0)(ps_2_0) - - const char* p = szLine; - - if (strlen(szLine) < 4) - { - return false; - } - - int Value0 = 0; - int Value1 = 0; - - if (*p != '<') - { - return false; - } - - char Last = 0; - while (IsDecNumberCharacter(Last = *++p)) - { - Value0 = Value0 * 10 + (Last - '0'); - } - - if (*p++ != '>') - { - return false; - } - - if (*p == '<') - { - while (IsDecNumberCharacter(Last = *++p)) - { - Value1 = Value1 * 10 + (Last - '0'); - } - - if (*p++ != '>') - { - return false; - } - - rMD.m_Version = Value1; - rMD.m_Count = Value0; - } - else - { - rMD.m_Version = Value0; - rMD.m_Count = -1; - } - - const char* pStart = p; - - // e.g. "Blurcloak@BlurCloakPS" - while (IsNameCharacter(*p++)) - { - ; - } - p--; - - // e.g. "(%BUMP_MAP|%SPECULAR)(%_RT_FOG|%_RT_HDR_MODE|%_RT_BUMP)" - for (int i = 0; i < 2; ++i) - { - if (*p++ != '(') - { - return false; - } - while (true) - { - while (IsNameCharacter(*p++)) - { - ; - } - p--; - if (*p != '|') - { - break; - } - p++; - } - if (*p++ != ')') - { - return false; - } - } - - // e.g. "(0)(0)(0)" - for (int i = 0; i < 3; ++i) - { - if (*p++ != '(') - { - return false; - } - while (IsHexNumberCharacter(*p++)) - { - ; - } - p--; - if (*p++ != ')') - { - return false; - } - } - - // e.g. "(ps_2_0)" - if (*p++ != '(') - { - return false; - } - while (IsNameCharacter(*p++)) - { - ; - } - p--; - if (*p++ != ')') - { - return false; - } - - // Copy rest of the line. - if (sOutStr) - { - *sOutStr = pStart; - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::InsertLine(const char* szLine) -{ - if (*szLine != 0) - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - m_newLines.push_back(szLine); - m_bModified = true; - } -} - -////////////////////////////////////////////////////////////////////////// -bool CShaderListFile::InsertLineInternal(const char* szLine) -{ - const char* szCorrectedLine = 0; - SMetaData MD; - if (CheckSyntax(szLine, MD, &szCorrectedLine)) - { - // Trim \n\r - char* s = const_cast(szCorrectedLine); - for (size_t p = strlen(s) - 1; p > 0; p--) - { - if (s[p] == '\n' || s[p] == '\r') - { - s[p] = '\0'; - } - else - { - break; - } - } - - if (szCorrectedLine) - { - Entries::iterator it = m_entries.find(szCorrectedLine); - if (it == m_entries.end()) - { - m_entries[szCorrectedLine] = MD; - m_bModified = true; - } - else - { - if (it->second.m_Version < MD.m_Version) - { - it->second = MD; - m_bModified = true; - } - else - if (it->second.m_Count < MD.m_Count) - { - it->second.m_Count = MD.m_Count; - m_bModified = true; - } - } - } - return true; - } - - - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::MergeNewLines() -{ - std::vector newLines; - - { - CCrySimpleMutexAutoLock Lock(m_Mutex); - newLines.swap(m_newLines); - } - - m_bModified = false; - - if (newLines.empty()) - { - return; - } - - for (std::vector::iterator it = newLines.begin(); it != newLines.end(); ++it) - { - InsertLineInternal((*it).c_str()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CShaderListFile::MergeNewLinesAndSave() -{ - if (m_bModified) - { - MergeNewLines(); - } - if (m_bModified) - { - if (SEnviropment::Instance().m_PrintListUpdates) - { - logmessage("Updating: %s\n", m_listname.c_str()); - } - Save(); - } -} diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp deleted file mode 100644 index f624581b5f..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/Server/ShaderList.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __SHADERLIST__ -#define __SHADERLIST__ - -#include -#include -#include - -#include "CrySimpleMutex.hpp" - -#include -#include -#include - -class CShaderListFile -{ - ////////////////////////////////////////////////////////////////////////// - struct SMetaData - { - SMetaData() - : m_Version(0) - , m_Count(-1) - {} - int32_t m_Version; - int32_t m_Count; - }; - bool m_bModified; - std::string m_listname; - std::string m_filename; - std::string m_filenametmp; - typedef std::map Entries; - Entries m_entries; - std::vector m_newLines; - - CCrySimpleMutex m_Mutex; - - //do not copy -> not safe - CShaderListFile(const CShaderListFile&); - CShaderListFile& operator=(const CShaderListFile&); - -public: - CShaderListFile(std::string ListName); - - bool Load(const char* filename); - bool Save(); - bool Reload(); - bool IsModified() const { return m_bModified; } - - void InsertLine(const char* szLine); - void MergeNewLinesAndSave(); - -private: - void CreatePath(const std::string& rPath); - void MergeNewLines(); - // Returns: - // true - line was instered, false otherwise - bool InsertLineInternal(const char* szLine); - - // Returns - // true=syntax is ok, false=syntax is wrong - static bool CheckSyntax(const char* szLine, SMetaData& rMD, const char** sOutStr = NULL); -}; - -typedef std::map tdShaderLists; - -class CShaderList -{ - CCrySimpleMutex m_Mutex; - CCrySimpleMutex m_Mutex2; - unsigned long m_lastTime; - - tdShaderLists m_ShaderLists; - - void Save(); -public: - static CShaderList& Instance(); - CShaderList(); - - void Add(const std::string& rShaderListName, const char* pLine); - void Tick(); -}; - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp deleted file mode 100644 index c505d91a51..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/StdTypes.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef __STDTYPES_DUMMY__ -#define __STDTYPES_DUMMY__ - -#include - - -#if defined(AZ_PLATFORM_WINDOWS) -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef signed __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#endif - -#if defined(UNIX) -#include -#include "Core/UnixCompat.h" -#endif - -#if defined(AZ_PLATFORM_MAC) -#include -#endif - -#endif - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp deleted file mode 100644 index 8e23fcfb78..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "WindowsAPIImplementation.h" - -#if defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX) - -#include -#include -#import -#include - -bool QueryPerformanceCounter(LARGE_INTEGER* counter) -{ -#if defined(LINUX) - // replaced gettimeofday - // http://fixunix.com/kernel/378888-gettimeofday-resolution-linux.html - timespec tv; - clock_gettime(CLOCK_MONOTONIC, &tv); - counter->QuadPart = (uint64_t)tv.tv_sec * 1000000 + tv.tv_nsec / 1000; -#elif defined(APPLE) - counter->QuadPart = mach_absolute_time(); -#endif - return true; -} - -bool QueryPerformanceFrequency(LARGE_INTEGER* frequency) -{ -#if defined(LINUX) - // On Linux we'll use gettimeofday(). The API resolution is microseconds, - // so we'll report that to the caller. - frequency->u.LowPart = 1000000; - frequency->u.HighPart = 0; -#elif defined(APPLE) - static mach_timebase_info_data_t s_kTimeBaseInfoData; - if (s_kTimeBaseInfoData.denom == 0) - { - mach_timebase_info(&s_kTimeBaseInfoData); - } - // mach_timebase_info_data_t expresses the tick period in nanoseconds - frequency->QuadPart = 1e+9 * (uint64_t)s_kTimeBaseInfoData.denom / (uint64_t)s_kTimeBaseInfoData.numer; -#endif - return true; -} - -int WSAGetLastError() -{ - return errno; -} - -DWORD Sleep(DWORD dwMilliseconds) -{ - timespec req; - timespec rem; - - memset(&req, 0, sizeof(req)); - memset(&rem, 0, sizeof(rem)); - - time_t sec = (int)(dwMilliseconds / 1000); - req.tv_sec = sec; - req.tv_nsec = (dwMilliseconds - (sec * 1000)) * 1000000L; - if (nanosleep(&req, &rem) == -1) - { - nanosleep(&rem, 0); - } - - return 0; -} - - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h b/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h deleted file mode 100644 index 5879612917..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Core/WindowsAPIImplementation.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#include -#include - -#if defined(AZ_PLATFORM_MAC) || defined(AZ_PLATFORM_LINUX) -#include - -#ifndef MAX_PATH -#define MAX_PATH PATH_MAX -#endif - -typedef uint32_t DWORD; - -typedef union _LARGE_INTEGER -{ - struct - { - uint32_t LowPart; - int32_t HighPart; - }; - struct - { - uint32_t LowPart; - int32_t HighPart; - } u; - - int64_t QuadPart; -} LARGE_INTEGER; - -bool QueryPerformanceCounter(LARGE_INTEGER* counter); - -bool QueryPerformanceFrequency(LARGE_INTEGER* frequency); - -int WSAGetLastError(); - -DWORD Sleep(DWORD dwMilliseconds); - -#if defined(AZ_PLATFORM_LINUX) - -namespace PthreadImplementation -{ - static pthread_mutex_t g_interlockMutex; -} - -template -const volatile T InterlockedIncrement(volatile T* pT) -{ - pthread_mutex_lock(&PthreadImplementation::g_interlockMutex); - ++(*pT); - pthread_mutex_unlock(&PthreadImplementation::g_interlockMutex); - return *pT; -} - -template -const volatile T InterlockedDecrement(volatile T* pT) -{ - pthread_mutex_lock(&PthreadImplementation::g_interlockMutex); - --(*pT); - pthread_mutex_unlock(&PthreadImplementation::g_interlockMutex); - return *pT; -} - -#endif - -#endif diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp deleted file mode 100644 index cec8628d30..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/CrySCompileServer.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "Core/StdTypes.hpp" -#include "Core/Server/CrySimpleServer.hpp" -#include "Core/Server/CrySimpleHTTP.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#if AZ_TRAIT_OS_PLATFORM_APPLE -// Needed for geteuid() -#include -#include -#endif - -namespace -{ - const int STD_TCP_PORT = 61453; - const int DEFAULT_MAX_CONNECTIONS = 255; -} - -////////////////////////////////////////////////////////////////////////// -class CConfigFile -{ -public: - CConfigFile() {} - ////////////////////////////////////////////////////////////////////////// - void OnLoadConfigurationEntry(const std::string& strKey, const std::string& strValue, [[maybe_unused]] const std::string& strGroup) - { - if (azstricmp(strKey.c_str(), "MailError") == 0) - { - SEnviropment::Instance().m_FailEMail = strValue; - } - if (azstricmp(strKey.c_str(), "port") == 0) - { - SEnviropment::Instance().m_port = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "MailInterval") == 0) - { - SEnviropment::Instance().m_MailInterval = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "TempDir") == 0) - { - SEnviropment::Instance().m_TempPath = AZStd::string_view{ strValue.c_str(), strValue.size() }; - } - if (azstricmp(strKey.c_str(), "MailServer") == 0) - { - SEnviropment::Instance().m_MailServer = strValue; - } - if (azstricmp(strKey.c_str(), "Caching") == 0) - { - SEnviropment::Instance().m_Caching = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintErrors") == 0) - { - SEnviropment::Instance().m_PrintErrors = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintWarnings") == 0) - { - SEnviropment::Instance().m_PrintWarnings = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintCommands") == 0) - { - SEnviropment::Instance().m_PrintCommands = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "PrintListUpdates") == 0) - { - SEnviropment::Instance().m_PrintListUpdates = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "DedupeErrors") == 0) - { - SEnviropment::Instance().m_DedupeErrors = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "FallbackServer") == 0) - { - SEnviropment::Instance().m_FallbackServer = strValue; - } - if (azstricmp(strKey.c_str(), "FallbackTreshold") == 0) - { - SEnviropment::Instance().m_FallbackTreshold = atoi(strValue.c_str()); - } - if (azstricmp(strKey.c_str(), "DumpShaders") == 0) - { - SEnviropment::Instance().m_DumpShaders = atoi(strValue.c_str()) != 0; - } - if (azstricmp(strKey.c_str(), "MaxConnections") == 0) - { - int maxConnections = atoi(strValue.c_str()); - if (maxConnections <= 0) - { - printf("Warning: MaxConnections value is invalid. Using default value of %d\n", DEFAULT_MAX_CONNECTIONS); - } - else - { - SEnviropment::Instance().m_MaxConnections = maxConnections; - } - } - if (azstricmp(strKey.c_str(), "whitelist") == 0 || azstricmp(strKey.c_str(), "white_list") == 0) - { - std::regex ip4_address_regex("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))?$"); - AZStd::vector addresses; - AzFramework::StringFunc::Tokenize(strValue.c_str(), addresses, ','); - for (const auto& address : addresses) - { - if (std::regex_match(address.c_str(), ip4_address_regex)) - { - SEnviropment::Instance().m_WhitelistAddresses.push_back(address); - } - else - { - printf("Warning: invalid IP address in the whitelist field: %s", address.c_str()); - } - } - } - if (azstricmp(strKey.c_str(), "AllowElevatedPermissions") == 0) - { - int runAsRoot = atoi(strValue.c_str()); - SEnviropment::Instance().m_RunAsRoot = (runAsRoot == 1); - } - -#if defined(TOOLS_SUPPORT_JASPER) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, jasper) -#endif -#if defined(TOOLS_SUPPORT_PROVO) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, provo) -#endif -#if defined(TOOLS_SUPPORT_SALEM) -#include AZ_RESTRICTED_FILE_EXPLICIT(CrySCompileServer_cpp, salem) -#endif - } - - ////////////////////////////////////////////////////////////////////////// - bool ParseConfig(const char* filename) - { - FILE* file = nullptr; - azfopen(&file, filename, "rb"); - if (!file) - { - std::cout << "Config file not found" << std::endl; - return false; - } - - fseek(file, 0, SEEK_END); - int nLen = ftell(file); - fseek(file, 0, SEEK_SET); - - char* sAllText = new char [nLen + 16]; - - fread(sAllText, 1, nLen, file); - - sAllText[nLen] = '\0'; - sAllText[nLen + 1] = '\0'; - - std::string strGroup; // current group e.g. "[General]" - - char* strLast = sAllText + nLen; - char* str = sAllText; - while (str < strLast) - { - char* s = str; - while (str < strLast && *str != '\n' && *str != '\r') - { - str++; - } - *str = '\0'; - str++; - while (str < strLast && (*str == '\n' || *str == '\r')) - { - str++; - } - - - std::string strLine = s; - - // detect groups e.g. "[General]" should set strGroup="General" - { - std::string strTrimmedLine(RemoveWhiteSpaces(strLine)); - size_t size = strTrimmedLine.size(); - - if (size >= 3) - { - if (strTrimmedLine[0] == '[' && strTrimmedLine[size - 1] == ']') // currently no comments are allowed to be behind groups - { - strGroup = &strTrimmedLine[1]; - strGroup.resize(size - 2); // remove [ and ] - continue; // next line - } - } - } - - // skip comments - if (0 < strLine.find("--")) - { - // extract key - std::string::size_type posEq(strLine.find("=", 0)); - if (std::string::npos != posEq) - { - std::string stemp(strLine, 0, posEq); - std::string strKey(RemoveWhiteSpaces(stemp)); - - // if (!strKey.empty()) - { - // extract value - std::string::size_type posValueStart(strLine.find("\"", posEq + 1) + 1); - // std::string::size_type posValueEnd( strLine.find( "\"", posValueStart ) ); - std::string::size_type posValueEnd(strLine.rfind('\"')); - - std::string strValue; - - if (std::string::npos != posValueStart && std::string::npos != posValueEnd) - { - strValue = std::string(strLine, posValueStart, posValueEnd - posValueStart); - } - else - { - std::string strTmp(strLine, posEq + 1, strLine.size() - (posEq + 1)); - strValue = RemoveWhiteSpaces(strTmp); - } - OnLoadConfigurationEntry(strKey, strValue, strGroup); - } - } - } //-- - } - delete []sAllText; - fclose(file); - - return true; - } - std::string RemoveWhiteSpaces(std::string& str) - { - std::string::size_type pos1 = str.find_first_not_of(' '); - std::string::size_type pos2 = str.find_last_not_of(' '); - str = str.substr(pos1 == std::string::npos ? 0 : pos1, pos2 == std::string::npos ? str.length() - 1 : pos2 - pos1 + 1); - return str; - } - std::string AddSlash(const std::string& str) - { - if (!str.empty() && - (str[str.size() - 1] != '\\') && - (str[str.size() - 1] != '/')) - { - return str + "/"; - } - return str; - } -}; - -namespace -{ - AZ::JobManager* jobManager; - AZ::JobContext* globalJobContext; - -#if defined(AZ_PLATFORM_WINDOWS) - BOOL ControlHandler([[maybe_unused]] DWORD controlType) - { - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - return FALSE; - } -#endif -} - -void InitDefaults() -{ - SEnviropment::Instance().m_port = STD_TCP_PORT; - SEnviropment::Instance().m_MaxConnections = DEFAULT_MAX_CONNECTIONS; - SEnviropment::Instance().m_FailEMail = ""; - SEnviropment::Instance().m_MailInterval = 10; - SEnviropment::Instance().m_MailServer = "example.com"; - SEnviropment::Instance().m_Caching = true; - SEnviropment::Instance().m_PrintErrors = true; - SEnviropment::Instance().m_PrintWarnings = false; - SEnviropment::Instance().m_PrintCommands = false; - SEnviropment::Instance().m_DedupeErrors = true; - SEnviropment::Instance().m_PrintListUpdates = true; - SEnviropment::Instance().m_FallbackTreshold = 16; - SEnviropment::Instance().m_FallbackServer = ""; - SEnviropment::Instance().m_WhitelistAddresses.push_back("127.0.0.1"); - SEnviropment::Instance().m_RunAsRoot = false; - SEnviropment::Instance().InitializePlatformAttributes(); -} - -bool ReadConfigFile() -{ - char executableDir[AZ_MAX_PATH_LEN]; - if (AZ::Utils::GetExecutableDirectory(executableDir, AZ_MAX_PATH_LEN) == AZ::Utils::ExecutablePathResult::Success) - { - auto configFilename = AZ::IO::Path(executableDir).Append("config.ini"); - CConfigFile config; - config.ParseConfig(configFilename.c_str()); - return true; - } - else - { - printf("error: failed to get executable directory.\n"); - return false; - } -} - -void RunServer(bool isRunningAsRoot) -{ - if (isRunningAsRoot) - { - printf("\nWARNING: Attempting to run the CrySCompileServer as a user that has admininstrator permissions. This is a security risk and not recommended. Please run the service with a user account that does not have administrator permissions.\n\n"); - } - - if (!isRunningAsRoot || SEnviropment::Instance().m_RunAsRoot) - { - CCrySimpleHTTP HTTP; - CCrySimpleServer(); - } - else - { - printf("If you need to run CrySCompileServer with administrator permisions you can create/edit the config.ini file in the same directory as this executable and add the following line to it:\n\tAllowElevatedPermissions=1\n"); - } -} - -int main(int argc, [[maybe_unused]] char* argv[]) -{ - if (argc != 1) - { - printf("usage: run without arguments\n"); - return 0; - } - - bool isRunningAsRoot = false; - -#if defined(AZ_PLATFORM_WINDOWS) - // Check to see if we are running as root... - SID_IDENTIFIER_AUTHORITY ntAuthority = { SECURITY_NT_AUTHORITY }; - PSID administratorsGroup; - BOOL sidAllocated = AllocateAndInitializeSid( - &ntAuthority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &administratorsGroup); - - if(sidAllocated) - { - BOOL isRoot = FALSE; - if (!CheckTokenMembership( NULL, administratorsGroup, &isRoot)) - { - isRoot = FALSE; - } - FreeSid(administratorsGroup); - - isRunningAsRoot = (isRoot == TRUE); - } - -#if defined(_DEBUG) - int tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - tmpFlag |= _CRTDBG_LEAK_CHECK_DF; - // tmpFlag &= ~_CRTDBG_CHECK_CRT_DF; - _CrtSetDbgFlag(tmpFlag); -#endif - AZ_Verify(SetConsoleCtrlHandler(ControlHandler, TRUE), "Unable to setup windows console control handler"); -#else - // if either the effective user id or effective group id is root, then we - // are running as root - isRunningAsRoot = (geteuid() == 0 || getegid() == 0); -#endif - - AZ::AllocatorInstance::Create(); - AZ::AllocatorInstance::Create(); - - AZ::JobManagerDesc jobManagerDescription; - - int workers = AZStd::GetMin(AZStd::thread::hardware_concurrency(), static_cast(8)); - for (int idx = 0; idx < workers; ++idx) - { - jobManagerDescription.m_workerThreads.push_back(AZ::JobManagerThreadDesc()); - } - - jobManager = aznew AZ::JobManager(jobManagerDescription); - globalJobContext = aznew AZ::JobContext(*jobManager); - AZ::JobContext::SetGlobalContext(globalJobContext); - - SEnviropment::Create(); - - InitDefaults(); - - if (ReadConfigFile()) - { - RunServer(isRunningAsRoot); - } - - SEnviropment::Destroy(); - - AZ::JobContext::SetGlobalContext(nullptr); - delete globalJobContext; - delete jobManager; - - AZ::AllocatorInstance::Destroy(); - AZ::AllocatorInstance::Destroy(); - - return 0; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt deleted file mode 100644 index 89d9e8d38b..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/readme.txt +++ /dev/null @@ -1,530 +0,0 @@ -/** @mainpage - -

TinyXML

- -TinyXML is a simple, small, C++ XML parser that can be easily -integrated into other programs. - -

What it does.

- -In brief, TinyXML parses an XML document, and builds from that a -Document Object Model (DOM) that can be read, modified, and saved. - -XML stands for "eXtensible Markup Language." It allows you to create -your own document markups. Where HTML does a very good job of marking -documents for browsers, XML allows you to define any kind of document -markup, for example a document that describes a "to do" list for an -organizer application. XML is a very structured and convenient format. -All those random file formats created to store application data can -all be replaced with XML. One parser for everything. - -The best place for the complete, correct, and quite frankly hard to -read spec is at
-http://www.w3.org/TR/2004/REC-xml-20040204/. An intro to XML -(that I really like) can be found at -http://skew.org/xml/tutorial. - -There are different ways to access and interact with XML data. -TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed -into a C++ objects that can be browsed and manipulated, and then -written to disk or another output stream. You can also construct an XML document -from scratch with C++ objects and write this to disk or another output -stream. - -TinyXML is designed to be easy and fast to learn. It is two headers -and four cpp files. Simply add these to your project and off you go. -There is an example file - xmltest.cpp - to get you started. - -TinyXML is released under the ZLib license, -so you can use it in open source or commercial code. The details -of the license are at the top of every source file. - -TinyXML attempts to be a flexible parser, but with truly correct and -compliant XML output. TinyXML should compile on any reasonably C++ -compliant system. It does not rely on exceptions or RTTI. It can be -compiled with or without STL support. TinyXML fully supports -the UTF-8 encoding, and the first 64k character entities. - - -

What it doesn't do.

- -TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs -(eXtensible Stylesheet Language.) There are other parsers out there -(check out www.sourceforge.org, search for XML) that are much more fully -featured. But they are also much bigger, take longer to set up in -your project, have a higher learning curve, and often have a more -restrictive license. If you are working with browsers or have more -complete XML needs, TinyXML is not the parser for you. - -The following DTD syntax will not parse at this time in TinyXML: - -@verbatim - - ]> -@endverbatim - -because TinyXML sees this as a !DOCTYPE node with an illegally -embedded !ELEMENT node. This may be addressed in the future. - -

Tutorials.

- -For the impatient, here is a tutorial to get you going. A great way to get started, -but it is worth your time to read this (very short) manual completely. - -- @subpage tutorial0 - -

Code Status.

- -TinyXML is mature, tested code. It is very stable. If you find -bugs, please file a bug report on the sourceforge web site -(www.sourceforge.net/projects/tinyxml). We'll get them straightened -out as soon as possible. - -There are some areas of improvement; please check sourceforge if you are -interested in working on TinyXML. - -

Related Projects

- -TinyXML projects you may find useful! (Descriptions provided by the projects.) - -
    -
  • TinyXPath (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint - XPath syntax decoder, written in C++.
  • -
  • TinyXML++ (http://code.google.com/p/ticpp/). TinyXML++ is a completely new - interface to TinyXML that uses MANY of the C++ strengths. Templates, - exceptions, and much better error handling.
  • -
- -

Features

- -

Using STL

- -TinyXML can be compiled to use or not use STL. When using STL, TinyXML -uses the std::string class, and fully supports std::istream, std::ostream, -operator<<, and operator>>. Many API methods have both 'const char*' and -'const std::string&' forms. - -When STL support is compiled out, no STL files are included whatsoever. All -the string classes are implemented by TinyXML itself. API methods -all use the 'const char*' form for input. - -Use the compile time #define: - - TIXML_USE_STL - -to compile one version or the other. This can be passed by the compiler, -or set as the first line of "tinyxml.h". - -Note: If compiling the test code in Linux, setting the environment -variable TINYXML_USE_STL=YES/NO will control STL compilation. In the -Windows project file, STL and non STL targets are provided. In your project, -It's probably easiest to add the line "#define TIXML_USE_STL" as the first -line of tinyxml.h. - -

UTF-8

- -TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML -also supports "legacy mode" - the encoding used before UTF-8 support and -probably best described as "extended ascii". - -Normally, TinyXML will try to detect the correct encoding and use it. However, -by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML -can be forced to always use one encoding. - -TinyXML will assume Legacy Mode until one of the following occurs: -
    -
  1. If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf) - begin the file or data stream, TinyXML will read it as UTF-8.
  2. -
  3. If the declaration tag is read, and it has an encoding="UTF-8", then - TinyXML will read it as UTF-8.
  4. -
  5. If the declaration tag is read, and it has no encoding specified, then TinyXML will - read it as UTF-8.
  6. -
  7. If the declaration tag is read, and it has an encoding="something else", then TinyXML - will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's - not clear what that mode does exactly, but old content should keep working.
  8. -
  9. Until one of the above criteria is met, TinyXML runs in Legacy Mode.
  10. -
- -What happens if the encoding is incorrectly set or detected? TinyXML will try -to read and pass through text seen as improperly encoded. You may get some strange results or -mangled characters. You may want to force TinyXML to the correct mode. - -You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or -LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all -the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may -force it to TIXML_ENCODING_UTF8 with the same technique. - -For English users, using English XML, UTF-8 is the same as low-ASCII. You -don't need to be aware of UTF-8 or change your code in any way. You can think -of UTF-8 as a "superset" of ASCII. - -UTF-8 is not a double byte format - but it is a standard encoding of Unicode! -TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. -It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding -of unicode. This is a source of confusion. - -For "high-ascii" languages - everything not English, pretty much - TinyXML can -handle all languages, at the same time, as long as the XML is encoded -in UTF-8. That can be a little tricky, older programs and operating systems -tend to use the "default" or "traditional" code page. Many apps (and almost all -modern ones) can output UTF-8, but older or stubborn (or just broken) ones -still output text in the default code page. - -For example, Japanese systems traditionally use SHIFT-JIS encoding. -Text encoded as SHIFT-JIS can not be read by TinyXML. -A good text editor can import SHIFT-JIS and then save as UTF-8. - -The Skew.org link does a great -job covering the encoding issue. - -The test file "utf8test.xml" is an XML containing English, Spanish, Russian, -and Simplified Chinese. (Hopefully they are translated correctly). The file -"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that -if you don't have the correct fonts (Simplified Chinese or Russian) on your -system, you won't see output that matches the GIF file even if you can parse -it correctly. Also note that (at least on my Windows machine) console output -is in a Western code page, so that Print() or printf() cannot correctly display -the file. This is not a bug in TinyXML - just an OS issue. No data is lost or -destroyed by TinyXML. The console just doesn't render UTF-8. - - -

Entities

-TinyXML recognizes the pre-defined "character entities", meaning special -characters. Namely: - -@verbatim - & & - < < - > > - " " - ' ' -@endverbatim - -These are recognized when the XML document is read, and translated to there -UTF-8 equivalents. For instance, text with the XML of: - -@verbatim - Far & Away -@endverbatim - -will have the Value() of "Far & Away" when queried from the TiXmlText object, -and will be written back to the XML stream/file as an ampersand. Older versions -of TinyXML "preserved" character entities, but the newer versions will translate -them into characters. - -Additionally, any character can be specified by its Unicode code point: -The syntax " " or " " are both to the non-breaking space characher. - -

Printing

-TinyXML can print output in several different ways that all have strengths and limitations. - -- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout. - - "Pretty prints", but you don't have control over printing options. - - The output is streamed directly to the FILE object, so there is no memory overhead - in the TinyXML code. - - used by Print() and SaveFile() - -- operator<<. Output to a c++ stream. - - Integrates with standart C++ iostreams. - - Outputs in "network printing" mode without line breaks. Good for network transmission - and moving XML between C++ objects, but hard for a human to read. - -- TiXmlPrinter. Output to a std::string or memory buffer. - - API is less concise - - Future printing options will be put here. - - Printing may change slightly in future versions as it is refined and expanded. - -

Streams

-With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well -as C (FILE*) streams. There are some differences that you may need to be aware of. - -C style output: - - based on FILE* - - the Print() and SaveFile() methods - - Generates formatted output, with plenty of white space, intended to be as - human-readable as possible. They are very fast, and tolerant of ill formed - XML documents. For example, an XML document that contains 2 root elements - and 2 declarations, will still print. - -C style input: - - based on FILE* - - the Parse() and LoadFile() methods - - A fast, tolerant read. Use whenever you don't need the C++ streams. - -C++ style output: - - based on std::ostream - - operator<< - - Generates condensed output, intended for network transmission rather than - readability. Depending on your system's implementation of the ostream class, - these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML: - a document should contain the correct one root element. Additional root level - elements will not be streamed out. - -C++ style input: - - based on std::istream - - operator>> - - Reads XML from a stream, making it useful for network transmission. The tricky - part is knowing when the XML document is complete, since there will almost - certainly be other data in the stream. TinyXML will assume the XML data is - complete after it reads the root element. Put another way, documents that - are ill-constructed with more than one root element will not read correctly. - Also note that operator>> is somewhat slower than Parse, due to both - implementation of the STL and limitations of TinyXML. - -

White space

-The world simply does not agree on whether white space should be kept, or condensed. -For example, pretend the '_' is a space, and look at "Hello____world". HTML, and -at least some XML parsers, will interpret this as "Hello_world". They condense white -space. Some XML parsers do not, and will leave it as "Hello____world". (Remember -to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become -Hello___world. - -It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the -first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior. -The default is to condense white space. - -If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool ) -before making any calls to Parse XML data, and I don't recommend changing it after -it has been set. - - -

Handles

- -Where browsing an XML document in a robust way, it is important to check -for null returns from method calls. An error safe implementation can -generate a lot of code like: - -@verbatim -TiXmlElement* root = document.FirstChildElement( "Document" ); -if ( root ) -{ - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. -@endverbatim - -Handles have been introduced to clean this up. Using the TiXmlHandle class, -the previous code reduces to: - -@verbatim -TiXmlHandle docHandle( &document ); -TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); -if ( child2 ) -{ - // do something useful -@endverbatim - -Which is much easier to deal with. See TiXmlHandle for more information. - - -

Row and Column tracking

-Being able to track nodes and attributes back to their origin location -in source files can be very important for some applications. Additionally, -knowing where parsing errors occured in the original source can be very -time saving. - -TinyXML can tracks the row and column origin of all nodes and attributes -in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return -the origin of the node in the source text. The correct tabs can be -configured in TiXmlDocument::SetTabSize(). - - -

Using and Installing

- -To Compile and Run xmltest: - -A Linux Makefile and a Windows Visual C++ .dsw file is provided. -Simply compile and run. It will write the file demotest.xml to your -disk and generate output on the screen. It also tests walking the -DOM by printing out the number of nodes found using different -techniques. - -The Linux makefile is very generic and runs on many systems - it -is currently tested on mingw and -MacOSX. You do not need to run 'make depend'. The dependecies have been -hard coded. - -

Windows project file for VC6

-
    -
  • tinyxml: tinyxml library, non-STL
  • -
  • tinyxmlSTL: tinyxml library, STL
  • -
  • tinyXmlTest: test app, non-STL
  • -
  • tinyXmlTestSTL: test app, STL
  • -
- -

Makefile

-At the top of the makefile you can set: - -PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in -the makefile. - -In the tinyxml directory, type "make clean" then "make". The executable -file 'xmltest' will be created. - - - -

To Use in an Application:

- -Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your -project or make file. That's it! It should compile on any reasonably -compliant C++ system. You do not need to enable exceptions or -RTTI for TinyXML. - - -

How TinyXML works.

- -An example is probably the best way to go. Take: -@verbatim - - - - Go to the Toy store! - Do bills - -@endverbatim - -Its not much of a To Do list, but it will do. To read this file -(say "demo.xml") you would create a document, and parse it in: -@verbatim - TiXmlDocument doc( "demo.xml" ); - doc.LoadFile(); -@endverbatim - -And its ready to go. Now lets look at some lines and how they -relate to the DOM. - -@verbatim - -@endverbatim - - The first line is a declaration, and gets turned into the - TiXmlDeclaration class. It will be the first child of the - document node. - - This is the only directive/special tag parsed by TinyXML. - Generally directive tags are stored in TiXmlUnknown so the - commands wont be lost when it is saved back to disk. - -@verbatim - -@endverbatim - - A comment. Will become a TiXmlComment object. - -@verbatim - -@endverbatim - - The "ToDo" tag defines a TiXmlElement object. This one does not have - any attributes, but does contain 2 other elements. - -@verbatim - -@endverbatim - - Creates another TiXmlElement which is a child of the "ToDo" element. - This element has 1 attribute, with the name "priority" and the value - "1". - -@verbatim -Go to the -@endverbatim - - A TiXmlText. This is a leaf node and cannot contain other nodes. - It is a child of the "Item" TiXmlElement. - -@verbatim - -@endverbatim - - - Another TiXmlElement, this one a child of the "Item" element. - -Etc. - -Looking at the entire object tree, you end up with: -@verbatim -TiXmlDocument "demo.xml" - TiXmlDeclaration "version='1.0'" "standalone=no" - TiXmlComment " Our to do list data" - TiXmlElement "ToDo" - TiXmlElement "Item" Attribtutes: priority = 1 - TiXmlText "Go to the " - TiXmlElement "bold" - TiXmlText "Toy store!" - TiXmlElement "Item" Attributes: priority=2 - TiXmlText "Do bills" -@endverbatim - -

Documentation

- -The documentation is build with Doxygen, using the 'dox' -configuration file. - -

License

- -TinyXML is released under the zlib license: - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. - -

References

- -The World Wide Web Consortium is the definitive standard body for -XML, and their web pages contain huge amounts of information. - -The definitive spec: -http://www.w3.org/TR/2004/REC-xml-20040204/ - -I also recommend "XML Pocket Reference" by Robert Eckstein and published by -OReilly...the book that got the whole thing started. - -

Contributors, Contacts, and a Brief History

- -Thanks very much to everyone who sends suggestions, bugs, ideas, and -encouragement. It all helps, and makes this project fun. A special thanks -to the contributors on the web pages that keep it lively. - -So many people have sent in bugs and ideas, that rather than list here -we try to give credit due in the "changes.txt" file. - -TinyXML was originally written by Lee Thomason. (Often the "I" still -in the documentation.) Lee reviews changes and releases new versions, -with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community. - -We appreciate your suggestions, and would love to know if you -use TinyXML. Hopefully you will enjoy it and find it useful. -Please post questions, comments, file bugs, or contact us at: - -www.sourceforge.net/projects/tinyxml - -Lee Thomason, Yves Berquin, Andrew Ellerton -*/ diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp deleted file mode 100644 index b0e117d674..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -/* - * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. - */ - - -#ifndef TIXML_USE_STL - -#include "tinystr.h" - -// Error value for find primitive -const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); - - -// Null rep. -TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; - - -void TiXmlString::reserve (size_type cap) -{ - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } -} - - -TiXmlString& TiXmlString::assign(const char* str, size_type len) -{ - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; -} - - -TiXmlString& TiXmlString::append(const char* str, size_type len) -{ - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; -} - - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) -{ - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; -} - -TiXmlString operator + (const TiXmlString & a, const char* b) -{ - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; -} - -TiXmlString operator + (const char* a, const TiXmlString & b) -{ - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; -} - - -#endif // TIXML_USE_STL diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h deleted file mode 100644 index ab0cc81547..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinystr.h +++ /dev/null @@ -1,309 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates. - -/* -www.sourceforge.net/projects/tinyxml -Original file by Yves Berquin. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#ifndef TIXML_USE_STL - -#ifndef TIXML_STRING_INCLUDED -#define TIXML_STRING_INCLUDED - -#include -#include - -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: -*/ -#if defined(_MSC_VER) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit -#elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit -#else - #define TIXML_EXPLICIT -#endif - - -/* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase - a string and there's no more room, we allocate a buffer twice as big as we need. -*/ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - // = operator - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - // = operator - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; - -} ; - - -inline bool operator == (const TiXmlString & a, const TiXmlString & b) -{ - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare -} -inline bool operator < (const TiXmlString & a, const TiXmlString & b) -{ - return strcmp(a.c_str(), b.c_str()) < 0; -} - -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } - -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } - -TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); -TiXmlString operator + (const TiXmlString & a, const char* b); -TiXmlString operator + (const char* a, const TiXmlString & b); - - -/* - TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. - Only the operators that we need for TinyXML have been developped. -*/ -class TiXmlOutStream : public TiXmlString -{ -public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } - -} ; - -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp deleted file mode 100644 index 0915c669b3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.cpp +++ /dev/null @@ -1,1889 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - -#include - -#ifdef TIXML_USE_STL -#include -#include -#endif - -#include "tinyxml.h" - - -bool TiXmlBase::condenseWhiteSpace = true; - -// Microsoft compiler security -FILE* TiXmlFOpen( const char* filename, const char* mode ) -{ - #if defined(_MSC_VER) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - // Not using fopen_s() as it's not available in Mac or Linux - return fopen( filename, mode ); - #endif -} - -void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) -{ - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } -} - - -TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() -{ - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; -} - - -TiXmlNode::~TiXmlNode() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } -} - - -void TiXmlNode::CopyTo( TiXmlNode* target ) const -{ - target->SetValue (value.c_str() ); - target->userData = userData; -} - - -void TiXmlNode::Clear() -{ - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; - - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } - - firstChild = 0; - lastChild = 0; -} - - -TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) -{ - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - - if ( node->Type() == TiXmlNode::DOCUMENT ) - { - delete node; - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - node->parent = this; - - node->prev = lastChild; - node->next = 0; - - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. - - lastChild = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) -{ - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - - return LinkEndChild( node ); -} - - -TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; -} - - -TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) -{ - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::DOCUMENT ) - { - if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; -} - - -TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) -{ - if ( replaceThis->parent != this ) - return 0; - - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; - - node->next = replaceThis->next; - node->prev = replaceThis->prev; - - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; - - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; - - delete replaceThis; - node->parent = this; - return node; -} - - -bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) -{ - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } - - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; - - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; - - delete removeThis; - return true; -} - -const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } -} - - -const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const -{ - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } -} - - -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const -{ - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; -} - - -void TiXmlElement::RemoveAttribute( const char * name ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } -} - -const TiXmlElement* TiXmlNode::FirstChildElement() const -{ - const TiXmlNode* node; - - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement() const -{ - const TiXmlNode* node; - - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const -{ - const TiXmlNode* node; - - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; -} - - -const TiXmlDocument* TiXmlNode::GetDocument() const -{ - const TiXmlNode* node; - - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; -} - - -TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} - - -#ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - value = _value; -} -#endif - - -TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::ELEMENT ) -{ - firstChild = lastChild = 0; - copy.CopyTo( this ); -} - - -void TiXmlElement::operator=( const TiXmlElement& base ) -{ - ClearThis(); - base.CopyTo( this ); -} - - -TiXmlElement::~TiXmlElement() -{ - ClearThis(); -} - - -void TiXmlElement::ClearThis() -{ - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } -} - - -const char* TiXmlElement::Attribute( const char* name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return &node->ValueStr(); - return 0; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, int* i ) const -{ - const char* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s ); - } - else { - *i = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const -{ - const std::string* s = Attribute( name ); - if ( i ) - { - if ( s ) { - *i = atoi( s->c_str() ); - } - else { - *i = 0; - } - } - return s; -} -#endif - - -const char* TiXmlElement::Attribute( const char* name, double* d ) const -{ - const char* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s ); - } - else { - *d = 0; - } - } - return s; -} - - -#ifdef TIXML_USE_STL -const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const -{ - const std::string* s = Attribute( name ); - if ( d ) - { - if ( s ) { - *d = atof( s->c_str() ); - } - else { - *d = 0; - } - } - return s; -} -#endif - - -int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryIntValue( ival ); -} -#endif - - -int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} - - -#ifdef TIXML_USE_STL -int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const -{ - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - return node->QueryDoubleValue( dval ); -} -#endif - - -void TiXmlElement::SetAttribute( const char * name, int val ) -{ - char buf[64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); - #else - sprintf( buf, "%d", val ); - #endif - SetAttribute( name, buf ); -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - std::ostringstream oss; - oss << val; - SetAttribute( name, oss.str() ); -} -#endif - - -void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - char buf[256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); - #else - sprintf( buf, "%f", val ); - #endif - SetAttribute( name, buf ); -} - - -void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) -{ - #ifdef TIXML_USE_STL - TIXML_STRING _name( cname ); - TIXML_STRING _value( cvalue ); - #else - const char* _name = cname; - const char* _value = cvalue; - #endif - - TiXmlAttribute* node = attributeSet.Find( _name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} - - -#ifdef TIXML_USE_STL -void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) -{ - TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - { - node->SetValue( _value ); - return; - } - - TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); - if ( attrib ) - { - attributeSet.Add( attrib ); - } - else - { - TiXmlDocument* document = GetDocument(); - if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); - } -} -#endif - - -void TiXmlElement::Print( FILE* cfile, int depth ) const -{ - int i; - assert( cfile ); - for ( i=0; iNext() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a node - // 2) An element with only a text child is printed as text - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i", value.c_str() ); - } -} - - -void TiXmlElement::CopyTo( TiXmlElement* target ) const -{ - // superclass: - TiXmlNode::CopyTo( target ); - - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - -bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -TiXmlNode* TiXmlElement::Clone() const -{ - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -const char* TiXmlElement::GetText() const -{ - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; -} - - -TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); -} - -TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} - - -#ifdef TIXML_USE_STL -TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); -} -#endif - - -TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDocument::operator=( const TiXmlDocument& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) -{ - // See STL_STRING_BUG below. - //StringToBuffer buf( value ); - - return LoadFile( Value(), encoding ); -} - - -bool TiXmlDocument::SaveFile() const -{ - // See STL_STRING_BUG below. -// StringToBuffer buf( value ); -// -// if ( buf.buffer && SaveFile( buf.buffer ) ) -// return true; -// -// return false; - return SaveFile( Value() ); -} - -bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) -{ - // There was a really terrifying little bug here. The code: - // value = filename - // in the STL case, cause the assignment method of the std::string to - // be called. What is strange, is that the std::string had the same - // address as it's c_str() method, and so bad things happen. Looks - // like a bug in the Microsoft STL implementation. - // Add an extra string to avoid the crash. - TIXML_STRING filename( _filename ); - value = filename; - - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } -} - -bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) -{ - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // If we have a file, assume it is all one big XML file, and read it in. - // The document parser may decide the document ends sooner than the entire file, however. - TIXML_STRING data; - data.reserve( length ); - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // - // - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - const char* lastPos = buf; - const char* p = buf; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - if ( *p == 0xa ) { - // Newline character. No special rules for this. Append all the characters - // since the last string, and include the newline. - data.append( lastPos, (p-lastPos+1) ); // append, include the newline - ++p; // move past the newline - lastPos = p; // and point to the new buffer (may be 0) - assert( p <= (buf+length) ); - } - else if ( *p == 0xd ) { - // Carriage return. Append what we have so far, then - // handle moving forward in the buffer. - if ( (p-lastPos) > 0 ) { - data.append( lastPos, p-lastPos ); // do not add the CR - } - data += (char)0xa; // a proper newline - - if ( *(p+1) == 0xa ) { - // Carriage return - new line sequence - p += 2; - lastPos = p; - assert( p <= (buf+length) ); - } - else { - // it was followed by something else...that is presumably characters again. - ++p; - lastPos = p; - assert( p <= (buf+length) ); - } - } - else { - ++p; - } - } - // Handle any left over characters. - if ( p-lastPos ) { - data.append( lastPos, p-lastPos ); - } - delete [] buf; - buf = 0; - - Parse( data.c_str(), 0, encoding ); - - if ( Error() ) - return false; - else - return true; -} - - -bool TiXmlDocument::SaveFile( const char * filename ) const -{ - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; -} - - -bool TiXmlDocument::SaveFile( FILE* fp ) const -{ - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); -} - - -void TiXmlDocument::CopyTo( TiXmlDocument* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; - - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } -} - - -TiXmlNode* TiXmlDocument::Clone() const -{ - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlDocument::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } -} - - -bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const -{ - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); -} - - -const TiXmlAttribute* TiXmlAttribute::Next() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} - -/* -TiXmlAttribute* TiXmlAttribute::Next() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; -} -*/ - -const TiXmlAttribute* TiXmlAttribute::Previous() const -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} - -/* -TiXmlAttribute* TiXmlAttribute::Previous() -{ - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; -} -*/ - -void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } -} - - -int TiXmlAttribute::QueryIntValue( int* ival ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -int TiXmlAttribute::QueryDoubleValue( double* dval ) const -{ - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; -} - -void TiXmlAttribute::SetIntValue( int _value ) -{ - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); -} - -void TiXmlAttribute::SetDoubleValue( double _value ) -{ - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); - #else - sprintf (buf, "%lf", _value); - #endif - SetValue (buf); -} - -int TiXmlAttribute::IntValue() const -{ - return atoi (value.c_str ()); -} - -double TiXmlAttribute::DoubleValue() const -{ - return atof (value.c_str ()); -} - - -TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) -{ - copy.CopyTo( this ); -} - - -void TiXmlComment::operator=( const TiXmlComment& base ) -{ - Clear(); - base.CopyTo( this ); -} - - -void TiXmlComment::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlComment::CopyTo( TiXmlComment* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlComment::Clone() const -{ - TiXmlComment* clone = new TiXmlComment(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlText::Print( FILE* cfile, int depth ) const -{ - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } -} - - -void TiXmlText::CopyTo( TiXmlText* target ) const -{ - TiXmlNode::CopyTo( target ); - target->cdata = cdata; -} - - -bool TiXmlText::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} - - -#ifdef TIXML_USE_STL -TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - version = _version; - encoding = _encoding; - standalone = _standalone; -} -#endif - - -TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::DECLARATION ) -{ - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) -{ - Clear(); - copy.CopyTo( this ); -} - - -void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const -{ - if ( cfile ) fprintf( cfile, "" ); - if ( str ) (*str) += "?>"; -} - - -void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const -{ - TiXmlNode::CopyTo( target ); - - target->version = version; - target->encoding = encoding; - target->standalone = standalone; -} - - -bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -void TiXmlUnknown::Print( FILE* cfile, int depth ) const -{ - for ( int i=0; i", value.c_str() ); -} - - -void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const -{ - TiXmlNode::CopyTo( target ); -} - - -bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const -{ - return visitor->Visit( *this ); -} - - -TiXmlNode* TiXmlUnknown::Clone() const -{ - TiXmlUnknown* clone = new TiXmlUnknown(); - - if ( !clone ) - return 0; - - CopyTo( clone ); - return clone; -} - - -TiXmlAttributeSet::TiXmlAttributeSet() -{ - sentinel.next = &sentinel; - sentinel.prev = &sentinel; -} - - -TiXmlAttributeSet::~TiXmlAttributeSet() -{ - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); -} - - -void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) -{ - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif - - addMe->next = &sentinel; - addMe->prev = sentinel.prev; - - sentinel.prev->next = addMe; - sentinel.prev = addMe; -} - -void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) -{ - TiXmlAttribute* node; - - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. -} - - -#ifdef TIXML_USE_STL -const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; -} -*/ -#endif - - -const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const -{ - for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} - -/* -TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) -{ - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; -} -*/ - -#ifdef TIXML_USE_STL -std::istream& operator>> (std::istream & in, TiXmlNode & base) -{ - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); - - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; -} -#endif - - -#ifdef TIXML_USE_STL -std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); - - return out; -} - - -std::string& operator<< (std::string& out, const TiXmlNode& base ) -{ - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); - - return out; -} -#endif - - -TiXmlHandle TiXmlHandle::FirstChild() const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const -{ - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement() const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const -{ - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && iNextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && iNextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && iNextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const -{ - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && iNextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); -} - - -bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) -{ - return true; -} - -bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) -{ - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; -} - - -bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) -{ - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += ""; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlText& text ) -{ - if ( text.CDATA() ) - { - DoIndent(); - buffer += ""; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) -{ - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlComment& comment ) -{ - DoIndent(); - buffer += ""; - DoLineBreak(); - return true; -} - - -bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) -{ - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; -} - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h b/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h deleted file mode 100644 index c230c02afb..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/External/tinyxml/tinyxml.h +++ /dev/null @@ -1,1785 +0,0 @@ -/* -www.sourceforge.net/projects/tinyxml -Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any -damages arising from the use of this software. - -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and -redistribute it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and -must not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. -*/ - - -#ifndef TINYXML_INCLUDED -#define TINYXML_INCLUDED - -#include -#include -#include -#include -#include - -// Help out windows: -#if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG -#endif - -#ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string -#else - #include "tinystr.h" - #define TIXML_STRING TiXmlString -#endif - -// Deprecated library function hell. Compilers want to use the -// new safe versions. This probably doesn't fully address the problem, -// but it gets closer. There are too many compilers for me to fully -// test. If you get compilation troubles, undefine TIXML_SAFE -#define TIXML_SAFE - -#ifdef TIXML_SAFE - #if defined(_MSC_VER) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SNSCANF _snscanf_s - #define TIXML_SSCANF sscanf_s - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SNSCANF snscanf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SSCANF sscanf - #endif -#endif - -class TiXmlDocument; -class TiXmlElement; -class TiXmlComment; -class TiXmlUnknown; -class TiXmlAttribute; -class TiXmlText; -class TiXmlDeclaration; -class TiXmlParsingData; - -const int TIXML_MAJOR_VERSION = 2; -const int TIXML_MINOR_VERSION = 5; -const int TIXML_PATCH_VERSION = 3; - -/* Internal structure for tracking location of items - in the XML file. -*/ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. -}; - - -/** - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simple called with Visit(). - - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. - - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. - - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - - You should never change the document from a callback. - - @sa TiXmlNode::Accept() -*/ -class TiXmlVisitor -{ -public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } -}; - -// Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE -}; - - -// Used by the parsing routines. -enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; - -const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; - -/** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim -*/ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - -public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_OUT_OF_MEMORY, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - -protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - -private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; -}; - - -/** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. -*/ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - -public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - DOCUMENT, - ELEMENT, - COMMENT, - UNKNOWN, - TEXT, - DECLARATION, - TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } - - #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif - - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - - - /** Add a new node related to this. Adds a child past the LastChild. - - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. - - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } - - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } - - #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - -protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; - - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif - - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. -}; - - -/** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. - - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. -*/ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - -public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. - - #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - -private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; -}; - - -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. - - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. -*/ -class TiXmlAttributeSet -{ -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - const TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* Find( const char* _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - #ifdef TIXML_USE_STL - const TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* Find( const std::string& _name ) { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); - } - - #endif - -private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - - TiXmlAttribute sentinel; -}; - - -/** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. -*/ -class TiXmlElement : public TiXmlNode -{ -public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } - - #ifdef TIXML_USE_STL - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - /* - This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" - but template specialization is hard to get working cross-compiler. Leaving the bug for now. - - // The above will fail for std::string because the space character is used as a seperator. - // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string - template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - */ - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); - - #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); - #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - -private: - - TiXmlAttributeSet attributeSet; -}; - - -/** An XML comment. -*/ -class TiXmlComment : public TiXmlNode -{ -public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: - -}; - - -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). -*/ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; -public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - bool cdata; // true if this should be input and output as a CDATA style text element -}; - - -/** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim - - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. - - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. -*/ -class TiXmlDeclaration : public TiXmlNode -{ -public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} - -#ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); -#endif - - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - -protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; -}; - - -/** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. - - DTD tags get thrown into TiXmlUnknowns. -*/ -class TiXmlUnknown : public TiXmlNode -{ -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected: - void CopyTo( TiXmlUnknown* target ) const; - - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - -}; - - -/** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. -*/ -class TiXmlDocument : public TiXmlNode -{ -public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && LoadFile( f.buffer, encoding )); - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { -// StringToBuffer f( filename ); -// return ( f.buffer && SaveFile( f.buffer )); - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - -protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. -}; - - -/** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim -*/ -class TiXmlHandle -{ -public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - -private: - TiXmlNode* node; -}; - - -/** Print to memory functionality. The TiXmlPrinter is useful when you need to: - - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) - - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. - - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); - - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim -*/ -class TiXmlPrinter : public TiXmlVisitor -{ -public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif - -private: - void DoIndent() { - for( int i=0; i -#include - -#include "tinyxml.h" - -//#define DEBUG_PARSER -#if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif -#endif - -// Note tha "PutString" hardcodes the same list. This -// is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } -}; - -// Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html -// Including the basic of this table, which determines the #bytes in the -// sequence from the lead byte. 1 placed for invalid sequences -- -// although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf - -const unsigned char TIXML_UTF_LEAD_0 = 0xefU; -const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; -const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid -}; - - -void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) -{ - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } -} - - -/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalpha( anyByte ); -// } -} - - -/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) -{ - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. - -// if ( encoding == TIXML_ENCODING_UTF8 ) -// { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. -// } -// else -// { -// return isalnum( anyByte ); -// } -} - - -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; -}; - - -void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) -{ - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); -} - - -const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) -{ - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) - ++p; - } - - return p; -} - -#ifdef TIXML_USE_STL -/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) -{ - for( ;; ) - { - if ( !in->good() ) return false; - - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; - - *tag += (char) in->get(); - } -} - -/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) -{ - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; -} -#endif - -// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The -// "assign" optimization removes over 10% of the execution time. -// -const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) -{ - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; -} - -const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) -{ - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; iappend( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p ) - p += strlen( endTag ); - return p; -} - -#ifdef TIXML_USE_STL - -void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); -} - -#endif - -const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) -{ - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; -} - -void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } -} - - -TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) -{ - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - TiXmlDocument* doc = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: "; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p ) - p += strlen( endTag ); - - return p; -} - - -const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - -// int tabsize = 4; -// if ( document ) -// tabsize = document->TabSize(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; -} - -#ifdef TIXML_USE_STL -void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } -} -#endif - -const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = ""; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p ) - return p-1; // don't truncate the '<' - return 0; - } -} - -#ifdef TIXML_USE_STL -void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) -{ - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } -} -#endif - -const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) -{ - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; -} - -bool TiXmlText::Blank() const -{ - for ( unsigned i=0; i - #include -using namespace std; -#else - #include -#endif - -#if defined(WIN32) && defined(TUNE) - #include -_CrtMemState startMemState; -_CrtMemState endMemState; -#endif - -#include "tinyxml.h" - -static int gPass = 0; -static int gFail = 0; - - -bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false) -{ - bool pass = !strcmp(expected, found); - if (pass) - { - printf ("[pass]"); - } - else - { - printf ("[fail]"); - } - - if (noEcho) - { - printf (" %s\n", testString); - } - else - { - printf (" %s [%s][%s]\n", testString, expected, found); - } - - if (pass) - { - ++gPass; - } - else - { - ++gFail; - } - return pass; -} - - -bool XmlTest(const char* testString, int expected, int found, bool noEcho = false) -{ - bool pass = (expected == found); - if (pass) - { - printf ("[pass]"); - } - else - { - printf ("[fail]"); - } - - if (noEcho) - { - printf (" %s\n", testString); - } - else - { - printf (" %s [%d][%d]\n", testString, expected, found); - } - - if (pass) - { - ++gPass; - } - else - { - ++gFail; - } - return pass; -} - - -// -// This file demonstrates some basic functionality of TinyXml. -// Note that the example is very contrived. It presumes you know -// what is in the XML file. But it does test the basic operations, -// and show how to add and remove nodes. -// - -int main() -{ - // - // We start with the 'demoStart' todo list. Process it. And - // should hopefully end up with the todo list as illustrated. - // - const char* demoStart = - "\n" - "" - "\n" - "\n" - " Go to the Toy store!" - " Do bills " - " Look for Evil Dinosaurs! " - ""; - - { - #ifdef TIXML_USE_STL - /* What the todo list should look like after processing. - In stream (no formatting) representation. */ - const char* demoEnd = - "" - "" - "" - "" - "Go to the" - "Toy store!" - "" - "" - "Talk to:" - "" - "" - "" - "" - "" - "" - "Do bills" - "" - ""; - #endif - - // The example parses from the character string (above): - #if defined(WIN32) && defined(TUNE) - _CrtMemCheckpoint(&startMemState); - #endif - - { - // Write to a file and read it back, to check file I/O. - - TiXmlDocument doc("demotest.xml"); - doc.Parse(demoStart); - - if (doc.Error()) - { - printf("Error in %s: %s\n", doc.Value(), doc.ErrorDesc()); - exit(1); - } - doc.SaveFile(); - } - - TiXmlDocument doc("demotest.xml"); - bool loadOkay = doc.LoadFile(); - - if (!loadOkay) - { - printf("Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc()); - exit(1); - } - - printf("** Demo doc read from disk: ** \n\n"); - printf("** Printing via doc.Print **\n"); - doc.Print(stdout); - - { - printf("** Printing via TiXmlPrinter **\n"); - TiXmlPrinter printer; - doc.Accept(&printer); - fprintf(stdout, "%s", printer.CStr()); - } - #ifdef TIXML_USE_STL - { - printf("** Printing via operator<< **\n"); - std::cout << doc; - } - #endif - TiXmlNode* node = 0; - TiXmlElement* todoElement = 0; - TiXmlElement* itemElement = 0; - - - // -------------------------------------------------------- - // An example of changing existing attributes, and removing - // an element from the document. - // -------------------------------------------------------- - - // Get the "ToDo" element. - // It is a child of the document, and can be selected by name. - node = doc.FirstChild("ToDo"); - assert(node); - todoElement = node->ToElement(); - assert(todoElement); - - // Going to the toy store is now our second priority... - // So set the "priority" attribute of the first item in the list. - node = todoElement->FirstChildElement(); // This skips the "PDA" comment. - assert(node); - itemElement = node->ToElement(); - assert(itemElement); - itemElement->SetAttribute("priority", 2); - - // Change the distance to "doing bills" from - // "none" to "here". It's the next sibling element. - itemElement = itemElement->NextSiblingElement(); - assert(itemElement); - itemElement->SetAttribute("distance", "here"); - - // Remove the "Look for Evil Dinosaurs!" item. - // It is 1 more sibling away. We ask the parent to remove - // a particular child. - itemElement = itemElement->NextSiblingElement(); - todoElement->RemoveChild(itemElement); - - itemElement = 0; - - // -------------------------------------------------------- - // What follows is an example of created elements and text - // nodes and adding them to the document. - // -------------------------------------------------------- - - // Add some meetings. - TiXmlElement item("Item"); - item.SetAttribute("priority", "1"); - item.SetAttribute("distance", "far"); - - TiXmlText text("Talk to:"); - - TiXmlElement meeting1("Meeting"); - meeting1.SetAttribute("where", "School"); - - TiXmlElement meeting2("Meeting"); - meeting2.SetAttribute("where", "Lunch"); - - TiXmlElement attendee1("Attendee"); - attendee1.SetAttribute("name", "Marple"); - attendee1.SetAttribute("position", "teacher"); - - TiXmlElement attendee2("Attendee"); - attendee2.SetAttribute("name", "Voel"); - attendee2.SetAttribute("position", "counselor"); - - // Assemble the nodes we've created: - meeting1.InsertEndChild(attendee1); - meeting1.InsertEndChild(attendee2); - - item.InsertEndChild(text); - item.InsertEndChild(meeting1); - item.InsertEndChild(meeting2); - - // And add the node to the existing list after the first child. - node = todoElement->FirstChild("Item"); - assert(node); - itemElement = node->ToElement(); - assert(itemElement); - - todoElement->InsertAfterChild(itemElement, item); - - printf("\n** Demo doc processed: ** \n\n"); - doc.Print(stdout); - - - #ifdef TIXML_USE_STL - printf("** Demo doc processed to stream: ** \n\n"); - cout << doc << endl << endl; - #endif - - // -------------------------------------------------------- - // Different tests...do we have what we expect? - // -------------------------------------------------------- - - int count = 0; - TiXmlElement* element; - - ////////////////////////////////////////////////////// - - #ifdef TIXML_USE_STL - cout << "** Basic structure. **\n"; - ostringstream outputStream(ostringstream::out); - outputStream << doc; - XmlTest("Output stream correct.", string(demoEnd).c_str(), - outputStream.str().c_str(), true); - #endif - - node = doc.RootElement(); - assert(node); - XmlTest("Root element exists.", true, (node != 0 && node->ToElement())); - XmlTest ("Root element value is 'ToDo'.", "ToDo", node->Value()); - - node = node->FirstChild(); - XmlTest("First child exists & is a comment.", true, (node != 0 && node->ToComment())); - node = node->NextSibling(); - XmlTest("Sibling element exists & is an element.", true, (node != 0 && node->ToElement())); - XmlTest ("Value is 'Item'.", "Item", node->Value()); - - node = node->FirstChild(); - XmlTest ("First child exists.", true, (node != 0 && node->ToText())); - XmlTest ("Value is 'Go to the'.", "Go to the", node->Value()); - - - ////////////////////////////////////////////////////// - printf ("\n** Iterators. **\n"); - - // Walk all the top level nodes of the document. - count = 0; - for (node = doc.FirstChild(); - node; - node = node->NextSibling()) - { - count++; - } - XmlTest("Top level nodes, using First / Next.", 3, count); - - count = 0; - for (node = doc.LastChild(); - node; - node = node->PreviousSibling()) - { - count++; - } - XmlTest("Top level nodes, using Last / Previous.", 3, count); - - // Walk all the top level nodes of the document, - // using a different syntax. - count = 0; - for (node = doc.IterateChildren(0); - node; - node = doc.IterateChildren(node)) - { - count++; - } - XmlTest("Top level nodes, using IterateChildren.", 3, count); - - // Walk all the elements in a node. - count = 0; - for (element = todoElement->FirstChildElement(); - element; - element = element->NextSiblingElement()) - { - count++; - } - XmlTest("Children of the 'ToDo' element, using First / Next.", - 3, count); - - // Walk all the elements in a node by value. - count = 0; - for (node = todoElement->FirstChild("Item"); - node; - node = node->NextSibling("Item")) - { - count++; - } - XmlTest("'Item' children of the 'ToDo' element, using First/Next.", 3, count); - - count = 0; - for (node = todoElement->LastChild("Item"); - node; - node = node->PreviousSibling("Item")) - { - count++; - } - XmlTest("'Item' children of the 'ToDo' element, using Last/Previous.", 3, count); - - #ifdef TIXML_USE_STL - { - cout << "\n** Parsing. **\n"; - istringstream parse0(""); - TiXmlElement element0("default"); - parse0 >> element0; - - XmlTest ("Element parsed, value is 'Element0'.", "Element0", element0.Value()); - XmlTest ("Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute("attribute0")); - XmlTest ("Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute("attribute1")); - XmlTest ("Read attribute with entity value '>'.", ">", element0.Attribute("attribute2")); - } - #endif - - { - const char* error = "\n" - "\n" - " \n" - ""; - - TiXmlDocument docTest; - docTest.Parse(error); - XmlTest("Error row", docTest.ErrorRow(), 3); - XmlTest("Error column", docTest.ErrorCol(), 17); - //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 ); - } - - #ifdef TIXML_USE_STL - { - ////////////////////////////////////////////////////// - cout << "\n** Streaming. **\n"; - - // Round trip check: stream in, then stream back out to verify. The stream - // out has already been checked, above. We use the output - - istringstream inputStringStream(outputStream.str()); - TiXmlDocument document0; - - inputStringStream >> document0; - - ostringstream outputStream0(ostringstream::out); - outputStream0 << document0; - - XmlTest("Stream round trip correct.", string(demoEnd).c_str(), - outputStream0.str().c_str(), true); - - std::string str; - str << document0; - - XmlTest("String printing correct.", string(demoEnd).c_str(), - str.c_str(), true); - } - #endif - } - - { - const char* str = ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlElement* ele = doc.FirstChildElement(); - - int iVal, result; - double dVal; - - result = ele->QueryDoubleAttribute("attr0", &dVal); - XmlTest("Query attribute: int as double", result, TIXML_SUCCESS); - XmlTest("Query attribute: int as double", (int)dVal, 1); - result = ele->QueryDoubleAttribute("attr1", &dVal); - XmlTest("Query attribute: double as double", (int)dVal, 2); - result = ele->QueryIntAttribute("attr1", &iVal); - XmlTest("Query attribute: double as int", result, TIXML_SUCCESS); - XmlTest("Query attribute: double as int", iVal, 2); - result = ele->QueryIntAttribute("attr2", &iVal); - XmlTest("Query attribute: not a number", result, TIXML_WRONG_TYPE); - result = ele->QueryIntAttribute("bar", &iVal); - XmlTest("Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE); - } - - { - const char* str = "\t\t\n" - ""; - - TiXmlDocument doc; - doc.SetTabSize(8); - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle roomHandle = docHandle.FirstChildElement("room"); - - assert(docHandle.Node()); - assert(roomHandle.Element()); - - TiXmlElement* room = roomHandle.Element(); - assert(room); - TiXmlAttribute* doors = room->FirstAttribute(); - assert(doors); - - XmlTest("Location tracking: Tab 8: room row", room->Row(), 1); - XmlTest("Location tracking: Tab 8: room col", room->Column(), 49); - XmlTest("Location tracking: Tab 8: doors row", doors->Row(), 1); - XmlTest("Location tracking: Tab 8: doors col", doors->Column(), 55); - } - - { - const char* str = "\t\t\n" - " \n" - " A great door!\n" - "\t" - ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle roomHandle = docHandle.FirstChildElement("room"); - TiXmlHandle commentHandle = docHandle.FirstChildElement("room").FirstChild(); - TiXmlHandle textHandle = docHandle.FirstChildElement("room").ChildElement("door", 0).FirstChild(); - TiXmlHandle door0Handle = docHandle.FirstChildElement("room").ChildElement(0); - TiXmlHandle door1Handle = docHandle.FirstChildElement("room").ChildElement(1); - - assert(docHandle.Node()); - assert(roomHandle.Element()); - assert(commentHandle.Node()); - assert(textHandle.Text()); - assert(door0Handle.Element()); - assert(door1Handle.Element()); - - TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration(); - assert(declaration); - TiXmlElement* room = roomHandle.Element(); - assert(room); - TiXmlAttribute* doors = room->FirstAttribute(); - assert(doors); - TiXmlText* text = textHandle.Text(); - TiXmlComment* comment = commentHandle.Node()->ToComment(); - assert(comment); - TiXmlElement* door0 = door0Handle.Element(); - TiXmlElement* door1 = door1Handle.Element(); - - XmlTest("Location tracking: Declaration row", declaration->Row(), 1); - XmlTest("Location tracking: Declaration col", declaration->Column(), 5); - XmlTest("Location tracking: room row", room->Row(), 1); - XmlTest("Location tracking: room col", room->Column(), 45); - XmlTest("Location tracking: doors row", doors->Row(), 1); - XmlTest("Location tracking: doors col", doors->Column(), 51); - XmlTest("Location tracking: Comment row", comment->Row(), 2); - XmlTest("Location tracking: Comment col", comment->Column(), 3); - XmlTest("Location tracking: text row", text->Row(), 3); - XmlTest("Location tracking: text col", text->Column(), 24); - XmlTest("Location tracking: door0 row", door0->Row(), 3); - XmlTest("Location tracking: door0 col", door0->Column(), 5); - XmlTest("Location tracking: door1 row", door1->Row(), 4); - XmlTest("Location tracking: door1 col", door1->Column(), 5); - } - - - // -------------------------------------------------------- - // UTF-8 testing. It is important to test: - // 1. Making sure name, value, and text read correctly - // 2. Row, Col functionality - // 3. Correct output - // -------------------------------------------------------- - printf ("\n** UTF-8 **\n"); - { - TiXmlDocument doc("utf8test.xml"); - doc.LoadFile(); - if (doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE) - { - printf("WARNING: File 'utf8test.xml' not found.\n" - "(Are you running the test from the wrong directory?)\n" - "Could not test UTF-8 functionality.\n"); - } - else - { - TiXmlHandle docH(&doc); - // Get the attribute "value" from the "Russian" element and check it. - TiXmlElement* element = docH.FirstChildElement("document").FirstChildElement("Russian").Element(); - const unsigned char correctValue[] = { - 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU, - 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 - }; - - XmlTest("UTF-8: Russian value.", (const char*)correctValue, element->Attribute("value"), true); - XmlTest("UTF-8: Russian value row.", 4, element->Row()); - XmlTest("UTF-8: Russian value column.", 5, element->Column()); - - const unsigned char russianElementName[] = { - 0xd0U, 0xa0U, 0xd1U, 0x83U, - 0xd1U, 0x81U, 0xd1U, 0x81U, - 0xd0U, 0xbaU, 0xd0U, 0xb8U, - 0xd0U, 0xb9U, 0 - }; - const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>"; - - TiXmlText* text = docH.FirstChildElement("document").FirstChildElement((const char*) russianElementName).Child(0).Text(); - XmlTest("UTF-8: Browsing russian element name.", - russianText, - text->Value(), - true); - XmlTest("UTF-8: Russian element name row.", 7, text->Row()); - XmlTest("UTF-8: Russian element name column.", 47, text->Column()); - - TiXmlDeclaration* dec = docH.Child(0).Node()->ToDeclaration(); - XmlTest("UTF-8: Declaration column.", 1, dec->Column()); - XmlTest("UTF-8: Document column.", 1, doc.Column()); - - // Now try for a round trip. - doc.SaveFile("utf8testout.xml"); - - // Check the round trip. - char savedBuf[256]; - char verifyBuf[256]; - int okay = 1; - - FILE* saved = fopen("utf8testout.xml", "r"); - FILE* verify = fopen("utf8testverify.xml", "r"); - if (saved && verify) - { - while (fgets(verifyBuf, 256, verify)) - { - fgets(savedBuf, 256, saved); - if (strcmp(verifyBuf, savedBuf)) - { - okay = 0; - break; - } - } - } - if(saved) - { - fclose(saved); - } - if(verify) - { - fclose(verify); - } - XmlTest("UTF-8: Verified multi-language round trip.", 1, okay); - - // On most Western machines, this is an element that contains - // the word "resume" with the correct accents, in a latin encoding. - // It will be something else completely on non-wester machines, - // which is why TinyXml is switching to UTF-8. - const char latin[] = "r\x82sum\x82"; - - TiXmlDocument latinDoc; - latinDoc.Parse(latin, 0, TIXML_ENCODING_LEGACY); - - text = latinDoc.FirstChildElement()->FirstChild()->ToText(); - XmlTest("Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value()); - } - } - - ////////////////////// - // Copy and assignment - ////////////////////// - printf ("\n** Copy and Assignment **\n"); - { - TiXmlElement element("foo"); - element.Parse("", 0, TIXML_ENCODING_UNKNOWN); - - TiXmlElement elementCopy(element); - TiXmlElement elementAssign("foo"); - elementAssign.Parse("", 0, TIXML_ENCODING_UNKNOWN); - elementAssign = element; - - XmlTest("Copy/Assign: element copy #1.", "element", elementCopy.Value()); - XmlTest("Copy/Assign: element copy #2.", "value", elementCopy.Attribute("name")); - XmlTest("Copy/Assign: element assign #1.", "element", elementAssign.Value()); - XmlTest("Copy/Assign: element assign #2.", "value", elementAssign.Attribute("name")); - XmlTest("Copy/Assign: element assign #3.", true, (0 == elementAssign.Attribute("foo"))); - - TiXmlComment comment; - comment.Parse("", 0, TIXML_ENCODING_UNKNOWN); - TiXmlComment commentCopy(comment); - TiXmlComment commentAssign; - commentAssign = commentCopy; - XmlTest("Copy/Assign: comment copy.", "comment", commentCopy.Value()); - XmlTest("Copy/Assign: comment assign.", "comment", commentAssign.Value()); - - TiXmlUnknown unknown; - unknown.Parse("<[unknown]>", 0, TIXML_ENCODING_UNKNOWN); - TiXmlUnknown unknownCopy(unknown); - TiXmlUnknown unknownAssign; - unknownAssign.Parse("incorrect", 0, TIXML_ENCODING_UNKNOWN); - unknownAssign = unknownCopy; - XmlTest("Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value()); - XmlTest("Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value()); - - TiXmlText text("TextNode"); - TiXmlText textCopy(text); - TiXmlText textAssign("incorrect"); - textAssign = text; - XmlTest("Copy/Assign: text copy.", "TextNode", textCopy.Value()); - XmlTest("Copy/Assign: text assign.", "TextNode", textAssign.Value()); - - TiXmlDeclaration dec; - dec.Parse("", 0, TIXML_ENCODING_UNKNOWN); - TiXmlDeclaration decCopy(dec); - TiXmlDeclaration decAssign; - decAssign = dec; - - XmlTest("Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding()); - XmlTest("Copy/Assign: text assign.", "UTF-8", decAssign.Encoding()); - - TiXmlDocument doc; - elementCopy.InsertEndChild(textCopy); - doc.InsertEndChild(decAssign); - doc.InsertEndChild(elementCopy); - doc.InsertEndChild(unknownAssign); - - TiXmlDocument docCopy(doc); - TiXmlDocument docAssign; - docAssign = docCopy; - - #ifdef TIXML_USE_STL - std::string original, copy, assign; - original << doc; - copy << docCopy; - assign << docAssign; - XmlTest("Copy/Assign: document copy.", original.c_str(), copy.c_str(), true); - XmlTest("Copy/Assign: document assign.", original.c_str(), assign.c_str(), true); - - #endif - } - - ////////////////////////////////////////////////////// -#ifdef TIXML_USE_STL - printf ("\n** Parsing, no Condense Whitespace **\n"); - TiXmlBase::SetCondenseWhiteSpace(false); - { - istringstream parse1("This is \ntext"); - TiXmlElement text1("text"); - parse1 >> text1; - - XmlTest ("Condense white space OFF.", "This is \ntext", - text1.FirstChild()->Value(), - true); - } - TiXmlBase::SetCondenseWhiteSpace(true); -#endif - - ////////////////////////////////////////////////////// - // GetText(); - { - const char* str = "This is text"; - TiXmlDocument doc; - doc.Parse(str); - const TiXmlElement* element = doc.RootElement(); - - XmlTest("GetText() normal use.", "This is text", element->GetText()); - - str = "This is text"; - doc.Clear(); - doc.Parse(str); - element = doc.RootElement(); - - XmlTest("GetText() contained element.", element->GetText() == 0, true); - - str = "This is text"; - doc.Clear(); - TiXmlBase::SetCondenseWhiteSpace(false); - doc.Parse(str); - TiXmlBase::SetCondenseWhiteSpace(true); - element = doc.RootElement(); - - XmlTest("GetText() partial.", "This is ", element->GetText()); - } - - - ////////////////////////////////////////////////////// - // CDATA - { - const char* str = "" - " the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse(str); - doc.Print(); - - XmlTest("CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - - #ifdef TIXML_USE_STL - //cout << doc << '\n'; - - doc.Clear(); - - istringstream parse0(str); - parse0 >> doc; - //cout << doc << '\n'; - - XmlTest("CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest("CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - } - { - // [ 1482728 ] Wrong wide char parsing - char buf[256]; - buf[255] = 0; - for (int i = 0; i < 255; ++i) - { - buf[i] = (char)((i >= 32) ? i : 32); - } - TIXML_STRING str(""; - - TiXmlDocument doc; - doc.Parse(str.c_str()); - - TiXmlPrinter printer; - printer.SetStreamPrinting(); - doc.Accept(&printer); - - XmlTest("CDATA with all bytes #1.", str.c_str(), printer.CStr(), true); - - #ifdef TIXML_USE_STL - doc.Clear(); - istringstream iss(printer.Str()); - iss >> doc; - std::string out; - out << doc; - XmlTest("CDATA with all bytes #2.", out.c_str(), printer.CStr(), true); - #endif - } - { - // [ 1480107 ] Bug-fix for STL-streaming of CDATA that contains tags - // CDATA streaming had a couple of bugs, that this tests for. - const char* str = "" - "I am > the rules!\n" - "...since I make symbolic puns" - "]]>" - ""; - TiXmlDocument doc; - doc.Parse(str); - doc.Print(); - - XmlTest("CDATA parse. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - - #ifdef TIXML_USE_STL - - doc.Clear(); - - istringstream parse0(str); - parse0 >> doc; - - XmlTest("CDATA stream. [ 1480107 ]", doc.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - #endif - - TiXmlDocument doc1 = doc; - //doc.Print(); - - XmlTest("CDATA copy. [ 1480107 ]", doc1.FirstChildElement()->FirstChild()->Value(), - "I am > the rules!\n...since I make symbolic puns", - true); - } - ////////////////////////////////////////////////////// - // Visit() - - - - ////////////////////////////////////////////////////// - printf("\n** Fuzzing... **\n"); - - const int FUZZ_ITERATION = 300; - - // The only goal is not to crash on bad input. - int len = (int) strlen(demoStart); - for (int i = 0; i < FUZZ_ITERATION; ++i) - { - char* demoCopy = new char[ len + 1 ]; - strcpy(demoCopy, demoStart); - - demoCopy[ i % len ] = (char)((i + 1) * 3); - demoCopy[ (i * 7) % len ] = '>'; - demoCopy[ (i * 11) % len ] = '<'; - - TiXmlDocument xml; - xml.Parse(demoCopy); - - delete [] demoCopy; - } - printf("** Fuzzing Complete. **\n"); - - ////////////////////////////////////////////////////// - printf ("\n** Bug regression tests **\n"); - - // InsertBeforeChild and InsertAfterChild causes crash. - { - TiXmlElement parent("Parent"); - TiXmlElement childText0("childText0"); - TiXmlElement childText1("childText1"); - TiXmlNode* childNode0 = parent.InsertEndChild(childText0); - TiXmlNode* childNode1 = parent.InsertBeforeChild(childNode0, childText1); - - XmlTest("Test InsertBeforeChild on empty node.", (childNode1 == parent.FirstChild()), true); - } - - { - // InsertBeforeChild and InsertAfterChild causes crash. - TiXmlElement parent("Parent"); - TiXmlElement childText0("childText0"); - TiXmlElement childText1("childText1"); - TiXmlNode* childNode0 = parent.InsertEndChild(childText0); - TiXmlNode* childNode1 = parent.InsertAfterChild(childNode0, childText1); - - XmlTest("Test InsertAfterChild on empty node. ", (childNode1 == parent.LastChild()), true); - } - - // Reports of missing constructors, irregular string problems. - { - // Missing constructor implementation. No test -- just compiles. - TiXmlText text("Missing"); - - #ifdef TIXML_USE_STL - // Missing implementation: - TiXmlDocument doc; - string name = "missing"; - doc.LoadFile(name); - - TiXmlText textSTL(name); - #else - // verifying some basic string functions: - TiXmlString a; - TiXmlString b("Hello"); - TiXmlString c("ooga"); - - c = " World!"; - a = b; - a += c; - a = a; - - XmlTest("Basic TiXmlString test. ", "Hello World!", a.c_str()); - #endif - } - - // Long filenames crashing STL version - { - TiXmlDocument doc("midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml"); - bool loadOkay = doc.LoadFile(); - loadOkay = true; // get rid of compiler warning. - // Won't pass on non-dev systems. Just a "no crash" check. - //XmlTest( "Long filename. ", true, loadOkay ); - } - - { - // Entities not being written correctly. - // From Lynn Allen - - const char* passages = - "" - "" - " " - ""; - - TiXmlDocument doc("passages.xml"); - doc.Parse(passages); - TiXmlElement* psg = doc.RootElement()->FirstChildElement(); - const char* context = psg->Attribute("context"); - const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9."; - - XmlTest("Entity transformation: read. ", expected, context, true); - - FILE* textfile = fopen("textfile.txt", "w"); - if (textfile) - { - psg->Print(textfile, 0); - fclose(textfile); - } - textfile = fopen("textfile.txt", "r"); - assert(textfile); - if (textfile) - { - char buf[ 1024 ]; - fgets(buf, 1024, textfile); - XmlTest("Entity transformation: write. ", - "", - buf, - true); - } - fclose(textfile); - } - - { - FILE* textfile = fopen("test5.xml", "w"); - if (textfile) - { - fputs("", textfile); - fclose(textfile); - - TiXmlDocument doc; - doc.LoadFile("test5.xml"); - XmlTest("dot in element attributes and names", doc.Error(), 0); - } - } - - { - FILE* textfile = fopen("test6.xml", "w"); - if (textfile) - { - fputs("1.1 Start easy ignore fin thickness ", textfile); - fclose(textfile); - - TiXmlDocument doc; - bool result = doc.LoadFile("test6.xml"); - XmlTest("Entity with one digit.", result, true); - - TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText(); - XmlTest("Entity with one digit.", - text->Value(), "1.1 Start easy ignore fin thickness\n"); - } - } - - { - // DOCTYPE not preserved (950171) - // - const char* doctype = - "" - "" - "" - "" - ""; - - TiXmlDocument doc; - doc.Parse(doctype); - doc.SaveFile("test7.xml"); - doc.Clear(); - doc.LoadFile("test7.xml"); - - TiXmlHandle docH(&doc); - TiXmlUnknown* unknown = docH.Child(1).Unknown(); - XmlTest("Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value()); - #ifdef TIXML_USE_STL - TiXmlNode* node = docH.Child(2).Node(); - std::string str; - str << (*node); - XmlTest("Correct streaming of unknown.", "", str.c_str()); - #endif - } - - { - // [ 791411 ] Formatting bug - // Comments do not stream out correctly. - const char* doctype = - ""; - TiXmlDocument doc; - doc.Parse(doctype); - - TiXmlHandle docH(&doc); - TiXmlComment* comment = docH.Child(0).Node()->ToComment(); - - XmlTest("Comment formatting.", " Somewhat ", comment->Value()); - #ifdef TIXML_USE_STL - std::string str; - str << (*comment); - XmlTest("Comment streaming.", "", str.c_str()); - #endif - } - - { - // [ 870502 ] White space issues - TiXmlDocument doc; - TiXmlText* text; - TiXmlHandle docH(&doc); - - const char* doctype0 = " This has leading and trailing space "; - const char* doctype1 = "This has internal space"; - const char* doctype2 = " This has leading, trailing, and internal space "; - - TiXmlBase::SetCondenseWhiteSpace(false); - doc.Clear(); - doc.Parse(doctype0); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", " This has leading and trailing space ", text->Value()); - - doc.Clear(); - doc.Parse(doctype1); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", "This has internal space", text->Value()); - - doc.Clear(); - doc.Parse(doctype2); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space kept.", " This has leading, trailing, and internal space ", text->Value()); - - TiXmlBase::SetCondenseWhiteSpace(true); - doc.Clear(); - doc.Parse(doctype0); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has leading and trailing space", text->Value()); - - doc.Clear(); - doc.Parse(doctype1); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has internal space", text->Value()); - - doc.Clear(); - doc.Parse(doctype2); - text = docH.FirstChildElement("element").Child(0).Text(); - XmlTest("White space condensed.", "This has leading, trailing, and internal space", text->Value()); - } - - { - // Double attributes - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse(doctype); - - XmlTest("Parsing repeated attributes.", 0, (int)doc.Error()); // not an error to tinyxml - XmlTest("Parsing repeated attributes.", "blue", doc.FirstChildElement("element")->Attribute("attr")); - } - - { - // Embedded null in stream. - const char* doctype = ""; - - TiXmlDocument doc; - doc.Parse(doctype); - XmlTest("Embedded null throws error.", true, doc.Error()); - - #ifdef TIXML_USE_STL - istringstream strm(doctype); - doc.Clear(); - doc.ClearError(); - strm >> doc; - XmlTest("Embedded null throws error.", true, doc.Error()); - #endif - } - - { - // Legacy mode test. (This test may only pass on a western system) - const char* str = - "" - "<ä>" - "CöntäntßäöüÄÖÜ" - ""; - - TiXmlDocument doc; - doc.Parse(str); - - TiXmlHandle docHandle(&doc); - TiXmlHandle aHandle = docHandle.FirstChildElement("ä"); - TiXmlHandle tHandle = aHandle.Child(0); - assert(aHandle.Element()); - assert(tHandle.Text()); - XmlTest("ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value()); - } - - { - // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717 - const char* str = " "; - TiXmlDocument doc; - doc.Parse(str); - XmlTest("Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId()); - } - #ifndef TIXML_USE_STL - { - // String equality. [ 1006409 ] string operator==/!= no worky in all cases - TiXmlString temp; - XmlTest("Empty tinyxml string compare equal", (temp == ""), true); - - TiXmlString foo; - TiXmlString bar(""); - XmlTest("Empty tinyxml string compare equal", (foo == bar), true); - } - - #endif - { - // Bug [ 1195696 ] from marlonism - TiXmlBase::SetCondenseWhiteSpace(false); - TiXmlDocument xml; - xml.Parse("This hangs"); - XmlTest("Test safe error return.", xml.Error(), false); - } - - { - // Bug [ 1243992 ] - another infinite loop - TiXmlDocument doc; - doc.SetCondenseWhiteSpace(false); - doc.Parse("

test

"); - } - { - // Low entities - TiXmlDocument xml; - xml.Parse(""); - const char result[] = { 0x0e, 0 }; - XmlTest("Low entities.", xml.FirstChildElement()->GetText(), result); - xml.Print(); - } - { - // Bug [ 1451649 ] Attribute values with trailing quotes not handled correctly - TiXmlDocument xml; - xml.Parse(""); - XmlTest("Throw error with bad end quotes.", xml.Error(), true); - } - #ifdef TIXML_USE_STL - { - // Bug [ 1449463 ] Consider generic query - TiXmlDocument xml; - xml.Parse(""); - - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - float f; - bool b; - //std::string str; - - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &d), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &i), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &f), TIXML_SUCCESS); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("bar", &b), TIXML_WRONG_TYPE); - XmlTest("QueryValueAttribute", ele->QueryValueAttribute("nobar", &b), TIXML_NO_ATTRIBUTE); - //XmlTest( "QueryValueAttribute", ele->QueryValueAttribute( "barStr", &str ), TIXML_SUCCESS ); - - XmlTest("QueryValueAttribute", (d == 3.0), true); - XmlTest("QueryValueAttribute", (i == 3), true); - XmlTest("QueryValueAttribute", (f == 3.0f), true); - //XmlTest( "QueryValueAttribute", (str==std::string( "a string" )), true ); - } - #endif - - #ifdef TIXML_USE_STL - { - // [ 1505267 ] redundant malloc in TiXmlElement::Attribute - TiXmlDocument xml; - xml.Parse(""); - TiXmlElement* ele = xml.FirstChildElement(); - double d; - int i; - - std::string bar = "bar"; - - const std::string* atrrib = ele->Attribute(bar); - ele->Attribute(bar, &d); - ele->Attribute(bar, &i); - - XmlTest("Attribute", atrrib->empty(), false); - XmlTest("Attribute", (d == 3.0), true); - XmlTest("Attribute", (i == 3), true); - } - #endif - - { - // [ 1356059 ] Allow TiXMLDocument to only be at the top level - TiXmlDocument xml, xml2; - xml.InsertEndChild(xml2); - XmlTest("Document only at top level.", xml.Error(), true); - XmlTest("Document only at top level.", xml.ErrorId(), TiXmlBase::TIXML_ERROR_DOCUMENT_TOP_ONLY); - } - - { - // [ 1663758 ] Failure to report error on bad XML - TiXmlDocument xml; - xml.Parse(""); - XmlTest("Missing end tag at end of input", xml.Error(), true); - xml.Parse(" "); - XmlTest("Missing end tag with trailing whitespace", xml.Error(), true); - } - - { - // [ 1635701 ] fail to parse files with a tag separated into two lines - // I'm not sure this is a bug. Marked 'pending' for feedback. - TiXmlDocument xml; - xml.Parse("<p>text</p\n><title>"); - //xml.Print(); - //XmlTest( "Tag split by newline", xml.Error(), false ); - } - - #ifdef TIXML_USE_STL - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - istringstream parse1("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->"); - parse1 >> xml; - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest("Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true); - XmlTest("Comments ignore entities.", " far & away ", c1->Value(), true); - } - #endif - - { - // [ 1475201 ] TinyXML parses entities in comments - TiXmlDocument xml; - xml.Parse("<!-- declarations for <head> & <body> -->" - "<!-- far & away -->"); - - TiXmlNode* e0 = xml.FirstChild(); - TiXmlNode* e1 = e0->NextSibling(); - TiXmlComment* c0 = e0->ToComment(); - TiXmlComment* c1 = e1->ToComment(); - - XmlTest("Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true); - XmlTest("Comments ignore entities.", " far & away ", c1->Value(), true); - } - /* - { - TiXmlDocument xml; - xml.Parse( "<tag>/</tag>" ); - xml.Print(); - xml.FirstChild()->Print( stdout, 0 ); - xml.FirstChild()->Type(); - } - */ - - /* 1417717 experiment - { - TiXmlDocument xml; - xml.Parse("<text>Dan & Tracie</text>"); - xml.Print(stdout); - } - { - TiXmlDocument xml; - xml.Parse("<text>Dan &foo; Tracie</text>"); - xml.Print(stdout); - } - */ - #if defined(WIN32) && defined(TUNE) - _CrtMemCheckpoint(&endMemState); - //_CrtMemDumpStatistics( &endMemState ); - - _CrtMemState diffMemState; - _CrtMemDifference(&diffMemState, &startMemState, &endMemState); - _CrtMemDumpStatistics(&diffMemState); - #endif - - printf ("\nPass %d, Fail %d\n", gPass, gFail); - return gFail; -} - - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat b/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat deleted file mode 100644 index ba6badf0c0..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/ListCache.bat +++ /dev/null @@ -1,16 +0,0 @@ -@echo off -REM -REM All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -REM its licensors. -REM -REM REM For complete copyright and license terms please see the LICENSE at the root of this -REM distribution (the "License"). All use of this software is governed by the License, -REM or, if provided, by the license below or the license accompanying this file. Do not -REM remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -REM -REM -REM Original file Copyright Crytek GMBH or its affiliates, used under license. -REM - -dir Cache /a:-d /s /b >dir.txt \ No newline at end of file diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/PAL_android.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Android/platform_android.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake deleted file mode 100644 index 5963f882c3..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/Clang/cryscompileserver_clang.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(LY_COMPILE_OPTIONS - PRIVATE - -fexceptions -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake deleted file mode 100644 index 74ca22aaea..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Common/MSVC/cryscompileserver_msvc.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(LY_COMPILE_OPTIONS - PRIVATE - /EHsc -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/PAL_linux.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Linux/platform_linux.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake deleted file mode 100644 index 6fa34f74b4..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/PAL_mac.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED TRUE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake deleted file mode 100644 index c46eb1cb4e..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Mac/platform_mac.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(LY_RUNTIME_DEPENDENCIES - 3rdParty::DirectXShaderCompiler::dxcGL - 3rdParty::DirectXShaderCompiler::dxcMetal -) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake deleted file mode 100644 index 6fa34f74b4..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/PAL_windows.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED TRUE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake deleted file mode 100644 index 9bb1423231..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/Windows/platform_windows.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(LY_RUNTIME_DEPENDENCIES - 3rdParty::DirectXShaderCompiler::dxcGL - 3rdParty::DirectXShaderCompiler::dxcMetal -) - -file(TO_CMAKE_PATH "$ENV{ProgramFiles\(x86\)}" program_files_path) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCD3D11/v006 - FILES - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/fxc.exe" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcompiler_47.dll" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcsx_47.dll" - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcsxd_47.dll" -) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCGL/V006 - FILES - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGL/V006/D3DCompiler_47.dll" - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGL/V006/HLSLcc.exe" -) - -ly_add_target_files( - TARGETS CrySCompileServer - OUTPUT_SUBDIRECTORY Compiler/PCGMETAL/HLSLcc - FILES - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGMETAL/HLSLcc/HLSLcc_d.exe" - "${LY_ROOT_FOLDER}/Tools/CrySCompileServer/Compiler/PCGMETAL/HLSLcc/HLSLcc.exe" -) - diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake deleted file mode 100644 index c89a9eb1cd..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/PAL_ios.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED FALSE) diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake deleted file mode 100644 index a6510a297f..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/Platform/iOS/platform_ios.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# \ No newline at end of file diff --git a/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake b/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake deleted file mode 100644 index b57c6a3dfe..0000000000 --- a/Code/Tools/CrySCompileServer/CrySCompileServer/cryscompileserver_files.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - CrySCompileServer.cpp - Core/Common.h - Core/Error.cpp - Core/Error.hpp - Core/WindowsAPIImplementation.h - Core/WindowsAPIImplementation.cpp - Core/Mailer.cpp - Core/Mailer.h - Core/MD5.hpp - Core/StdTypes.hpp - Core/STLHelper.cpp - Core/STLHelper.hpp - Core/Server/CrySimpleCache.cpp - Core/Server/CrySimpleCache.hpp - Core/Server/CrySimpleErrorLog.cpp - Core/Server/CrySimpleErrorLog.hpp - Core/Server/CrySimpleFileGuard.hpp - Core/Server/CrySimpleHTTP.cpp - Core/Server/CrySimpleHTTP.hpp - Core/Server/CrySimpleJob.cpp - Core/Server/CrySimpleJob.hpp - Core/Server/CrySimpleJobCache.cpp - Core/Server/CrySimpleJobCache.hpp - Core/Server/CrySimpleJobCompile.cpp - Core/Server/CrySimpleJobCompile.hpp - Core/Server/CrySimpleJobCompile1.cpp - Core/Server/CrySimpleJobCompile1.hpp - Core/Server/CrySimpleJobCompile2.cpp - Core/Server/CrySimpleJobCompile2.hpp - Core/Server/CrySimpleJobRequest.cpp - Core/Server/CrySimpleJobRequest.hpp - Core/Server/CrySimpleJobGetShaderList.cpp - Core/Server/CrySimpleJobGetShaderList.hpp - Core/Server/CrySimpleMutex.cpp - Core/Server/CrySimpleMutex.hpp - Core/Server/CrySimpleServer.cpp - Core/Server/CrySimpleServer.hpp - Core/Server/CrySimpleSock.cpp - Core/Server/CrySimpleSock.hpp - Core/Server/ShaderList.cpp - Core/Server/ShaderList.hpp - External/tinyxml/tinystr.cpp - External/tinyxml/tinystr.h - External/tinyxml/tinyxml.cpp - External/tinyxml/tinyxml.h - External/tinyxml/tinyxmlerror.cpp - External/tinyxml/tinyxmlparser.cpp -) diff --git a/cmake/3rdParty/FindDirectXShaderCompiler.cmake b/cmake/3rdParty/FindDirectXShaderCompiler.cmake deleted file mode 100644 index 8973775e48..0000000000 --- a/cmake/3rdParty/FindDirectXShaderCompiler.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -ly_add_external_target( - NAME dxcGL - PACKAGE DirectXShaderCompiler - VERSION 1.0.1-az.1 -) - -ly_add_external_target( - NAME dxcMetal - PACKAGE DirectXShaderCompiler - VERSION 1.0.1-az.1 -) diff --git a/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake b/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake deleted file mode 100644 index c00f71dbc1..0000000000 --- a/cmake/3rdParty/Platform/Mac/DirectXShaderCompiler_mac.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(DIRECTXSHADERCOMPILER_BINARY_BASE_PATH ${BASE_PATH}/bin/darwin_x64/$<IF:$<CONFIG:Debug>,debug,release>) - -set(DIRECTXSHADERCOMPILER_DXCGL_RUNTIME_DEPENDENCIES ${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcGL\nCompiler/LLVMGL/$<IF:$<CONFIG:Debug>,debug,release>) - -set(DIRECTXSHADERCOMPILER_DXCMETAL_RUNTIME_DEPENDENCIES ${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcMetal\nCompiler/LLVMMETAL/$<IF:$<CONFIG:Debug>,debug,release>) diff --git a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake index f786f80cf7..2f18546934 100644 --- a/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake +++ b/cmake/3rdParty/Platform/Mac/cmake_mac_files.cmake @@ -13,7 +13,6 @@ set(FILES BuiltInPackages_mac.cmake civetweb_mac.cmake Clang_mac.cmake - DirectXShaderCompiler_mac.cmake FbxSdk_mac.cmake OpenSSL_mac.cmake Wwise_mac.cmake diff --git a/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake b/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake deleted file mode 100644 index 2b50bc7f72..0000000000 --- a/cmake/3rdParty/Platform/Windows/DirectXShaderCompiler_windows.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(DIRECTXSHADERCOMPILER_BINARY_BASE_PATH "${BASE_PATH}/bin/win_x64/$<IF:$<CONFIG:Debug>,debug,release>/") - -set(DIRECTXSHADERCOMPILER_DXCGL_RUNTIME_DEPENDENCIES "${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcGL.exe\nCompiler/LLVMGL/$<IF:$<CONFIG:Debug>,debug,release>") - -set(DIRECTXSHADERCOMPILER_DXCMETAL_RUNTIME_DEPENDENCIES "${DIRECTXSHADERCOMPILER_BINARY_BASE_PATH}/dxcMetal.exe\nCompiler/LLVMMETAL/$<IF:$<CONFIG:Debug>,debug,release>") diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index 2c7890fcc4..5c6baea7cc 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -14,7 +14,6 @@ set(FILES BuiltInPackages_windows.cmake Clang_windows.cmake Crashpad_windows.cmake - DirectXShaderCompiler_windows.cmake dyad_windows.cmake FbxSdk_windows.cmake libav_windows.cmake diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index 3fe15bc0ce..fe73cca4dc 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -14,7 +14,6 @@ set(FILES FindAWSGameLiftServerSDK.cmake Findcivetweb.cmake FindClang.cmake - FindDirectXShaderCompiler.cmake Finddyad.cmake FindFbxSdk.cmake Findlibav.cmake From c1e3e0fe5e47aa93733b852c204f2c9da4628a35 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Mon, 19 Apr 2021 16:31:05 -0700 Subject: [PATCH 12/96] Moving hydra util files into a package --- .../Blast/ActorSplitsAfterCapsuleDamage.py | 2 +- .../Blast/ActorSplitsAfterCollision.py | 8 +- .../Blast/ActorSplitsAfterDamage.py | 6 +- .../ActorSplitsAfterImpactSpreadDamage.py | 2 +- .../Blast/ActorSplitsAfterRadialDamage.py | 2 +- .../Blast/ActorSplitsAfterShearDamage.py | 2 +- .../Blast/ActorSplitsAfterStressDamage.py | 2 +- .../Blast/ActorSplitsAfterTriangleDamage.py | 2 +- .../ComponentUpdateListProperty_test.py | 2 +- .../PySide_Example_test_case.py | 2 +- ...977329_NvCloth_AddClothSimulationToMesh.py | 9 +- ...77330_NvCloth_AddClothSimulationToActor.py | 9 +- ...C28798177_WhiteBox_AddComponentToEntity.py | 5 +- .../C28798205_WhiteBox_SetInvisible.py | 7 +- .../C29279329_WhiteBox_SetDefaultShape.py | 5 +- .../automatedtesting_shared/asset_utils.py | 2 +- .../landscape_canvas_utils.py | 2 +- .../AssetBrowser_SearchFiltering.py | 6 +- .../editor/EditorScripts/AssetPicker_UI_UX.py | 6 +- .../ComponentCRUD_Add_Delete_Components.py | 6 +- .../InputBindings_Add_Remove_Input_Events.py | 6 +- .../PythonTests/editor/test_AssetBrowser.py | 3 +- .../PythonTests/editor/test_AssetPicker.py | 3 +- .../PythonTests/editor/test_ComponentCRUD.py | 3 +- .../Gem/PythonTests/editor/test_Docking.py | 3 +- .../PythonTests/editor/test_InputBindings.py | 3 +- .../Gem/PythonTests/editor/test_Menus.py | 3 +- .../editor/test_SearchFiltering.py | 3 +- .../PythonTests/editor/test_TreeNavigation.py | 3 +- ...rides_InstancesPlantAtSpecifiedAltitude.py | 4 +- .../AltitudeFilter_FilterStageToggle.py | 4 +- ...ample_InstancesPlantAtSpecifiedAltitude.py | 4 +- ...Slices_SliceCreationAndVisibilityToggle.py | 4 +- ...binedDescriptorsExpressInConfiguredArea.py | 4 +- ...tSelector_InstancesExpressBasedOnWeight.py | 4 +- .../EditorScripts/Debugger_DebugCVarsWorks.py | 4 +- ...errides_InstancesPlantAtSpecifiedRadius.py | 4 +- ...nFilter_InstancesPlantAtSpecifiedRadius.py | 4 +- ...nstanceSpawner_DynamicSliceSpawnerWorks.py | 4 +- ...ynamicSliceInstanceSpawner_Embedded_E2E.py | 4 +- ...ynamicSliceInstanceSpawner_External_E2E.py | 4 +- .../EmptyInstanceSpawner_EmptySpawnerWorks.py | 4 +- ...anceSpawnerPriority_LayerAndSubPriority.py | 4 +- .../EditorScripts/LayerBlender_E2E_Editor.py | 4 +- ...locker_InstancesBlockedInConfiguredArea.py | 4 +- .../LayerSpawner_FilterStageToggle.py | 4 +- .../LayerSpawner_InheritBehaviorFlag.py | 4 +- ...wner_InstancesPlantInAllSupportedShapes.py | 4 +- .../MeshBlocker_InstancesBlockedByMesh.py | 4 +- ...cker_InstancesBlockedByMeshHeightTuning.py | 4 +- ...faceTagEmitter_DependentOnMeshComponent.py | 4 +- ...mitter_SurfaceTagsAddRemoveSuccessfully.py | 4 +- ...ysXColliderSurfaceTagEmitter_E2E_Editor.py | 4 +- ...PositionModifier_AutoSnapToSurfaceWorks.py | 4 +- ...rrides_InstancesPlantAtSpecifiedOffsets.py | 4 +- ...ierOverrides_InstancesRotateWithinRange.py | 4 +- ...tionModifier_InstancesRotateWithinRange.py | 4 +- ...odifierOverrides_InstancesProperlyScale.py | 4 +- .../ScaleModifier_InstancesProperlyScale.py | 4 +- ...ionFilter_InstancesPlantInAssignedShape.py | 4 +- ...ifierOverrides_InstanceSurfaceAlignment.py | 4 +- ...gnmentModifier_InstanceSurfaceAlignment.py | 4 +- ...AndOverrides_InstancesPlantOnValidSlope.py | 4 +- .../SlopeFilter_FilterStageToggle.py | 4 +- .../SurfaceDataRefreshes_RemainsStable.py | 2 +- ...tipleDescriptorOverridesPlantAsExpected.py | 4 +- ...rfaceMaskFilter_BasicSurfaceTagCreation.py | 2 +- .../SurfaceMaskFilter_ExclusionList.py | 4 +- .../SurfaceMaskFilter_InclusionList.py | 4 +- .../SystemSettings_SectorPointDensity.py | 4 +- .../SystemSettings_SectorSize.py | 4 +- ...getationInstances_DespawnWhenOutOfRange.py | 2 +- .../dyn_veg/test_AltitudeFilter.py | 2 +- .../dyn_veg/test_AreaComponentSlices.py | 2 +- .../dyn_veg/test_AssetListCombiner.py | 2 +- .../dyn_veg/test_AssetWeightSelector.py | 2 +- .../largeworlds/dyn_veg/test_Debugger.py | 2 +- .../dyn_veg/test_DistanceBetweenFilter.py | 2 +- .../dyn_veg/test_DynVeg_Regressions.py | 2 +- .../test_DynamicSliceInstanceSpawner.py | 2 +- .../dyn_veg/test_EmptyInstanceSpawner.py | 3 +- .../dyn_veg/test_InstanceSpawnerPriority.py | 2 +- .../largeworlds/dyn_veg/test_LayerBlender.py | 8 +- .../largeworlds/dyn_veg/test_LayerBlocker.py | 2 +- .../largeworlds/dyn_veg/test_LayerSpawner.py | 2 +- .../largeworlds/dyn_veg/test_MeshBlocker.py | 2 +- .../dyn_veg/test_MeshSurfaceTagEmitter.py | 2 +- .../test_PhysXColliderSurfaceTagEmitter.py | 2 +- .../dyn_veg/test_PositionModifier.py | 3 +- .../dyn_veg/test_RotationModifier.py | 2 +- .../largeworlds/dyn_veg/test_ScaleModifier.py | 2 +- .../dyn_veg/test_ShapeIntersectionFilter.py | 3 +- .../dyn_veg/test_SlopeAlignmentModifier.py | 3 +- .../largeworlds/dyn_veg/test_SlopeFilter.py | 2 +- .../dyn_veg/test_SurfaceMaskFilter.py | 2 +- .../dyn_veg/test_SystemSettings.py | 2 +- .../GradientGenerators_Incompatibilities.py | 4 +- .../GradientModifiers_Incompatibilities.py | 4 +- ...ClearingPinnedEntitySetsPreviewToOrigin.py | 4 +- ...eviewSettings_DefaultPinnedEntityIsSelf.py | 4 +- ...GradientReferencesAddRemoveSuccessfully.py | 4 +- ...SurfaceTagEmitter_ComponentDependencies.py | 5 +- ...mitter_SurfaceTagsAddRemoveSuccessfully.py | 4 +- ...ponentIncompatibleWithExpectedGradients.py | 4 +- ...sform_ComponentIncompatibleWithSpawners.py | 4 +- ..._FrequencyZoomCanBeSetBeyondSliderRange.py | 4 +- .../GradientTransform_RequiresShape.py | 4 +- ...ient_ProcessedImageAssignedSuccessfully.py | 4 +- .../ImageGradient_RequiresShape.py | 4 +- .../test_GradientIncompatibilities.py | 2 +- .../test_GradientPreviewSettings.py | 3 +- .../gradient_signal/test_GradientSampling.py | 2 +- .../test_GradientSurfaceTagEmitter.py | 2 +- .../gradient_signal/test_GradientTransform.py | 3 +- .../gradient_signal/test_ImageGradient.py | 3 +- .../AreaNodes_DependentComponentsAdded.py | 4 +- .../AreaNodes_EntityCreatedOnNodeAdd.py | 4 +- .../ComponentUpdates_UpdateGraph.py | 4 +- .../EditorScripts/CreateNewGraph.py | 4 +- .../Edit_DisabledNodeDuplication.py | 4 +- .../Edit_UndoNodeDelete_SliceEntity.py | 4 +- .../GradientMixer_NodeConstruction.py | 4 +- ...entModifierNodes_EntityCreatedOnNodeAdd.py | 4 +- ...ModifierNodes_EntityRemovedOnNodeDelete.py | 2 +- .../GradientNodes_DependentComponentsAdded.py | 4 +- .../GradientNodes_EntityCreatedOnNodeAdd.py | 4 +- ...GradientNodes_EntityRemovedOnNodeDelete.py | 2 +- .../GraphClosed_OnEntityDelete.py | 2 +- .../GraphClosed_OnLevelChange.py | 2 +- .../EditorScripts/GraphClosed_TabbedGraph.py | 2 +- .../GraphUpdates_UpdateComponents.py | 5 +- .../LandscapeCanvasComponent_AddedRemoved.py | 4 +- .../LandscapeCanvas_SliceCreateInstantiate.py | 4 +- .../LayerBlender_NodeConstruction.py | 4 +- .../LayerExtenderNodes_ComponentEntitySync.py | 4 +- .../ShapeNodes_EntityCreatedOnNodeAdd.py | 4 +- .../ShapeNodes_EntityRemovedOnNodeDelete.py | 2 +- ...otConnections_UpdateComponentReferences.py | 4 +- .../landscape_canvas/test_AreaNodes.py | 3 +- .../test_EditFunctionality.py | 3 +- .../test_GeneralGraphFunctionality.py | 2 +- .../test_GradientModifierNodes.py | 3 +- .../landscape_canvas/test_GradientNodes.py | 3 +- .../test_GraphComponentSync.py | 3 +- .../landscape_canvas/test_ShapeNodes.py | 3 +- .../editor_dynveg_test_helper.py | 2 +- ...00000_RigidBody_EnablingGravityWorksPoC.py | 6 +- ...ablingGravityWorksUsingNotificationsPoC.py | 6 +- .../C12712452_ScriptCanvas_CollisionEvents.py | 7 +- ...712453_ScriptCanvas_MultipleRaycastNode.py | 6 +- ...54_ScriptCanvas_OverlapNodeVerification.py | 7 +- ...2455_ScriptCanvas_ShapeCastVerification.py | 7 +- ...eRegion_DirectionHasNoAffectOnMagnitude.py | 7 +- ...580_ForceRegion_SplineModifiedTransform.py | 6 +- ...12905527_ForceRegion_MagnitudeDeviation.py | 6 +- ...5528_ForceRegion_WithNonTriggerCollider.py | 9 +- .../C13351703_COM_NotIncludeTriggerShapes.py | 7 +- ...13352089_RigidBodies_MaxAngularVelocity.py | 6 +- ...8019_Terrain_TerrainTexturePainterWorks.py | 5 +- .../physics/C13895144_Ragdoll_ChangeLevel.py | 7 +- .../C14195074_ScriptCanvas_PostUpdateEvent.py | 7 +- ...654881_CharacterController_SwitchLevels.py | 6 +- .../C14654882_Ragdoll_ragdollAPTest.py | 7 +- .../C14861498_ConfirmError_NoPxMesh.py | 8 +- .../C14861500_DefaultSetting_ColliderShape.py | 8 +- ...01_PhysXCollider_RenderMeshAutoAssigned.py | 6 +- ...4861502_PhysXCollider_AssetAutoAssigned.py | 8 +- ...C14861504_RenderMeshAsset_WithNoPxAsset.py | 8 +- .../C14902097_ScriptCanvas_PreUpdateEvent.py | 7 +- ...14902098_ScriptCanvas_PostPhysicsUpdate.py | 7 +- .../C14976307_Gravity_SetGravityWorks.py | 7 +- ...criptCanvas_SetKinematicTargetTransform.py | 7 +- ...DefaultLibraryUpdatedAcrossLevels_after.py | 7 +- ...efaultLibraryUpdatedAcrossLevels_before.py | 7 +- ...735_Materials_DefaultLibraryConsistency.py | 6 +- ...Materials_DefaultMaterialLibraryChanges.py | 7 +- ...096740_Material_LibraryUpdatedCorrectly.py | 8 +- .../physics/C15308217_NoCrash_LevelSwitch.py | 7 +- ...21_Material_ComponentsInSyncWithLibrary.py | 7 +- .../physics/C15425929_Undo_Redo.py | 9 +- ...935_Material_LibraryUpdatedAcrossLevels.py | 6 +- ...s_CharacterControllerMaterialAssignment.py | 6 +- ...al_AddModifyDeleteOnCharacterController.py | 7 +- ...5879_ForceRegion_HighLinearDampingForce.py | 7 +- .../C17411467_AddPhysxRagdollComponent.py | 8 +- ...18243580_Joints_Fixed2BodiesConstrained.py | 7 +- .../C18243581_Joints_FixedBreakable.py | 7 +- ...8243582_Joints_FixedLeadFollowerCollide.py | 7 +- ...18243583_Joints_Hinge2BodiesConstrained.py | 7 +- ...43584_Joints_HingeSoftLimitsConstrained.py | 7 +- ...8243585_Joints_HingeNoLimitsConstrained.py | 7 +- ...8243586_Joints_HingeLeadFollowerCollide.py | 7 +- .../C18243587_Joints_HingeBreakable.py | 7 +- ...C18243588_Joints_Ball2BodiesConstrained.py | 7 +- ...243589_Joints_BallSoftLimitsConstrained.py | 7 +- ...18243590_Joints_BallNoLimitsConstrained.py | 7 +- ...18243591_Joints_BallLeadFollowerCollide.py | 7 +- .../physics/C18243592_Joints_BallBreakable.py | 7 +- ...C18243593_Joints_GlobalFrameConstrained.py | 7 +- ...977601_Material_FrictionCombinePriority.py | 6 +- ...526_Material_RestitutionCombinePriority.py | 7 +- .../C19536274_GetCollisionName_PrintsName.py | 6 +- ...19536277_GetCollisionName_PrintsNothing.py | 6 +- ...78018_ShapeColliderWithNoShapeComponent.py | 8 +- .../C19578021_ShapeCollider_CanBeAdded.py | 10 +- ...19723164_ShapeColliders_WontCrashEditor.py | 8 +- ...rShapeCollider_CollidesWithPhysXTerrain.py | 6 +- .../C28978033_Ragdoll_WorldBodyBusTests.py | 8 +- ...2500_EditorComponents_WorldBodyBusWorks.py | 8 +- .../C3510642_Terrain_NotCollideWithTerrain.py | 7 +- .../C3510644_Collider_CollisionGroups.py | 6 +- ...044455_Material_libraryChangesInstantly.py | 7 +- .../C4044456_Material_FrictionCombine.py | 7 +- .../C4044457_Material_RestitutionCombine.py | 7 +- .../C4044459_Material_DynamicFriction.py | 7 +- .../C4044460_Material_StaticFriction.py | 7 +- .../physics/C4044461_Material_Restitution.py | 7 +- ...044694_Material_EmptyLibraryUsesDefault.py | 7 +- ...695_PhysXCollider_AddMultipleSurfaceFbx.py | 6 +- ...4697_Material_PerfaceMaterialValidation.py | 7 +- ...8315_Material_AddModifyDeleteOnCollider.py | 7 +- ...577_Materials_MaterialAssignedToTerrain.py | 7 +- ...25579_Material_AddModifyDeleteOnTerrain.py | 7 +- .../C4925580_Material_RagdollBonesMaterial.py | 7 +- ..._Material_AddModifyDeleteOnRagdollBones.py | 7 +- ...4976194_RigidBody_PhysXComponentIsValid.py | 7 +- ...76195_RigidBodies_InitialLinearVelocity.py | 6 +- ...6197_RigidBodies_InitialAngularVelocity.py | 6 +- ...9_RigidBodies_LinearDampingObjectMotion.py | 6 +- ..._RigidBody_AngularDampingObjectRotation.py | 8 +- .../C4976201_RigidBody_MassIsAssigned.py | 7 +- ...igidBody_StopsWhenBelowKineticThreshold.py | 7 +- .../C4976204_Verify_Start_Asleep_Condition.py | 7 +- ...976206_RigidBodies_GravityEnabledActive.py | 6 +- ...6207_PhysXRigidBodies_KinematicBehavior.py | 6 +- .../physics/C4976209_RigidBody_ComputesCOM.py | 7 +- .../physics/C4976210_COM_ManualSetting.py | 6 +- ...8_RigidBodies_InertiaObjectsNotComputed.py | 6 +- .../physics/C4976227_Collider_NewGroup.py | 7 +- .../C4976236_AddPhysxColliderComponent.py | 10 +- ...on_SameCollisionlayerSameCollisiongroup.py | 7 +- ...n_SameCollisionGroupDiffCollisionLayers.py | 7 +- ...44_Collider_SameGroupSameLayerCollision.py | 6 +- ...976245_PhysXCollider_CollisionLayerTest.py | 6 +- ...982593_PhysXCollider_CollisionLayerTest.py | 6 +- ...82595_Collider_TriggerDisablesCollision.py | 7 +- .../C4982797_Collider_ColliderOffset.py | 6 +- ...4982798_Collider_ColliderRotationOffset.py | 6 +- ...982800_PhysXColliderShape_CanBeSelected.py | 8 +- ...982801_PhysXColliderShape_CanBeSelected.py | 8 +- ...982802_PhysXColliderShape_CanBeSelected.py | 8 +- .../physics/C4982803_Enable_PxMesh_Option.py | 8 +- .../C5296614_PhysXMaterial_ColliderShape.py | 6 +- ...5340400_RigidBody_ManualMomentOfInertia.py | 7 +- ...8_PhysXTerrain_CollidesWithPhysXTerrain.py | 6 +- ...ysxterrain_AddPhysxterrainNoEditorCrash.py | 9 +- ..._MultipleTerrains_CheckWarningInConsole.py | 8 +- ...89528_Terrain_MultipleTerrainComponents.py | 9 +- ..._Verify_Terrain_RigidBody_Collider_Mesh.py | 7 +- ...31_Warning_TerrainSliceTerrainComponent.py | 9 +- ...932040_ForceRegion_CubeExertsWorldForce.py | 7 +- ...orceRegion_LocalSpaceForceOnRigidBodies.py | 7 +- ...C5932042_PhysXForceRegion_LinearDamping.py | 6 +- ...043_ForceRegion_SimpleDragOnRigidBodies.py | 5 +- ...32044_ForceRegion_PointForceOnRigidBody.py | 7 +- .../physics/C5932045_ForceRegion_Spline.py | 7 +- ...9_RigidBody_ForceRegionSpherePointForce.py | 6 +- ...760_PhysXForceRegion_PointForceExertion.py | 6 +- ...1_ForceRegion_PhysAssetExertsPointForce.py | 6 +- ...763_ForceRegion_ForceRegionImpulsesCube.py | 5 +- ..._ForceRegion_ForceRegionImpulsesCapsule.py | 5 +- .../C5959765_ForceRegion_AssetGetsImpulsed.py | 5 +- .../C5959808_ForceRegion_PositionOffset.py | 6 +- .../C5959809_ForceRegion_RotationalOffset.py | 6 +- ...0_ForceRegion_ForceRegionCombinesForces.py | 6 +- ...ceRegion_ExertsSeveralForcesOnRigidBody.py | 5 +- ...5968760_ForceRegion_CheckNetForceChange.py | 7 +- ...032082_Terrain_MultipleResolutionsValid.py | 7 +- ...90546_ForceRegion_SliceFileInstantiates.py | 7 +- ...547_ForceRegion_ParentChildForceRegions.py | 7 +- ...550_ForceRegion_WorldSpaceForceNegative.py | 7 +- ...551_ForceRegion_LocalSpaceForceNegative.py | 7 +- ...90552_ForceRegion_LinearDampingNegative.py | 7 +- ...orceRegion_SimpleDragForceOnRigidBodies.py | 7 +- ...C6090554_ForceRegion_PointForceNegative.py | 7 +- ...5_ForceRegion_SplineFollowOnRigidBodies.py | 7 +- ...6131473_StaticSlice_OnDynamicSliceSpawn.py | 7 +- .../C6224408_ScriptCanvas_EntitySpawn.py | 7 +- .../C6274125_ScriptCanvas_TriggerEvents.py | 7 +- .../C6321601_Force_HighValuesDirectionAxes.py | 9 +- .../Gem/PythonTests/physics/JointsHelper.py | 2 +- .../physics/UtilTest_Managed_Files.py | 4 +- .../physics/UtilTest_Physmaterial_Editor.py | 5 +- .../UtilTest_Tracer_PicksErrorsAndWarnings.py | 7 +- .../Gem/PythonTests/scripting/Docking_Pane.py | 8 +- .../scripting/Opening_Closing_Pane.py | 8 +- .../PythonTests/scripting/Resizing_Pane.py | 8 +- Tools/EditorPythonTestTools/README.txt | 100 ++++++++++++++++++ Tools/EditorPythonTestTools/__init__.py | 10 ++ .../editor_python_test_tools/__init__.py | 10 ++ .../editor_entity_utils.py | 10 +- .../editor_test_helper.py | 3 +- .../hydra_editor_utils.py | 0 .../hydra_test_utils.py | 17 ++- .../pyside_component_utils.py | 2 +- .../editor_python_test_tools}/pyside_utils.py | 0 .../editor_python_test_tools}/utils.py | 0 Tools/EditorPythonTestTools/setup.py | 43 ++++++++ cmake/LYPython.cmake | 1 + 309 files changed, 936 insertions(+), 806 deletions(-) create mode 100644 Tools/EditorPythonTestTools/README.txt create mode 100644 Tools/EditorPythonTestTools/__init__.py create mode 100644 Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/editor_entity_utils.py (98%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/editor_test_helper.py (99%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/hydra_editor_utils.py (100%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/hydra_test_utils.py (92%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/pyside_component_utils.py (98%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/pyside_utils.py (100%) mode change 100755 => 100644 rename {AutomatedTesting/Gem/PythonTests/automatedtesting_shared => Tools/EditorPythonTestTools/editor_python_test_tools}/utils.py (100%) mode change 100755 => 100644 create mode 100644 Tools/EditorPythonTestTools/setup.py diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCapsuleDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCapsuleDamage.py index 80f83b26e2..a961ccdc52 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCapsuleDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCapsuleDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def CapsuleDamage(target_id, position0): position1 = azlmbr.object.construct('Vector3', position0.x + 1.0, position0.y, position0.z) diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCollision.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCollision.py index d141cd3ce1..5692773d6d 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCollision.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterCollision.py @@ -54,14 +54,14 @@ def run(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus - from Utils import CollisionHandler - from Utils import BlastNotificationHandler + from editor_python_test_tools.utils import CollisionHandler + from editor_python_test_tools.utils import BlastNotificationHandler # Constants TIMEOUT = 2.0 diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterDamage.py index e991daebcd..ddd90ca89a 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterDamage.py @@ -50,13 +50,13 @@ def run(damage_func): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus - from Utils import BlastNotificationHandler + from editor_python_test_tools.utils import BlastNotificationHandler # Constants TIMEOUT = 2.0 diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterImpactSpreadDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterImpactSpreadDamage.py index 9139fe02b1..9b3fd1e596 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterImpactSpreadDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterImpactSpreadDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def ImpactSpreadDamage(target_id, position): azlmbr.destruction.BlastFamilyDamageRequestBus(azlmbr.bus.Event, "Impact Spread Damage", target_id, diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterRadialDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterRadialDamage.py index 77b942e95c..a219e63d34 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterRadialDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterRadialDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def RadialDamage(target_id, position): azlmbr.destruction.BlastFamilyDamageRequestBus(azlmbr.bus.Event, "Radial Damage", target_id, diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterShearDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterShearDamage.py index 404e655d36..e775be302d 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterShearDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterShearDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def ShearDamage(target_id, position): normal = azlmbr.object.construct('Vector3', 1.0, 0.0, 0.0) diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterStressDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterStressDamage.py index be002d5451..0195190348 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterStressDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterStressDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def StressDamage(target_id, position): force = azlmbr.object.construct('Vector3', 0.0, 0.0, -100.0) # Should be enough to break `brittle` objects diff --git a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterTriangleDamage.py b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterTriangleDamage.py index 4635d67455..0351fe42e2 100755 --- a/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterTriangleDamage.py +++ b/AutomatedTesting/Gem/PythonTests/Blast/ActorSplitsAfterTriangleDamage.py @@ -17,7 +17,7 @@ from ActorSplitsAfterDamage import Tests def run(): from ActorSplitsAfterDamage import run as internal_run - from Utils import Constants + from editor_python_test_tools.utils import Constants def TriangleDamage(target_id, position): # Some points that form a triangle that contains the given position diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ComponentUpdateListProperty_test.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ComponentUpdateListProperty_test.py index 3ac4832428..9ab83a0723 100755 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ComponentUpdateListProperty_test.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/ComponentUpdateListProperty_test.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/PySide_Example_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/PySide_Example_test_case.py index 8aba60e8e9..ed1c048fa6 100755 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/PySide_Example_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/PySide_Example_test_case.py @@ -25,7 +25,7 @@ import azlmbr.bus as bus import azlmbr.entity as entity import azlmbr.editor as editor import azlmbr.legacy.general as general -import pyside_component_utils +import editor_python_test_tools.pyside_component_utils as pysde_component_utils def PySide_Example_test_case(): diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh.py b/AutomatedTesting/Gem/PythonTests/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh.py index d54edc4cb3..2677ba5605 100755 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh.py +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/C18977329_NvCloth_AddClothSimulationToMesh.py @@ -47,14 +47,15 @@ def run(): import azlmbr.legacy.general as general + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + # Helper file Imports import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer # Constants FRAMES_IN_GAME_MODE = 200 diff --git a/AutomatedTesting/Gem/PythonTests/NvCloth/C18977330_NvCloth_AddClothSimulationToActor.py b/AutomatedTesting/Gem/PythonTests/NvCloth/C18977330_NvCloth_AddClothSimulationToActor.py index 2882ca6be2..2d4fa4e325 100755 --- a/AutomatedTesting/Gem/PythonTests/NvCloth/C18977330_NvCloth_AddClothSimulationToActor.py +++ b/AutomatedTesting/Gem/PythonTests/NvCloth/C18977330_NvCloth_AddClothSimulationToActor.py @@ -47,14 +47,15 @@ def run(): import azlmbr.legacy.general as general + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + # Helper file Imports import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer # Constants FRAMES_IN_GAME_MODE = 200 diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798177_WhiteBox_AddComponentToEntity.py b/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798177_WhiteBox_AddComponentToEntity.py index 9438b9d546..252126674c 100755 --- a/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798177_WhiteBox_AddComponentToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798177_WhiteBox_AddComponentToEntity.py @@ -33,8 +33,9 @@ def run(): import azlmbr.editor as editor import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + + from editor_python_test_tools.utils import TestHelper as helper # open level helper.init_idle() diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798205_WhiteBox_SetInvisible.py b/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798205_WhiteBox_SetInvisible.py index 605361e071..b7c6719721 100755 --- a/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798205_WhiteBox_SetInvisible.py +++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/C28798205_WhiteBox_SetInvisible.py @@ -30,7 +30,7 @@ def run(): import sys import WhiteBoxInit as init import ImportPathHelper as imports - import Tests.ly_shared.hydra_editor_utils as hydra + import editor_python_test_tools.hydra_editor_utils as hydra imports.init() import azlmbr.whitebox.api as api @@ -40,8 +40,9 @@ def run(): import azlmbr.entity as entity import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + + from editor_python_test_tools.utils import TestHelper as helper # open level helper.init_idle() diff --git a/AutomatedTesting/Gem/PythonTests/WhiteBox/C29279329_WhiteBox_SetDefaultShape.py b/AutomatedTesting/Gem/PythonTests/WhiteBox/C29279329_WhiteBox_SetDefaultShape.py index 399a9f27d4..0b0a081186 100755 --- a/AutomatedTesting/Gem/PythonTests/WhiteBox/C29279329_WhiteBox_SetDefaultShape.py +++ b/AutomatedTesting/Gem/PythonTests/WhiteBox/C29279329_WhiteBox_SetDefaultShape.py @@ -37,8 +37,9 @@ def run(): import azlmbr.bus as bus import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + + from editor_python_test_tools.utils import TestHelper as helper def check_shape_result(success_fail_tuple, condition): result = Report.result(success_fail_tuple, condition) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py index 1fe2771370..4d78e4f28b 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/asset_utils.py @@ -22,7 +22,7 @@ class Asset: """ Used to find Asset Id by its path and path of asset by its Id If a component has any asset property, then this class object can be called as: - asset_id = editor_entity_utils.EditorComponent.get_component_property_value(<arguments>) + asset_id = editor_python_test_tools.editor_entity_utils.EditorComponent.get_component_property_value(<arguments>) asset = asset_utils.Asset(asset_id) """ def __init__(self, id: azasset.AssetId): diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/landscape_canvas_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/landscape_canvas_utils.py index 6609e1a34f..d20dcabd73 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/landscape_canvas_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/landscape_canvas_utils.py @@ -13,7 +13,7 @@ import azlmbr.bus as bus import azlmbr.editor as editor import azlmbr.landscapecanvas as landscapecanvas -from . import hydra_editor_utils as hydra +import editor_python_test_tools.hydra_editor_utils as hydra def find_nodes_matching_entity_component(component_name, entity_id): diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py index 6dc59d9be0..75c17b2a69 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetBrowser_SearchFiltering.py @@ -22,9 +22,9 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper -import automatedtesting_shared.pyside_utils as pyside_utils +import editor_python_test_tools.hydra_editor_utils as hydra +import editor_python_test_tools.pyside_utils as pyside_utils +from editor_python_test_tools.editor_test_helper import EditorTestHelper class AssetBrowserSearchFilteringTest(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py index c51e4ca55f..ce7dd33971 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/AssetPicker_UI_UX.py @@ -25,9 +25,9 @@ import azlmbr.paths import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper -import automatedtesting_shared.pyside_utils as pyside_utils +import editor_python_test_tools.hydra_editor_utils as hydra +import editor_python_test_tools.pyside_utils as pyside_utils +from editor_python_test_tools.editor_test_helper import EditorTestHelper class AssetPickerUIUXTest(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py index cdc204043e..5e07a6df7d 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/ComponentCRUD_Add_Delete_Components.py @@ -26,9 +26,9 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper -import automatedtesting_shared.pyside_utils as pyside_utils +import editor_python_test_tools.hydra_editor_utils as hydra +import editor_python_test_tools.pyside_utils as pyside_utils +from editor_python_test_tools.editor_test_helper import EditorTestHelper class AddDeleteComponentsTest(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py index d6d284664a..dbc942f471 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/InputBindings_Add_Remove_Input_Events.py @@ -25,9 +25,9 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper -import automatedtesting_shared.pyside_utils as pyside_utils +import editor_python_test_tools.hydra_editor_utils as hydra +import editor_python_test_tools.pyside_utils as pyside_utils +from editor_python_test_tools.editor_test_helper import EditorTestHelper class AddRemoveInputEventsTest(EditorTestHelper): def __init__(self): diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_AssetBrowser.py b/AutomatedTesting/Gem/PythonTests/editor/test_AssetBrowser.py index 18dbee2424..48e65cd9fe 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_AssetBrowser.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_AssetBrowser.py @@ -15,10 +15,11 @@ C13660195: Asset Browser - File Tree Navigation import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 180 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_AssetPicker.py b/AutomatedTesting/Gem/PythonTests/editor/test_AssetPicker.py index b7b6280125..ac499d734f 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_AssetPicker.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_AssetPicker.py @@ -15,10 +15,11 @@ C13751579: Asset Picker UI/UX import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 90 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_ComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/test_ComponentCRUD.py index 8ee24d9aac..f4ae57c338 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/test_ComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_ComponentCRUD.py @@ -15,10 +15,11 @@ C16929880: Add Delete Components import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 180 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py b/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py index 16cccca3fe..a75b3b36cd 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Docking.py @@ -13,10 +13,11 @@ C6376081: Basic Function: Docked/Undocked Tools import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 180 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_InputBindings.py b/AutomatedTesting/Gem/PythonTests/editor/test_InputBindings.py index f7e6a8ce5f..cdcfe86ef7 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/test_InputBindings.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_InputBindings.py @@ -15,10 +15,11 @@ C1506881: Adding/Removing Event Groups import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 180 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py index 1df25dc593..251bd7cfed 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_Menus.py @@ -13,10 +13,11 @@ C16780783: Base Edit Menu Options (New Viewport Interaction Model) import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 180 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_SearchFiltering.py b/AutomatedTesting/Gem/PythonTests/editor/test_SearchFiltering.py index fa8b143739..a3d4739fd8 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/test_SearchFiltering.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_SearchFiltering.py @@ -15,10 +15,11 @@ C13660194 : Asset Browser - Filtering import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 90 diff --git a/AutomatedTesting/Gem/PythonTests/editor/test_TreeNavigation.py b/AutomatedTesting/Gem/PythonTests/editor/test_TreeNavigation.py index a97e4696d5..069d09f144 100755 --- a/AutomatedTesting/Gem/PythonTests/editor/test_TreeNavigation.py +++ b/AutomatedTesting/Gem/PythonTests/editor/test_TreeNavigation.py @@ -15,10 +15,11 @@ C13660195: Asset Browser - File Tree Navigation import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") log_monitor_timeout = 90 diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py index 673e473390..a0279aecec 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ComponentAndOverrides_InstancesPlantAtSpecifiedAltitude.py @@ -25,8 +25,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py index 1c51cc9554..720fbf9a4d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py index 7e76a80cc4..5d4154b030 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_ShapeSample_InstancesPlantAtSpecifiedAltitude.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py index d1fe82e3f7..5ace171099 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py @@ -21,8 +21,8 @@ import azlmbr.asset as asset import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py index 786348bcc6..374813b298 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetListCombiner_CombinedDescriptorsExpressInConfiguredArea.py @@ -21,8 +21,8 @@ import azlmbr.paths import azlmbr.vegetation as vegetation sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py index 85d4edfe6d..37bd47ed5d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AssetWeightSelector_InstancesExpressBasedOnWeight.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py index 7d133f492d..aeb6170e43 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/Debugger_DebugCVarsWorks.py @@ -16,8 +16,8 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestDebuggerDebugCVarsWorks(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py index 82b2fc8407..748719e95b 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py index 9f15215358..2d192d6a82 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py index b58c7488e5..47bd7f6e3c 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py @@ -18,8 +18,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py index f25fbb2b6d..1c81b5446a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py index 8af75f2d17..624ea1f180 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py index 4067de90fc..e8ea5710a5 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py @@ -18,8 +18,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py index 507d8f505e..684ca70e38 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/InstanceSpawnerPriority_LayerAndSubPriority.py @@ -21,8 +21,8 @@ import azlmbr.paths import azlmbr.vegetation as vegetation sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py index 2e6992d7e2..0da7acc987 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlender_E2E_Editor.py @@ -29,8 +29,8 @@ import azlmbr.entity as EntityId import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py index 53c29344e1..a856d8c093 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerBlocker_InstancesBlockedInConfiguredArea.py @@ -19,8 +19,8 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_FilterStageToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_FilterStageToggle.py index 01c5001642..d84cd575e7 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_FilterStageToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_FilterStageToggle.py @@ -19,8 +19,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py index f55243bc9c..bc59de1b0e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py @@ -19,8 +19,8 @@ import azlmbr.surface_data as surface_data import azlmbr.vegetation as vegetation sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InstancesPlantInAllSupportedShapes.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InstancesPlantInAllSupportedShapes.py index c124c631fd..add45d9671 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InstancesPlantInAllSupportedShapes.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InstancesPlantInAllSupportedShapes.py @@ -19,8 +19,8 @@ import azlmbr.entity as EntityId import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py index 02dcc1f067..a1fd0ef831 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py @@ -20,8 +20,8 @@ import azlmbr.legacy.general as general import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMeshHeightTuning.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMeshHeightTuning.py index 66250bf451..a7a0bc146b 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMeshHeightTuning.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMeshHeightTuning.py @@ -24,8 +24,8 @@ import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py index a5d04a3b6a..5757ed7559 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_DependentOnMeshComponent.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestMeshSurfaceTagEmitter(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py index e0011ea28f..ffa805cb41 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py @@ -18,8 +18,8 @@ import azlmbr.paths import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestMeshSurfaceTagEmitter(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py index 13003cdfcd..1826549a01 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PhysXColliderSurfaceTagEmitter_E2E_Editor.py @@ -19,8 +19,8 @@ import azlmbr.bus as bus import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py index d2d112907a..a215e21a94 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_AutoSnapToSurfaceWorks.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py index bd2a2df16f..e3ee0e5313 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/PositionModifier_ComponentAndOverrides_InstancesPlantAtSpecifiedOffsets.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py index b63692527c..c73bcaf5a2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py @@ -24,8 +24,8 @@ import azlmbr.bus as bus import azlmbr.areasystem as areasystem sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py index a14363d5e9..6f552ea4fc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py @@ -19,8 +19,8 @@ import azlmbr.bus as bus import azlmbr.areasystem as areasystem sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifierOverrides_InstancesProperlyScale.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifierOverrides_InstancesProperlyScale.py index 296ffe793b..2c9d33eae4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifierOverrides_InstancesProperlyScale.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifierOverrides_InstancesProperlyScale.py @@ -19,8 +19,8 @@ import azlmbr.legacy.general as general import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg # Constants diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifier_InstancesProperlyScale.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifier_InstancesProperlyScale.py index 333bc92352..f81758b2dd 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifier_InstancesProperlyScale.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ScaleModifier_InstancesProperlyScale.py @@ -19,8 +19,8 @@ import azlmbr.legacy.general as general import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py index 4d904e9623..de1f50e481 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/ShapeIntersectionFilter_InstancesPlantInAssignedShape.py @@ -24,8 +24,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment.py index cb96575a5d..ee5d79d6d2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifierOverrides_InstanceSurfaceAlignment.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifier_InstanceSurfaceAlignment.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifier_InstanceSurfaceAlignment.py index b358328886..400abf0212 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifier_InstanceSurfaceAlignment.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeAlignmentModifier_InstanceSurfaceAlignment.py @@ -23,8 +23,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py index 6f3b1d5629..2271ee51ce 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_ComponentAndOverrides_InstancesPlantOnValidSlope.py @@ -24,8 +24,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py index a907c7a0af..df0763f1f8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py @@ -19,8 +19,8 @@ import azlmbr.entity as EntityId import azlmbr.components as components sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg class TestSlopeFilterFilterStageToggle(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceDataRefreshes_RemainsStable.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceDataRefreshes_RemainsStable.py index 5b6a421e49..04e748661b 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceDataRefreshes_RemainsStable.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceDataRefreshes_RemainsStable.py @@ -18,7 +18,7 @@ import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py index b164d34973..c1bf53b03a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilterOverrides_MultipleDescriptorOverridesPlantAsExpected.py @@ -22,8 +22,8 @@ import azlmbr.paths import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py index 101b84f4bb..4f58a23a19 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_BasicSurfaceTagCreation.py @@ -15,7 +15,7 @@ import sys import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestSurfaceMaskFilter_BasicSurfaceTagCreation(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py index 1bec5e46ae..c8d0c8e507 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py @@ -25,8 +25,8 @@ import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py index fbaecf1972..d5eedc1245 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py @@ -25,8 +25,8 @@ import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py index f1e6a93760..3b0dc987d4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py @@ -17,8 +17,8 @@ import azlmbr.editor as editor import azlmbr.bus as bus sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py index 5e80bd6b33..3fd2f856d4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py @@ -17,8 +17,8 @@ import azlmbr.editor as editor import azlmbr.bus as bus sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py index 076dbd950b..c25761d655 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/VegetationInstances_DespawnWhenOutOfRange.py @@ -24,7 +24,7 @@ import azlmbr.legacy.general as general import azlmbr.math as math sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper from largeworlds.large_worlds_utils import editor_dynveg_test_helper as dynveg diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AltitudeFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AltitudeFilter.py index 6378b36447..65b5198213 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AltitudeFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AltitudeFilter.py @@ -15,7 +15,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AreaComponentSlices.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AreaComponentSlices.py index 014655f966..1353efbf2e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AreaComponentSlices.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AreaComponentSlices.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetListCombiner.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetListCombiner.py index c36f36d58c..ad0917ca22 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetListCombiner.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetListCombiner.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetWeightSelector.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetWeightSelector.py index cd383581cc..65472df3bc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetWeightSelector.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_AssetWeightSelector.py @@ -20,7 +20,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py index 84709b59a4..45518b71fc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_Debugger.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py index 980d754d2b..3171cc032f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DistanceBetweenFilter.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynVeg_Regressions.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynVeg_Regressions.py index 4a8831542f..b3cf344b2b 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynVeg_Regressions.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynVeg_Regressions.py @@ -15,7 +15,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynamicSliceInstanceSpawner.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynamicSliceInstanceSpawner.py index 1183c0769c..c5b8046f73 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynamicSliceInstanceSpawner.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_DynamicSliceInstanceSpawner.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_EmptyInstanceSpawner.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_EmptyInstanceSpawner.py index 32e00cdeb9..a7f221b780 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_EmptyInstanceSpawner.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_EmptyInstanceSpawner.py @@ -12,10 +12,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import os import pytest import logging + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_InstanceSpawnerPriority.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_InstanceSpawnerPriority.py index 7ef4185faf..d04b827985 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_InstanceSpawnerPriority.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_InstanceSpawnerPriority.py @@ -21,7 +21,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlender.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlender.py index 5fa7f04179..2286238364 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlender.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlender.py @@ -22,14 +22,14 @@ pytest.importorskip("ly_test_tools") import time as time +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.launchers.launcher_helper as launcher_helper -import ly_remote_console.remote_console_commands as remote_console_commands -from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response import ly_test_tools.environment.waiter as waiter import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra -import automatedtesting_shared.screenshot_utils as screenshot_utils +import ly_remote_console.remote_console_commands as remote_console_commands +from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response +import automatedtesting_shared.screenshot_utils as screenshot_utils from automatedtesting_shared.network_utils import check_for_listening_port diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlocker.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlocker.py index 94fe4d2e48..6da0cdd6db 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlocker.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerBlocker.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerSpawner.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerSpawner.py index ad08d7c214..e74ecc8bd1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerSpawner.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_LayerSpawner.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshBlocker.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshBlocker.py index 4437865a00..5e8ffe4d50 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshBlocker.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshBlocker.py @@ -16,7 +16,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshSurfaceTagEmitter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshSurfaceTagEmitter.py index 3a7a859b35..77638cb576 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshSurfaceTagEmitter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_MeshSurfaceTagEmitter.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PhysXColliderSurfaceTagEmitter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PhysXColliderSurfaceTagEmitter.py index d46c15024a..ca4e30a719 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PhysXColliderSurfaceTagEmitter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PhysXColliderSurfaceTagEmitter.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PositionModifier.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PositionModifier.py index e25820ed7e..47ff17bfa6 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PositionModifier.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_PositionModifier.py @@ -12,10 +12,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import os import pytest import logging + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_RotationModifier.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_RotationModifier.py index 1812c3c1b0..518949c0c0 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_RotationModifier.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_RotationModifier.py @@ -16,7 +16,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system logger = logging.getLogger(__name__) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ScaleModifier.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ScaleModifier.py index d6d9f5e991..6acd95e4f6 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ScaleModifier.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ScaleModifier.py @@ -19,7 +19,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ShapeIntersectionFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ShapeIntersectionFilter.py index 6b58ab23c5..ea90b67a7f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ShapeIntersectionFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_ShapeIntersectionFilter.py @@ -12,10 +12,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import os import pytest import logging + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeAlignmentModifier.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeAlignmentModifier.py index 3134bafed9..563ac1dcc5 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeAlignmentModifier.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeAlignmentModifier.py @@ -16,9 +16,10 @@ C4814459 - Surface Alignment overrides function as expected import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeFilter.py index 991e82caf3..dc0f0e6514 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SlopeFilter.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SurfaceMaskFilter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SurfaceMaskFilter.py index dfc0878a41..20cab85293 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SurfaceMaskFilter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SurfaceMaskFilter.py @@ -15,7 +15,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra import ly_test_tools.environment.file_system as file_system test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SystemSettings.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SystemSettings.py index 8b6e95ea14..adf9a90587 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SystemSettings.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/test_SystemSettings.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py index c6f7a3c438..cc9a15bba0 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientGenerators_Incompatibilities.py @@ -17,8 +17,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientGeneratorIncompatibilities(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py index 7fb94dab50..b7d12d074a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientModifiers_Incompatibilities.py @@ -17,8 +17,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientModifiersIncompatibilities(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py index 868d9d08e3..c37ee36265 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_ClearingPinnedEntitySetsPreviewToOrigin.py @@ -33,8 +33,8 @@ import azlmbr.paths import azlmbr.entity as EntityId sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientPreviewSettings(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py index 30d224f8c4..5a758b9d89 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientPreviewSettings_DefaultPinnedEntityIsSelf.py @@ -18,8 +18,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class Scoped: diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py index d94c197fea..5d4e575e4e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSampling_GradientReferencesAddRemoveSuccessfully.py @@ -18,8 +18,8 @@ import azlmbr.paths import azlmbr.entity as EntityId sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientSampling(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py index 7cdd029f3d..a16e37e0fc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_ComponentDependencies.py @@ -16,9 +16,10 @@ import azlmbr.bus as bus import azlmbr.entity as entity import azlmbr.paths import azlmbr.editor as editor + sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientSurfaceTagEmitterDependencies(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py index a37ae97361..e150070281 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientSurfaceTagEmitter_SurfaceTagsAddRemoveSuccessfully.py @@ -18,8 +18,8 @@ import azlmbr.paths import azlmbr.surface_data as surface_data sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientSurfaceTagEmitter(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py index 31f0ee2693..41860ecaec 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithExpectedGradients.py @@ -19,8 +19,8 @@ import azlmbr.math as math import azlmbr.entity as EntityId sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientTransform_ComponentIncompatibleWithExpectedGradients(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py index 0542e5e1b4..e2a7df6cf1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_ComponentIncompatibleWithSpawners.py @@ -19,8 +19,8 @@ import azlmbr.math as math import azlmbr.entity as EntityId sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientTransform_ComponentIncompatibleWithSpawners(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py index 22518e61be..bd664a9424 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_FrequencyZoomCanBeSetBeyondSliderRange.py @@ -24,8 +24,8 @@ import azlmbr.paths import azlmbr.entity as EntityId sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientTransformFrequencyZoom(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py index 3986076980..e1e901f2f7 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/GradientTransform_RequiresShape.py @@ -17,8 +17,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestGradientTransformRequiresShape(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py index 6b4a8bf17c..c24fc69b57 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_ProcessedImageAssignedSuccessfully.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestImageGradient(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py index 152f256266..dab8e6928a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/EditorScripts/ImageGradient_RequiresShape.py @@ -17,8 +17,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestImageGradientRequiresShape(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientIncompatibilities.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientIncompatibilities.py index 108bc79afd..1f16dbae97 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientIncompatibilities.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientIncompatibilities.py @@ -19,7 +19,7 @@ import pytest pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientPreviewSettings.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientPreviewSettings.py index fd886945af..6f755accb2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientPreviewSettings.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientPreviewSettings.py @@ -11,10 +11,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSampling.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSampling.py index ac3ffaff06..315ec11986 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSampling.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSampling.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSurfaceTagEmitter.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSurfaceTagEmitter.py index 91ae577b62..61e3832b24 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSurfaceTagEmitter.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientSurfaceTagEmitter.py @@ -16,7 +16,7 @@ import logging # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientTransform.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientTransform.py index ecc4e5a027..7fb690c041 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientTransform.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_GradientTransform.py @@ -17,10 +17,11 @@ the same Entity that provides the ShapeService (e.g. box shape, or reference sha import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py index 11712f8b65..785f92067d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/gradient_signal/test_ImageGradient.py @@ -11,10 +11,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py index b8e61ab7f2..d1e0b68ef4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_DependentComponentsAdded.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py index f15301d180..4e429a192b 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/AreaNodes_EntityCreatedOnNodeAdd.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py index d8172c1be3..26062c01f8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ComponentUpdates_UpdateGraph.py @@ -41,8 +41,8 @@ import azlmbr.slice as slice import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestComponentUpdatesUpdateGraph(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py index 86f8f83201..5fed13985d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/CreateNewGraph.py @@ -19,8 +19,8 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID new_root_entity_id = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py index e25553b64a..7fd3f075e0 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_DisabledNodeDuplication.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py index f88ce893ba..27ab6fded3 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/Edit_UndoNodeDelete_SliceEntity.py @@ -35,8 +35,8 @@ import azlmbr.slice as slice import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestUndoNodeDeleteSlice(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py index 8883dc0d93..ca3bc04f47 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientMixer_NodeConstruction.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py index 9419322000..d40b19e7db 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityCreatedOnNodeAdd.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py index 9fbcb1382f..dc263924d1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientModifierNodes_EntityRemovedOnNodeDelete.py @@ -21,7 +21,7 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID createdEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py index 4315acac62..5e203e1892 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_DependentComponentsAdded.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py index f2809b0cf2..6d4a2f58a7 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityCreatedOnNodeAdd.py @@ -20,8 +20,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py index c6147e8bb4..2b49e3a911 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GradientNodes_EntityRemovedOnNodeDelete.py @@ -21,7 +21,7 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID createdEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py index b3eeafced7..d3ad5c1c1e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnEntityDelete.py @@ -19,7 +19,7 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newRootEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py index 302cb9dcc0..b7b0008eb2 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_OnLevelChange.py @@ -18,7 +18,7 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py index ea6bbb94ff..efd1cc5a55 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphClosed_TabbedGraph.py @@ -18,7 +18,7 @@ import azlmbr.legacy.general as general import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py index 4149504aca..f350d37178 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/GraphUpdates_UpdateComponents.py @@ -38,10 +38,11 @@ import azlmbr.math as math import azlmbr.slice as slice import azlmbr.paths +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper + sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra import automatedtesting_shared.landscape_canvas_utils as lc -from automatedtesting_shared.editor_test_helper import EditorTestHelper class TestGraphUpdatesUpdateComponents(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py index b6f9457f0e..176429885f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvasComponent_AddedRemoved.py @@ -18,8 +18,8 @@ import azlmbr.entity as entity import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py index cfa685e875..e0f13adaa9 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LandscapeCanvas_SliceCreateInstantiate.py @@ -19,8 +19,8 @@ import azlmbr.asset as asset import azlmbr.slice as slice sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper class TestLandscapeCanvasSliceCreateInstantiate(EditorTestHelper): diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py index 6ed9b80dbe..ecc529b9b4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerBlender_NodeConstruction.py @@ -22,8 +22,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py index d65f86b77f..00fcb5170c 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/LayerExtenderNodes_ComponentEntitySync.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py index e5d3c436c3..bd10e5f4c6 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityCreatedOnNodeAdd.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py index db5542a3fd..f71f5ae906 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/ShapeNodes_EntityRemovedOnNodeDelete.py @@ -21,7 +21,7 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -from automatedtesting_shared.editor_test_helper import EditorTestHelper +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID createdEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py index 346358641d..968f39c64d 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/EditorScripts/SlotConnections_UpdateComponentReferences.py @@ -21,8 +21,8 @@ import azlmbr.math as math import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra -from automatedtesting_shared.editor_test_helper import EditorTestHelper +import editor_python_test_tools.hydra_editor_utils as hydra +from editor_python_test_tools.editor_test_helper import EditorTestHelper editorId = azlmbr.globals.property.LANDSCAPE_CANVAS_EDITOR_ID newEntityId = None diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_AreaNodes.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_AreaNodes.py index 46ca74a3df..4805d46e75 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_AreaNodes.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_AreaNodes.py @@ -18,10 +18,11 @@ C13815873 - All Filters/Modifiers/Selectors can be added to/removed from a Layer import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import automateeditor_python_test_toolsdtesting_shared.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_EditFunctionality.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_EditFunctionality.py index dcb35e01fb..6899847d81 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_EditFunctionality.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_EditFunctionality.py @@ -16,10 +16,11 @@ C30813586 - Editor remains stable after Undoing deletion of a node on a slice en import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py index edbd86a7a1..09235ca2ae 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GeneralGraphFunctionality.py @@ -21,7 +21,7 @@ import pytest # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip("ly_test_tools") import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientModifierNodes.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientModifierNodes.py index 20961df4b0..bce57b6da8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientModifierNodes.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientModifierNodes.py @@ -16,10 +16,11 @@ C18055051 - All Gradient Modifier nodes can be removed from a graph import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientNodes.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientNodes.py index 83a2a9686c..639bec7827 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientNodes.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GradientNodes.py @@ -17,10 +17,11 @@ C17461363 - All Gradient nodes can be removed from a graph import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GraphComponentSync.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GraphComponentSync.py index 33fbeeec1b..efeba3b74a 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GraphComponentSync.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_GraphComponentSync.py @@ -19,10 +19,11 @@ C21333743 - Vegetation Layer Blenders are properly setup when constructing in a import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_ShapeNodes.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_ShapeNodes.py index b74c2a70bc..3705cdc94e 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_ShapeNodes.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/test_ShapeNodes.py @@ -16,10 +16,11 @@ C17412059 - All Shape nodes can be removed from a graph import os import pytest + # Bail on the test if ly_test_tools doesn't exist. pytest.importorskip('ly_test_tools') import ly_test_tools.environment.file_system as file_system -import automatedtesting_shared.hydra_test_utils as hydra +import editor_python_test_tools.hydra_test_utils as hydra test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts') diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py b/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py index 6123729b1c..5e4432eafc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/large_worlds_utils/editor_dynveg_test_helper.py @@ -21,7 +21,7 @@ import azlmbr.areasystem as areasystem import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devroot, 'AutomatedTesting', 'Gem', 'PythonTests')) -import automatedtesting_shared.hydra_editor_utils as hydra +import editor_python_test_tools.hydra_editor_utils as hydra def create_surface_entity(name, center_point, box_size_x, box_size_y, box_size_z): diff --git a/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py b/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py index 04ff07daa2..e0277180ae 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C100000_RigidBody_EnablingGravityWorksPoC.py @@ -34,8 +34,8 @@ def C100000_RigidBody_EnablingGravityWorksPoC(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -84,5 +84,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C100000_RigidBody_EnablingGravityWorksPoC) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py b/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py index 031b3121ab..c7dd8debb9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC.py @@ -34,8 +34,8 @@ def C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -93,5 +93,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C111111_RigidBody_EnablingGravityWorksUsingNotificationsPoC) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py b/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py index e5cee76415..216a75233f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712452_ScriptCanvas_CollisionEvents.py @@ -76,14 +76,13 @@ def C12712452_ScriptCanvas_CollisionEvents(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components import azlmbr.entity import azlmbr.physics - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Constants TIME_OUT_SECONDS = 3.0 @@ -209,5 +208,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12712452_ScriptCanvas_CollisionEvents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py b/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py index bcbd0d6e0a..2adf30e65e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712453_ScriptCanvas_MultipleRaycastNode.py @@ -81,8 +81,8 @@ def C12712453_ScriptCanvas_MultipleRaycastNode(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -203,6 +203,6 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report # Disabled until Script Canvas merges the new backend #Report.start_test(C12712453_ScriptCanvas_MultipleRaycastNode) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py b/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py index 808f1e4c31..94eed900ff 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712454_ScriptCanvas_OverlapNodeVerification.py @@ -106,9 +106,8 @@ def C12712454_ScriptCanvas_OverlapNodeVerification(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -328,5 +327,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12712454_ScriptCanvas_OverlapNodeVerification) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py b/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py index a5c827edb9..61f26ebecb 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12712455_ScriptCanvas_ShapeCastVerification.py @@ -76,9 +76,8 @@ def C12712455_ScriptCanvas_ShapeCastVerification(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -145,5 +144,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12712455_ScriptCanvas_ShapeCastVerification) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py b/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py index b84adcd246..4745927e89 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude.py @@ -95,9 +95,8 @@ def C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -291,5 +290,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12868578_ForceRegion_DirectionHasNoAffectOnMagnitude) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py index 481c1fa43c..937fdd85a6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12868580_ForceRegion_SplineModifiedTransform.py @@ -83,8 +83,8 @@ def C12868580_ForceRegion_SplineModifiedTransform(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import itertools import azlmbr @@ -175,5 +175,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12868580_ForceRegion_SplineModifiedTransform) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py b/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py index a9fb92b4fa..0cb0a2f841 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12905527_ForceRegion_MagnitudeDeviation.py @@ -63,8 +63,8 @@ def C12905527_ForceRegion_MagnitudeDeviation(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -150,5 +150,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C12905527_ForceRegion_MagnitudeDeviation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py b/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py index d3fe35b1cd..42565333f7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C12905528_ForceRegion_WithNonTriggerCollider.py @@ -50,11 +50,12 @@ def run(): # Helper file Imports import ImportPathHelper as imports + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer helper.init_idle() # 1) Load the empty level diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py b/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py index d4bbdca52f..828022ccf2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13351703_COM_NotIncludeTriggerShapes.py @@ -64,9 +64,8 @@ def C13351703_COM_NotIncludeTriggerShapes(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -101,5 +100,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C13351703_COM_NotIncludeTriggerShapes) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py index eb3429f852..77d93d9752 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13352089_RigidBodies_MaxAngularVelocity.py @@ -131,8 +131,8 @@ def C13352089_RigidBodies_MaxAngularVelocity(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.math as lymath import azlmbr.legacy.general as general import azlmbr.bus @@ -288,5 +288,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C13352089_RigidBodies_MaxAngularVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py b/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py index 943fb4d754..1c580bfbfe 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13508019_Terrain_TerrainTexturePainterWorks.py @@ -48,7 +48,8 @@ def C13508019_Terrain_TerrainTexturePainterWorks(): imports.init() - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -143,5 +144,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C13508019_Terrain_TerrainTexturePainterWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py b/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py index db497dabc6..61efe20dbd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C13895144_Ragdoll_ChangeLevel.py @@ -67,9 +67,8 @@ def C13895144_Ragdoll_ChangeLevel(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -112,5 +111,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C13895144_Ragdoll_ChangeLevel) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py index 4837de3538..5668082f78 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14195074_ScriptCanvas_PostUpdateEvent.py @@ -70,9 +70,8 @@ def C14195074_ScriptCanvas_PostUpdateEvent(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -190,5 +189,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14195074_ScriptCanvas_PostUpdateEvent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py b/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py index 0958a4bbbb..fd5653b801 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14654881_CharacterController_SwitchLevels.py @@ -62,8 +62,8 @@ def C14654881_CharacterController_SwitchLevels(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -100,5 +100,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14654881_CharacterController_SwitchLevels) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py b/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py index 2bc620e0c1..03c18a5f1a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14654882_Ragdoll_ragdollAPTest.py @@ -78,9 +78,8 @@ def C14654882_Ragdoll_ragdollAPTest(): imports.init() - - from utils import TestHelper as helper - from utils import Report + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -137,5 +136,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14654882_Ragdoll_ragdollAPTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py b/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py index 9aac3ae91c..e52bdb7574 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861498_ConfirmError_NoPxMesh.py @@ -57,9 +57,9 @@ def C14861498_ConfirmError_NoPxMesh(): imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.legacy.general as general @@ -92,5 +92,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14861498_ConfirmError_NoPxMesh) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py index 43d4d0e905..7a65448dcd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861500_DefaultSetting_ColliderShape.py @@ -47,9 +47,9 @@ def C14861500_DefaultSetting_ColliderShape(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Open 3D Engine Imports import azlmbr.legacy.general as general @@ -77,5 +77,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14861500_DefaultSetting_ColliderShape) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py index a7fc5cf3b5..eae5ea547a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861501_PhysXCollider_RenderMeshAutoAssigned.py @@ -55,9 +55,9 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from asset_utils import Asset # Asset paths diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py index 94c1d8e404..6ea81ea2ff 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861502_PhysXCollider_AssetAutoAssigned.py @@ -54,9 +54,9 @@ def C14861502_PhysXCollider_AssetAutoAssigned(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from asset_utils import Asset # Open 3D Engine Imports @@ -100,5 +100,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14861502_PhysXCollider_AssetAutoAssigned) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py b/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py index 0a6962a31c..abc79ba1b0 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14861504_RenderMeshAsset_WithNoPxAsset.py @@ -59,10 +59,10 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer from asset_utils import Asset # Open 3D Engine Imports diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py b/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py index ea62be9768..45557098f7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14902097_ScriptCanvas_PreUpdateEvent.py @@ -72,9 +72,8 @@ def C14902097_ScriptCanvas_PreUpdateEvent(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -197,5 +196,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14902097_ScriptCanvas_PreUpdateEvent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py b/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py index fc3ae2bc18..19caaab4fe 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14902098_ScriptCanvas_PostPhysicsUpdate.py @@ -84,9 +84,8 @@ def C14902098_ScriptCanvas_PostPhysicsUpdate(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general @@ -118,5 +117,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14902098_ScriptCanvas_PostPhysicsUpdate) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py b/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py index 33a26d9433..342ac6bdbd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14976307_Gravity_SetGravityWorks.py @@ -69,9 +69,8 @@ def C14976307_Gravity_SetGravityWorks(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -130,5 +129,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14976307_Gravity_SetGravityWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py b/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py index ea01c71310..815e922a76 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C14976308_ScriptCanvas_SetKinematicTargetTransform.py @@ -100,14 +100,13 @@ def C14976308_ScriptCanvas_SetKinematicTargetTransform(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components import azlmbr.math import azlmbr.physics - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import itertools class Entity: @@ -228,5 +227,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C14976308_ScriptCanvas_SetKinematicTargetTransform) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py index f637981b1d..76ea9475ff 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after.py @@ -108,9 +108,8 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -293,5 +292,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15096732_Material_DefaultLibraryUpdatedAcrossLevels_after) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py index fcbc0ff723..748052db56 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before.py @@ -101,9 +101,8 @@ def C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -245,5 +244,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15096732_Material_DefaultLibraryUpdatedAcrossLevels_before) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py b/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py index f393ddf527..4c7949cc91 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096735_Materials_DefaultLibraryConsistency.py @@ -149,8 +149,8 @@ def C15096735_Materials_DefaultLibraryConsistency(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -424,5 +424,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15096735_Materials_DefaultLibraryConsistency) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py b/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py index cf849bbea8..cc7dc3c5e2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096737_Materials_DefaultMaterialLibraryChanges.py @@ -115,9 +115,8 @@ def C15096737_Materials_DefaultMaterialLibraryChanges(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus from Physmaterial_Editor import Physmaterial_Editor @@ -301,5 +300,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15096737_Materials_DefaultMaterialLibraryChanges) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py index c69b722e27..0f33f0858b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15096740_Material_LibraryUpdatedCorrectly.py @@ -58,9 +58,9 @@ def C15096740_Material_LibraryUpdatedCorrectly(): imports.init() # Helper file Imports - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from asset_utils import Asset # Open 3D Engine Imports @@ -107,5 +107,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15096740_Material_LibraryUpdatedCorrectly) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py b/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py index 998d21067b..625a8bfb4a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15308217_NoCrash_LevelSwitch.py @@ -71,9 +71,8 @@ def C15308217_NoCrash_LevelSwitch(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -114,5 +113,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15308217_NoCrash_LevelSwitch) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py b/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py index a6ddb73438..3f6457f15c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15308221_Material_ComponentsInSyncWithLibrary.py @@ -114,7 +114,6 @@ def C15308221_Material_ComponentsInSyncWithLibrary(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -122,8 +121,8 @@ def C15308221_Material_ComponentsInSyncWithLibrary(): import azlmbr.math as lymath from Physmaterial_Editor import Physmaterial_Editor - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper TIMEOUT = 3.0 BOUNCE_TOLERANCE = 0.1 @@ -252,5 +251,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15308221_Material_ComponentsInSyncWithLibrary) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py b/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py index f5a1fcebc3..57a0e6a75e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15425929_Undo_Redo.py @@ -53,10 +53,9 @@ def C15425929_Undo_Redo(): imports.init() - - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.legacy.general as general @@ -99,5 +98,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15425929_Undo_Redo) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py b/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py index d2db2239c2..f61886ccd0 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15425935_Material_LibraryUpdatedAcrossLevels.py @@ -122,8 +122,8 @@ def C15425935_Material_LibraryUpdatedAcrossLevels(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -314,5 +314,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15425935_Material_LibraryUpdatedAcrossLevels) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py b/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py index cb38a8a768..99e0dcc669 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15556261_PhysXMaterials_CharacterControllerMaterialAssignment.py @@ -88,8 +88,8 @@ def C15556261_PhysXMaterials_CharacterControllerMaterialAssignment(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -209,5 +209,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15556261_PhysXMaterials_CharacterControllerMaterialAssignment) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py b/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py index 8b0fba05b1..4572dd322a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15563573_Material_AddModifyDeleteOnCharacterController.py @@ -116,14 +116,13 @@ def C15563573_Material_AddModifyDeleteOnCharacterController(): imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath from Physmaterial_Editor import Physmaterial_Editor - from utils import Report - from utils import TestHelper as helper from AddModifyDelete_Utils import Box + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper FORCE_IMPULSE = lymath.Vector3(5.0, 0.0, 0.0) TIMEOUT = 3.0 @@ -205,5 +204,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15563573_Material_AddModifyDeleteOnCharacterController) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py b/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py index 2eb7759ead..52af7d8be5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C15845879_ForceRegion_HighLinearDampingForce.py @@ -65,9 +65,8 @@ def C15845879_ForceRegion_HighLinearDampingForce(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -177,5 +176,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C15845879_ForceRegion_HighLinearDampingForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py index a3115ceeab..68efd452b2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C17411467_AddPhysxRagdollComponent.py @@ -53,10 +53,10 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer helper.init_idle() # 1) Load the level diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py index 76b05a4ce9..b13869ce12 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243580_Joints_Fixed2BodiesConstrained.py @@ -58,9 +58,8 @@ def C18243580_Joints_Fixed2BodiesConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -107,5 +106,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243580_Joints_Fixed2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py index ffc48f6e3c..19feee575b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243581_Joints_FixedBreakable.py @@ -57,9 +57,8 @@ def C18243581_Joints_FixedBreakable(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -106,5 +105,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243581_Joints_FixedBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py index 6c0f98b694..c9c90d35a7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243582_Joints_FixedLeadFollowerCollide.py @@ -59,9 +59,8 @@ def C18243582_Joints_FixedLeadFollowerCollide(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -101,5 +100,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243582_Joints_FixedLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py index fd1fb02557..66343534a7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243583_Joints_Hinge2BodiesConstrained.py @@ -61,9 +61,8 @@ def C18243583_Joints_Hinge2BodiesConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -124,5 +123,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243583_Joints_Hinge2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py index c1ed3328a7..3b335cc5c6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243584_Joints_HingeSoftLimitsConstrained.py @@ -61,9 +61,8 @@ def C18243584_Joints_HingeSoftLimitsConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -120,5 +119,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243584_Joints_HingeSoftLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py index 515c51eb0b..289522fcac 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243585_Joints_HingeNoLimitsConstrained.py @@ -61,9 +61,8 @@ def C18243585_Joints_HingeNoLimitsConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -120,5 +119,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243585_Joints_HingeNoLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py index d673885ea1..60b9189c83 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243586_Joints_HingeLeadFollowerCollide.py @@ -58,9 +58,8 @@ def C18243586_Joints_HingeLeadFollowerCollide(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -100,5 +99,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243586_Joints_HingeLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py index d58d618b99..af6fa8cbac 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243587_Joints_HingeBreakable.py @@ -59,9 +59,8 @@ def C18243587_Joints_HingeBreakable(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -118,5 +117,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243587_Joints_HingeBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py index 1ead30c65e..074ca03000 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243588_Joints_Ball2BodiesConstrained.py @@ -60,9 +60,8 @@ def C18243588_Joints_Ball2BodiesConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -122,5 +121,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243588_Joints_Ball2BodiesConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py index d29c472fcd..e038b33043 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243589_Joints_BallSoftLimitsConstrained.py @@ -62,9 +62,8 @@ def C18243589_Joints_BallSoftLimitsConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -123,5 +122,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243589_Joints_BallSoftLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py index d3a0c8e82c..ede46fd5c5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243590_Joints_BallNoLimitsConstrained.py @@ -63,9 +63,8 @@ def C18243590_Joints_BallNoLimitsConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -121,5 +120,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243590_Joints_BallNoLimitsConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py index ba8967acab..c3e527956f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243591_Joints_BallLeadFollowerCollide.py @@ -58,9 +58,8 @@ def C18243591_Joints_BallLeadFollowerCollide(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -100,5 +99,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243591_Joints_BallLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py b/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py index 2b07d63a43..350fccd125 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243592_Joints_BallBreakable.py @@ -58,9 +58,8 @@ def C18243592_Joints_BallBreakable(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -116,5 +115,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243592_Joints_BallBreakable) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py b/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py index 1ebdaf73b3..4580a229ea 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18243593_Joints_GlobalFrameConstrained.py @@ -62,9 +62,8 @@ def C18243593_Joints_GlobalFrameConstrained(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -129,5 +128,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18243593_Joints_GlobalFrameConstrained) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py index 46f1535bf4..57dfc0f349 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18977601_Material_FrictionCombinePriority.py @@ -136,8 +136,8 @@ def C18977601_Material_FrictionCombinePriority(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -364,5 +364,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18977601_Material_FrictionCombinePriority) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py b/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py index 800ad38264..9b7fea1ab9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C18981526_Material_RestitutionCombinePriority.py @@ -135,9 +135,8 @@ def C18981526_Material_RestitutionCombinePriority(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -425,5 +424,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C18981526_Material_RestitutionCombinePriority) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py b/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py index 8dbee3cd4e..48c947aa1f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19536274_GetCollisionName_PrintsName.py @@ -50,9 +50,9 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import TestHelper as helper ACTIVE_STATUS = azlmbr.globals.property.EditorEntityStartStatus_StartActive diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py b/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py index 141c9fb4db..66e1302b5b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19536277_GetCollisionName_PrintsNothing.py @@ -50,9 +50,9 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import TestHelper as helper ACTIVE_STATUS = azlmbr.globals.property.EditorEntityStartStatus_StartActive diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py index 8910a4ded4..32ece8541c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19578018_ShapeColliderWithNoShapeComponent.py @@ -56,9 +56,9 @@ def C19578018_ShapeColliderWithNoShapeComponent(): imports.init() # Helper Imports - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import TestHelper as helper # Open 3D Engine Imports import azlmbr.bus as bus @@ -99,5 +99,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C19578018_ShapeColliderWithNoShapeComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py b/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py index 5c940264ff..0c42f5457d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19578021_ShapeCollider_CanBeAdded.py @@ -51,10 +51,10 @@ def C19578021_ShapeCollider_CanBeAdded(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer # Open 3D Engine Imports import azlmbr.legacy.general as general @@ -97,5 +97,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C19578021_ShapeCollider_CanBeAdded) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py b/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py index 3296b32fc9..769f08e3c4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C19723164_ShapeColliders_WontCrashEditor.py @@ -47,9 +47,9 @@ def C19723164_ShapeColliders_WontCrashEditor(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity # Open 3D Engine Imports import azlmbr.legacy.general as general @@ -103,5 +103,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C19723164_ShapeColliders_WontCrashEditor) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py index b879e37aa9..d8e0a6769c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain.py @@ -57,8 +57,8 @@ def C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain(): import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Global time out TIME_OUT = 1.0 @@ -119,5 +119,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C24308873_CylinderShapeCollider_CollidesWithPhysXTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py b/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py index 9f595616e7..8980e68250 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C28978033_Ragdoll_WorldBodyBusTests.py @@ -56,9 +56,9 @@ def C28978033_Ragdoll_WorldBodyBusTests(): import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper - from utils import vector3_str, aabb_str + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import vector3_str, aabb_str # Global time out TIME_OUT = 1.0 @@ -123,5 +123,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C28978033_Ragdoll_WorldBodyBusTests) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py b/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py index 2dc9a306c7..be541e4bf9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C29032500_EditorComponents_WorldBodyBusWorks.py @@ -94,9 +94,9 @@ def C29032500_EditorComponents_WorldBodyBusWorks(): import azlmbr.legacy.general as general import azlmbr.bus import math - from utils import Report - from utils import TestHelper as helper - from utils import vector3_str, aabb_str + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import vector3_str, aabb_str AABB_THRESHOLD = 0.01 # Entities won't move in the simulation @@ -161,5 +161,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C29032500_EditorComponents_WorldBodyBusWorks) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py index 086f045eec..3e3770adb9 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C3510642_Terrain_NotCollideWithTerrain.py @@ -74,12 +74,11 @@ def C3510642_Terrain_NotCollideWithTerrain(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Constants TIMEOUT = 2.0 @@ -176,5 +175,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C3510642_Terrain_NotCollideWithTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py b/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py index 765f7cbfe0..4ae10288bd 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C3510644_Collider_CollisionGroups.py @@ -100,8 +100,8 @@ def C3510644_Collider_CollisionGroups(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -370,5 +370,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C3510644_Collider_CollisionGroups) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py b/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py index aae538527a..5f2c40f11e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044455_Material_libraryChangesInstantly.py @@ -182,9 +182,8 @@ def C4044455_Material_libraryChangesInstantly(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -486,5 +485,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044455_Material_libraryChangesInstantly) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py index 80b7c6443f..b71c1e8ede 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044456_Material_FrictionCombine.py @@ -100,9 +100,8 @@ def C4044456_Material_FrictionCombine(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -221,5 +220,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044456_Material_FrictionCombine) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py b/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py index 856a663fe6..1ed2e8086c 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044457_Material_RestitutionCombine.py @@ -105,9 +105,8 @@ def C4044457_Material_RestitutionCombine(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -253,5 +252,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044457_Material_RestitutionCombine) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py b/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py index ab4a8c1574..c420250dfa 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044459_Material_DynamicFriction.py @@ -91,9 +91,8 @@ def C4044459_Material_DynamicFriction(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -199,5 +198,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044459_Material_DynamicFriction) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py b/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py index 9918c5fac6..4e330002ff 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044460_Material_StaticFriction.py @@ -89,9 +89,8 @@ def C4044460_Material_StaticFriction(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -196,5 +195,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044460_Material_StaticFriction) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py b/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py index a11cfd47f6..af8990d87f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044461_Material_Restitution.py @@ -96,9 +96,8 @@ def C4044461_Material_Restitution(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -238,5 +237,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044461_Material_Restitution) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py b/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py index 3c3b777a69..a8375114d5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044694_Material_EmptyLibraryUsesDefault.py @@ -75,15 +75,14 @@ def C4044694_Material_EmptyLibraryUsesDefault(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components import azlmbr.physics import azlmbr.math as lymath - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper FORCE_IMPULSE = lymath.Vector3(5.0, 0.0, 0.0) TIMEOUT = 3.0 @@ -197,5 +196,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044694_Material_EmptyLibraryUsesDefault) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py index cc2caaf3b6..a92927a9db 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044695_PhysXCollider_AddMultipleSurfaceFbx.py @@ -60,9 +60,9 @@ def run(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from asset_utils import Asset # Constants diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py b/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py index 46a6b04edf..dba759015f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4044697_Material_PerfaceMaterialValidation.py @@ -116,9 +116,8 @@ def C4044697_Material_PerfaceMaterialValidation(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -310,5 +309,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4044697_Material_PerfaceMaterialValidation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py b/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py index 49673da217..145a5e1b60 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4888315_Material_AddModifyDeleteOnCollider.py @@ -99,13 +99,12 @@ def C4888315_Material_AddModifyDeleteOnCollider(): imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath from Physmaterial_Editor import Physmaterial_Editor - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from AddModifyDelete_Utils import Box FORCE_IMPULSE = lymath.Vector3(5.0, 0.0, 0.0) @@ -184,5 +183,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4888315_Material_AddModifyDeleteOnCollider) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py index 80a83e0222..59b6a3fdfc 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925577_Materials_MaterialAssignedToTerrain.py @@ -85,9 +85,8 @@ def C4925577_Materials_MaterialAssignedToTerrain(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -313,5 +312,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4925577_Materials_MaterialAssignedToTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py index 87f94c6dd4..e0425c35be 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925579_Material_AddModifyDeleteOnTerrain.py @@ -100,13 +100,12 @@ def C4925579_Material_AddModifyDeleteOnTerrain(): imports.init() - import azlmbr.legacy.general as general import azlmbr.math as lymath from Physmaterial_Editor import Physmaterial_Editor - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from AddModifyDelete_Utils import Box FORCE_IMPULSE = lymath.Vector3(5.0, 0.0, 0.0) @@ -184,5 +183,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4925579_Material_AddModifyDeleteOnTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py b/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py index abb97da143..9944a033e3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925580_Material_RagdollBonesMaterial.py @@ -75,13 +75,12 @@ def C4925580_Material_RagdollBonesMaterial(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components import azlmbr.physics - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Constants TIME_OUT_SECONDS = 3.0 @@ -202,5 +201,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4925580_Material_RagdollBonesMaterial) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py b/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py index 0a309133a4..ed872ae99e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4925582_Material_AddModifyDeleteOnRagdollBones.py @@ -101,7 +101,6 @@ def C4925582_Material_AddModifyDeleteOnRagdollBones(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components @@ -109,8 +108,8 @@ def C4925582_Material_AddModifyDeleteOnRagdollBones(): import azlmbr.math as lymath from Physmaterial_Editor import Physmaterial_Editor - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper TIMEOUT = 3.0 BOUNCE_TOLERANCE = 0.05 @@ -220,5 +219,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4925582_Material_AddModifyDeleteOnRagdollBones) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py b/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py index 90feb352b3..aa059eb224 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976194_RigidBody_PhysXComponentIsValid.py @@ -62,9 +62,8 @@ def C4976194_RigidBody_PhysXComponentIsValid(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -118,5 +117,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976194_RigidBody_PhysXComponentIsValid) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py index 287bc75214..c5740b2798 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976195_RigidBodies_InitialLinearVelocity.py @@ -67,8 +67,8 @@ def C4976195_RigidBodies_InitialLinearVelocity(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -139,5 +139,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976195_RigidBodies_InitialLinearVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py b/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py index 82b8df29f7..08e171269e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976197_RigidBodies_InitialAngularVelocity.py @@ -80,8 +80,8 @@ def C4976197_RigidBodies_InitialAngularVelocity(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -184,5 +184,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976197_RigidBodies_InitialAngularVelocity) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py b/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py index 1660e71955..2e19b633c4 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976199_RigidBodies_LinearDampingObjectMotion.py @@ -65,8 +65,8 @@ def C4976199_RigidBodies_LinearDampingObjectMotion(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -277,5 +277,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976199_RigidBodies_LinearDampingObjectMotion) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py b/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py index e5438cd132..b90b34be53 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976200_RigidBody_AngularDampingObjectRotation.py @@ -69,9 +69,9 @@ def C4976200_RigidBody_AngularDampingObjectRotation(): imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import AngleHelper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import AngleHelper import azlmbr.legacy.general as general import azlmbr.bus @@ -292,5 +292,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976200_RigidBody_AngularDampingObjectRotation) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py b/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py index e8086e4965..7fb0ff84ce 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976201_RigidBody_MassIsAssigned.py @@ -110,13 +110,12 @@ def C4976201_RigidBody_MassIsAssigned(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper MOVEMENT_TIMEOUT = 7.0 COLLISION_TIMEOUT = 2.0 @@ -381,5 +380,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976201_RigidBody_MassIsAssigned) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py b/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py index f74119dd28..7d4cf1066e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976202_RigidBody_StopsWhenBelowKineticThreshold.py @@ -133,12 +133,11 @@ def C4976202_RigidBody_StopsWhenBelowKineticThreshold(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -334,5 +333,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976202_RigidBody_StopsWhenBelowKineticThreshold) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py b/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py index fae8ea9a3a..29fc2ec2a3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976204_Verify_Start_Asleep_Condition.py @@ -71,9 +71,8 @@ def C4976204_Verify_Start_Asleep_Condition(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -120,5 +119,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976204_Verify_Start_Asleep_Condition) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py b/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py index a8227b6b1f..b97c590a93 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976206_RigidBodies_GravityEnabledActive.py @@ -73,8 +73,8 @@ def C4976206_RigidBodies_GravityEnabledActive(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -152,5 +152,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976206_RigidBodies_GravityEnabledActive) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py b/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py index 8003f495c8..4481c00fc5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976207_PhysXRigidBodies_KinematicBehavior.py @@ -70,8 +70,8 @@ def C4976207_PhysXRigidBodies_KinematicBehavior(): import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Specific wait times in seconds TIME_OUT = 3.0 @@ -139,5 +139,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976207_PhysXRigidBodies_KinematicBehavior) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py b/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py index 9f67751d67..79ea6e5dc7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976209_RigidBody_ComputesCOM.py @@ -95,9 +95,8 @@ def C4976209_RigidBody_ComputesCOM(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -181,5 +180,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976209_RigidBody_ComputesCOM) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py b/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py index 7cda1bf6f0..451081ba23 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976210_COM_ManualSetting.py @@ -77,8 +77,8 @@ def C4976210_COM_ManualSetting(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus import azlmbr @@ -305,5 +305,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976210_COM_ManualSetting) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py b/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py index 289584ef51..63f0d382c3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976218_RigidBodies_InertiaObjectsNotComputed.py @@ -47,13 +47,13 @@ def C4976218_RigidBodies_InertiaObjectsNotComputed(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.components import azlmbr.physics - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper class UpperBox: def __init__(self, name): @@ -167,5 +167,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976218_RigidBodies_InertiaObjectsNotComputed) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py b/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py index c9b9dfb89f..8d9dc01396 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976227_Collider_NewGroup.py @@ -60,9 +60,8 @@ def C4976227_Collider_NewGroup(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -92,5 +91,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976227_Collider_NewGroup) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py index 8c1527fc89..906c6db55b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976236_AddPhysxColliderComponent.py @@ -55,10 +55,10 @@ def C4976236_AddPhysxColliderComponent(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from utils import Tracer - from editor_entity_utils import EditorEntity + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer from asset_utils import Asset helper.init_idle() @@ -103,5 +103,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976236_AddPhysxColliderComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py b/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py index 93d1981187..bb6234b69e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976242_Collision_SameCollisionlayerSameCollisiongroup.py @@ -71,9 +71,8 @@ def C4976242_Collision_SameCollisionlayerSameCollisiongroup(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -196,5 +195,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976242_Collision_SameCollisionlayerSameCollisiongroup) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py b/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py index a4a89fcdec..949ebb2b2a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976243_Collision_SameCollisionGroupDiffCollisionLayers.py @@ -75,9 +75,8 @@ def C4976243_Collision_SameCollisionGroupDiffCollisionLayers(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -135,5 +134,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976243_Collision_SameCollisionGroupDiffCollisionLayers) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py b/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py index 2770b0142c..c35b9fab81 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976244_Collider_SameGroupSameLayerCollision.py @@ -71,8 +71,8 @@ def C4976244_Collider_SameGroupSameLayerCollision(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -192,5 +192,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976244_Collider_SameGroupSameLayerCollision) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py index c70154f0be..dafb8d9014 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4976245_PhysXCollider_CollisionLayerTest.py @@ -76,8 +76,8 @@ def C4976245_PhysXCollider_CollisionLayerTest(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -230,5 +230,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4976245_PhysXCollider_CollisionLayerTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py b/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py index a05550ba90..8d985de402 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982593_PhysXCollider_CollisionLayerTest.py @@ -76,8 +76,8 @@ def C4982593_PhysXCollider_CollisionLayerTest(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -238,5 +238,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982593_PhysXCollider_CollisionLayerTest) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py b/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py index 86d862d547..8746996ca8 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982595_Collider_TriggerDisablesCollision.py @@ -84,13 +84,12 @@ def C4982595_Collider_TriggerDisablesCollision(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.components import azlmbr.physics - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper TIME_OUT_SECONDS = 3.0 SPHERE_RADIUS = 1.0 @@ -242,5 +241,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982595_Collider_TriggerDisablesCollision) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py index cbe8d7d47e..2bd4fc5adc 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982797_Collider_ColliderOffset.py @@ -95,8 +95,8 @@ def C4982797_Collider_ColliderOffset(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus import azlmbr @@ -339,5 +339,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982797_Collider_ColliderOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py index f64d762b3b..f86890d8bf 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982798_Collider_ColliderRotationOffset.py @@ -96,8 +96,8 @@ def C4982798_Collider_ColliderRotationOffset(): # Internal editor imports - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus import azlmbr @@ -307,5 +307,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982798_Collider_ColliderRotationOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py index d38bf780d4..c37ad2b2d2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982800_PhysXColliderShape_CanBeSelected.py @@ -50,9 +50,9 @@ def C4982800_PhysXColliderShape_CanBeSelected(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Open 3D Engine Imports import azlmbr.math as math @@ -98,5 +98,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982800_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py index 940f774088..19a835da18 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982801_PhysXColliderShape_CanBeSelected.py @@ -50,9 +50,9 @@ def C4982801_PhysXColliderShape_CanBeSelected(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Open 3D Engine Imports import azlmbr.math as math @@ -110,5 +110,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982801_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py b/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py index eba549abde..e1365d0887 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982802_PhysXColliderShape_CanBeSelected.py @@ -50,9 +50,9 @@ def C4982802_PhysXColliderShape_CanBeSelected(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.editor_entity_utils import EditorEntity as Entity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Open 3D Engine Imports import azlmbr.math as math @@ -110,5 +110,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982802_PhysXColliderShape_CanBeSelected) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py b/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py index da201ddeda..4ae177934a 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C4982803_Enable_PxMesh_Option.py @@ -63,9 +63,9 @@ def C4982803_Enable_PxMesh_Option(): import ImportPathHelper as imports imports.init() - from utils import Report - from utils import TestHelper as helper - from editor_entity_utils import EditorEntity + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper from asset_utils import Asset import azlmbr.math as math @@ -146,5 +146,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C4982803_Enable_PxMesh_Option) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py b/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py index cca768fb52..9d2a49ac70 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5296614_PhysXMaterial_ColliderShape.py @@ -69,8 +69,8 @@ def C5296614_PhysXMaterial_ColliderShape(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -159,5 +159,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5296614_PhysXMaterial_ColliderShape) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py b/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py index f012fe73c0..7617e41cad 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5340400_RigidBody_ManualMomentOfInertia.py @@ -76,11 +76,10 @@ def C5340400_RigidBody_ManualMomentOfInertia(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Specific wait time in seconds TIME_OUT = 3.0 @@ -168,5 +167,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5340400_RigidBody_ManualMomentOfInertia) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py b/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py index 359565402a..0686adf15d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689518_PhysXTerrain_CollidesWithPhysXTerrain.py @@ -58,8 +58,8 @@ def C5689518_PhysXTerrain_CollidesWithPhysXTerrain(): import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Global time out TIME_OUT = 1.0 @@ -120,5 +120,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689518_PhysXTerrain_CollidesWithPhysXTerrain) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py b/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py index 10ebcacdb7..ffafeaab34 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689522_Physxterrain_AddPhysxterrainNoEditorCrash.py @@ -67,12 +67,11 @@ def C5689522_Physxterrain_AddPhysxterrainNoEditorCrash(): imports.init() - import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.bus @@ -113,5 +112,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689522_Physxterrain_AddPhysxterrainNoEditorCrash) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py b/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py index b00821343b..2b1a73f1f3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689524_MultipleTerrains_CheckWarningInConsole.py @@ -72,9 +72,9 @@ def C5689524_MultipleTerrains_CheckWarningInConsole(): import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.bus @@ -114,5 +114,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689524_MultipleTerrains_CheckWarningInConsole) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py b/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py index f540cae081..265836489d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689528_Terrain_MultipleTerrainComponents.py @@ -69,10 +69,9 @@ def C5689528_Terrain_MultipleTerrainComponents(): imports.init() - - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.legacy.general as general @@ -111,5 +110,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689528_Terrain_MultipleTerrainComponents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py b/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py index 2fbf21fb72..138ae68408 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689529_Verify_Terrain_RigidBody_Collider_Mesh.py @@ -67,9 +67,8 @@ def C5689529_Verify_Terrain_RigidBody_Collider_Mesh(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -114,5 +113,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689529_Verify_Terrain_RigidBody_Collider_Mesh) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py b/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py index c8e5d6873b..7d60a61ec1 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5689531_Warning_TerrainSliceTerrainComponent.py @@ -74,10 +74,9 @@ def C5689531_Warning_TerrainSliceTerrainComponent(): imports.init() - - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.legacy.general as general @@ -123,5 +122,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5689531_Warning_TerrainSliceTerrainComponent) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py b/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py index 87bc4812b2..f01dd4582f 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932040_ForceRegion_CubeExertsWorldForce.py @@ -74,9 +74,8 @@ def C5932040_ForceRegion_CubeExertsWorldForce(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -191,5 +190,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932040_ForceRegion_CubeExertsWorldForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py index d78f0f386a..095a669541 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies.py @@ -74,9 +74,8 @@ def C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -169,5 +168,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932041_PhysXForceRegion_LocalSpaceForceOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py b/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py index a3f6de6a5f..04cecd45b2 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932042_PhysXForceRegion_LinearDamping.py @@ -80,8 +80,8 @@ def C5932042_PhysXForceRegion_LinearDamping(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -276,5 +276,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932042_PhysXForceRegion_LinearDamping) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py index 2c019b092c..512698ce4b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932043_ForceRegion_SimpleDragOnRigidBodies.py @@ -50,7 +50,8 @@ def C5932043_ForceRegion_SimpleDragOnRigidBodies(): imports.init() - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -145,5 +146,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932043_ForceRegion_SimpleDragOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py index 4f8121e254..b7257b488b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932044_ForceRegion_PointForceOnRigidBody.py @@ -74,9 +74,8 @@ def C5932044_ForceRegion_PointForceOnRigidBody(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -197,5 +196,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932044_ForceRegion_PointForceOnRigidBody) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py b/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py index 4cb71ab54c..eca0679921 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5932045_ForceRegion_Spline.py @@ -79,9 +79,8 @@ def C5932045_ForceRegion_Spline(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import itertools import azlmbr @@ -170,5 +169,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5932045_ForceRegion_Spline) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py b/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py index 5271bec2ec..6aff0a7145 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959759_RigidBody_ForceRegionSpherePointForce.py @@ -47,8 +47,8 @@ def C5959759_RigidBody_ForceRegionSpherePointForce(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -157,5 +157,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959759_RigidBody_ForceRegionSpherePointForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py b/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py index 42020c78b7..89eb1842be 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959760_PhysXForceRegion_PointForceExertion.py @@ -72,8 +72,8 @@ def C5959760_PhysXForceRegion_PointForceExertion(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -230,5 +230,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959760_PhysXForceRegion_PointForceExertion) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py b/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py index af9af57363..ba0475266b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959761_ForceRegion_PhysAssetExertsPointForce.py @@ -76,8 +76,8 @@ def C5959761_ForceRegion_PhysAssetExertsPointForce(): import azlmbr.bus as bus import azlmbr.math - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper TIMEOUT = 2.0 @@ -147,5 +147,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959761_ForceRegion_PhysAssetExertsPointForce) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py b/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py index 2b7bf49278..76130d25eb 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959763_ForceRegion_ForceRegionImpulsesCube.py @@ -50,7 +50,8 @@ def C5959763_ForceRegion_ForceRegionImpulsesCube(): imports.init() - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -171,5 +172,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959763_ForceRegion_ForceRegionImpulsesCube) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py b/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py index 02bba2f848..f314dae5b7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959764_ForceRegion_ForceRegionImpulsesCapsule.py @@ -50,7 +50,8 @@ def C5959764_ForceRegion_ForceRegionImpulsesCapsule(): imports.init() - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -173,5 +174,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959764_ForceRegion_ForceRegionImpulsesCapsule) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py b/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py index 1afd7b4536..ddcba5996b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959765_ForceRegion_AssetGetsImpulsed.py @@ -53,7 +53,8 @@ def C5959765_ForceRegion_AssetGetsImpulsed(): imports.init() - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -175,5 +176,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959765_ForceRegion_AssetGetsImpulsed) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py index f105c5642e..175f73a420 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959808_ForceRegion_PositionOffset.py @@ -133,8 +133,8 @@ def C5959808_ForceRegion_PositionOffset(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.math as azmath @@ -412,5 +412,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959808_ForceRegion_PositionOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py b/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py index f0379d20f7..1ad53194d3 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959809_ForceRegion_RotationalOffset.py @@ -134,8 +134,8 @@ def C5959809_ForceRegion_RotationalOffset(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.math as azmath @@ -412,5 +412,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959809_ForceRegion_RotationalOffset) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py b/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py index e09b58ecdc..212f7cc86b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5959810_ForceRegion_ForceRegionCombinesForces.py @@ -74,8 +74,8 @@ def C5959810_ForceRegion_ForceRegionCombinesForces(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -241,5 +241,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5959810_ForceRegion_ForceRegionCombinesForces) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py b/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py index 3bdb4410ea..4aa0fef642 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody.py @@ -67,7 +67,8 @@ def C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody(): import azlmbr.legacy.general as general import azlmbr.bus as bus import azlmbr.physics - from utils import Report, TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Constants TIME_OUT = 6.0 # Second to wait before timing out @@ -181,5 +182,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5968759_ForceRegion_ExertsSeveralForcesOnRigidBody) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py b/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py index 7c7c11f548..ba491c96a7 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C5968760_ForceRegion_CheckNetForceChange.py @@ -70,9 +70,8 @@ def C5968760_ForceRegion_CheckNetForceChange(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -171,5 +170,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C5968760_ForceRegion_CheckNetForceChange) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py b/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py index d79954d26f..4543b0b8f6 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6032082_Terrain_MultipleResolutionsValid.py @@ -89,9 +89,8 @@ def C6032082_Terrain_MultipleResolutionsValid(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -217,5 +216,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6032082_Terrain_MultipleResolutionsValid) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py b/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py index 825b8287d1..557b7e7ec5 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090546_ForceRegion_SliceFileInstantiates.py @@ -72,9 +72,8 @@ def C6090546_ForceRegion_SliceFileInstantiates(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -146,5 +145,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090546_ForceRegion_SliceFileInstantiates) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py b/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py index a62a673b9f..a07fd1861b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090547_ForceRegion_ParentChildForceRegions.py @@ -81,13 +81,12 @@ def C6090547_ForceRegion_ParentChildForceRegions(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus import azlmbr.math as lymath - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Constants TIMEOUT = 3.0 @@ -207,5 +206,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090547_ForceRegion_ParentChildForceRegions) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py index c85dc6a273..f8da62ebac 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090550_ForceRegion_WorldSpaceForceNegative.py @@ -78,12 +78,11 @@ def C6090550_ForceRegion_WorldSpaceForceNegative(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -251,5 +250,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090550_ForceRegion_WorldSpaceForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py index 45f9b21522..0788b1da66 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090551_ForceRegion_LocalSpaceForceNegative.py @@ -78,12 +78,11 @@ def C6090551_ForceRegion_LocalSpaceForceNegative(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -251,5 +250,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090551_ForceRegion_LocalSpaceForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py index 5751f55b0c..a878819045 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090552_ForceRegion_LinearDampingNegative.py @@ -77,12 +77,11 @@ def C6090552_ForceRegion_LinearDampingNegative(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -250,5 +249,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090552_ForceRegion_LinearDampingNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py index 3c995bca62..43c4335918 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090553_ForceRegion_SimpleDragForceOnRigidBodies.py @@ -72,12 +72,11 @@ def C6090553_ForceRegion_SimpleDragForceOnRigidBodies(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper # Holds details about the ball class Ball: @@ -182,5 +181,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090553_ForceRegion_SimpleDragForceOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py b/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py index 0ea8ca2e4b..d7781b6040 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090554_ForceRegion_PointForceNegative.py @@ -78,12 +78,11 @@ def C6090554_ForceRegion_PointForceNegative(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -251,5 +250,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090554_ForceRegion_PointForceNegative) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py b/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py index dfa992bc21..b1b76d896d 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6090555_ForceRegion_SplineFollowOnRigidBodies.py @@ -74,9 +74,8 @@ def C6090555_ForceRegion_SplineFollowOnRigidBodies(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr import azlmbr.legacy.general as general @@ -184,5 +183,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6090555_ForceRegion_SplineFollowOnRigidBodies) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py b/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py index 5e475a4c4c..11281df4eb 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6131473_StaticSlice_OnDynamicSliceSpawn.py @@ -67,9 +67,8 @@ def C6131473_StaticSlice_OnDynamicSliceSpawn(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -111,5 +110,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6131473_StaticSlice_OnDynamicSliceSpawn) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py b/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py index f88e07bf86..6501e11e68 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6224408_ScriptCanvas_EntitySpawn.py @@ -69,9 +69,8 @@ def C6224408_ScriptCanvas_EntitySpawn(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus @@ -152,5 +151,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6224408_ScriptCanvas_EntitySpawn) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py b/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py index 64baa81140..44c8be9e1e 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6274125_ScriptCanvas_TriggerEvents.py @@ -75,12 +75,11 @@ def C6274125_ScriptCanvas_TriggerEvents(): imports.init() - import azlmbr.legacy.general as general import azlmbr.bus - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() @@ -136,5 +135,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6274125_ScriptCanvas_TriggerEvents) diff --git a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py b/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py index 2b0168a2fe..c1a51f2887 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py +++ b/AutomatedTesting/Gem/PythonTests/physics/C6321601_Force_HighValuesDirectionAxes.py @@ -99,10 +99,9 @@ def C6321601_Force_HighValuesDirectionAxes(): imports.init() - - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer import azlmbr.legacy.general as general import azlmbr.bus @@ -256,5 +255,5 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(C6321601_Force_HighValuesDirectionAxes) diff --git a/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py index db07f4e14a..e61118ef5b 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py +++ b/AutomatedTesting/Gem/PythonTests/physics/JointsHelper.py @@ -13,7 +13,7 @@ import ImportPathHelper as imports imports.init() -from utils import Report +from editor_python_test_tools.utils import Report import azlmbr.legacy.general as general import azlmbr.bus diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py index 94c1335536..bc6697afaf 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py +++ b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Managed_Files.py @@ -22,8 +22,8 @@ def run(): imports.init() - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper helper.init_idle() Report.success(Tests.passed) diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py index 666b4910a1..5f24f41083 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py +++ b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Physmaterial_Editor.py @@ -58,9 +58,8 @@ def run(): imports.init() - - from utils import Report - from utils import TestHelper as helper + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general from Physmaterial_Editor import Physmaterial_Editor diff --git a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py index 0aeb8aa73a..fa904250ea 100755 --- a/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py +++ b/AutomatedTesting/Gem/PythonTests/physics/UtilTest_Tracer_PicksErrorsAndWarnings.py @@ -39,12 +39,11 @@ def run(): imports.init() - import azlmbr.legacy.general as general - from utils import Report - from utils import TestHelper as helper - from utils import Tracer + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + from editor_python_test_tools.utils import Tracer helper.init_idle() diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py index 3b54c0de72..25dd83e5e2 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Docking_Pane.py @@ -51,9 +51,9 @@ def Docking_Pane(): imports.init() - from utils import Report - from utils import TestHelper as helper - import pyside_utils + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.pyside_utils as pyside_utils # Open 3D Engine imports import azlmbr.legacy.general as general @@ -114,6 +114,6 @@ if __name__ == "__main__": imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(Docking_Pane) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py index 4ea4d791dd..6100285092 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Opening_Closing_Pane.py @@ -54,9 +54,9 @@ def Opening_Closing_Pane(): imports.init() - from utils import Report - from utils import TestHelper as helper - import pyside_utils + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.pyside_utils as pyside_utils # Open 3D Engine Imports import azlmbr.legacy.general as general @@ -123,6 +123,6 @@ if __name__ == "__main__": imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(Opening_Closing_Pane) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py b/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py index 216ef4fb7d..9262e76cb0 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/Resizing_Pane.py @@ -51,9 +51,9 @@ def Resizing_Pane(): imports.init() - from utils import Report - from utils import TestHelper as helper - import pyside_utils + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.pyside_utils as pyside_utils # Open 3D Engine imports import azlmbr.legacy.general as general @@ -115,6 +115,6 @@ if __name__ == "__main__": import ImportPathHelper as imports imports.init() - from utils import Report + from editor_python_test_tools.utils import Report Report.start_test(Resizing_Pane) diff --git a/Tools/EditorPythonTestTools/README.txt b/Tools/EditorPythonTestTools/README.txt new file mode 100644 index 0000000000..d32d3d21a3 --- /dev/null +++ b/Tools/EditorPythonTestTools/README.txt @@ -0,0 +1,100 @@ +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +INTRODUCTION +------------ + +EditorPythonBindings is a Python project that contains a collection of testing tools +developed by the Lumberyard Test Tech team. The project contains +the following tools: + + * Workspace Manager: + A library to manipulate Lumberyard installations + * Launchers: + A library to test the game in a variety of platforms + + +REQUIREMENTS +------------ + + * Python 3.7.5 (64-bit) + +It is recommended that you completely remove any other versions of Python +installed on your system. + + +INSTALL +----------- +It is recommended to set up these these tools with Lumberyard's CMake build commands. +Assuming CMake is already setup on your operating system, below are some sample build commands: + cd /path/to/od3e/ + mkdir windows_vs2019 + cd windows_vs2019 + cmake .. -G "Visual Studio 16 2019" -A x64 -T host=x64 -DLY_3RDPARTY_PATH="%3RDPARTYPATH%" -DLY_PROJECTS=AutomatedTesting +NOTE: +Using the above command also adds LyTestTools to the PYTHONPATH OS environment variable. +Additionally, some CTest scripts will add the Python interpreter path to the PYTHON OS environment variable. +There is some LyTestTools functionality that will search for these, so feel free to populate them manually. + +To manually install the project in development mode using your own installed Python interpreter: + cd /path/to/lumberyard/dev/Tools/LyTestTools/ + /path/to/your/python -m pip install -e . + +For console/mobile testing, update the following .ini file in your root user directory: + i.e. C:/Users/myusername/ly_test_tools/devices.ini (a.k.a. %USERPROFILE%/ly_test_tools/devices.ini) + +You will need to add a section for the device, and a key holding the device identifier value (usually an IP or ID). +It should look similar to this for each device: + [android] + id = 988939353955305449 + + [gameconsole] + ip = 192.168.1.1 + + [gameconsole2] + ip = 192.168.1.2 + + +PACKAGE STRUCTURE +----------------- + +The project is organized into packages. Each package corresponds to a tool: + +- LyTestTools.ly_test_tools._internal: contains logging setup, pytest fixture, and o3de workspace manager modules +- LyTestTools.ly_test_tools.builtin: builtin helpers and fixtures for quickly writing tests +- LyTestTools.ly_test_tools.console: modules used for consoles +- LyTestTools.ly_test_tools.environment: functions related to file/process management and cleanup +- LyTestTools.ly_test_tools.image: modules related to image capturing and processing +- LyTestTools.ly_test_tools.launchers: game launchers library +- LyTestTools.ly_test_tools.log: modules for interacting with generated or existing log files +- LyTestTools.ly_test_tools.o3de: modules used to interact with Open 3D Engine +- LyTestTools.ly_test_tools.mobile: modules used for android/ios +- LyTestTools.ly_test_tools.report: modules used for reporting +- LyTestTools.tests: LyTestTools integration, unit, and example usage tests + + +DIRECTORY STRUCTURE +------------------- + +The directory structure corresponds to the package structure. For example, the +ly_test_tools.builtin package is located in the ly_test_tools/builtin/ directory. + + +ENTRY POINTS +------------ + +Deploying the project in development mode installs only entry points for pytest fixtures. + + +UNINSTALLATION +-------------- + +The preferred way to uninstall the project is: + /path/to/your/python -m pip uninstall ly_test_tools diff --git a/Tools/EditorPythonTestTools/__init__.py b/Tools/EditorPythonTestTools/__init__.py new file mode 100644 index 0000000000..79f8fa4422 --- /dev/null +++ b/Tools/EditorPythonTestTools/__init__.py @@ -0,0 +1,10 @@ +""" +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +""" diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py b/Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py new file mode 100644 index 0000000000..6ed3dc4bda --- /dev/null +++ b/Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py @@ -0,0 +1,10 @@ +""" +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +""" \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py index 3e009563b8..4dc71bf16b --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_entity_utils.py +++ b/Tools/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py @@ -13,8 +13,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. from __future__ import annotations from typing import List, Tuple, Union -# Helper file Imports -import utils # Open 3D Engine Imports import azlmbr @@ -23,6 +21,8 @@ import azlmbr.editor as editor import azlmbr.math as math import azlmbr.legacy.general as general +# Helper file Imports +from editor_python_test_tools.utils import Report class EditorComponent: """ @@ -61,7 +61,7 @@ class EditorComponent: build_prop_tree_outcome.IsSuccess() ), f"Failure: Could not build property tree of component: '{self.get_component_name()}'" prop_tree = build_prop_tree_outcome.GetValue() - utils.Report.info(prop_tree.build_paths_list()) + Report.info(prop_tree.build_paths_list()) return prop_tree def get_component_property_value(self, component_property_path: str): @@ -291,7 +291,7 @@ class EditorEntity: status_text = "inactive" elif status == azlmbr.globals.property.EditorEntityStartStatus_EditorOnly: status_text = "editor" - utils.Report.info(f"The start status for {self.get_name} is {status_text}") + Report.info(f"The start status for {self.get_name} is {status_text}") self.start_status = status return status @@ -308,7 +308,7 @@ class EditorEntity: elif desired_start_status == "editor": status_to_set = azlmbr.globals.property.EditorEntityStartStatus_EditorOnly else: - utils.Report.info( + Report.info( f"Invalid desired_start_status argument for {self.get_name} set_start_status command;\ Use editor, active, or inactive" ) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py b/Tools/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py old mode 100755 new mode 100644 similarity index 99% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py index 64a19aafdf..2ecf092f1c --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py +++ b/Tools/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py @@ -15,12 +15,13 @@ import sys import time from typing import Sequence -from .report import Report # Open 3D Engine specific imports import azlmbr.legacy.general as general import azlmbr.legacy.settings as settings +from editor_python_test_tools.utils import Report + class EditorTestHelper: def __init__(self, log_prefix: str, args: Sequence[str] = None) -> None: diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_editor_utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_test_utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py old mode 100755 new mode 100644 similarity index 92% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_test_utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py index a796fd70da..ee352f8a73 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/hydra_test_utils.py +++ b/Tools/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py @@ -12,10 +12,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import logging import os import tempfile + import ly_test_tools.log.log_monitor import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter -from automatedtesting_shared.network_utils import check_for_listening_port from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole from ly_remote_console.remote_console_commands import send_command_and_expect_response as send_command_and_expect_response logger = logging.getLogger(__name__) @@ -86,6 +86,19 @@ def launch_and_validate_results_launcher(launcher, level, remote_console_instanc :param log_monitor_timeout: Timeout for monitoring for lines in Game.log :param remote_console_port: The port used to communicate with the Remote Console. """ + + def _check_for_listening_port(port): + """ + Checks to see if the connection to the designated port was established. + :param port: Port to listen to. + :return: True if port is listening. + """ + port_listening = False + for conn in psutil.net_connections(): + if 'port={}'.format(port) in str(conn): + port_listening = True + return port_listening + if null_renderer: launcher.args.extend(["-NullRenderer"]) @@ -94,7 +107,7 @@ def launch_and_validate_results_launcher(launcher, level, remote_console_instanc # Ensure Remote Console can be reached waiter.wait_for( - lambda: check_for_listening_port(remote_console_port), + lambda: _check_for_listening_port(remote_console_port), port_listener_timeout, exc=AssertionError("Port {} not listening.".format(remote_console_port)), ) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/pyside_component_utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py old mode 100755 new mode 100644 similarity index 98% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/pyside_component_utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py index 38e5800c53..0432d4ae25 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/pyside_component_utils.py +++ b/Tools/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py @@ -11,7 +11,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. import PySide2 -import pyside_utils +import editor_python_test_tools.pyside_utils def get_component_combobox_values(component_name, property_name, log_fn=None): diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/pyside_utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/pyside_utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/utils.py b/Tools/EditorPythonTestTools/editor_python_test_tools/utils.py old mode 100755 new mode 100644 similarity index 100% rename from AutomatedTesting/Gem/PythonTests/automatedtesting_shared/utils.py rename to Tools/EditorPythonTestTools/editor_python_test_tools/utils.py diff --git a/Tools/EditorPythonTestTools/setup.py b/Tools/EditorPythonTestTools/setup.py new file mode 100644 index 0000000000..b11b5d32ad --- /dev/null +++ b/Tools/EditorPythonTestTools/setup.py @@ -0,0 +1,43 @@ +""" +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +""" +import os +import platform + +from setuptools import setup, find_packages +from setuptools.command.develop import develop +from setuptools.command.build_py import build_py + +PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) + +PYTHON_64 = platform.architecture()[0] == '64bit' + + +if __name__ == '__main__': + if not PYTHON_64: + raise RuntimeError("32-bit Python is not a supported platform.") + + with open(os.path.join(PROJECT_ROOT, 'README.txt')) as f: + long_description = f.read() + + setup( + name="editor_python_test_tools", + version="1.0.0", + description='Lumberyard editor Python bindings test tools', + long_description=long_description, + packages=find_packages(where='Tools', exclude=['tests']), + install_requires=[ + "ly_test_tools" + ], + tests_require=[ + ], + entry_points={ + }, + ) diff --git a/cmake/LYPython.cmake b/cmake/LYPython.cmake index 14ea19a96a..1fb6ac3790 100644 --- a/cmake/LYPython.cmake +++ b/cmake/LYPython.cmake @@ -268,6 +268,7 @@ if (NOT CMAKE_SCRIPT_MODE_FILE) ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/LyTestTools ly-test-tools) ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/RemoteConsole/ly_remote_console ly-remote-console) + ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/EditorPythonTestTools editor-python-test-tools) endif() endif() From f5cb6f438b09da7cb5c353d25903549fb7f93e3e Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Tue, 20 Apr 2021 00:12:53 -0700 Subject: [PATCH 13/96] Making room for specular cavity occlusion support in the buffer. We can pre-multiply the diffuseAmbientOcclusion into the albedo term output from the forward pass, instead of multiplying it in the diffuse GI passes. The difference due to precision is negligable. This can be seen in the corresponding changes in AtomSampleViewer baseline screenshots. ATOM-14040 Add Support for Cavity Maps --- .../ShaderLib/Atom/Features/PBR/LightingModel.azsli | 8 ++++---- .../DiffuseGlobalIllumination/DiffuseComposite.azsl | 12 ++++-------- .../DiffuseComposite_nomsaa.azsl | 12 ++++-------- .../DiffuseGlobalFullscreen.azsl | 10 +++------- .../DiffuseGlobalFullscreen_nomsaa.azsl | 10 +++------- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli index 678e8cf061..71e283291f 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli @@ -79,6 +79,7 @@ void PbrVsHelper(in VSInput IN, inout VSOutput OUT, float3 worldPosition, bool s struct PbrLightingOutput { + // Note some of these use special encodings, which are identical to struct ForwardPassOutput float4 m_diffuseColor; float4 m_specularColor; float4 m_albedo; @@ -98,7 +99,7 @@ PbrLightingOutput PbrLighting( in VSOutput IN, float3 vtxBitangent, float2 anisotropy, // angle and factor float3 emissive, - float occlusion, + float diffuseAmbientOcclusion, float4 transmissionTintThickness, float4 transmissionParams, float clearCoatFactor, @@ -213,7 +214,7 @@ PbrLightingOutput PbrLighting( in VSOutput IN, } // Apply ambient occlusion to indirect diffuse - iblDiffuse *= occlusion; + iblDiffuse *= diffuseAmbientOcclusion; // Adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); @@ -259,8 +260,7 @@ PbrLightingOutput PbrLighting( in VSOutput IN, // albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc) lightingOutput.m_specularF0 = float4(specularF0, roughness); - lightingOutput.m_albedo.rgb = surface.albedo * diffuseResponse; - lightingOutput.m_albedo.a = occlusion; + lightingOutput.m_albedo.rgb = surface.albedo * diffuseResponse * diffuseAmbientOcclusion; lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(normal); lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl index 9b4e703f89..b3b26c4d42 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite.azsl @@ -24,7 +24,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2DMS<float4> m_downsampledProbeIrradiance; Texture2DMS<float> m_downsampledDepth; Texture2DMS<float4> m_downsampledNormal; - Texture2DMS<float4> m_albedo; // RGB8 = Albedo, A = Occlusion + Texture2DMS<float4> m_albedo; // RGB8 = Albedo with pre-multiplied factors, A = Unused here Texture2DMS<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags Texture2DMS<float> m_depth; @@ -118,7 +118,7 @@ float3 SampleProbeIrradiance(uint sampleIndex, uint2 probeIrradianceCoords, floa } // retrieve irradiance from the global IBL diffuse cubemap -float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal, float3 albedo) +float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal) { uint2 dimensions; uint samples; @@ -160,23 +160,19 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); float4 albedo = PassSrg::m_albedo.Load(screenCoords, sampleIndex); - float occlusion = albedo.a; float useProbeIrradiance = PassSrg::m_downsampledProbeIrradiance.Load(probeIrradianceCoords, sampleIndex).a; float3 diffuse = float3(0.0f, 0.0f, 0.0f); if (useProbeIrradiance > 0.0f) { float3 irradiance = SampleProbeIrradiance(sampleIndex, probeIrradianceCoords, depth, normal, albedo, ImageScale); - diffuse = (albedo.rgb / PI) * irradiance * occlusion; + diffuse = (albedo.rgb / PI) * irradiance; } else { - float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal, albedo); + float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal); diffuse = albedo * irradiance; - // apply ambient occlusion to indirect diffuse - diffuse *= occlusion; - // adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); diffuse *= iblExposureFactor; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite_nomsaa.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite_nomsaa.azsl index 74571b5c6a..a5d761d815 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite_nomsaa.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseComposite_nomsaa.azsl @@ -27,7 +27,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass Texture2D<float4> m_downsampledProbeIrradiance; Texture2D<float> m_downsampledDepth; Texture2D<float4> m_downsampledNormal; - Texture2D<float4> m_albedo; // RGB8 = Albedo, A = Occlusion + Texture2D<float4> m_albedo; // RGB8 = Albedo with pre-multiplied factors, A = Unused here Texture2D<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags Texture2D<float> m_depth; @@ -121,7 +121,7 @@ float3 SampleProbeIrradiance(uint2 probeIrradianceCoords, float depth, float3 no } // retrieve irradiance from the global IBL diffuse cubemap -float3 SampleGlobalIBL(uint2 screenCoords, float depth, float3 normal, float3 albedo) +float3 SampleGlobalIBL(uint2 screenCoords, float depth, float3 normal) { uint2 dimensions; PassSrg::m_depth.GetDimensions(dimensions.x, dimensions.y); @@ -162,23 +162,19 @@ PSOutput MainPS(VSOutput IN) float4 encodedNormal = PassSrg::m_normal.Load(int3(screenCoords, 0)); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); float4 albedo = PassSrg::m_albedo.Load(int3(screenCoords, 0)); - float occlusion = albedo.a; float useProbeIrradiance = PassSrg::m_downsampledProbeIrradiance.Load(int3(probeIrradianceCoords,0)).a; float3 diffuse = float3(0.0f, 0.0f, 0.0f); if (useProbeIrradiance > 0.0f) { float3 irradiance = SampleProbeIrradiance(probeIrradianceCoords, depth, normal, albedo, ImageScale); - diffuse = (albedo.rgb / PI) * irradiance * occlusion; + diffuse = (albedo.rgb / PI) * irradiance; } else { - float3 irradiance = SampleGlobalIBL(screenCoords, depth, normal, albedo); + float3 irradiance = SampleGlobalIBL(screenCoords, depth, normal); diffuse = albedo * irradiance; - // apply ambient occlusion to indirect diffuse - diffuse *= occlusion; - // adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); diffuse *= iblExposureFactor; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.azsl index d6a0de8159..dbc134d2ff 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen.azsl @@ -21,7 +21,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { - Texture2DMS<float4> m_albedo; // RGB8 = Albedo, A = Occlusion + Texture2DMS<float4> m_albedo; // RGB8 = Albedo with pre-multiplied factors, A = Unused here Texture2DMS<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags Texture2DMS<float> m_depth; } @@ -41,7 +41,7 @@ VSOutput MainVS(VSInput input) } // retrieve irradiance from the global IBL diffuse cubemap -float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal, float3 albedo) +float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal) { uint2 dimensions; uint samples; @@ -76,14 +76,10 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 encodedNormal = PassSrg::m_normal.Load(screenCoords, sampleIndex); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); float4 albedo = PassSrg::m_albedo.Load(screenCoords, sampleIndex); - float occlusion = albedo.a; - float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal, albedo); + float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal); float3 diffuse = albedo * irradiance; - // apply ambient occlusion to indirect diffuse - diffuse *= occlusion; - // adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); diffuse *= iblExposureFactor; diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen_nomsaa.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen_nomsaa.azsl index fe3523210a..803046efd4 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen_nomsaa.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseGlobalFullscreen_nomsaa.azsl @@ -24,7 +24,7 @@ ShaderResourceGroup PassSrg : SRG_PerPass { - Texture2D<float4> m_albedo; // RGB8 = Albedo, A = Occlusion + Texture2D<float4> m_albedo; // RGB8 = Albedo with pre-multiplied factors, A = Unused here Texture2D<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags Texture2D<float> m_depth; } @@ -44,7 +44,7 @@ VSOutput MainVS(VSInput input) } // retrieve irradiance from the global IBL diffuse cubemap -float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal, float3 albedo) +float3 SampleGlobalIBL(uint sampleIndex, uint2 screenCoords, float depth, float3 normal) { uint2 dimensions; PassSrg::m_depth.GetDimensions(dimensions.x, dimensions.y); @@ -78,14 +78,10 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 encodedNormal = PassSrg::m_normal.Load(int3(screenCoords, 0)); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); float4 albedo = PassSrg::m_albedo.Load(int3(screenCoords, 0)); - float occlusion = albedo.a; - float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal, albedo); + float3 irradiance = SampleGlobalIBL(sampleIndex, screenCoords, depth, normal); float3 diffuse = albedo * irradiance; - // apply ambient occlusion to indirect diffuse - diffuse *= occlusion; - // adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); diffuse *= iblExposureFactor; From f0ae8056c81416a51f3df8a0cfd5434bcb17b115 Mon Sep 17 00:00:00 2001 From: greerdv <greerdv@amazon.com> Date: Tue, 20 Apr 2021 10:25:19 +0100 Subject: [PATCH 14/96] feedback from PR --- Code/Framework/AzCore/AzCore/Math/Aabb.h | 2 ++ Code/Framework/AzCore/AzCore/Math/Aabb.inl | 7 ++++ .../Atom/Feature/Mesh/MeshFeatureProcessor.h | 6 ++-- .../Mesh/MeshFeatureProcessorInterface.h | 11 +++--- .../ReflectionProbeFeatureProcessor.h | 2 +- ...ReflectionProbeFeatureProcessorInterface.h | 2 +- .../TransformServiceFeatureProcessor.h | 6 ++-- ...ransformServiceFeatureProcessorInterface.h | 13 ++++--- .../Code/Mocks/MockMeshFeatureProcessor.h | 5 +-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 34 ++++++++++++++----- .../RayTracingAccelerationStructurePass.cpp | 3 +- .../RayTracing/RayTracingFeatureProcessor.cpp | 15 ++++---- .../RayTracing/RayTracingFeatureProcessor.h | 8 +++-- .../ReflectionProbe/ReflectionProbe.cpp | 8 ++--- .../Source/ReflectionProbe/ReflectionProbe.h | 2 +- .../ReflectionProbeFeatureProcessor.cpp | 8 ++--- .../TransformServiceFeatureProcessor.cpp | 20 ++++++++--- .../RHI/RayTracingAccelerationStructure.h | 6 ++-- .../RHI/RayTracingAccelerationStructure.cpp | 13 +++++-- .../DX12/Code/Source/RHI/RayTracingTlas.cpp | 4 ++- .../Vulkan/Code/Source/RHI/RayTracingTlas.cpp | 4 ++- .../Source/Mesh/MeshComponentController.cpp | 23 ++++++------- .../Source/Mesh/MeshComponentController.h | 1 - .../ReflectionProbeComponentController.cpp | 2 +- .../Code/Source/AtomActorInstance.cpp | 5 ++- .../Editor/EditorBlastMeshDataComponent.cpp | 4 +-- .../Code/Source/Family/ActorRenderManager.cpp | 5 +-- .../Code/Tests/ActorRenderManagerTest.cpp | 2 +- .../Rendering/Atom/WhiteBoxAtomRenderMesh.cpp | 2 +- 29 files changed, 141 insertions(+), 82 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.h b/Code/Framework/AzCore/AzCore/Math/Aabb.h index 474ac2e2ee..2d2616f5de 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.h +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.h @@ -131,6 +131,8 @@ namespace AZ void ApplyMatrix3x4(const Matrix3x4& matrix3x4); + void MultiplyByScale(const Vector3& scale); + //! Transforms an Aabb and returns the resulting Obb. Obb GetTransformedObb(const Transform& transform) const; diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.inl b/Code/Framework/AzCore/AzCore/Math/Aabb.inl index 94ad3e3e7d..25a03d20b9 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.inl +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.inl @@ -292,6 +292,13 @@ namespace AZ } + AZ_MATH_INLINE void Aabb::MultiplyByScale(const Vector3& scale) + { + m_min *= scale; + m_max *= scale; + } + + AZ_MATH_INLINE Aabb Aabb::GetTransformedAabb(const Transform& transform) const { Aabb aabb = Aabb::CreateFromMinMax(m_min, m_max); diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h index bd0ede749d..eb49859141 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessor.h @@ -145,8 +145,10 @@ namespace AZ const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const override; void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) override; - void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) override; - Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) override; + void SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform, + const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) override; + Transform GetTransform(const MeshHandle& meshHandle) override; + Vector3 GetNonUniformScale(const MeshHandle& meshHandle) override; void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) override; RHI::DrawItemSortKey GetSortKey(const MeshHandle& meshHandle) override; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index ef8084d534..05f2a408b8 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -61,10 +61,13 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialAssignmentMap(const MeshHandle& meshHandle) const = 0; //! Connects a handler to any changes to an RPI::Model. Changes include loading and reloading. virtual void ConnectModelChangeEventHandler(const MeshHandle& meshHandle, ModelChangedEvent::Handler& handler) = 0; - //! Sets the Matrix3x4 for a given mesh handle. - virtual void SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) = 0; - //! Gets the Matrix3x4 for a given mesh handle. - virtual Matrix3x4 GetMatrix3x4(const MeshHandle& meshHandle) = 0; + //! Sets the transform for a given mesh handle. + virtual void SetTransform(const MeshHandle& meshHandle, const Transform& transform, + const Vector3& nonUniformScale = Vector3::CreateOne()) = 0; + //! Gets the transform for a given mesh handle. + virtual Transform GetTransform(const MeshHandle& meshHandle) = 0; + //! Gets the non-uniform scale for a given mesh handle. + virtual Vector3 GetNonUniformScale(const MeshHandle& meshHandle) = 0; //! Sets the sort key for a given mesh handle. virtual void SetSortKey(const MeshHandle& meshHandle, RHI::DrawItemSortKey sortKey) = 0; //! Gets the sort key for a given mesh handle. diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h index 610bb40369..a89875aaa6 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -37,7 +37,7 @@ namespace AZ void SetProbeOuterExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& outerExtents) override; void SetProbeInnerExtents(const ReflectionProbeHandle& probe, const AZ::Vector3& innerExtents) override; void SetProbeCubeMap(const ReflectionProbeHandle& probe, Data::Instance<RPI::Image>& cubeMapImage) override; - void SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) override; + void SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) override; void BakeProbe(const ReflectionProbeHandle& probe, BuildCubeMapCallback callback) override; void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) override; bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const override { return (probe.get() != nullptr); } diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h index 3053d9d44f..8b277e97c8 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h @@ -48,7 +48,7 @@ namespace AZ virtual void SetProbeOuterExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& outerExtents) = 0; virtual void SetProbeInnerExtents(const ReflectionProbeHandle& handle, const AZ::Vector3& innerExtents) = 0; virtual void SetProbeCubeMap(const ReflectionProbeHandle& handle, Data::Instance<RPI::Image>& cubeMapImage) = 0; - virtual void SetProbeMatrix3x4(const ReflectionProbeHandle& handle, const AZ::Matrix3x4& matrix3x4) = 0; + virtual void SetProbeTransform(const ReflectionProbeHandle& handle, const AZ::Transform& transform) = 0; virtual void BakeProbe(const ReflectionProbeHandle& handle, BuildCubeMapCallback callback) = 0; virtual void NotifyCubeMapAssetReady(const AZStd::string relativePath, NotifyCubeMapAssetReadyCallback callback) = 0; virtual bool IsValidProbeHandle(const ReflectionProbeHandle& probe) const = 0; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h index d6338d6b0c..ddec9a6a1d 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessor.h @@ -50,8 +50,10 @@ namespace AZ // TransformServiceFeatureProcessorInterface overrides ... ObjectId ReserveObjectId() override; void ReleaseObjectId(ObjectId& id) override; - void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) override; - AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId id) const override; + void SetTransformForId(ObjectId id, const AZ::Transform& transform, + const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) override; + AZ::Transform GetTransformForId(ObjectId id) const override; + AZ::Vector3 GetNonUniformScaleForId(ObjectId id) const override; private: diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h index b75257c485..bb3606b12b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/TransformService/TransformServiceFeatureProcessorInterface.h @@ -13,6 +13,7 @@ #pragma once #include <AzCore/Math/Transform.h> +#include <AzCore/Math/Vector3.h> #include <Atom/RPI.Public/FeatureProcessor.h> namespace AZ @@ -34,11 +35,13 @@ namespace AZ //! Releases an object ID to be used by others. The passed in handle is invalidated. virtual void ReleaseObjectId(ObjectId& id) = 0; - //! Sets the Matrix3x4 for a given id. Id must be one reserved earlier. - virtual void SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& transform) = 0; - //! Gets the Matrix3x4 for a given id. Id must be one reserved earlier. - virtual AZ::Matrix3x4 GetMatrix3x4ForId(ObjectId) const = 0; - + //! Sets the transform (and optionally non-uniform scale) for a given id. Id must be one reserved earlier. + virtual void SetTransformForId(ObjectId id, const AZ::Transform& transform, + const AZ::Vector3& nonUniformScale = AZ::Vector3::CreateOne()) = 0; + //! Gets the transform for a given id. Id must be one reserved earlier. + virtual AZ::Transform GetTransformForId(ObjectId) const = 0; + //! Gets the non-uniform scale for a given id. Id must be one reserved earlier. + virtual AZ::Vector3 GetNonUniformScaleForId(ObjectId id) const = 0; }; } } diff --git a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h index b6428754b5..a1a7e94cb0 100644 --- a/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Mocks/MockMeshFeatureProcessor.h @@ -31,11 +31,12 @@ namespace UnitTest MOCK_CONST_METHOD1(GetModel, AZStd::intrusive_ptr<AZ::RPI::Model>(const MeshHandle&)); MOCK_CONST_METHOD1(GetMaterialAssignmentMap, const AZ::Render::MaterialAssignmentMap&(const MeshHandle&)); MOCK_METHOD2(ConnectModelChangeEventHandler, void(const MeshHandle&, ModelChangedEvent::Handler&)); - MOCK_METHOD2(SetMatrix3x4, void(const MeshHandle&, const AZ::Matrix3x4&)); + MOCK_METHOD3(SetTransform, void(const MeshHandle&, const AZ::Transform&, const AZ::Vector3&)); MOCK_METHOD2(SetExcludeFromReflectionCubeMaps, void(const MeshHandle&, bool)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Data::Instance<AZ::RPI::Material>&)); MOCK_METHOD2(SetMaterialAssignmentMap, void(const MeshHandle&, const AZ::Render::MaterialAssignmentMap&)); - MOCK_METHOD1(GetMatrix3x4, AZ::Matrix3x4 (const MeshHandle&)); + MOCK_METHOD1(GetTransform, AZ::Transform(const MeshHandle&)); + MOCK_METHOD1(GetNonUniformScale, AZ::Vector3(const MeshHandle&)); MOCK_METHOD2(SetSortKey, void (const MeshHandle&, AZ::RHI::DrawItemSortKey)); MOCK_METHOD1(GetSortKey, AZ::RHI::DrawItemSortKey(const MeshHandle&)); MOCK_METHOD2(SetLodOverride, void(const MeshHandle&, AZ::RPI::Cullable::LodOverride)); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 409ff6ceaf..37f9360f5d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -256,7 +256,7 @@ namespace AZ } } - void MeshFeatureProcessor::SetMatrix3x4(const MeshHandle& meshHandle, const AZ::Matrix3x4& matrix3x4) + void MeshFeatureProcessor::SetTransform(const MeshHandle& meshHandle, const AZ::Transform& transform, const AZ::Vector3& nonUniformScale) { if (meshHandle.IsValid()) { @@ -264,26 +264,39 @@ namespace AZ meshData.m_cullBoundsNeedsUpdate = true; meshData.m_objectSrgNeedsUpdate = true; - m_transformService->SetMatrix3x4ForId(meshHandle->m_objectId, matrix3x4); + m_transformService->SetTransformForId(meshHandle->m_objectId, transform, nonUniformScale); // ray tracing data needs to be updated with the new transform if (m_rayTracingFeatureProcessor) { - m_rayTracingFeatureProcessor->SetMeshMatrix3x4(meshHandle->m_objectId, matrix3x4); + m_rayTracingFeatureProcessor->SetMeshTransform(meshHandle->m_objectId, transform, nonUniformScale); } } } - Matrix3x4 MeshFeatureProcessor::GetMatrix3x4(const MeshHandle& meshHandle) + Transform MeshFeatureProcessor::GetTransform(const MeshHandle& meshHandle) { if (meshHandle.IsValid()) { - return m_transformService->GetMatrix3x4ForId(meshHandle->m_objectId); + return m_transformService->GetTransformForId(meshHandle->m_objectId); } else { AZ_Assert(false, "Invalid mesh handle"); - return Matrix3x4::CreateIdentity(); + return Transform::CreateIdentity(); + } + } + + Vector3 MeshFeatureProcessor::GetNonUniformScale(const MeshHandle& meshHandle) + { + if (meshHandle.IsValid()) + { + return m_transformService->GetNonUniformScaleForId(meshHandle->m_objectId); + } + else + { + AZ_Assert(false, "Invalid mesh handle"); + return Vector3::CreateOne(); } } @@ -844,11 +857,14 @@ namespace AZ AZ_Assert(m_cullBoundsNeedsUpdate, "This function only needs to be called if the culling bounds need to be rebuilt"); AZ_Assert(m_model, "The model has not finished loading yet"); - Matrix3x4 localToWorld = transformService->GetMatrix3x4ForId(m_objectId); + Transform localToWorld = transformService->GetTransformForId(m_objectId); + Vector3 nonUniformScale = transformService->GetNonUniformScaleForId(m_objectId); Vector3 center; float radius; Aabb localAabb = m_model->GetAabb(); + localAabb.MultiplyByScale(nonUniformScale); + localAabb.GetTransformedAabb(localToWorld).GetAsSphere(center, radius); m_cullable.m_cullData.m_boundingSphere = Sphere(center, radius); @@ -922,11 +938,11 @@ namespace AZ // retrieve the list of probes that contain the centerpoint of the mesh TransformServiceFeatureProcessor* transformServiceFeatureProcessor = m_scene->GetFeatureProcessor<TransformServiceFeatureProcessor>(); - Matrix3x4 matrix3x4 = transformServiceFeatureProcessor->GetMatrix3x4ForId(m_objectId); + Transform transform = transformServiceFeatureProcessor->GetTransformForId(m_objectId); ReflectionProbeFeatureProcessor* reflectionProbeFeatureProcessor = m_scene->GetFeatureProcessor<ReflectionProbeFeatureProcessor>(); ReflectionProbeFeatureProcessor::ReflectionProbeVector reflectionProbes; - reflectionProbeFeatureProcessor->FindReflectionProbes(matrix3x4.GetTranslation(), reflectionProbes); + reflectionProbeFeatureProcessor->FindReflectionProbes(transform.GetTranslation(), reflectionProbes); if (!reflectionProbes.empty() && reflectionProbes[0]) { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp index 662886aaa2..2bb2fa2ac2 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingAccelerationStructurePass.cpp @@ -80,7 +80,8 @@ namespace AZ ->InstanceID(blasIndex) ->HitGroupIndex(blasIndex) ->Blas(rayTracingSubMesh.m_blas) - ->Matrix3x4(rayTracingMesh.second.m_matrix3x4) + ->Transform(rayTracingMesh.second.m_transform) + ->NonUniformScale(rayTracingMesh.second.m_nonUniformScale) ; } diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 63c51fa042..7ac502ca4a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -115,7 +115,7 @@ namespace AZ } // set initial transform - mesh.m_matrix3x4 = m_transformServiceFeatureProcessor->GetMatrix3x4ForId(objectId); + mesh.m_transform = m_transformServiceFeatureProcessor->GetTransformForId(objectId); m_revision++; m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size()); @@ -141,7 +141,7 @@ namespace AZ m_meshInfoBufferNeedsUpdate = true; } - void RayTracingFeatureProcessor::SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4) + void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, const AZ::Vector3 nonUniformScale) { if (!m_rayTracingEnabled) { @@ -151,7 +151,8 @@ namespace AZ MeshMap::iterator itMesh = m_meshes.find(objectId.GetIndex()); if (itMesh != m_meshes.end()) { - itMesh->second.m_matrix3x4 = matrix3x4; + itMesh->second.m_transform = transform; + itMesh->second.m_nonUniformScale = nonUniformScale; m_revision++; } @@ -296,10 +297,10 @@ namespace AZ for (const auto& mesh : m_meshes) { - AZ::Matrix3x4 meshMatrix3x4 = transformFeatureProcessor->GetMatrix3x4ForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); - AZ::Matrix3x4 noScaleMatrix3x4 = meshMatrix3x4; - noScaleMatrix3x4.ExtractScale(); - AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromMatrix3x4(noScaleMatrix3x4); + AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first)); + AZ::Transform noScaleTransform = meshTransform; + noScaleTransform.ExtractScale(); + AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform); rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose(); const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes; diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 05fd324178..f317f1c096 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -66,7 +66,10 @@ namespace AZ SubMeshVector m_subMeshes; // mesh transform - AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); + AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + + // mesh non-uniform scale + AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); // flag indicating if the Blas objects in the sub-meshes are built bool m_blasBuilt = false; @@ -85,7 +88,8 @@ namespace AZ //! Sets the ray tracing mesh transform //! This will cause an update to the RayTracing acceleration structure on the next frame - void SetMeshMatrix3x4(const ObjectId objectId, const AZ::Matrix3x4 matrix3x4); + void SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, + const AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne()); //! Retrieves ray tracing data for all meshes in the scene const MeshMap& GetMeshes() const { return m_meshes; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 7fe51d6c37..0826739119 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -70,7 +70,7 @@ namespace AZ m_visualizationMeshHandle = m_meshFeatureProcessor->AcquireMesh(m_visualizationModelAsset); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_visualizationMeshHandle, true); m_meshFeatureProcessor->SetRayTracingEnabled(m_visualizationMeshHandle, false); - m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, AZ::Matrix3x4::CreateIdentity()); + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, AZ::Transform::CreateIdentity()); // We have to pre-load this asset before creating a Material instance because the InstanceDatabase will attempt a blocking load which could deadlock, // particularly when slices are involved. @@ -206,10 +206,10 @@ namespace AZ } - void ReflectionProbe::SetMatrix3x4(const AZ::Matrix3x4& matrix3x4) + void ReflectionProbe::SetTransform(const AZ::Transform& transform) { - m_position = matrix3x4.GetTranslation(); - m_meshFeatureProcessor->SetMatrix3x4(m_visualizationMeshHandle, matrix3x4); + m_position = transform.GetTranslation(); + m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, transform); m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_outerExtents / 2.0f); m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_position, m_innerExtents / 2.0f); m_updateSrg = true; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 6b23afb1fc..22645a4ed3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -76,7 +76,7 @@ namespace AZ void Simulate(uint32_t probeIndex); const Vector3& GetPosition() const { return m_position; } - void SetMatrix3x4(const AZ::Matrix3x4& matrix3x4); + void SetTransform(const AZ::Transform& transform); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } void SetOuterExtents(const AZ::Vector3& outerExtents); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index e4c1c04f99..a0d3e6ac51 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -222,7 +222,7 @@ namespace AZ { AZStd::shared_ptr<ReflectionProbe> reflectionProbe = AZStd::make_shared<ReflectionProbe>(); reflectionProbe->Init(GetParentScene(), &m_reflectionRenderData); - reflectionProbe->SetMatrix3x4(AZ::Matrix3x4::CreateFromTransform(transform)); + reflectionProbe->SetTransform(transform); reflectionProbe->SetUseParallaxCorrection(useParallaxCorrection); m_reflectionProbes.push_back(reflectionProbe); m_probeSortRequired = true; @@ -263,10 +263,10 @@ namespace AZ probe->SetCubeMapImage(cubeMapImage); } - void ReflectionProbeFeatureProcessor::SetProbeMatrix3x4(const ReflectionProbeHandle& probe, const AZ::Matrix3x4& matrix3x4) + void ReflectionProbeFeatureProcessor::SetProbeTransform(const ReflectionProbeHandle& probe, const AZ::Transform& transform) { - AZ_Assert(probe.get(), "SetProbeMatrix3x4 called with an invalid handle"); - probe->SetMatrix3x4(matrix3x4); + AZ_Assert(probe.get(), "SetProbeTransform called with an invalid handle"); + probe->SetTransform(transform); m_probeSortRequired = true; } diff --git a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp index a3a91ca620..acb6e4a287 100644 --- a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp @@ -210,12 +210,14 @@ namespace AZ } } - void TransformServiceFeatureProcessor::SetMatrix3x4ForId(ObjectId id, const AZ::Matrix3x4& matrix3x4) + void TransformServiceFeatureProcessor::SetTransformForId(ObjectId id, const AZ::Transform& transform, const AZ::Vector3& nonUniformScale) { AZ_Error("TransformServiceFeatureProcessor", m_isWriteable, "Transform data cannot be written to during this phase"); AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); if (id.IsValid()) { + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform); + matrix3x4.MultiplyByScale(nonUniformScale); matrix3x4.StoreToRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); // Inverse transpose to take the non-uniform scale out of the transform for usage with normals. @@ -224,10 +226,20 @@ namespace AZ } } - AZ::Matrix3x4 TransformServiceFeatureProcessor::GetMatrix3x4ForId(ObjectId id) const + AZ::Transform TransformServiceFeatureProcessor::GetTransformForId(ObjectId id) const { - AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to set the transform for an invalid handle."); - return AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); + AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to get the transform for an invalid handle."); + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); + AZ::Transform transform = AZ::Transform::CreateFromMatrix3x4(matrix3x4); + transform.ExtractScale(); + return transform; + } + + AZ::Vector3 TransformServiceFeatureProcessor::GetNonUniformScaleForId(ObjectId id) const + { + AZ_Error("TransformServiceFeatureProcessor", id.IsValid(), "Attempting to get the non-uniform scale for an invalid handle."); + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromRowMajorFloat12(m_objectToWorldTransforms.at(id.GetIndex()).m_transform); + return matrix3x4.RetrieveScale(); } } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index 0225673efd..317094e24c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -110,7 +110,8 @@ namespace AZ { uint32_t m_instanceID = 0; uint32_t m_hitGroupIndex = 0; - AZ::Matrix3x4 m_matrix3x4 = AZ::Matrix3x4::CreateIdentity(); + AZ::Transform m_transform = AZ::Transform::CreateIdentity(); + AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); RHI::Ptr<RHI::RayTracingBlas> m_blas; }; using RayTracingTlasInstanceVector = AZStd::vector<RayTracingTlasInstance>; @@ -153,7 +154,8 @@ namespace AZ RayTracingTlasDescriptor* Instance(); RayTracingTlasDescriptor* InstanceID(uint32_t instanceID); RayTracingTlasDescriptor* HitGroupIndex(uint32_t hitGroupIndex); - RayTracingTlasDescriptor* Matrix3x4(const AZ::Matrix3x4& matrix3x4); + RayTracingTlasDescriptor* Transform(const AZ::Transform& transform); + RayTracingTlasDescriptor* NonUniformScale(const AZ::Vector3& nonUniformScale); RayTracingTlasDescriptor* Blas(RHI::Ptr<RHI::RayTracingBlas>& blas); RayTracingTlasDescriptor* InstancesBuffer(RHI::Ptr<RHI::Buffer>& tlasInstances); RayTracingTlasDescriptor* NumInstances(uint32_t numInstancesInBuffer); diff --git a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp index dadaeee5d4..4349761eb5 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RayTracingAccelerationStructure.cpp @@ -78,13 +78,20 @@ namespace AZ return this; } - RayTracingTlasDescriptor* RayTracingTlasDescriptor::Matrix3x4(const AZ::Matrix3x4& matrix3x4) + RayTracingTlasDescriptor* RayTracingTlasDescriptor::Transform(const AZ::Transform& transform) { - AZ_Assert(m_buildContext, "Matrix3x4 property can only be added to an Instance entry"); - m_buildContext->m_matrix3x4 = matrix3x4; + AZ_Assert(m_buildContext, "Transform property can only be added to an Instance entry"); + m_buildContext->m_transform = transform; return this; } + RayTracingTlasDescriptor* RayTracingTlasDescriptor::NonUniformScale(const AZ::Vector3& nonUniformScale) + { + AZ_Assert(m_buildContext, "NonUniformSCale property can only be added to an Instance entry"); + m_buildContext->m_nonUniformScale = nonUniformScale; + return this; + } + RayTracingTlasDescriptor* RayTracingTlasDescriptor::Blas(RHI::Ptr<RHI::RayTracingBlas>& blas) { AZ_Assert(m_buildContext, "Blas property can only be added to an Instance entry"); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index 8c01b798a6..1342db5690 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -89,7 +89,9 @@ namespace AZ mappedData[i].InstanceID = instance.m_instanceID; mappedData[i].InstanceContributionToHitGroupIndex = instance.m_hitGroupIndex; // convert transform to row-major 3x4 - instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); + matrix3x4.MultiplyByScale(instance.m_nonUniformScale); + matrix3x4.StoreToRowMajorFloat12(&mappedData[i].Transform[0][0]); mappedData[i].AccelerationStructure = static_cast<DX12::Buffer*>(blas->GetBuffers().m_blasBuffer.get())->GetMemoryView().GetGpuAddress(); // [GFX TODO][ATOM-5270] Add ray tracing TLAS instance mask support mappedData[i].InstanceMask = 0x1; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp index 161104060e..a1346612c9 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp @@ -92,7 +92,9 @@ namespace AZ mappedData[i].instanceCustomIndex = instance.m_instanceID; mappedData[i].instanceShaderBindingTableRecordOffset = instance.m_hitGroupIndex; - instance.m_matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); + AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(instance.m_transform); + matrix3x4.MultiplyByScale(instance.m_nonUniformScale); + matrix3x4.StoreToRowMajorFloat12(&mappedData[i].transform.matrix[0][0]); RayTracingBlas* blas = static_cast<RayTracingBlas*>(instance.m_blas.get()); VkAccelerationStructureDeviceAddressInfoKHR addressInfo = {}; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index 59f4a8a92a..e4e9080cd1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -214,6 +214,8 @@ namespace AZ MaterialReceiverRequestBus::Handler::BusDisconnect(); MaterialComponentNotificationBus::Handler::BusDisconnect(); + m_nonUniformScaleChangedHandler.Disconnect(); + m_meshFeatureProcessor = nullptr; m_transformInterface = nullptr; m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId); @@ -232,22 +234,18 @@ namespace AZ void MeshComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world) { - UpdateOverallMatrix(); + if (m_meshFeatureProcessor) + { + m_meshFeatureProcessor->SetTransform(m_meshHandle, world, m_cachedNonUniformScale); + } } void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3 & nonUniformScale) { m_cachedNonUniformScale = nonUniformScale; - UpdateOverallMatrix(); - } - - void MeshComponentController::UpdateOverallMatrix() - { if (m_meshFeatureProcessor) { - Matrix3x4 world = Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()); - world.MultiplyByScale(m_cachedNonUniformScale); - m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, world); + m_meshFeatureProcessor->SetTransform(m_meshHandle, m_transformInterface->GetWorldTM(), m_cachedNonUniformScale); } } @@ -293,10 +291,9 @@ namespace AZ m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials); m_meshFeatureProcessor->ConnectModelChangeEventHandler(m_meshHandle, m_changeEventHandler); - const AZ::Matrix3x4& matrix3x4 = m_transformInterface - ? Matrix3x4::CreateFromTransform(m_transformInterface->GetWorldTM()) * Matrix3x4::CreateScale(m_cachedNonUniformScale) - : Matrix3x4::Identity(); - m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, matrix3x4); + const AZ::Transform& transform = m_transformInterface ? m_transformInterface->GetWorldTM() : AZ::Transform::CreateIdentity(); + + m_meshFeatureProcessor->SetTransform(m_meshHandle, transform, m_cachedNonUniformScale); m_meshFeatureProcessor->SetSortKey(m_meshHandle, m_configuration.m_sortKey); m_meshFeatureProcessor->SetLodOverride(m_meshHandle, m_configuration.m_lodOverride); m_meshFeatureProcessor->SetExcludeFromReflectionCubeMaps(m_meshHandle, m_configuration.m_excludeFromReflectionCubeMaps); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 6c48a863ff..afdcfa25c7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -124,7 +124,6 @@ namespace AZ void RefreshModelRegistration(); void HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale); - void UpdateOverallMatrix(); Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp index 57aaa6a83f..005e9a6ff5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/ReflectionProbeComponentController.cpp @@ -199,7 +199,7 @@ namespace AZ return; } - m_featureProcessor->SetProbeMatrix3x4(m_handle, Matrix3x4::CreateFromTransform(world)); + m_featureProcessor->SetProbeTransform(m_handle, world); } void ReflectionProbeComponentController::OnShapeChanged(ShapeChangeReasons changeReason) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp index 8f60d3fedd..0a17a6444d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/AtomActorInstance.cpp @@ -192,9 +192,8 @@ namespace AZ void AtomActorInstance::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) { - // The mesh Matrix3x4 is used to determine where the actor instance is actually rendered - AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(world); - m_meshFeatureProcessor->SetMatrix3x4(*m_meshHandle, matrix3x4); // handle validity is checked internally. + // The mesh transform is used to determine where the actor instance is actually rendered + m_meshFeatureProcessor->SetTransform(*m_meshHandle, world); // handle validity is checked internally. if (m_skinnedMeshRenderProxy.IsValid()) { diff --git a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp index 6227fc4d45..51789f68da 100644 --- a/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp +++ b/Gems/Blast/Code/Source/Editor/EditorBlastMeshDataComponent.cpp @@ -193,7 +193,7 @@ namespace Blast AZ::Transform transform = AZ::Transform::Identity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformInterface::GetWorldTM); - m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(transform)); + m_meshFeatureProcessor->SetTransform(m_meshHandle, transform); } } @@ -232,7 +232,7 @@ namespace Blast { if (m_meshFeatureProcessor) { - m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(world)); + m_meshFeatureProcessor->SetTransform(m_meshHandle, world); } } } // namespace Blast diff --git a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp index d057e5a619..74bba48d3c 100644 --- a/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp +++ b/Gems/Blast/Code/Source/Family/ActorRenderManager.cpp @@ -74,10 +74,7 @@ namespace Blast { if (m_chunkActors[chunkId]) { - auto matrix3x4 = AZ::Matrix3x4::CreateFromTransform(m_chunkActors[chunkId]->GetWorldBody()->GetTransform()); - // Multiply by scale because the transform on the world body does not store scale - matrix3x4.MultiplyByScale(m_scale); - m_meshFeatureProcessor->SetMatrix3x4(m_chunkMeshHandles[chunkId], matrix3x4); + m_meshFeatureProcessor->SetTransform(m_chunkMeshHandles[chunkId], m_chunkActors[chunkId]->GetWorldBody()->GetTransform(), m_scale); } } } diff --git a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp index 0a7cd229a3..114721a095 100644 --- a/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp +++ b/Gems/Blast/Code/Tests/ActorRenderManagerTest.cpp @@ -114,7 +114,7 @@ namespace Blast // ActorRenderManager::SyncMeshes { - EXPECT_CALL(*m_mockMeshFeatureProcessor, SetMatrix3x4(_, _)) + EXPECT_CALL(*m_mockMeshFeatureProcessor, SetTransform(_, _, _)) .Times(aznumeric_cast<int>(m_actorFactory->m_mockActors[0]->GetChunkIndices().size())); actorRenderManager->SyncMeshes(); } diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp index 9c3428ad63..9aa29cb288 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxAtomRenderMesh.cpp @@ -248,7 +248,7 @@ namespace WhiteBox void AtomRenderMesh::UpdateTransform(const AZ::Transform& worldFromLocal) { - m_meshFeatureProcessor->SetMatrix3x4(m_meshHandle, AZ::Matrix3x4::CreateFromTransform(worldFromLocal)); + m_meshFeatureProcessor->SetTransform(m_meshHandle, worldFromLocal); } void AtomRenderMesh::UpdateMaterial([[maybe_unused]] const WhiteBoxMaterial& material) From 03350134c59fd61fc938bec1a37b830d09964013 Mon Sep 17 00:00:00 2001 From: greerdv <greerdv@amazon.com> Date: Tue, 20 Apr 2021 13:41:18 +0100 Subject: [PATCH 15/96] more feedback from PR --- .../CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index e4e9080cd1..f17972ab6a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -240,7 +240,7 @@ namespace AZ } } - void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3 & nonUniformScale) + void MeshComponentController::HandleNonUniformScaleChange(const AZ::Vector3& nonUniformScale) { m_cachedNonUniformScale = nonUniformScale; if (m_meshFeatureProcessor) From cc937e08097a0692e4c1c3cbb3c19db0bf1a0033 Mon Sep 17 00:00:00 2001 From: greerdv <greerdv@amazon.com> Date: Tue, 20 Apr 2021 14:44:31 +0100 Subject: [PATCH 16/96] feedback from PR --- Code/Framework/AzCore/AzCore/Math/Aabb.h | 8 ++++---- .../Code/Source/Mesh/MeshComponentController.cpp | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.h b/Code/Framework/AzCore/AzCore/Math/Aabb.h index 2d2616f5de..ef7704533e 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.h +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.h @@ -134,16 +134,16 @@ namespace AZ void MultiplyByScale(const Vector3& scale); //! Transforms an Aabb and returns the resulting Obb. - Obb GetTransformedObb(const Transform& transform) const; + [[nodiscard]] Obb GetTransformedObb(const Transform& transform) const; //! Transforms an Aabb and returns the resulting Obb. - Obb GetTransformedObb(const Matrix3x4& matrix3x4) const; + [[nodiscard]] Obb GetTransformedObb(const Matrix3x4& matrix3x4) const; //! Returns a new AABB containing the transformed AABB. - Aabb GetTransformedAabb(const Transform& transform) const; + [[nodiscard]] Aabb GetTransformedAabb(const Transform& transform) const; //! Returns a new AABB containing the transformed AABB. - Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const; + [[nodiscard]] Aabb GetTransformedAabb(const Matrix3x4& matrix3x4) const; //! Checks if this aabb is equal to another within a floating point tolerance. bool IsClose(const Aabb& rhs, float tolerance = Constants::Tolerance) const; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index f17972ab6a..c99ca7b848 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -433,8 +433,7 @@ namespace AZ if (model) { Aabb aabb = model->GetAabb(); - aabb.SetMin(aabb.GetMin() * m_cachedNonUniformScale); - aabb.SetMax(aabb.GetMax() * m_cachedNonUniformScale); + aabb.MultiplyByScale(m_cachedNonUniformScale); return aabb; } else From f8a72e5a040c62a5c489a87c8ad39f2256b9153a Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 11:05:01 -0500 Subject: [PATCH 17/96] Removed HLSL cry compilers and tools --- Code/Tools/CMakeLists.txt | 2 - Code/Tools/CryFXC/cryfxc.sln | 26 - Code/Tools/CryFXC/cryfxc/cryfxc.cpp | 494 -- Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj | 153 - Code/Tools/CryFXC/cryfxc/stdafx.cpp | 14 - Code/Tools/CryFXC/cryfxc/stdafx.h | 29 - Code/Tools/CryFXC/cryfxc/targetver.h | 16 - Code/Tools/HLSLCrossCompiler/CMakeLists.txt | 57 - .../Platform/Linux/platform_linux.cmake | 10 - .../Platform/Mac/platform_mac.cmake | 11 - .../Platform/Windows/platform_windows.cmake | 18 - Code/Tools/HLSLCrossCompiler/README | 71 - .../HLSLCrossCompiler/hlslcc_files.cmake | 60 - .../hlslcc_header_files.cmake | 18 - .../include/amazon_changes.h | 13 - Code/Tools/HLSLCrossCompiler/include/hlslcc.h | 580 -- .../HLSLCrossCompiler/include/hlslcc.hpp | 7 - .../HLSLCrossCompiler/include/hlslcc_bin.hpp | 419 -- .../Tools/HLSLCrossCompiler/include/pstdint.h | 801 --- Code/Tools/HLSLCrossCompiler/jni/Android.mk | 32 - .../HLSLCrossCompiler/jni/Application.mk | 3 - .../lib/android-armeabi-v7a/libHLSLcc.a | 3 - .../lib/ios-arm64/libHLSLcc.a | 3 - .../lib/ios-simx86_64/libHLSLcc.a | 3 - .../HLSLCrossCompiler/lib/ios/libHLSLcc.a | 3 - .../HLSLCrossCompiler/lib/linux/libHLSLcc.a | 3 - .../HLSLCrossCompiler/lib/linux/libHLSLcc_d.a | 3 - .../HLSLCrossCompiler/lib/mac/libHLSLcc.a | 3 - .../HLSLCrossCompiler/lib/mac/libHLSLcc_d.a | 3 - .../HLSLCrossCompiler/lib/steamos/libHLSLcc.a | 3 - .../lib/steamos/libHLSLcc_d.a | 3 - .../HLSLCrossCompiler/lib/win32/libHLSLcc.lib | 3 - .../HLSLCrossCompiler/lib/win64/libHLSLcc.lib | 3 - Code/Tools/HLSLCrossCompiler/license.txt | 53 - .../HLSLCrossCompiler/offline/cjson/README | 247 - .../HLSLCrossCompiler/offline/cjson/cJSON.c | 578 -- .../HLSLCrossCompiler/offline/cjson/cJSON.h | 142 - .../offline/compilerStandalone.cpp | 803 --- Code/Tools/HLSLCrossCompiler/offline/hash.h | 152 - .../offline/serializeReflection.cpp | 207 - .../offline/serializeReflection.h | 11 - .../Tools/HLSLCrossCompiler/offline/timer.cpp | 40 - Code/Tools/HLSLCrossCompiler/offline/timer.h | 29 - .../HLSLCrossCompiler/src/amazon_changes.c | 219 - .../HLSLCrossCompiler/src/cbstring/bsafe.c | 20 - .../HLSLCrossCompiler/src/cbstring/bsafe.h | 45 - .../HLSLCrossCompiler/src/cbstring/bstraux.c | 1134 ---- .../HLSLCrossCompiler/src/cbstring/bstraux.h | 113 - .../HLSLCrossCompiler/src/cbstring/bstrlib.c | 2976 --------- .../HLSLCrossCompiler/src/cbstring/bstrlib.h | 305 - .../src/cbstring/bstrlib.txt | 3201 ---------- .../src/cbstring/license.txt | 29 - .../src/cbstring/porting.txt | 172 - .../src/cbstring/security.txt | 221 - Code/Tools/HLSLCrossCompiler/src/decode.c | 1845 ------ Code/Tools/HLSLCrossCompiler/src/decodeDX9.c | 1113 ---- .../HLSLCrossCompiler/src/hlslccToolkit.c | 167 - .../src/internal_includes/debug.h | 21 - .../src/internal_includes/decode.h | 21 - .../src/internal_includes/hlslccToolkit.h | 35 - .../src/internal_includes/hlslcc_malloc.c | 16 - .../src/internal_includes/hlslcc_malloc.h | 15 - .../src/internal_includes/languages.h | 242 - .../src/internal_includes/reflect.h | 42 - .../src/internal_includes/shaderLimits.h | 36 - .../src/internal_includes/structs.h | 374 -- .../src/internal_includes/toGLSLDeclaration.h | 19 - .../src/internal_includes/toGLSLInstruction.h | 18 - .../src/internal_includes/toGLSLOperand.h | 46 - .../internal_includes/toMETALDeclaration.h | 16 - .../internal_includes/toMETALInstruction.h | 18 - .../src/internal_includes/toMETALOperand.h | 38 - .../src/internal_includes/tokens.h | 812 --- .../src/internal_includes/tokensDX9.h | 304 - Code/Tools/HLSLCrossCompiler/src/reflect.c | 1075 ---- Code/Tools/HLSLCrossCompiler/src/toGLSL.c | 1921 ------ .../HLSLCrossCompiler/src/toGLSLDeclaration.c | 2908 --------- .../HLSLCrossCompiler/src/toGLSLInstruction.c | 5598 ----------------- .../HLSLCrossCompiler/src/toGLSLOperand.c | 2121 ------- .../HLSLCrossCompilerMETAL/CMakeLists.txt | 54 - .../Platform/Linux/PAL_linux.cmake | 12 - .../Platform/Mac/PAL_mac.cmake | 12 - .../Platform/Windows/PAL_windows.cmake | 12 - Code/Tools/HLSLCrossCompilerMETAL/README | 52 - .../bin/win32/HLSLcc.exe | 3 - .../bin/win32/HLSLcc_d.exe | 3 - .../hlslcc_metal_files.cmake | 65 - .../HLSLCrossCompilerMETAL/include/hlslcc.h | 537 -- .../HLSLCrossCompilerMETAL/include/hlslcc.hpp | 7 - .../include/hlslcc_bin.hpp | 448 -- .../HLSLCrossCompilerMETAL/include/pstdint.h | 801 --- .../HLSLCrossCompilerMETAL/jni/Android.mk | 32 - .../HLSLCrossCompilerMETAL/jni/Application.mk | 3 - .../lib/android-armeabi-v7a/libHLSLcc.a | 3 - .../lib/ios/libHLSLcc.a | 3 - .../lib/linux/libHLSLcc.a | 3 - .../lib/linux/libHLSLcc_d.a | 3 - .../lib/mac/libHLSLcc.a | 3 - .../lib/mac/libHLSLcc_d.a | 3 - .../lib/steamos/libHLSLcc.a | 3 - .../lib/steamos/libHLSLcc_d.a | 3 - .../lib/win32/Debug/libHLSLcc.lib | 3 - .../lib/win32/Release/libHLSLcc.lib | 3 - .../lib/win32/libHLSLcc.lib | 3 - .../lib/win64/Release/libHLSLcc.lib | 3 - .../lib/win64/libHLSLcc.lib | 3 - Code/Tools/HLSLCrossCompilerMETAL/license.txt | 52 - .../offline/cjson/README | 247 - .../offline/cjson/cJSON.c | 578 -- .../offline/cjson/cJSON.h | 142 - .../offline/compilerStandalone.cpp | 825 --- .../HLSLCrossCompilerMETAL/offline/hash.h | 128 - .../offline/serializeReflection.cpp | 207 - .../offline/serializeReflection.h | 11 - .../HLSLCrossCompilerMETAL/offline/timer.cpp | 40 - .../HLSLCrossCompilerMETAL/offline/timer.h | 29 - .../src/cbstring/bsafe.c | 20 - .../src/cbstring/bsafe.h | 39 - .../src/cbstring/bstraux.c | 1134 ---- .../src/cbstring/bstraux.h | 113 - .../src/cbstring/bstrlib.c | 2976 --------- .../src/cbstring/bstrlib.h | 305 - .../src/cbstring/bstrlib.txt | 3201 ---------- .../src/cbstring/license.txt | 29 - .../src/cbstring/porting.txt | 172 - .../src/cbstring/security.txt | 221 - .../Tools/HLSLCrossCompilerMETAL/src/decode.c | 1750 ------ .../HLSLCrossCompilerMETAL/src/decodeDX9.c | 1133 ---- .../src/internal_includes/debug.h | 21 - .../src/internal_includes/decode.h | 18 - .../src/internal_includes/hlslcc_malloc.c | 37 - .../src/internal_includes/hlslcc_malloc.h | 15 - .../src/internal_includes/languages.h | 213 - .../src/internal_includes/reflect.h | 73 - .../src/internal_includes/shaderLimits.h | 14 - .../src/internal_includes/structs.h | 338 - .../src/internal_includes/structsMETAL.c | 15 - .../src/internal_includes/structsMetal.h | 19 - .../src/internal_includes/toGLSLDeclaration.h | 19 - .../src/internal_includes/toGLSLInstruction.h | 18 - .../src/internal_includes/toGLSLOperand.h | 72 - .../internal_includes/toMETALDeclaration.h | 15 - .../internal_includes/toMETALInstruction.h | 20 - .../src/internal_includes/toMETALOperand.h | 78 - .../src/internal_includes/tokens.h | 819 --- .../src/internal_includes/tokensDX9.h | 304 - .../HLSLCrossCompilerMETAL/src/reflect.c | 1213 ---- .../Tools/HLSLCrossCompilerMETAL/src/toGLSL.c | 851 --- .../src/toGLSLDeclaration.c | 2678 -------- .../src/toGLSLInstruction.c | 4576 -------------- .../src/toGLSLOperand.c | 1869 ------ .../HLSLCrossCompilerMETAL/src/toMETAL.c | 440 -- .../src/toMETALDeclaration.c | 2281 ------- .../src/toMETALInstruction.c | 4946 --------------- .../src/toMETALOperand.c | 2377 ------- 155 files changed, 71159 deletions(-) delete mode 100644 Code/Tools/CryFXC/cryfxc.sln delete mode 100644 Code/Tools/CryFXC/cryfxc/cryfxc.cpp delete mode 100644 Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj delete mode 100644 Code/Tools/CryFXC/cryfxc/stdafx.cpp delete mode 100644 Code/Tools/CryFXC/cryfxc/stdafx.h delete mode 100644 Code/Tools/CryFXC/cryfxc/targetver.h delete mode 100644 Code/Tools/HLSLCrossCompiler/CMakeLists.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake delete mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake delete mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake delete mode 100644 Code/Tools/HLSLCrossCompiler/README delete mode 100644 Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake delete mode 100644 Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake delete mode 100644 Code/Tools/HLSLCrossCompiler/include/amazon_changes.h delete mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc.h delete mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp delete mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp delete mode 100644 Code/Tools/HLSLCrossCompiler/include/pstdint.h delete mode 100644 Code/Tools/HLSLCrossCompiler/jni/Android.mk delete mode 100644 Code/Tools/HLSLCrossCompiler/jni/Application.mk delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompiler/license.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/README delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/hash.h delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/timer.cpp delete mode 100644 Code/Tools/HLSLCrossCompiler/offline/timer.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/amazon_changes.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt delete mode 100644 Code/Tools/HLSLCrossCompiler/src/decode.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/decodeDX9.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h delete mode 100644 Code/Tools/HLSLCrossCompiler/src/reflect.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSL.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c delete mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/README delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/license.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/decode.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c delete mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index d2500dfd04..3cac4e7932 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -15,8 +15,6 @@ add_subdirectory(AWSNativeSDKInit) add_subdirectory(AzTestRunner) add_subdirectory(CryCommonTools) add_subdirectory(CryXML) -add_subdirectory(HLSLCrossCompiler) -add_subdirectory(HLSLCrossCompilerMETAL) add_subdirectory(News) add_subdirectory(PythonBindingsExample) add_subdirectory(RC) diff --git a/Code/Tools/CryFXC/cryfxc.sln b/Code/Tools/CryFXC/cryfxc.sln deleted file mode 100644 index 26c5dc4e6d..0000000000 --- a/Code/Tools/CryFXC/cryfxc.sln +++ /dev/null @@ -1,26 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryfxc", "cryfxc\cryfxc.vcxproj", "{A505D345-D712-4C80-8BDE-6FBC08A390D8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|Win32.ActiveCfg = Debug|Win32 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|Win32.Build.0 = Debug|Win32 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|x64.ActiveCfg = Debug|x64 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|x64.Build.0 = Debug|x64 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|Win32.ActiveCfg = Release|Win32 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|Win32.Build.0 = Release|Win32 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|x64.ActiveCfg = Release|x64 - {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Code/Tools/CryFXC/cryfxc/cryfxc.cpp b/Code/Tools/CryFXC/cryfxc/cryfxc.cpp deleted file mode 100644 index 0d7e3435dd..0000000000 --- a/Code/Tools/CryFXC/cryfxc/cryfxc.cpp +++ /dev/null @@ -1,494 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "stdafx.h" - -#pragma comment(lib, "D3Dcompiler.lib") - -#define CRYFXC_VER "1.01" - - -enum SwitchType -{ - FXC_E, FXC_T, FXC_Help, FXC_CmdOptFile, FXC_Cc, FXC_Compress, FXC_D, FXC_Decompress, FXC_Fc, - FXC_Fh, FXC_Fo, FXC_Fx, FXC_P, FXC_Gch, FXC_Gdp, FXC_Gec, FXC_Ges, FXC_Gfa, FXC_Gfp, FXC_Gis, - FXC_Gpp, FXC_I, FXC_LD, FXC_Ni, FXC_NoLogo, FXC_Od, FXC_Op, FXC_O0, FXC_O1, FXC_O2, FXC_O3, - FXC_Vd, FXC_Vi, FXC_Vn, FXC_Zi, FXC_Zpc, FXC_Zpr, - - FXC_NumArgs -}; - - -struct SwitchEntry -{ - SwitchType type; - const char* text; - bool hasValue; - bool supported; -}; - - -const static SwitchEntry s_switchEntries[] = -{ - {FXC_E, "/E", 1, true}, - {FXC_T, "/T", 1, true}, - {FXC_Fh, "/Fh", 1, true}, - {FXC_Fo, "/Fo", 1, true}, - - {FXC_Gec, "/Gec", 0, true}, - {FXC_Ges, "/Ges", 0, true}, - {FXC_Gfa, "/Gfa", 0, true}, - {FXC_Gfp, "/Gfp", 0, true}, - {FXC_Gis, "/Gis", 0, true}, - {FXC_Gpp, "/Gpp", 0, true}, - {FXC_Od, "/Od", 0, true}, - {FXC_O0, "/O0", 0, true}, - {FXC_O1, "/O1", 0, true}, - {FXC_O2, "/O2", 0, true}, - {FXC_O3, "/O3", 0, true}, - {FXC_Op, "/Op", 0, true}, - {FXC_Vd, "/Vd", 0, true}, - {FXC_Vn, "/Vn", 1, true}, - {FXC_Zi, "/Zi", 0, true}, - {FXC_Zpc, "/Zpc", 0, true}, - {FXC_Zpr, "/Zpr", 0, true}, - {FXC_NoLogo, "/nologo", 0, true}, - - {FXC_Help, "/?", 0, false}, - {FXC_Help, "/help", 0, false}, - {FXC_Cc, "/Cc", 0, false}, - {FXC_Compress, "/compress", 0, false}, - {FXC_D, "/D", 1, false}, - {FXC_Decompress, "/decompress", 0, false}, - {FXC_Fc, "/Fc", 1, false}, - {FXC_Fx, "/Fx", 1, false}, - {FXC_P, "/P", 1, false}, - {FXC_Gch, "/Gch", 0, false}, - {FXC_Gdp, "/Gdp", 0, false}, - {FXC_I, "/I", 1, false}, - {FXC_LD, "/LD", 0, false}, - {FXC_Ni, "/Ni", 0, false}, - {FXC_Vi, "/Vi", 0, false} -}; - - -bool IsSwitch(const char* p) -{ - assert(p); - return *p == '/' || *p == '@'; -} - - -const SwitchEntry* GetSwitch(const char* p) -{ - assert(p); - for (size_t i = 0; i < sizeof(s_switchEntries) / sizeof(s_switchEntries[0]); ++i) - { - if (_stricmp(s_switchEntries[i].text, p) == 0) - { - return &s_switchEntries[i]; - } - } - - if (*p == '@') - { - const static SwitchEntry sw = {FXC_CmdOptFile, "@", 0, false}; - return &sw; - } - - return 0; -} - - -struct ParserResults -{ - const char* pProfile; - const char* pEntry; - const char* pOutFile; - const char* pInFile; - const char* pHeaderVariableName; - unsigned int compilerFlags; - bool disassemble; - - void Init() - { - pProfile = 0; - pEntry = 0; - pOutFile = 0; - pInFile = 0; - pHeaderVariableName = 0; - compilerFlags = 0; - disassemble = false; - } -}; - - -bool ParseCommandLine(const char* const* args, size_t numargs, ParserResults& parserRes) -{ - parserRes.Init(); - - if (numargs < 4) - { - fprintf(stderr, "Failed to specify all required arguments: infile, outfile, profile and entry point\n"); - return false; - } - - for (size_t i = 1; i < numargs; ++i) - { - if (IsSwitch(args[i])) - { - const SwitchEntry* sw = GetSwitch(args[i]); - if (!sw) - { - fprintf(stderr, "Unknown switch: %s\n", args[i]); - return false; - } - - if (!sw->supported) - { - fprintf(stderr, "Unsupported switch: %s\n", sw->text); - return false; - } - - if (sw->hasValue) - { - if (i + 1 == numargs || IsSwitch(args[i + 1])) - { - fprintf(stderr, "Missing value for switch: %s\n", sw->text); - return false; - } - - const char* pValue = args[i + 1]; - switch (sw->type) - { - case FXC_E: - parserRes.pEntry = pValue; - break; - case FXC_T: - parserRes.pProfile = pValue; - break; - case FXC_Fh: - parserRes.pOutFile = pValue; - parserRes.disassemble = true; - break; - case FXC_Fo: - parserRes.pOutFile = pValue; - break; - case FXC_Vn: - parserRes.pHeaderVariableName = pValue; - break; - default: - fprintf(stderr, "Failed assigning switch: %s | value: %s\n", sw->text, pValue); - return false; - } - - ++i; - } - else - { - switch (sw->type) - { - case FXC_Gec: - parserRes.compilerFlags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY; - break; - case FXC_Od: - parserRes.compilerFlags |= D3D10_SHADER_SKIP_OPTIMIZATION; - break; - case FXC_O0: - parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL0; - break; - case FXC_O1: - parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL1; - break; - case FXC_O2: - parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL2; - break; - case FXC_O3: - parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL3; - break; - case FXC_Zi: - parserRes.compilerFlags |= D3D10_SHADER_DEBUG; - break; - case FXC_Zpc: - parserRes.compilerFlags |= D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR; - break; - case FXC_Zpr: - parserRes.compilerFlags |= D3D10_SHADER_PACK_MATRIX_ROW_MAJOR; - break; - case FXC_Ges: - parserRes.compilerFlags |= D3D10_SHADER_ENABLE_STRICTNESS; - break; - case FXC_Gfa: - parserRes.compilerFlags |= D3D10_SHADER_AVOID_FLOW_CONTROL; - break; - case FXC_Gfp: - parserRes.compilerFlags |= D3D10_SHADER_PREFER_FLOW_CONTROL; - break; - case FXC_Gis: - parserRes.compilerFlags |= D3D10_SHADER_IEEE_STRICTNESS; - break; - case FXC_Gpp: - parserRes.compilerFlags |= D3D10_SHADER_PARTIAL_PRECISION; - break; - case FXC_Op: - parserRes.compilerFlags |= D3D10_SHADER_NO_PRESHADER; - break; - case FXC_Vd: - parserRes.compilerFlags |= D3D10_SHADER_SKIP_VALIDATION; - break; - case FXC_NoLogo: - break; - default: - fprintf(stderr, "Failed assigning switch: %s\n", sw->text); - return false; - } - } - } - else if (i == numargs - 1) - { - parserRes.pInFile = args[i]; - } - else - { - fprintf(stderr, "Error in command line at token: %s\n", args[i]); - return false; - } - } - - const bool successful = parserRes.pProfile && parserRes.pEntry && parserRes.pInFile && parserRes.pOutFile; - if (!successful) - { - fprintf(stderr, "Failed to specify all required arguments: infile, outfile, profile and entry point\n"); - } - - return successful; -} - - -bool ReadInFile(const char* pInFile, std::vector<char>& data) -{ - if (!pInFile) - { - return false; - } - - bool read = false; - - FILE* fin = 0; - fopen_s(&fin, pInFile, "rb"); - if (fin) - { - fseek(fin, 0, SEEK_END); - const long l = ftell(fin); - if (l >= 0) - { - fseek(fin, 0, SEEK_SET); - const size_t len = l > 0 ? (size_t) l : 0; - data.resize(len); - fread(&data[0], 1, len, fin); - read = true; - } - - fclose(fin); - } - - return read; -} - - -bool WriteByteCode(const char* pFileName, const void* pCode, size_t codeSize) -{ - if (!pFileName || !pCode && codeSize) - { - return false; - } - - bool written = false; - - FILE* fout = 0; - fopen_s(&fout, pFileName, "wb"); - if (fout) - { - fwrite(pCode, 1, codeSize, fout); - fclose(fout); - written = true; - } - - return written; -} - - -bool WriteHexListing(const char* pFileName, const char* pHdrVarName, const char* pDisassembly, const void* pCode, size_t codeSize) -{ - if (!pFileName || !pHdrVarName || !pDisassembly || !pCode && codeSize) - { - return false; - } - - bool written = false; - - FILE* fout = 0; - fopen_s(&fout, pFileName, "w"); - if (fout) - { - fprintf(fout, "#if 0\n%s#endif\n\n", pDisassembly); - fprintf(fout, "const BYTE g_%s[] = \n{", pHdrVarName); - - const size_t blockSize = 6; - const size_t numBlocks = codeSize / blockSize; - - const unsigned char* p = (const unsigned char*) pCode; - - size_t i = 0; - for (; i < numBlocks * blockSize; i += blockSize) - { - fprintf(fout, "\n %3d, %3d, %3d, %3d, %3d, %3d", p[i], p[i + 1], p[i + 2], p[i + 3], p[i + 4], p[i + 5]); - if (i + blockSize < codeSize) - { - fprintf(fout, ","); - } - } - - if (i < codeSize) - { - fprintf(fout, "\n "); - - for (; i < codeSize; ++i) - { - fprintf(fout, "%3d", p[i]); - if (i < codeSize - 1) - { - fprintf(fout, ", "); - } - } - } - - fprintf(fout, "\n};\n"); - - fclose(fout); - written = true; - } - - return written; -} - - -void DisplayInfo() -{ - fprintf(stdout, "FXC stub for remote shader compile server\n(C) 2012 Crytek. All rights reserved.\n\nVersion "CRYFXC_VER " for %d bit, linked against D3DCompiler_%d.dll\n\n", sizeof(void*) * 8, D3DX11_SDK_VERSION); - fprintf(stdout, "Syntax: fxc SwitchOptions Filename\n\n"); - fprintf(stdout, "Supported switches: "); - - bool firstSw = true; - for (size_t i = 0; i < sizeof(s_switchEntries) / sizeof(s_switchEntries[0]); ++i) - { - if (s_switchEntries[i].supported) - { - fprintf(stdout, "%s%s", firstSw ? "" : ", ", s_switchEntries[i].text); - firstSw = false; - } - } - - fprintf(stdout, "\n"); -} - - -int _tmain(int argc, _TCHAR* argv[]) -{ - if (argc == 1) - { - DisplayInfo(); - return 0; - } - - ParserResults parserRes; - if (!ParseCommandLine(argv, argc, parserRes)) - { - return 1; - } - - std::vector<char> program; - if (!ReadInFile(parserRes.pInFile, program)) - { - fprintf(stderr, "Failed to read input file: %s\n", parserRes.pInFile); - return 1; - } - - ID3D10Blob* pShader = 0; - ID3D10Blob* pErr = 0; - - bool successful = SUCCEEDED(D3DCompile(&program[0], program.size(), parserRes.pInFile, 0, 0, parserRes.pEntry, parserRes.pProfile, parserRes.compilerFlags, 0, &pShader, &pErr)) && pShader; - - if (successful) - { - const unsigned char* pCode = (unsigned char*) pShader->GetBufferPointer(); - const size_t codeSize = pShader->GetBufferSize(); - - if (!parserRes.disassemble) - { - successful = WriteByteCode(parserRes.pOutFile, pCode, codeSize); - if (!successful) - { - fprintf(stderr, "Failed to write output file: %s\n", parserRes.pOutFile); - } - } - else - { - ID3D10Blob* pDisassembled = 0; - successful = SUCCEEDED(D3DDisassemble(pCode, codeSize, 0, 0, &pDisassembled)) && pDisassembled; - - if (successful) - { - const char* pDisassembly = (char*) pDisassembled->GetBufferPointer(); - const char* pHdrVarName = parserRes.pHeaderVariableName ? parserRes.pHeaderVariableName : parserRes.pEntry; - successful = WriteHexListing(parserRes.pOutFile, pHdrVarName, pDisassembly, pCode, codeSize); - if (!successful) - { - fprintf(stderr, "Failed to write output file: %s\n", parserRes.pOutFile); - } - } - else - { - fprintf(stderr, "Failed to disassemble shader code\n", parserRes.pOutFile); - } - - if (pDisassembled) - { - pDisassembled->Release(); - pDisassembled = 0; - } - } - } - else - { - if (pErr) - { - const char* pMsg = (const char*) pErr->GetBufferPointer(); - fprintf(stderr, "%s\n", pMsg); - } - } - - if (pShader) - { - pShader->Release(); - pShader = 0; - } - - if (pErr) - { - pErr->Release(); - pErr = 0; - } - - return successful ? 0 : 1; -} diff --git a/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj b/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj deleted file mode 100644 index ab57f4c7f6..0000000000 --- a/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj +++ /dev/null @@ -1,153 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{A505D345-D712-4C80-8BDE-6FBC08A390D8}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>cryfxc</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <LinkIncremental>true</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <LinkIncremental>false</LinkIncremental> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <PrecompiledHeader>Use</PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <PrecompiledHeader>Use</PrecompiledHeader> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader>Use</PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PrecompiledHeader>Use</PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <RuntimeLibrary>MultiThreaded</RuntimeLibrary> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="StdAfx.h" /> - <ClInclude Include="targetver.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="cryfxc.cpp" /> - <ClCompile Include="StdAfx.cpp"> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> - </ClCompile> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file diff --git a/Code/Tools/CryFXC/cryfxc/stdafx.cpp b/Code/Tools/CryFXC/cryfxc/stdafx.cpp deleted file mode 100644 index 209929990b..0000000000 --- a/Code/Tools/CryFXC/cryfxc/stdafx.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "stdafx.h" diff --git a/Code/Tools/CryFXC/cryfxc/stdafx.h b/Code/Tools/CryFXC/cryfxc/stdafx.h deleted file mode 100644 index 698d14574b..0000000000 --- a/Code/Tools/CryFXC/cryfxc/stdafx.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -#include <stdio.h> -#include <tchar.h> -#include <string.h> -#include <assert.h> - -#include <vector> - -#include <D3DX11.h> -#include <D3Dcompiler.h> diff --git a/Code/Tools/CryFXC/cryfxc/targetver.h b/Code/Tools/CryFXC/cryfxc/targetver.h deleted file mode 100644 index d139ba1901..0000000000 --- a/Code/Tools/CryFXC/cryfxc/targetver.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#pragma once - -#include <SDKDDKVer.h> diff --git a/Code/Tools/HLSLCrossCompiler/CMakeLists.txt b/Code/Tools/HLSLCrossCompiler/CMakeLists.txt deleted file mode 100644 index 3b60e715a8..0000000000 --- a/Code/Tools/HLSLCrossCompiler/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -ly_add_target( - NAME HLSLcc.Headers HEADERONLY - NAMESPACE AZ - FILES_CMAKE - hlslcc_header_files.cmake - INCLUDE_DIRECTORIES - INTERFACE - include -) - -if (NOT PAL_TRAIT_BUILD_HOST_TOOLS) - return() -endif() - -ly_add_target( - NAME HLSLcc EXECUTABLE - NAMESPACE AZ - OUTPUT_SUBDIRECTORY Compiler/PCGL/V006 - FILES_CMAKE - hlslcc_files.cmake - PLATFORM_INCLUDE_FILES - Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - INCLUDE_DIRECTORIES - PRIVATE - src - src/cbstring - offline/cjson - BUILD_DEPENDENCIES - PRIVATE - AZ::AzCore - PUBLIC - AZ::HLSLcc.Headers -) -ly_add_source_properties( - SOURCES - offline/compilerStandalone.cpp - offline/cjson/cJSON.c - src/toGLSL.c - src/toGLSLDeclaration.c - src/cbstring/bstrlib.c - src/cbstring/bstraux.c - src/reflect.c - src/amazon_changes.c - PROPERTY COMPILE_DEFINITIONS - VALUES _CRT_SECURE_NO_WARNINGS -) diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake deleted file mode 100644 index 4d5680a30d..0000000000 --- a/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake deleted file mode 100644 index f5b9ea77a2..0000000000 --- a/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake deleted file mode 100644 index 926c831fb9..0000000000 --- a/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -file(TO_CMAKE_PATH "$ENV{ProgramFiles\(x86\)}" program_files_path) - -ly_add_target_files( - TARGETS HLSLcc - FILES - "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcompiler_47.dll" -) diff --git a/Code/Tools/HLSLCrossCompiler/README b/Code/Tools/HLSLCrossCompiler/README deleted file mode 100644 index 4369f1a3b2..0000000000 --- a/Code/Tools/HLSLCrossCompiler/README +++ /dev/null @@ -1,71 +0,0 @@ -Overview: - This is a modified version of https://github.com/James-Jones/HLSLCrossCompiler - - It can be used either: - 1. As an executable. - This is the default use case for release builds - This is run by the RemoteShaderCompiler when compiling the shaders for the GL4 and GLES3 platforms. - 2. As a static library. - This is used by the DXGL translation layer if compiled with DXGL_USE_GLSL set to 0. - In this case DXGL translation layer to translate DirectX shader model 5 bytecode coming from the renderer front end (runtime translation). - -Editing: - When modifying the source code, in order to use the updated version in the engine, you will have to recompile the library. - To do this, please follow these steps: - - A. Edit /Code/Tools/HLSLCrossCompiler/bin/mk/rsc_version.txt and bump the version string. - Please use the format for released branches and main: - V[3_decimal_digits_version_number] - and optionally for development branches: - V[3_decimal_digits_version_number]_[custom_version_label] - - B. From a Windows machine: - Verify that the following folders and the contained files are writeable (checkout if needed): - - /Code/Tools/HLSLCrossCompiler/bin - - /Code/Tools/HLSLCrossCompiler/lib - - /Tools/RemoteShaderCompiler/Compiler/PCGL - Run: - /Code/Tools/HLSLCrossCompiler/mk/build_win_all.py - Note: - This will compile: - - The static library (2) for win32 and win64 in release - - The executable (1) with the PORTABLE define enabled (required to run from machines without Direct3D runtime, such ass the RSC servers) - for win64 release in and place it in /Tools/RemoteShaderCompiler/Compiler/PCGL/[rsc_version]/ - - C. From a Linux machine: - Verify that the following folder and the contained files are writeable (checkout if needed): - - /Code/Tools/HLSLCrossCompiler/lib - Run: - /Code/Tools/HLSLCrossCompiler/mk/build_linux_all.py - Note: - This will compile: - - The static library (2) for linux (64 bit) in release - - The static library (2) for android (android-armeabi-v7a) in release - - D. Edit: - /Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp - and update the two command lines in CShaderMan::mfGetShaderCompileFlags: - const char* pCompilerGL4="PCGL/[rsc_version]/HLSLcc.exe [generic_gl4_flags ...]"; - const char* pCompilerGLES3="PCGL/[rsc_version]/HLSLcc.exe [generic_gles3_flags ...]"; - with the rsc_version string chosen. - - E. Edit: - /Code/CryEngine/RenderDll/Common/Shaders/Shader.h - and bump by one minor decimal unit: - #define FX_CACHE_VER [major_decimal_digit_0].[minor_decimal_digit_0] - Note: - This is required to flush cached shaders generated with the previous versions that might be stored - in ShaderCache.pak or in a user cache folder. - -Submitting: - Before submitting any change to HLSLCrossCompiler source code, please - make sure to do so together with the updated: - /Code/Tools/HLSLCrossCompiler/bin/mk/rsc_version.txt - /Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib - /Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib - /Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a - /Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a - /Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp - /Code/CryEngine/RenderDll/Common/Shaders/Shader.h - /Tools/RemoteShaderCompiler/Compiler/PCGL/[rsc_version]/HLSLcc.exe - This will make sure there is no mismatch between any cached shaders, and remotely or locally compiled shaders. \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake b/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake deleted file mode 100644 index f19b52084a..0000000000 --- a/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake +++ /dev/null @@ -1,60 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - offline/hash.h - offline/serializeReflection.h - offline/timer.h - offline/compilerStandalone.cpp - offline/serializeReflection.cpp - offline/timer.cpp - offline/cjson/cJSON.h - offline/cjson/cJSON.c - src/amazon_changes.c - src/decode.c - src/decodeDX9.c - src/reflect.c - src/toGLSL.c - src/toGLSLDeclaration.c - src/toGLSLInstruction.c - src/toGLSLOperand.c - src/hlslccToolkit.c - src/internal_includes/debug.h - src/internal_includes/decode.h - src/internal_includes/hlslcc_malloc.h - src/internal_includes/hlslcc_malloc.c - src/internal_includes/languages.h - src/internal_includes/reflect.h - src/internal_includes/shaderLimits.h - src/internal_includes/structs.h - src/internal_includes/toGLSLDeclaration.h - src/internal_includes/toGLSLInstruction.h - src/internal_includes/toGLSLOperand.h - src/internal_includes/tokens.h - src/internal_includes/tokensDX9.h - src/internal_includes/hlslccToolkit.h - src/cbstring/bsafe.h - src/cbstring/bstraux.h - src/cbstring/bstrlib.h - src/cbstring/bsafe.c - src/cbstring/bstraux.c - src/cbstring/bstrlib.c - include/amazon_changes.h - include/hlslcc.h - include/hlslcc.hpp - include/hlslcc_bin.hpp - include/pstdint.h -) - -set(SKIP_UNITY_BUILD_INCLUSION_FILES - # 'bsafe.c' tries to forward declar 'strncpy', 'strncat', etc, but they are already declared in other modules. Remove from unity builds conideration - src/cbstring/bsafe.c -) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake b/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake deleted file mode 100644 index f242cc95e6..0000000000 --- a/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES hlslcc_files.cmake - include/amazon_changes.h - include/hlslcc.h - include/hlslcc.hpp - include/pstdint.h - include/hlslcc_bin.hpp -) diff --git a/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h b/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h deleted file mode 100644 index bbc2b22625..0000000000 --- a/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h +++ /dev/null @@ -1,13 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef AMAZON_CHANGES_H -#define AMAZON_CHANGES_H - -// There is a bug on the Adreno 420 driver where reinterpret casts can destroy a variable. We need to replace all instances that look like this: -// floatBitsToInt(Temp2); -// We do not need to change cases that evaluate an expression within the cast operation, like so: -// floatBitsToInt(Temp2 + 1.0f); -void ModifyLineForQualcommReinterpretCastBug( HLSLCrossCompilerContext* psContext, bstring* originalString, bstring* overloadString ); - -#endif // AMAZON_CHANGES_H diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc.h b/Code/Tools/HLSLCrossCompiler/include/hlslcc.h deleted file mode 100644 index efa43d8f4f..0000000000 --- a/Code/Tools/HLSLCrossCompiler/include/hlslcc.h +++ /dev/null @@ -1,580 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HLSLCC_H_ -#define HLSLCC_H_ - -#if defined (_WIN32) && defined(HLSLCC_DYNLIB) - #define HLSLCC_APIENTRY __stdcall - #if defined(libHLSLcc_EXPORTS) - #define HLSLCC_API __declspec(dllexport) - #else - #define HLSLCC_API __declspec(dllimport) - #endif -#else - #define HLSLCC_APIENTRY - #define HLSLCC_API -#endif - -#include <stdint.h> -#include <stddef.h> - -typedef enum -{ - LANG_DEFAULT,// Depends on the HLSL shader model. - LANG_ES_100, - LANG_ES_300, - LANG_ES_310, - LANG_120, - LANG_130, - LANG_140, - LANG_150, - LANG_330, - LANG_400, - LANG_410, - LANG_420, - LANG_430, - LANG_440, -} GLLang; - -typedef struct { - uint32_t ARB_explicit_attrib_location : 1; - uint32_t ARB_explicit_uniform_location : 1; - uint32_t ARB_shading_language_420pack : 1; -}GlExtensions; - -enum {MAX_SHADER_VEC4_OUTPUT = 512}; -enum {MAX_SHADER_VEC4_INPUT = 512}; -enum {MAX_TEXTURES = 128}; -enum {MAX_FORK_PHASES = 2}; -enum {MAX_FUNCTION_BODIES = 1024}; -enum {MAX_CLASS_TYPES = 1024}; -enum {MAX_FUNCTION_POINTERS = 128}; - -//Reflection -#define MAX_REFLECT_STRING_LENGTH 512 -#define MAX_SHADER_VARS 256 -#define MAX_CBUFFERS 256 -#define MAX_UAV 256 -#define MAX_FUNCTION_TABLES 256 -#define MAX_RESOURCE_BINDINGS 256 - -//Operands flags -#define TO_FLAG_NONE 0x0 -#define TO_FLAG_INTEGER 0x1 -#define TO_FLAG_NAME_ONLY 0x2 -#define TO_FLAG_DECLARATION_NAME 0x4 -#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. -#define TO_FLAG_UNSIGNED_INTEGER 0x10 -#define TO_FLAG_DOUBLE 0x20 -#define TO_FLAG_FLOAT 0x40 -#define TO_FLAG_COPY 0x80 - -typedef enum SPECIAL_NAME -{ - NAME_UNDEFINED = 0, - NAME_POSITION = 1, - NAME_CLIP_DISTANCE = 2, - NAME_CULL_DISTANCE = 3, - NAME_RENDER_TARGET_ARRAY_INDEX = 4, - NAME_VIEWPORT_ARRAY_INDEX = 5, - NAME_VERTEX_ID = 6, - NAME_PRIMITIVE_ID = 7, - NAME_INSTANCE_ID = 8, - NAME_IS_FRONT_FACE = 9, - NAME_SAMPLE_INDEX = 10, - // The following are added for D3D11 - NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11, - NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12, - NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13, - NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14, - NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15, - NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16, - NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17, - NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18, - NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19, - NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20, - NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21, - NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22, -} SPECIAL_NAME; - - -typedef enum { - INOUT_COMPONENT_UNKNOWN = 0, - INOUT_COMPONENT_UINT32 = 1, - INOUT_COMPONENT_SINT32 = 2, - INOUT_COMPONENT_FLOAT32 = 3 -} INOUT_COMPONENT_TYPE; - -typedef enum MIN_PRECISION { - MIN_PRECISION_DEFAULT = 0, - MIN_PRECISION_FLOAT_16 = 1, - MIN_PRECISION_FLOAT_2_8 = 2, - MIN_PRECISION_RESERVED = 3, - MIN_PRECISION_SINT_16 = 4, - MIN_PRECISION_UINT_16 = 5, - MIN_PRECISION_ANY_16 = 0xf0, - MIN_PRECISION_ANY_10 = 0xf1 -} MIN_PRECISION; - -typedef struct InOutSignature_TAG -{ - char SemanticName[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32SemanticIndex; - SPECIAL_NAME eSystemValueType; - INOUT_COMPONENT_TYPE eComponentType; - uint32_t ui32Register; - uint32_t ui32Mask; - uint32_t ui32ReadWriteMask; - - uint32_t ui32Stream; - MIN_PRECISION eMinPrec; - -} InOutSignature; - -typedef enum ResourceType_TAG -{ - RTYPE_CBUFFER,//0 - RTYPE_TBUFFER,//1 - RTYPE_TEXTURE,//2 - RTYPE_SAMPLER,//3 - RTYPE_UAV_RWTYPED,//4 - RTYPE_STRUCTURED,//5 - RTYPE_UAV_RWSTRUCTURED,//6 - RTYPE_BYTEADDRESS,//7 - RTYPE_UAV_RWBYTEADDRESS,//8 - RTYPE_UAV_APPEND_STRUCTURED,//9 - RTYPE_UAV_CONSUME_STRUCTURED,//10 - RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11 - RTYPE_COUNT, -} ResourceType; - -typedef enum ResourceGroup_TAG { - RGROUP_CBUFFER, - RGROUP_TEXTURE, - RGROUP_SAMPLER, - RGROUP_UAV, - RGROUP_COUNT, -} ResourceGroup; - -typedef enum REFLECT_RESOURCE_DIMENSION -{ - REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0, - REFLECT_RESOURCE_DIMENSION_BUFFER = 1, - REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2, - REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3, - REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7, - REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8, - REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9, - REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, - REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, -} REFLECT_RESOURCE_DIMENSION; - -typedef struct ResourceBinding_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - ResourceType eType; - uint32_t ui32BindPoint; - uint32_t ui32BindCount; - uint32_t ui32Flags; - REFLECT_RESOURCE_DIMENSION eDimension; - uint32_t ui32ReturnType; - uint32_t ui32NumSamples; -} ResourceBinding; - -// Do not change the value of these enums or they will not match what we find in the DXBC file -typedef enum _SHADER_VARIABLE_TYPE { - SVT_VOID = 0, - SVT_BOOL = 1, - SVT_INT = 2, - SVT_FLOAT = 3, - SVT_STRING = 4, - SVT_TEXTURE = 5, - SVT_TEXTURE1D = 6, - SVT_TEXTURE2D = 7, - SVT_TEXTURE3D = 8, - SVT_TEXTURECUBE = 9, - SVT_SAMPLER = 10, - SVT_PIXELSHADER = 15, - SVT_VERTEXSHADER = 16, - SVT_UINT = 19, - SVT_UINT8 = 20, - SVT_GEOMETRYSHADER = 21, - SVT_RASTERIZER = 22, - SVT_DEPTHSTENCIL = 23, - SVT_BLEND = 24, - SVT_BUFFER = 25, - SVT_CBUFFER = 26, - SVT_TBUFFER = 27, - SVT_TEXTURE1DARRAY = 28, - SVT_TEXTURE2DARRAY = 29, - SVT_RENDERTARGETVIEW = 30, - SVT_DEPTHSTENCILVIEW = 31, - SVT_TEXTURE2DMS = 32, - SVT_TEXTURE2DMSARRAY = 33, - SVT_TEXTURECUBEARRAY = 34, - SVT_HULLSHADER = 35, - SVT_DOMAINSHADER = 36, - SVT_INTERFACE_POINTER = 37, - SVT_COMPUTESHADER = 38, - SVT_DOUBLE = 39, - SVT_RWTEXTURE1D = 40, - SVT_RWTEXTURE1DARRAY = 41, - SVT_RWTEXTURE2D = 42, - SVT_RWTEXTURE2DARRAY = 43, - SVT_RWTEXTURE3D = 44, - SVT_RWBUFFER = 45, - SVT_BYTEADDRESS_BUFFER = 46, - SVT_RWBYTEADDRESS_BUFFER = 47, - SVT_STRUCTURED_BUFFER = 48, - SVT_RWSTRUCTURED_BUFFER = 49, - SVT_APPEND_STRUCTURED_BUFFER = 50, - SVT_CONSUME_STRUCTURED_BUFFER = 51, - - // Partial precision types - SVT_FLOAT10 = 53, - SVT_FLOAT16 = 54, - SVT_INT16 = 156, - SVT_INT12 = 157, - SVT_UINT16 = 158, - - SVT_FORCE_DWORD = 0x7fffffff -} SHADER_VARIABLE_TYPE; - -typedef enum _SHADER_VARIABLE_CLASS { - SVC_SCALAR = 0, - SVC_VECTOR = ( SVC_SCALAR + 1 ), - SVC_MATRIX_ROWS = ( SVC_VECTOR + 1 ), - SVC_MATRIX_COLUMNS = ( SVC_MATRIX_ROWS + 1 ), - SVC_OBJECT = ( SVC_MATRIX_COLUMNS + 1 ), - SVC_STRUCT = ( SVC_OBJECT + 1 ), - SVC_INTERFACE_CLASS = ( SVC_STRUCT + 1 ), - SVC_INTERFACE_POINTER = ( SVC_INTERFACE_CLASS + 1 ), - SVC_FORCE_DWORD = 0x7fffffff -} SHADER_VARIABLE_CLASS; - -typedef struct ShaderVarType_TAG { - SHADER_VARIABLE_CLASS Class; - SHADER_VARIABLE_TYPE Type; - uint32_t Rows; - uint32_t Columns; - uint32_t Elements; - uint32_t MemberCount; - uint32_t Offset; - char Name[MAX_REFLECT_STRING_LENGTH]; - - uint32_t ParentCount; - struct ShaderVarType_TAG * Parent; - - struct ShaderVarType_TAG * Members; -} ShaderVarType; - -typedef struct ShaderVar_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - int haveDefaultValue; - uint32_t* pui32DefaultValues; - //Offset/Size in bytes. - uint32_t ui32StartOffset; - uint32_t ui32Size; - uint32_t ui32Flags; - - ShaderVarType sType; -} ShaderVar; - -typedef struct ConstantBuffer_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - - uint32_t ui32NumVars; - ShaderVar asVars[MAX_SHADER_VARS]; - - uint32_t ui32TotalSizeInBytes; - int blob; -} ConstantBuffer; - -typedef struct ClassType_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - uint16_t ui16ID; - uint16_t ui16ConstBufStride; - uint16_t ui16Texture; - uint16_t ui16Sampler; -} ClassType; - -typedef struct ClassInstance_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - uint16_t ui16ID; - uint16_t ui16ConstBuf; - uint16_t ui16ConstBufOffset; - uint16_t ui16Texture; - uint16_t ui16Sampler; -} ClassInstance; - -typedef enum TESSELLATOR_PARTITIONING -{ - TESSELLATOR_PARTITIONING_UNDEFINED = 0, - TESSELLATOR_PARTITIONING_INTEGER = 1, - TESSELLATOR_PARTITIONING_POW2 = 2, - TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3, - TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4 -} TESSELLATOR_PARTITIONING; - -typedef enum TESSELLATOR_OUTPUT_PRIMITIVE -{ - TESSELLATOR_OUTPUT_UNDEFINED = 0, - TESSELLATOR_OUTPUT_POINT = 1, - TESSELLATOR_OUTPUT_LINE = 2, - TESSELLATOR_OUTPUT_TRIANGLE_CW = 3, - TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4 -} TESSELLATOR_OUTPUT_PRIMITIVE; - -typedef enum INTERPOLATION_MODE -{ - INTERPOLATION_UNDEFINED = 0, - INTERPOLATION_CONSTANT = 1, - INTERPOLATION_LINEAR = 2, - INTERPOLATION_LINEAR_CENTROID = 3, - INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, - INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, - INTERPOLATION_LINEAR_SAMPLE = 6, - INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, -} INTERPOLATION_MODE; - -typedef enum TRACE_VARIABLE_GROUP -{ - TRACE_VARIABLE_INPUT = 0, - TRACE_VARIABLE_TEMP = 1, - TRACE_VARIABLE_OUTPUT = 2 -} TRACE_VARIABLE_GROUP; - -typedef enum TRACE_VARIABLE_TYPE -{ - TRACE_VARIABLE_FLOAT = 0, - TRACE_VARIABLE_SINT = 1, - TRACE_VARIABLE_UINT = 2, - TRACE_VARIABLE_DOUBLE = 3, - TRACE_VARIABLE_UNKNOWN = 4 -} TRACE_VARIABLE_TYPE; - -typedef struct VariableTraceInfo_TAG -{ - TRACE_VARIABLE_GROUP eGroup; - TRACE_VARIABLE_TYPE eType; - uint8_t ui8Index; - uint8_t ui8Component; -} VariableTraceInfo; - -typedef struct StepTraceInfo_TAG -{ - uint32_t ui32NumVariables; - VariableTraceInfo* psVariables; -} StepTraceInfo; - -typedef enum SYMBOL_TYPE -{ - SYMBOL_TESSELLATOR_PARTITIONING = 0, - SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE = 1, - SYMBOL_INPUT_INTERPOLATION_MODE = 2, - SYMBOL_EMULATE_DEPTH_CLAMP = 3 -} SYMBOL_TYPE; - -typedef struct Symbol_TAG -{ - SYMBOL_TYPE eType; - uint32_t ui32ID; - uint32_t ui32Value; -} Symbol; - -typedef struct EmbeddedResourceName_TAG -{ - uint32_t ui20Offset : 20; - uint32_t ui12Size : 12; -} EmbeddedResourceName; - -typedef struct SamplerMask_TAG -{ - uint32_t ui10TextureBindPoint : 10; - uint32_t ui10SamplerBindPoint : 10; - uint32_t ui10TextureUnit : 10; - uint32_t bNormalSample : 1; - uint32_t bCompareSample : 1; -} SamplerMask; - -typedef struct Sampler_TAG -{ - SamplerMask sMask; - EmbeddedResourceName sNormalName; - EmbeddedResourceName sCompareName; -} Sampler; - -typedef struct Resource_TAG -{ - uint32_t ui32BindPoint; - ResourceGroup eGroup; - EmbeddedResourceName sName; -} Resource; - -typedef struct ShaderInfo_TAG -{ - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - - uint32_t ui32NumInputSignatures; - InOutSignature* psInputSignatures; - - uint32_t ui32NumOutputSignatures; - InOutSignature* psOutputSignatures; - - uint32_t ui32NumResourceBindings; - ResourceBinding* psResourceBindings; - - uint32_t ui32NumConstantBuffers; - ConstantBuffer* psConstantBuffers; - ConstantBuffer* psThisPointerConstBuffer; - - uint32_t ui32NumClassTypes; - ClassType* psClassTypes; - - uint32_t ui32NumClassInstances; - ClassInstance* psClassInstances; - - //Func table ID to class name ID. - uint32_t aui32TableIDToTypeID[MAX_FUNCTION_TABLES]; - - uint32_t aui32ResourceMap[RGROUP_COUNT][MAX_RESOURCE_BINDINGS]; - - // GLSL resources - Sampler asSamplers[MAX_RESOURCE_BINDINGS]; - Resource asImages[MAX_RESOURCE_BINDINGS]; - Resource asUniformBuffers[MAX_RESOURCE_BINDINGS]; - Resource asStorageBuffers[MAX_RESOURCE_BINDINGS]; - uint32_t ui32NumSamplers; - uint32_t ui32NumImages; - uint32_t ui32NumUniformBuffers; - uint32_t ui32NumStorageBuffers; - - // Trace info if tracing is enabled - uint32_t ui32NumTraceSteps; - StepTraceInfo* psTraceSteps; - - // Symbols imported - uint32_t ui32NumImports; - Symbol* psImports; - - // Symbols exported - uint32_t ui32NumExports; - Symbol* psExports; - - // Hash of the input shader for debugging purposes - uint32_t ui32InputHash; - - // Offset in the GLSL string where symbol definitions can be inserted - uint32_t ui32SymbolsOffset; - - TESSELLATOR_PARTITIONING eTessPartitioning; - TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; - - //Required if PixelInterpDependency is true - INTERPOLATION_MODE aePixelInputInterpolation[MAX_SHADER_VEC4_INPUT]; -} ShaderInfo; - -typedef struct -{ - int shaderType; //One of the GL enums. - char* sourceCode; - ShaderInfo reflection; - GLLang GLSLLanguage; -} GLSLShader; - -typedef enum _FRAMEBUFFER_FETCH_TYPE -{ - FBF_NONE = 0, - FBF_EXT_COLOR = 1 << 0, - FBF_ARM_COLOR = 1 << 1, - FBF_ARM_DEPTH = 1 << 2, - FBF_ARM_STENCIL = 1 << 3, - FBF_ANY = FBF_EXT_COLOR | FBF_ARM_COLOR | FBF_ARM_DEPTH | FBF_ARM_STENCIL -} FRAMEBUFFER_FETCH_TYPE; - -// NOTE: HLSLCC flags are specified by command line when executing this cross compiler. -// If these flags change, the command line switch '-flags=XXX' must change as well. -// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' - -/*HLSL constant buffers are treated as default-block unform arrays by default. This is done - to support versions of GLSL which lack ARB_uniform_buffer_object functionality. - Setting this flag causes each one to have its own uniform block. - Note: Currently the nth const buffer will be named UnformBufferN. This is likey to change to the original HLSL name in the future.*/ -static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT = 0x1; - -static const unsigned int HLSLCC_FLAG_ORIGIN_UPPER_LEFT = 0x2; - -static const unsigned int HLSLCC_FLAG_PIXEL_CENTER_INTEGER = 0x4; - -static const unsigned int HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO = 0x8; - -//GS enabled? -//Affects vertex shader (i.e. need to compile vertex shader again to use with/without GS). -//This flag is needed in order for the interfaces between stages to match when GS is in use. -//PS inputs VtxGeoOutput -//GS outputs VtxGeoOutput -//Vs outputs VtxOutput if GS enabled. VtxGeoOutput otherwise. -static const unsigned int HLSLCC_FLAG_GS_ENABLED = 0x10; - -static const unsigned int HLSLCC_FLAG_TESS_ENABLED = 0x20; - -//Either use this flag or glBindFragDataLocationIndexed. -//When set the first pixel shader output is the first input to blend -//equation, the others go to the second input. -static const unsigned int HLSLCC_FLAG_DUAL_SOURCE_BLENDING = 0x40; - -//If set, shader inputs and outputs are declared with their semantic name. -static const unsigned int HLSLCC_FLAG_INOUT_SEMANTIC_NAMES = 0x80; - -static const unsigned int HLSLCC_FLAG_INVERT_CLIP_SPACE_Y = 0x100; -static const unsigned int HLSLCC_FLAG_CONVERT_CLIP_SPACE_Z = 0x200; -static const unsigned int HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS = 0x400; -static const unsigned int HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING = 0x800; -static const unsigned int HLSLCC_FLAG_TRACING_INSTRUMENTATION = 0x1000; -static const unsigned int HLSLCC_FLAG_HASH_INPUT = 0x2000; -static const unsigned int HLSLCC_FLAG_ADD_DEBUG_HEADER = 0x4000; -static const unsigned int HLSLCC_FLAG_NO_VERSION_STRING = 0x8000; - -static const unsigned int HLSLCC_FLAG_AVOID_SHADER_LOAD_STORE_EXTENSION = 0x10000; - -// If set, HLSLcc will generate GLSL code which contains syntactic workarounds for -// driver bugs found in Qualcomm devices running OpenGL ES 3.0 -static const unsigned int HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND = 0x20000; - -// If set, HLSL DX9 lower precision qualifiers (e.g half) will be transformed to DX11 style (e.g min16float) -// before compiling. Necessary to preserve precision information. If not, FXC just silently transform -// everything to full precision (e.g float32). -static const unsigned int HLSLCC_FLAG_HALF_FLOAT_TRANSFORM = 0x40000; - -#ifdef __cplusplus -extern "C" { -#endif - -HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), - void* (*calloc_override)(size_t,size_t), - void (*free_override)(void *), - void* (*realloc_override)(void*,size_t)); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename, unsigned int flags, GLLang language, const GlExtensions *extensions, GLSLShader* result); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, size_t size, unsigned int flags, GLLang language, const GlExtensions *extensions, GLSLShader* result); - -HLSLCC_API const char* HLSLCC_APIENTRY GetVersionString(GLLang language); - -HLSLCC_API void HLSLCC_APIENTRY FreeGLSLShader(GLSLShader*); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp b/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp deleted file mode 100644 index 193415f277..0000000000 --- a/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -extern "C" { -#include "hlslcc.h" -} - diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp b/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp deleted file mode 100644 index f2062e58ac..0000000000 --- a/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp +++ /dev/null @@ -1,419 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include <algorithm> - -#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) - -enum -{ - DXBC_BASE_ALIGNMENT = 4, - FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C'), - FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F'), - FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N'), - FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N'), - FOURCC_PCSG = FOURCC('P', 'C', 'S', 'G'), - FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R'), - FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X'), - FOURCC_GLSL = FOURCC('G', 'L', 'S', 'L'), - FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1'), // When lower precision float/int/uint is used - FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1'), // When lower precision float/int/uint is used -}; - -#undef FOURCC - -template <typename T> -inline T DXBCSwapBytes(const T& kValue) -{ - return kValue; -} - -#if defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN - -inline uint16_t DXBCSwapBytes(const uint16_t& uValue) -{ - return - (((uValue) >> 8) & 0xFF) | - (((uValue) << 8) & 0xFF); -} - -inline uint32_t DXBCSwapBytes(const uint32_t& uValue) -{ - return - (((uValue) >> 24) & 0x000000FF) | - (((uValue) >> 8) & 0x0000FF00) | - (((uValue) << 8) & 0x00FF0000) | - (((uValue) << 24) & 0xFF000000); -} - -#endif //defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN - -template <typename Element> -struct SDXBCBufferBase -{ - Element* m_pBegin; - Element* m_pEnd; - Element* m_pIter; - - SDXBCBufferBase(Element* pBegin, Element* pEnd) - : m_pBegin(pBegin) - , m_pEnd(pEnd) - , m_pIter(pBegin) - { - } - - bool SeekRel(int32_t iOffset) - { - Element* pIterAfter(m_pIter + iOffset); - if (pIterAfter > m_pEnd) - return false; - - m_pIter = pIterAfter; - return true; - } - - bool SeekAbs(uint32_t uPosition) - { - Element* pIterAfter(m_pBegin + uPosition); - if (pIterAfter > m_pEnd) - return false; - - m_pIter = pIterAfter; - return true; - } -}; - -struct SDXBCInputBuffer : SDXBCBufferBase<const uint8_t> -{ - SDXBCInputBuffer(const uint8_t* pBegin, const uint8_t* pEnd) - : SDXBCBufferBase(pBegin, pEnd) - { - } - - bool Read(void* pElements, size_t uSize) - { - const uint8_t* pIterAfter(m_pIter + uSize); - if (pIterAfter > m_pEnd) - return false; - - memcpy(pElements, m_pIter, uSize); - - m_pIter = pIterAfter; - return true; - } -}; - -struct SDXBCOutputBuffer : SDXBCBufferBase<uint8_t> -{ - SDXBCOutputBuffer(uint8_t* pBegin, uint8_t* pEnd) - : SDXBCBufferBase(pBegin, pEnd) - { - } - - bool Write(const void* pElements, size_t uSize) - { - uint8_t* pIterAfter(m_pIter + uSize); - if (pIterAfter > m_pEnd) - return false; - - memcpy(m_pIter, pElements, uSize); - - m_pIter = pIterAfter; - return true; - } -}; - -template <typename S, typename External, typename Internal> -inline bool DXBCReadAs(S& kStream, External& kValue) -{ - Internal kInternal; - bool bResult(kStream.Read(&kInternal, sizeof(Internal))); - kValue = static_cast<External>(DXBCSwapBytes(kInternal)); - return bResult; -} - -template <typename S, typename Internal> -inline bool DXBCWriteAs(S& kStream, Internal kValue) -{ - Internal kInternal(DXBCSwapBytes(kValue)); - return kStream.Write(&kInternal, sizeof(Internal)); -} - -template <typename S, typename T> bool DXBCReadUint8 (S& kStream, T& kValue) { return DXBCReadAs<S, T, uint8_t >(kStream, kValue); } -template <typename S, typename T> bool DXBCReadUint16(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint16_t>(kStream, kValue); } -template <typename S, typename T> bool DXBCReadUint32(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint32_t>(kStream, kValue); } - -template <typename S> bool DXBCWriteUint8 (S& kStream, uint8_t kValue) { return DXBCWriteAs<S, uint8_t >(kStream, kValue); } -template <typename S> bool DXBCWriteUint16(S& kStream, uint16_t kValue) { return DXBCWriteAs<S, uint16_t>(kStream, kValue); } -template <typename S> bool DXBCWriteUint32(S& kStream, uint32_t kValue) { return DXBCWriteAs<S, uint32_t>(kStream, kValue); } - -template <typename O, typename I> -bool DXBCCopy(O& kOutput, I& kInput, size_t uSize) -{ - char acBuffer[1024]; - while (uSize > 0) - { - size_t uToCopy(std::min<size_t>(uSize, sizeof(acBuffer))); - if (!kInput.Read(acBuffer, uToCopy) || - !kOutput.Write(acBuffer, uToCopy)) - return false; - uSize -= uToCopy; - } - return true; -} - -enum -{ - DXBC_SIZE_POSITION = 6 * 4, - DXBC_HEADER_SIZE = 7 * 4, - DXBC_CHUNK_HEADER_SIZE = 2 * 4, - DXBC_MAX_NUM_CHUNKS_IN = 128, - DXBC_MAX_NUM_CHUNKS_OUT = 8, - DXBC_OUT_CHUNKS_INDEX_SIZE = (1 + 1 + DXBC_MAX_NUM_CHUNKS_OUT) * 4, - DXBC_OUT_FIXED_SIZE = DXBC_HEADER_SIZE + DXBC_OUT_CHUNKS_INDEX_SIZE, -}; - -enum -{ - GLSL_HEADER_SIZE = 4 * 8, // uNumSamplers, uNumImages, uNumStorageBuffers, uNumUniformBuffers, uNumImports, uNumExports, uInputHash, uSymbolsOffset - GLSL_SAMPLER_SIZE = 4 * 3, // uSamplerField, uEmbeddedNormalName, uEmbeddedCompareName - GLSL_RESOURCE_SIZE = 4 * 2, // uBindPoint, uName - GLSL_SYMBOL_SIZE = 4 * 3, // uType, uID, uValue -}; - -inline void DXBCSizeGLSLChunk(uint32_t& uGLSLChunkSize, uint32_t& uGLSLSourceSize, const GLSLShader* pShader) -{ - uint32_t uNumSymbols( - pShader->reflection.ui32NumImports + - pShader->reflection.ui32NumExports); - uint32_t uGLSLInfoSize( - DXBC_CHUNK_HEADER_SIZE + - GLSL_HEADER_SIZE + - pShader->reflection.ui32NumSamplers * GLSL_SAMPLER_SIZE + - pShader->reflection.ui32NumImages * GLSL_RESOURCE_SIZE + - pShader->reflection.ui32NumStorageBuffers * GLSL_RESOURCE_SIZE + - pShader->reflection.ui32NumUniformBuffers * GLSL_RESOURCE_SIZE + - uNumSymbols * GLSL_SYMBOL_SIZE); - uGLSLSourceSize = (uint32_t)strlen(pShader->sourceCode) + 1; - uGLSLChunkSize = uGLSLInfoSize + uGLSLSourceSize; - uGLSLChunkSize += DXBC_BASE_ALIGNMENT - 1 - (uGLSLChunkSize - 1) % DXBC_BASE_ALIGNMENT; -} - -inline uint32_t DXBCSizeOutputChunk(uint32_t uCode, uint32_t uSizeIn) -{ - uint32_t uSizeOut; - switch (uCode) - { - case FOURCC_RDEF: - case FOURCC_ISGN: - case FOURCC_OSGN: - case FOURCC_PCSG: - case FOURCC_OSG1: - case FOURCC_ISG1: - // Preserve entire chunk - uSizeOut = uSizeIn; - break; - case FOURCC_SHDR: - case FOURCC_SHEX: - // Only keep the shader version - uSizeOut = uSizeIn < 4u ? uSizeIn : 4u; - break; - default: - // Discard the chunk - uSizeOut = 0; - break; - } - - return uSizeOut + DXBC_BASE_ALIGNMENT - 1 - (uSizeOut - 1) % DXBC_BASE_ALIGNMENT; -} - -template <typename I> -size_t DXBCGetCombinedSize(I& kDXBCInput, const GLSLShader* pShader) -{ - uint32_t uNumChunksIn; - if (!kDXBCInput.SeekAbs(DXBC_HEADER_SIZE) || - !DXBCReadUint32(kDXBCInput, uNumChunksIn)) - return 0; - - uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - if (!DXBCReadUint32(kDXBCInput, auChunkOffsetsIn[uChunk])) - return 0; - } - - uint32_t uNumChunksOut(0); - uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); - for (uint32_t uChunk = 0; uChunk < uNumChunksIn && uNumChunksOut < DXBC_MAX_NUM_CHUNKS_OUT; ++uChunk) - { - uint32_t uChunkCode, uChunkSizeIn; - if (!kDXBCInput.SeekAbs(auChunkOffsetsIn[uChunk]) || - !DXBCReadUint32(kDXBCInput, uChunkCode) || - !DXBCReadUint32(kDXBCInput, uChunkSizeIn)) - return 0; - - uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); - if (uChunkSizeOut > 0) - { - uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; - } - } - - uint32_t uGLSLSourceSize, uGLSLChunkSize; - DXBCSizeGLSLChunk(uGLSLChunkSize, uGLSLSourceSize, pShader); - uOutSize += uGLSLChunkSize; - - return uOutSize; -} - -template <typename I, typename O> -bool DXBCCombineWithGLSL(I& kInput, O& kOutput, const GLSLShader* pShader) -{ - uint32_t uNumChunksIn; - if (!DXBCCopy(kOutput, kInput, DXBC_HEADER_SIZE) || - !DXBCReadUint32(kInput, uNumChunksIn) || - uNumChunksIn > DXBC_MAX_NUM_CHUNKS_IN) - return false; - - uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - if (!DXBCReadUint32(kInput, auChunkOffsetsIn[uChunk])) - return false; - } - - uint32_t auZeroChunkIndex[DXBC_OUT_CHUNKS_INDEX_SIZE] = {0}; - if (!kOutput.Write(auZeroChunkIndex, DXBC_OUT_CHUNKS_INDEX_SIZE)) - return false; - - // Copy required input chunks just after the chunk index - uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); - uint32_t uNumChunksOut(0); - uint32_t auChunkOffsetsOut[DXBC_MAX_NUM_CHUNKS_OUT]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - uint32_t uChunkCode, uChunkSizeIn; - if (!kInput.SeekAbs(auChunkOffsetsIn[uChunk]) || - !DXBCReadUint32(kInput, uChunkCode) || - !DXBCReadUint32(kInput, uChunkSizeIn)) - return false; - - // Filter only input chunks of the specified types - uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); - if (uChunkSizeOut > 0) - { - if (uNumChunksOut >= DXBC_MAX_NUM_CHUNKS_OUT) - return false; - - if (!DXBCWriteUint32(kOutput, uChunkCode) || - !DXBCWriteUint32(kOutput, uChunkSizeOut) || - !DXBCCopy(kOutput, kInput, uChunkSizeOut)) - return false; - - auChunkOffsetsOut[uNumChunksOut] = uOutSize; - ++uNumChunksOut; - uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; - } - } - - // Write GLSL chunk - uint32_t uGLSLChunkOffset(uOutSize); - uint32_t uGLSLChunkSize, uGLSLSourceSize; - DXBCSizeGLSLChunk(uGLSLChunkSize, uGLSLSourceSize, pShader); - if (!DXBCWriteUint32(kOutput, (uint32_t)FOURCC_GLSL) || - !DXBCWriteUint32(kOutput, uGLSLChunkSize) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumSamplers) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImages) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumStorageBuffers) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumUniformBuffers) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImports) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumExports) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32InputHash) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32SymbolsOffset)) - return false; - for (uint32_t uSampler = 0; uSampler < pShader->reflection.ui32NumSamplers; ++uSampler) - { - uint32_t uSamplerField = - (pShader->reflection.asSamplers[uSampler].sMask.ui10TextureBindPoint << 22) | - (pShader->reflection.asSamplers[uSampler].sMask.ui10SamplerBindPoint << 12) | - (pShader->reflection.asSamplers[uSampler].sMask.ui10TextureUnit << 2) | - (pShader->reflection.asSamplers[uSampler].sMask.bNormalSample << 1) | - (pShader->reflection.asSamplers[uSampler].sMask.bCompareSample << 0); - if (!DXBCWriteUint32(kOutput, uSamplerField)) - return false; - - uint32_t uEmbeddedNormalName = - (pShader->reflection.asSamplers[uSampler].sNormalName.ui20Offset << 12) | - (pShader->reflection.asSamplers[uSampler].sNormalName.ui12Size << 0); - if (!DXBCWriteUint32(kOutput, uEmbeddedNormalName)) - return false; - - uint32_t uEmbeddedCompareName = - (pShader->reflection.asSamplers[uSampler].sCompareName.ui20Offset << 12) | - (pShader->reflection.asSamplers[uSampler].sCompareName.ui12Size << 0); - if (!DXBCWriteUint32(kOutput, uEmbeddedCompareName)) - return false; - } - for (uint32_t uImage = 0; uImage < pShader->reflection.ui32NumImages; ++uImage) - { - const Resource* psResource = pShader->reflection.asImages + uImage; - uint32_t uEmbeddedName = - (psResource->sName.ui20Offset << 12) | - (psResource->sName.ui12Size << 0); - if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || - !DXBCWriteUint32(kOutput, uEmbeddedName)) - return false; - } - for (uint32_t uStorageBuffer = 0; uStorageBuffer < pShader->reflection.ui32NumStorageBuffers; ++uStorageBuffer) - { - const Resource* psResource = pShader->reflection.asStorageBuffers + uStorageBuffer; - uint32_t uEmbeddedName = - (psResource->sName.ui20Offset << 12) | - (psResource->sName.ui12Size << 0); - if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || - !DXBCWriteUint32(kOutput, uEmbeddedName)) - return false; - } - for (uint32_t uUniformBuffer = 0; uUniformBuffer < pShader->reflection.ui32NumUniformBuffers; ++uUniformBuffer) - { - const Resource* psResource = pShader->reflection.asUniformBuffers + uUniformBuffer; - uint32_t uEmbeddedName = - (psResource->sName.ui20Offset << 12) | - (psResource->sName.ui12Size << 0); - if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || - !DXBCWriteUint32(kOutput, uEmbeddedName)) - return false; - } - for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumImports; ++uSymbol) - { - if (!DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].eType) || - !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32ID) || - !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32Value)) - return false; - } - for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumExports; ++uSymbol) - { - if (!DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].eType) || - !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32ID) || - !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32Value)) - return false; - } - if (!kOutput.Write(pShader->sourceCode, uGLSLSourceSize)) - return false; - uOutSize += uGLSLChunkSize; - - // Write total size and chunk index - if (!kOutput.SeekAbs(DXBC_SIZE_POSITION) || - !DXBCWriteUint32(kOutput, uOutSize) || - !kOutput.SeekAbs(DXBC_HEADER_SIZE) || - !DXBCWriteUint32(kOutput, uNumChunksOut + 1)) - return false; - for (uint32_t uChunk = 0; uChunk < uNumChunksOut; ++uChunk) - { - if (!DXBCWriteUint32(kOutput, auChunkOffsetsOut[uChunk])) - return false; - } - DXBCWriteUint32(kOutput, uGLSLChunkOffset); - - return true; -} diff --git a/Code/Tools/HLSLCrossCompiler/include/pstdint.h b/Code/Tools/HLSLCrossCompiler/include/pstdint.h deleted file mode 100644 index 6998242aa1..0000000000 --- a/Code/Tools/HLSLCrossCompiler/include/pstdint.h +++ /dev/null @@ -1,801 +0,0 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2011 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - **************************************************************************** - * - * Version 0.1.12 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * John Dill - * - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#include <stddef.h> -#include <limits.h> -#include <signal.h> - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED) -#include <stdint.h> -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include <wchar.h> -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what did Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - -#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) - -/* - * Please compile with the maximum warning settings to make sure macros are not - * defined more than once. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#define glue3_aux(x,y,z) x ## y ## z -#define glue3(x,y,z) glue3_aux(x,y,z) - -#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); -#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); - -#define DECL(us,bits) glue3(DECL,us,) (bits) - -#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) - -int main () { - DECL(I,8) - DECL(U,8) - DECL(I,16) - DECL(U,16) - DECL(I,32) - DECL(U,32) -#ifdef INT64_MAX - DECL(I,64) - DECL(U,64) -#endif - intmax_t imax = INTMAX_C(0); - uintmax_t umax = UINTMAX_C(0); - char str0[256], str1[256]; - - sprintf (str0, "%d %x\n", 0, ~0); - - sprintf (str1, "%d %x\n", i8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); - sprintf (str1, "%u %x\n", u8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); - sprintf (str1, "%d %x\n", i16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); - sprintf (str1, "%u %x\n", u16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); -#ifdef INT64_MAX - sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); -#endif - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); - - TESTUMAX(8); - TESTUMAX(16); - TESTUMAX(32); -#ifdef INT64_MAX - TESTUMAX(64); -#endif - - return EXIT_SUCCESS; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/jni/Android.mk b/Code/Tools/HLSLCrossCompiler/jni/Android.mk deleted file mode 100644 index 66e2bb4ecf..0000000000 --- a/Code/Tools/HLSLCrossCompiler/jni/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Android Makefile conversion -# -# Leander Beernaert -# -# How to build: $ANDROID_NDK/ndk-build -# -VERSION=1.17 - -LOCAL_PATH := $(call my-dir)/../ - -include $(CLEAR_VARS) - -LOCAL_ARM_MODE := arm -LOCAL_ARM_NEON := true - -LOCAL_MODULE := HLSLcc - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - $(LOCAL_PATH)/src \ - $(LOCAL_PATH)/src/cbstring -LOCAL_CFLAGS += -Wall -W -# For dynamic library -#LOCAL_CFLAGS += -DHLSLCC_DYNLIB -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/src/*.c) \ - $(wildcard $(LOCAL_PATH)/src/cbstring/*.c) \ - $(wildcard $(LOCAL_PATH)/src/internal_includes/*.c) -#LOCAL_LDLIBS += -lGLESv3 - -include $(BUILD_STATIC_LIBRARY) - diff --git a/Code/Tools/HLSLCrossCompiler/jni/Application.mk b/Code/Tools/HLSLCrossCompiler/jni/Application.mk deleted file mode 100644 index a8ae0839b1..0000000000 --- a/Code/Tools/HLSLCrossCompiler/jni/Application.mk +++ /dev/null @@ -1,3 +0,0 @@ -APP_PLATFORM := android-18 -APP_ABI := armeabi-v7a -APP_OPTIM := release diff --git a/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a deleted file mode 100644 index 6bab978a58..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35c73c9602dbd539ddd4874c4231fe21d40e0db813394f89e1c837a59d4be755 -size 1092754 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a deleted file mode 100644 index 4e5a152c7c..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51ed960398777ebee83d838e344e4a1dd331acb4ae0e77cbf8a64f2c1146b2ce -size 184304 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a deleted file mode 100644 index cb80d6e7ee..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26083d66db7a82295514575af1160ab7aec52aa32f8431edbd1a09011154901b -size 190552 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a deleted file mode 100644 index c9ef9a0047..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3b322870fdff43b12034b4d9bcf72b59a5ef2f0cdd1f3042369c9f1a6911931b -size 374904 diff --git a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a deleted file mode 100644 index 2adc6a7397..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4ea9be963e0674546c2e8af2fd9a34e95100d9a1806399457b1e06d033149456 -size 375378 diff --git a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a deleted file mode 100644 index b1318b6000..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:544de0a5688c776e28b42bb189a738bc87743828b737d4bf653e46cd2e05938b -size 1171448 diff --git a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a deleted file mode 100644 index 85bf31eed4..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af9216c54d23dd3754f7ae18d56b97ae256eb29a0046d8e0d2a0716054d8c230 -size 218888 diff --git a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a deleted file mode 100644 index 00095a3615..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a07bec349614cdd3e40c3577bddace1203148016f9276c7ef807bdbc37dcabf -size 671232 diff --git a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a deleted file mode 100644 index c7b92fcc1e..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88acec4cedad5699900ec2d1a3ce83ab5e9365ebea4b4af0ababba562382f399 -size 296852 diff --git a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a deleted file mode 100644 index 29dd7fbf7a..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c0625b7f534df5817646dd1335f9d7916389f27a83b7d118fadab504064d910 -size 1144250 diff --git a/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib b/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib deleted file mode 100644 index 8ed661eb15..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4d49f4f011fe2835d5aafa7ac77fb660cf12078763ddef25e935da919bc65e6b -size 440242 diff --git a/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib b/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib deleted file mode 100644 index 452aa95688..0000000000 --- a/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a4a291f8b3d00e1865a98ad3c740d28ff10d43ca87b718403cfc920df2be9ab -size 618776 diff --git a/Code/Tools/HLSLCrossCompiler/license.txt b/Code/Tools/HLSLCrossCompiler/license.txt deleted file mode 100644 index 29f302da75..0000000000 --- a/Code/Tools/HLSLCrossCompiler/license.txt +++ /dev/null @@ -1,53 +0,0 @@ -Copyright (c) 2012 James Jones -Further improvements Copyright (c) 2014-2016 Unity Technologies -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -This software makes use of the bstring library which is provided under the following license: - -Copyright (c) 2002-2008 Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of bstrlib nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/README b/Code/Tools/HLSLCrossCompiler/offline/cjson/README deleted file mode 100644 index 7531c049a6..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/cjson/README +++ /dev/null @@ -1,247 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -Welcome to cJSON. - -cJSON aims to be the dumbest possible parser that you can get your job done with. -It's a single file of C, and a single header file. - -JSON is described best here: http://www.json.org/ -It's like XML, but fat-free. You use it to move data around, store things, or just -generally represent your program's state. - - -First up, how do I build? -Add cJSON.c to your project, and put cJSON.h somewhere in the header search path. -For example, to build the test app: - -gcc cJSON.c test.c -o test -lm -./test - - -As a library, cJSON exists to take away as much legwork as it can, but not get in your way. -As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it -in one of two modes: Auto and Manual. Let's have a quick run-through. - - -I lifted some JSON from this page: http://www.json.org/fatfree.html -That page inspired me to write cJSON, which is a parser that tries to share the same -philosophy as JSON itself. Simple, dumb, out of the way. - -Some JSON: -{ - "name": "Jack (\"Bee\") Nimble", - "format": { - "type": "rect", - "width": 1920, - "height": 1080, - "interlace": false, - "frame rate": 24 - } -} - -Assume that you got this from a file, a webserver, or magic JSON elves, whatever, -you have a char * to it. Everything is a cJSON struct. -Get it parsed: - cJSON *root = cJSON_Parse(my_json_string); - -This is an object. We're in C. We don't have objects. But we do have structs. -What's the framerate? - - cJSON *format = cJSON_GetObjectItem(root,"format"); - int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; - - -Want to change the framerate? - cJSON_GetObjectItem(format,"frame rate")->valueint=25; - -Back to disk? - char *rendered=cJSON_Print(root); - -Finished? Delete the root (this takes care of everything else). - cJSON_Delete(root); - -That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers -before you dereference them. If you want to see how you'd build this struct in code? - cJSON *root,*fmt; - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); - cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); - cJSON_AddStringToObject(fmt,"type", "rect"); - cJSON_AddNumberToObject(fmt,"width", 1920); - cJSON_AddNumberToObject(fmt,"height", 1080); - cJSON_AddFalseToObject (fmt,"interlace"); - cJSON_AddNumberToObject(fmt,"frame rate", 24); - -Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup. -Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and -a few from elsewhere. - -What about manual mode? First up you need some detail. -Let's cover how the cJSON objects represent the JSON data. -cJSON doesn't distinguish arrays from objects in handling; just type. -Each cJSON has, potentially, a child, siblings, value, a name. - -The root object has: Object Type and a Child -The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: -Sibling has type Object, name "format", and a child. -That child has type String, name "type", value "rect", and a sibling: -Sibling has type Number, name "width", value 1920, and a sibling: -Sibling has type Number, name "height", value 1080, and a sibling: -Sibling hs type False, name "interlace", and a sibling: -Sibling has type Number, name "frame rate", value 24 - -Here's the structure: -typedef struct cJSON { - struct cJSON *next,*prev; - struct cJSON *child; - - int type; - - char *valuestring; - int valueint; - double valuedouble; - - char *string; -} cJSON; - -By default all values are 0 unless set by virtue of being meaningful. - -next/prev is a doubly linked list of siblings. next takes you to your sibling, -prev takes you back from your sibling to you. -Only objects and arrays have a "child", and it's the head of the doubly linked list. -A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0. -The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in -cJSON.h - -A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read -valuedouble. - -Any entry which is in the linked list which is the child of an object will have a "string" -which is the "name" of the entry. When I said "name" in the above example, that's "string". -"string" is the JSON name for the 'variable name' if you will. - -Now you can trivially walk the lists, recursively, and parse as you please. -You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take -the root object, and traverse the structure (which is, formally, an N-tree), -and tokenise as you please. If you wanted to build a callback style parser, this is how -you'd do it (just an example, since these things are very specific): - -void parse_and_callback(cJSON *item,const char *prefix) -{ - while (item) - { - char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); - sprintf(newprefix,"%s/%s",prefix,item->name); - int dorecurse=callback(newprefix, item->type, item); - if (item->child && dorecurse) parse_and_callback(item->child,newprefix); - item=item->next; - free(newprefix); - } -} - -The prefix process will build you a separated list, to simplify your callback handling. -The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or -let you invoke it per-item. For the item above, your callback might look like this: - -int callback(const char *name,int type,cJSON *item) -{ - if (!strcmp(name,"name")) { /* populate name */ } - else if (!strcmp(name,"format/type") { /* handle "rect" */ } - else if (!strcmp(name,"format/width") { /* 800 */ } - else if (!strcmp(name,"format/height") { /* 600 */ } - else if (!strcmp(name,"format/interlace") { /* false */ } - else if (!strcmp(name,"format/frame rate") { /* 24 */ } - return 1; -} - -Alternatively, you might like to parse iteratively. -You'd use: - -void parse_object(cJSON *item) -{ - int i; for (i=0;i<cJSON_GetArraySize(item);i++) - { - cJSON *subitem=cJSON_GetArrayItem(item,i); - // handle subitem. - } -} - -Or, for PROPER manual mode: - -void parse_object(cJSON *item) -{ - cJSON *subitem=item->child; - while (subitem) - { - // handle subitem - if (subitem->child) parse_object(subitem->child); - - subitem=subitem->next; - } -} - -Of course, this should look familiar, since this is just a stripped-down version -of the callback-parser. - -This should cover most uses you'll find for parsing. The rest should be possible -to infer.. and if in doubt, read the source! There's not a lot of it! ;) - - -In terms of constructing JSON data, the example code above is the right way to do it. -You can, of course, hand your sub-objects to other functions to populate. -Also, if you find a use for it, you can manually build the objects. -For instance, suppose you wanted to build an array of objects? - -cJSON *objects[24]; - -cJSON *Create_array_of_anything(cJSON **items,int num) -{ - int i;cJSON *prev, *root=cJSON_CreateArray(); - for (i=0;i<24;i++) - { - if (!i) root->child=objects[i]; - else prev->next=objects[i], objects[i]->prev=prev; - prev=objects[i]; - } - return root; -} - -and simply: Create_array_of_anything(objects,24); - -cJSON doesn't make any assumptions about what order you create things in. -You can attach the objects, as above, and later add children to each -of those objects. - -As soon as you call cJSON_Print, it renders the structure to text. - - - -The test.c code shows how to handle a bunch of typical cases. If you uncomment -the code, it'll load, parse and print a bunch of test files, also from json.org, -which are more complex than I'd care to try and stash into a const char array[]. - - -Enjoy cJSON! - - -- Dave Gamble, Aug 2009 diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c deleted file mode 100644 index 78b1634fbf..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -// Modifications copyright Amazon.com, Inc. or its affiliates. - -/* cJSON */ -/* JSON parser in C. */ - -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <float.h> -#include <limits.h> -#include <ctype.h> -#include "cJSON.h" -#include <AzCore/PlatformDef.h> - -static const char *ep; - -const char *cJSON_GetErrorPtr(void) {return ep;} - -static int cJSON_strcasecmp(const char *s1,const char *s2) -{ - if (!s1) return (s1==s2)?0:1;if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free are not static -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void (*cJSON_free)(void *ptr) = free; -AZ_POP_DISABLE_WARNING - -static char* cJSON_strdup(const char* str) -{ - size_t len = strlen(str) + 1; - char* copy = (char*)cJSON_malloc(len); - - if (!copy) return 0; - memcpy(copy,str,len); - return copy; -} - -void cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(void) -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; -} - -/* Delete a cJSON structure. */ -void cJSON_Delete(cJSON *c) -{ - cJSON *next; - while (c) - { - next=c->next; - if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); - if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); - if (c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) -{ - double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; - - /* Could use sscanf for this? */ - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ - if (*num=='e' || *num=='E') /* Exponent? */ - { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ - while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ - } - - n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ - - item->valuedouble=n; - item->valueint=(int)n; - item->type=cJSON_Number; - return num; -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item) -{ - char *str; - double d=item->valuedouble; - if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ - if (str) sprintf(str,"%d",item->valueint); - } - else - { - str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ - if (str) - { - if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); - else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); - else sprintf(str,"%f",d); - } - } - return str; -} - -/* Parse the input text into an unescaped cstring, and populate item. */ -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static const char *parse_string(cJSON *item,const char *str) -{ - const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; - if (*str!='\"') {ep=str;return 0;} /* not a string! */ - - while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ - - out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ - if (!out) return 0; - - ptr=str+1;ptr2=out; - while (*ptr!='\"' && *ptr) - { - if (*ptr!='\\') *ptr2++=*ptr++; - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++='\b'; break; - case 'f': *ptr2++='\f'; break; - case 'n': *ptr2++='\n'; break; - case 'r': *ptr2++='\r'; break; - case 't': *ptr2++='\t'; break; - case 'u': /* transcode utf16 to utf8. */ - sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */ - - if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ - - if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ - { - if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ - sscanf(ptr+3,"%4x",&uc2);ptr+=6; - if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ - uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); - } - - len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; - - switch (len) { - case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 1: *--ptr2 =(uc | firstByteMark[len]); - } - ptr2+=len; - break; - default: *ptr2++=*ptr; break; - } - ptr++; - } - } - *ptr2=0; - if (*ptr=='\"') ptr++; - item->valuestring=out; - item->type=cJSON_String; - return ptr; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str) -{ - const char *ptr;char *ptr2,*out;int len=0;unsigned char token; - - if (!str) return cJSON_strdup(""); - ptr=str; - token = *ptr; - while (token && ++len) - { - if (strchr("\"\\\b\f\n\r\t",token)) len++; - else if (token<32) len+=5; - ptr++; - token = *ptr; - } - - out=(char*)cJSON_malloc(len+3); - if (!out) return 0; - - ptr2=out;ptr=str; - *ptr2++='\"'; - while (*ptr) - { - if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (token=*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ - } - } - } - *ptr2++='\"';*ptr2++=0; - return out; -} -/* Invote print_string_ptr (which is useful) on an item. */ -static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} - -/* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item,const char *value); -static char *print_value(cJSON *item,int depth,int fmt); -static const char *parse_array(cJSON *item,const char *value); -static char *print_array(cJSON *item,int depth,int fmt); -static const char *parse_object(cJSON *item,const char *value); -static char *print_object(cJSON *item,int depth,int fmt); - -/* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} - -/* Parse an object - create a new root, and populate. */ -cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) -{ - const char *end=0; - cJSON *c=cJSON_New_Item(); - ep=0; - if (!c) return 0; /* memory fail */ - - end=parse_value(c,skip(value)); - if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} - if (return_parse_end) *return_parse_end=end; - return c; -} -/* Default options for cJSON_Parse */ -cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} - -/* Render a cJSON item/entity/structure to text. */ -char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} -char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} - -/* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item,const char *value) -{ - if (!value) return 0; /* Fail on null. */ - if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } - if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } - if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } - if (*value=='\"') { return parse_string(item,value); } - if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } - if (*value=='[') { return parse_array(item,value); } - if (*value=='{') { return parse_object(item,value); } - - ep=value;return 0; /* failure. */ -} - -/* Render a value to text. */ -static char *print_value(cJSON *item,int depth,int fmt) -{ - char *out=0; - if (!item) return 0; - switch ((item->type)&255) - { - case cJSON_NULL: out=cJSON_strdup("null"); break; - case cJSON_False: out=cJSON_strdup("false");break; - case cJSON_True: out=cJSON_strdup("true"); break; - case cJSON_Number: out=print_number(item);break; - case cJSON_String: out=print_string(item);break; - case cJSON_Array: out=print_array(item,depth,fmt);break; - case cJSON_Object: out=print_object(item,depth,fmt);break; - } - return out; -} - -/* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='[') {ep=value;return 0;} /* not an array! */ - - item->type=cJSON_Array; - value=skip(value+1); - if (*value==']') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; /* memory fail */ - value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item = cJSON_New_Item(); - if (!new_item) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_value(child,skip(value+1))); - if (!value) return 0; /* memory fail */ - } - - if (*value==']') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an array to text */ -static char *print_array(cJSON *item,int depth,int fmt) -{ - char **entries; - char *out=0,*ptr,*ret;int len=5; - cJSON *child=item->child; - int numentries=0,i=0,fail=0; - - /* How many entries in the array? */ - while (child) numentries++,child=child->next; - /* Explicitly handle numentries==0 */ - if (!numentries) - { - out=(char*)cJSON_malloc(3); - if (out) strcpy(out,"[]"); - return out; - } - /* Allocate an array to hold the values for each */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - memset(entries,0,numentries*sizeof(char*)); - /* Retrieve all the results: */ - child=item->child; - while (child && !fail) - { - ret=print_value(child,depth+1,fmt); - entries[i++]=ret; - if (ret) len+=(int)strlen(ret)+2+(fmt?1:0); else fail=1; - child=child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - /* If that fails, we fail. */ - if (!out) fail=1; - - /* Handle failure. */ - if (fail) - { - for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); - cJSON_free(entries); - return 0; - } - - /* Compose the output array. */ - *out='['; - ptr=out+1;*ptr=0; - for (i=0;i<numentries;i++) - { - strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); - if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} - cJSON_free(entries[i]); - } - cJSON_free(entries); - *ptr++=']';*ptr++=0; - return out; -} - -/* Build an object from the text. */ -static const char *parse_object(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='{') {ep=value;return 0;} /* not an object! */ - - item->type=cJSON_Object; - value=skip(value+1); - if (*value=='}') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; - value=skip(parse_string(child,skip(value))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON* new_item = cJSON_New_Item(); - if (!new_item) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_string(child,skip(value+1))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - } - - if (*value=='}') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an object to text. */ -static char *print_object(cJSON *item,int depth,int fmt) -{ - char **entries=0,**names=0; - char *out=0,*ptr,*ret,*str;int len=7,i=0,j; - cJSON *child=item->child; - int numentries=0,fail=0; - /* Count the number of entries. */ - while (child) numentries++,child=child->next; - /* Explicitly handle empty object case */ - if (!numentries) - { - out=(char*)cJSON_malloc(fmt?depth+3:3); - if (!out) return 0; - ptr=out;*ptr++='{'; - if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} - *ptr++='}';*ptr++=0; - return out; - } - /* Allocate space for the names and the objects */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - names=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!names) {cJSON_free(entries);return 0;} - memset(entries,0,sizeof(char*)*numentries); - memset(names,0,sizeof(char*)*numentries); - - /* Collect all the results into our arrays: */ - child=item->child;depth++;if (fmt) len+=depth; - while (child) - { - names[i]=str=print_string_ptr(child->string); - entries[i++]=ret=print_value(child,depth,fmt); - if (str && ret) len+=(int)(strlen(ret)+strlen(str))+2+(fmt?2+depth:0); else fail=1; - child=child->next; - } - - /* Try to allocate the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - if (!out) fail=1; - - /* Handle failure */ - if (fail) - { - for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} - cJSON_free(names);cJSON_free(entries); - return 0; - } - - /* Compose the output: */ - *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; - for (i=0;i<numentries;i++) - { - if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; - strcpy(ptr,names[i]);ptr+=strlen(names[i]); - *ptr++=':';if (fmt) *ptr++='\t'; - strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); - if (i!=numentries-1) *ptr++=','; - if (fmt) *ptr++='\n';*ptr=0; - cJSON_free(names[i]);cJSON_free(entries[i]); - } - - cJSON_free(names);cJSON_free(entries); - if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; - *ptr++='}';*ptr++=0; - return out; -} - -/* Get Array size/item / object item. */ -int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} -cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} -cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} -/* Utility for handling references. */ -static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} - -/* Add item to array/object. */ -void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} -void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} -void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} -void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} - -cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; - if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} -void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} -cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} -void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} - -/* Replace array/object items with new ones. */ -void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; - newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; - if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} -void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} - -/* Create basic types: */ -cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} -cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} -cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} -cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} -cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} -cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} -cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} -cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} - -/* Create Arrays: */ -cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} - -/* Duplication */ -cJSON *cJSON_Duplicate(cJSON *item,int recurse) -{ - cJSON *newitem,*cptr,*nptr=0,*newchild; - /* Bail on bad ptr */ - if (!item) return 0; - /* Create new item */ - newitem=cJSON_New_Item(); - if (!newitem) return 0; - /* Copy over all vars */ - newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; - if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} - if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} - /* If non-recursive, then we're done! */ - if (!recurse) return newitem; - /* Walk the ->next chain for the child. */ - cptr=item->child; - while (cptr) - { - newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) {cJSON_Delete(newitem);return 0;} - if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ - cptr=cptr->next; - } - return newitem; -} diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h deleted file mode 100644 index 50ae02b6f9..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* cJSON Types: */ -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -#define cJSON_IsReference 256 - -/* The cJSON structure: */ -typedef struct cJSON { - struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - - int type; /* The type of the item, as above. */ - - char *valuestring; /* The item's string, if type==cJSON_String */ - int valueint; /* The item's number, if type==cJSON_Number */ - double valuedouble; /* The item's number, if type==cJSON_Number */ - - char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ -} cJSON; - -typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -/* Supply malloc, realloc and free functions to cJSON */ -extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -extern cJSON *cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -extern char *cJSON_Print(cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -extern char *cJSON_PrintUnformatted(cJSON *item); -/* Delete a cJSON entity and all subentities. */ -extern void cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -extern int cJSON_GetArraySize(cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); -/* Get item "string" from object. Case insensitive. */ -extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); - -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -extern const char *cJSON_GetErrorPtr(void); - -/* These calls create a cJSON item of the appropriate type. */ -extern cJSON *cJSON_CreateNull(void); -extern cJSON *cJSON_CreateTrue(void); -extern cJSON *cJSON_CreateFalse(void); -extern cJSON *cJSON_CreateBool(int b); -extern cJSON *cJSON_CreateNumber(double num); -extern cJSON *cJSON_CreateString(const char *string); -extern cJSON *cJSON_CreateArray(void); -extern cJSON *cJSON_CreateObject(void); - -/* These utilities create an Array of count items. */ -extern cJSON *cJSON_CreateIntArray(int *numbers,int count); -extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); -extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); -extern cJSON *cJSON_CreateStringArray(const char **strings,int count); - -/* Append item to the specified array/object. */ -extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); -extern void cJSON_DeleteItemFromArray(cJSON *array,int which); -extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); -extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); - -/* Update array items. */ -extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); -extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ - -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); - -/* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp b/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp deleted file mode 100644 index 5a22aa553f..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp +++ /dev/null @@ -1,803 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include <inttypes.h> -#include "hlslcc.hpp" -#include "stdlib.h" -#include "stdio.h" -#include <string> -#include <string.h> -#include "hash.h" -#include "serializeReflection.h" -#include "hlslcc_bin.hpp" - -#include <algorithm> -#include <cctype> - -#ifdef _WIN32 -#include <direct.h> -#else -#include <sys/stat.h> -#endif - -#include "timer.h" - -#if defined(_WIN32) && !defined(PORTABLE) -//#define VALIDATE_OUTPUT // NOTE: THIS IS OK DURING HLSLcc DEV BUT SHOULD NOT BE USED IN PRODUCTION. SOME EXT USED ARE NO SUPPORTED ON WINDOWS. -#endif - -#if defined(VALIDATE_OUTPUT) -#if defined(_WIN32) -#include <windows.h> -#include <gl/GL.h> - - #pragma comment(lib, "opengl32.lib") - -typedef char GLcharARB; /* native character */ -typedef unsigned int GLhandleARB; /* shader object handle */ -#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 -#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 -#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 -typedef void (WINAPI * PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj); -typedef GLhandleARB (WINAPI * PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType); -typedef void (WINAPI * PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB** string, const GLint* length); -typedef void (WINAPI * PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj); -typedef void (WINAPI * PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog); -typedef void (WINAPI * PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint* params); -typedef GLhandleARB (WINAPI * PFNGLCREATEPROGRAMOBJECTARBPROC)(void); -typedef void (WINAPI * PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj); -typedef void (WINAPI * PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj); -typedef void (WINAPI * PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj); -typedef void (WINAPI * PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLcharARB* infoLog); - -static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; -static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; -static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; -static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; -static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; -static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; -static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; -static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; -static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; - -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 - -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 - -typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int* attribList); -static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; - -void InitOpenGL() -{ - HGLRC rc; - - // setup minimal required GL - HWND wnd = CreateWindowA( - "STATIC", - "GL", - WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - 0, 0, 16, 16, - NULL, NULL, - GetModuleHandle(NULL), NULL); - HDC dc = GetDC(wnd); - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, - PFD_TYPE_RGBA, 32, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 16, 0, - 0, PFD_MAIN_PLANE, 0, 0, 0, 0 - }; - - int fmt = ChoosePixelFormat(dc, &pfd); - SetPixelFormat(dc, fmt, &pfd); - - rc = wglCreateContext(dc); - wglMakeCurrent(dc, rc); - - wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); - - if (wglCreateContextAttribsARB) - { - const int OpenGLContextAttribs [] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 3, - WGL_CONTEXT_MINOR_VERSION_ARB, 3, - #if defined(_DEBUG) - //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, - #else - //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, - #endif - //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - 0, 0 - }; - - const HGLRC OpenGLContext = wglCreateContextAttribsARB(dc, 0, OpenGLContextAttribs); - - wglMakeCurrent(dc, OpenGLContext); - - wglDeleteContext(rc); - - rc = OpenGLContext; - } - - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB"); - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB"); - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB"); - glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog"); -} -#endif - -void PrintSingleLineError(FILE* pFile, const char* error) -{ - while (*error != '\0') - { - const char* pLineEnd = strchr(error, '\n'); - if (pLineEnd == 0) - { - pLineEnd = error + strlen(error) - 1; - } - fwrite(error, 1, pLineEnd - error, pFile); - fwrite("\r", 1, 1, pFile); - error = pLineEnd + 1; - } -} - -int TryCompileShader(GLenum eShaderType, const char* inFilename, const char* shader, double* pCompileTime, int useStdErr) -{ - GLint iCompileStatus; - GLuint hShader; - Timer_t timer; - - InitTimer(&timer); - - InitOpenGL(); - - hShader = glCreateShaderObjectARB(eShaderType); - glShaderSourceARB(hShader, 1, (const char**)&shader, NULL); - - ResetTimer(&timer); - glCompileShaderARB(hShader); - *pCompileTime = ReadTimer(&timer); - - /* Check it compiled OK */ - glGetObjectParameterivARB (hShader, GL_OBJECT_COMPILE_STATUS_ARB, &iCompileStatus); - - if (iCompileStatus != GL_TRUE) - { - FILE* errorFile = NULL; - GLint iInfoLogLength = 0; - char* pszInfoLog; - - glGetObjectParameterivARB (hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iInfoLogLength); - - pszInfoLog = new char[iInfoLogLength]; - - printf("Error: Failed to compile GLSL shader\n"); - - glGetInfoLogARB (hShader, iInfoLogLength, NULL, pszInfoLog); - - printf(pszInfoLog); - - if (!useStdErr) - { - std::string filename; - filename += inFilename; - filename += "_compileErrors.txt"; - - //Dump to file - fopen_s(&errorFile, filename.c_str(), "w"); - - fclose(errorFile); - } - else - { - // Present error to stderror with no "new lines" as required by remote shader compiler - fprintf(stderr, "%s(-) error: ", inFilename); - PrintSingleLineError(stderr, pszInfoLog); - fprintf(stderr, "\rshader: "); - PrintSingleLineError(stderr, shader); - } - - delete [] pszInfoLog; - - return 0; - } - - return 1; -} -#endif - -int fileExists(const char* path) -{ - FILE* shaderFile; - shaderFile = fopen(path, "rb"); - - if (shaderFile) - { - fclose(shaderFile); - return 1; - } - return 0; -} - -GLLang LanguageFromString(const char* str) -{ - if (strcmp(str, "es100") == 0) - { - return LANG_ES_100; - } - if (strcmp(str, "es300") == 0) - { - return LANG_ES_300; - } - if (strcmp(str, "es310") == 0) - { - return LANG_ES_310; - } - if (strcmp(str, "120") == 0) - { - return LANG_120; - } - if (strcmp(str, "130") == 0) - { - return LANG_130; - } - if (strcmp(str, "140") == 0) - { - return LANG_140; - } - if (strcmp(str, "150") == 0) - { - return LANG_150; - } - if (strcmp(str, "330") == 0) - { - return LANG_330; - } - if (strcmp(str, "400") == 0) - { - return LANG_400; - } - if (strcmp(str, "410") == 0) - { - return LANG_410; - } - if (strcmp(str, "420") == 0) - { - return LANG_420; - } - if (strcmp(str, "430") == 0) - { - return LANG_430; - } - if (strcmp(str, "440") == 0) - { - return LANG_440; - } - return LANG_DEFAULT; -} - -#define MAX_PATH_CHARS 256 -#define MAX_FXC_CMD_CHARS 1024 - -typedef struct -{ - GLLang language; - - int flags; - - const char* shaderFile; - char* outputShaderFile; - - char* reflectPath; - - char cacheKey[MAX_PATH_CHARS]; - - int bUseFxc; - std::string fxcCmdLine; -} Options; - -void InitOptions(Options* psOptions) -{ - psOptions->language = LANG_DEFAULT; - psOptions->flags = 0; - psOptions->reflectPath = NULL; - - psOptions->shaderFile = NULL; - - psOptions->bUseFxc = 0; -} - -void PrintHelp() -{ - printf("Command line options:\n"); - - printf("\t-lang=X \t GLSL language to use. e.g. es100 or 140 or metal.\n"); - printf("\t-flags=X \t The integer value of the HLSLCC_FLAGS to used.\n"); - printf("\t-reflect=X \t File to write reflection JSON to.\n"); - printf("\t-in=X \t Shader file to compile.\n"); - printf("\t-out=X \t File to write the compiled shader from -in to.\n"); - - printf("\t-hashout=[dir/]out-file-name \t Output file name is a hash of 'out-file-name', put in the directory 'dir'.\n"); - - printf("\t-fxc=\"CMD\" HLSL compiler command line. If specified the input shader will be first compiled through this command first and then the resulting bytecode translated.\n"); - - printf("\n"); -} - -int GetOptions(int argc, char** argv, Options* psOptions) -{ - int i; - int fullShaderChain = -1; - - InitOptions(psOptions); - - for (i = 1; i < argc; i++) - { - char* option; - - option = strstr(argv[i], "-help"); - if (option != NULL) - { - PrintHelp(); - return 0; - } - - option = strstr(argv[i], "-reflect="); - if (option != NULL) - { - psOptions->reflectPath = option + strlen("-reflect="); - } - - option = strstr(argv[i], "-lang="); - if (option != NULL) - { - psOptions->language = LanguageFromString((&option[strlen("-lang=")])); - } - - option = strstr(argv[i], "-flags="); - if (option != NULL) - { - psOptions->flags = atol(&option[strlen("-flags=")]); - } - - option = strstr(argv[i], "-in="); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->shaderFile = option + strlen("-in="); - if (!fileExists(psOptions->shaderFile)) - { - printf("Invalid path: %s\n", psOptions->shaderFile); - return 0; - } - } - - option = strstr(argv[i], "-out="); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->outputShaderFile = option + strlen("-out="); - } - - option = strstr(argv[i], "-hashout"); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->outputShaderFile = option + strlen("-hashout="); - - char* dir; - int64_t length; - - uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0); - - - dir = strrchr(psOptions->outputShaderFile, '\\'); - - if (!dir) - { - dir = strrchr(psOptions->outputShaderFile, '//'); - } - - if (!dir) - { - length = 0; - } - else - { - length = (int)(dir - psOptions->outputShaderFile) + 1; - } - - for (i = 0; i < length; ++i) - { - psOptions->cacheKey[i] = psOptions->outputShaderFile[i]; - } - - //sprintf(psOptions->cacheKey, "%x%x", high, low); - sprintf(&psOptions->cacheKey[i], "%010" PRIX64, hash); - - psOptions->outputShaderFile = psOptions->cacheKey; - } - - option = strstr(argv[i], "-fxc="); - if (option != NULL) - { - char* cmdLine = option + strlen("-fxc="); - size_t cmdLineLen = strlen(cmdLine); - if (cmdLineLen == 0 || cmdLineLen + 1 >= MAX_FXC_CMD_CHARS) - { - return 0; - } - psOptions->fxcCmdLine = std::string(cmdLine, cmdLineLen); - psOptions->bUseFxc = 1; - } - } - - return 1; -} - -void* malloc_hook(size_t size) -{ - return malloc(size); -} -void* calloc_hook(size_t num, size_t size) -{ - return calloc(num, size); -} -void* realloc_hook(void* p, size_t size) -{ - return realloc(p, size); -} -void free_hook(void* p) -{ - free(p); -} - -int Run(const char* srcPath, const char* destPath, GLLang language, int flags, const char* reflectPath, GLSLShader* shader, int useStdErr) -{ - FILE* outputFile; - GLSLShader tempShader; - GLSLShader* result = shader ? shader : &tempShader; - Timer_t timer; - int compiledOK = 0; - double crossCompileTime = 0; - - HLSLcc_SetMemoryFunctions(malloc_hook, calloc_hook, free_hook, realloc_hook); - - InitTimer(&timer); - - ResetTimer(&timer); - GlExtensions ext; - ext.ARB_explicit_attrib_location = 0; - ext.ARB_explicit_uniform_location = 0; - ext.ARB_shading_language_420pack = 0; - compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext, result); - - crossCompileTime = ReadTimer(&timer); - - if (compiledOK) - { - printf("cc time: %.2f us\n", crossCompileTime); - - if (destPath) - { - //Dump to file - outputFile = fopen(destPath, "w"); - fprintf(outputFile, result->sourceCode); - fclose(outputFile); - } - - if (reflectPath) - { - const char* jsonString = SerializeReflection(&result->reflection); - outputFile = fopen(reflectPath, "w"); - fprintf(outputFile, jsonString); - fclose(outputFile); - } - -#if defined(VALIDATE_OUTPUT) - std::string shaderSource; - if (flags & HLSLCC_FLAG_NO_VERSION_STRING) - { - // Need to add the version string so that the shader will compile - shaderSource = GetVersionString(language); - shaderSource += result->sourceCode; - } - else - { - shaderSource = result->sourceCode; - } - compiledOK = TryCompileShader(result->shaderType, destPath ? destPath : "", shaderSource.c_str(), &glslCompileTime, useStdErr); - - if (compiledOK) - { - printf("glsl time: %.2f us\n", glslCompileTime); - } -#endif - - if (!shader) - { - FreeGLSLShader(result); - } - } - else if (useStdErr) - { - fprintf(stderr, "TranslateHLSLFromFile failed"); - } - - return compiledOK; -} - -struct SDXBCFile -{ - FILE* m_pFile; - - bool Read(void* pElements, size_t uSize) - { - return fread(pElements, 1, uSize, m_pFile) == uSize; - } - - bool Write(const void* pElements, size_t uSize) - { - return fwrite(pElements, 1, uSize, m_pFile) == uSize; - } - - bool SeekRel(int32_t iOffset) - { - return fseek(m_pFile, iOffset, SEEK_CUR) == 0; - } - - bool SeekAbs(uint32_t uPosition) - { - return fseek(m_pFile, uPosition, SEEK_SET) == 0; - } -}; - -int CombineDXBCWithGLSL(char* dxbcFileName, char* outputFileName, GLSLShader* shader) -{ - SDXBCFile dxbcFile = { fopen(dxbcFileName, "rb") }; - SDXBCFile outputFile = { fopen(outputFileName, "wb") }; - - bool result = - dxbcFile.m_pFile != NULL && outputFile.m_pFile != NULL && - DXBCCombineWithGLSL(dxbcFile, outputFile, shader); - - if (dxbcFile.m_pFile != NULL) - { - fclose(dxbcFile.m_pFile); - } - if (outputFile.m_pFile != NULL) - { - fclose(outputFile.m_pFile); - } - - return result; -} - -#if !defined(_MSC_VER) -#define sprintf_s(dest, size, ...) sprintf(dest, __VA_ARGS__) -#endif - -#if defined(_WIN32) && defined(PORTABLE) - -DWORD FilterException(DWORD uExceptionCode) -{ - const char* szExceptionName; - char acTemp[10]; - switch (uExceptionCode) - { -#define _CASE(_Name) \ -case _Name: \ - szExceptionName = #_Name; \ - break; - _CASE(EXCEPTION_ACCESS_VIOLATION) - _CASE(EXCEPTION_DATATYPE_MISALIGNMENT) - _CASE(EXCEPTION_BREAKPOINT) - _CASE(EXCEPTION_SINGLE_STEP) - _CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) - _CASE(EXCEPTION_FLT_DENORMAL_OPERAND) - _CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO) - _CASE(EXCEPTION_FLT_INEXACT_RESULT) - _CASE(EXCEPTION_FLT_INVALID_OPERATION) - _CASE(EXCEPTION_FLT_OVERFLOW) - _CASE(EXCEPTION_FLT_STACK_CHECK) - _CASE(EXCEPTION_FLT_UNDERFLOW) - _CASE(EXCEPTION_INT_DIVIDE_BY_ZERO) - _CASE(EXCEPTION_INT_OVERFLOW) - _CASE(EXCEPTION_PRIV_INSTRUCTION) - _CASE(EXCEPTION_IN_PAGE_ERROR) - _CASE(EXCEPTION_ILLEGAL_INSTRUCTION) - _CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION) - _CASE(EXCEPTION_STACK_OVERFLOW) - _CASE(EXCEPTION_INVALID_DISPOSITION) - _CASE(EXCEPTION_GUARD_PAGE) - _CASE(EXCEPTION_INVALID_HANDLE) - //_CASE(EXCEPTION_POSSIBLE_DEADLOCK) -#undef _CASE - default: - sprintf_s(acTemp, "0x%08X", uExceptionCode); - szExceptionName = acTemp; - } - - fprintf(stderr, "Hardware exception thrown (%s)\n", szExceptionName); - return 1; -} - -#endif - -const char* PatchHLSLShaderFile(const char* path) -{ - // Need to transform "half" into "min16float" so FXC preserve min precision to the operands. - static char patchedFileName[MAX_PATH_CHARS]; - const char* defines = "#define half min16float\n" - "#define half2 min16float2\n" - "#define half3 min16float3\n" - "#define half4 min16float4\n"; - - sprintf_s(patchedFileName, sizeof(patchedFileName), "%s.hlslPatched", path); - FILE* shaderFile = fopen(path, "rb"); - if (!shaderFile) - { - return NULL; - } - - FILE* patchedFile = fopen(patchedFileName, "wb"); - if (!patchedFile) - { - return NULL; - } - - // Get size of file - bool result = false; - fseek(shaderFile, 0, SEEK_END); - long size = ftell(shaderFile); - fseek(shaderFile, 0, SEEK_SET); - unsigned char* data = new unsigned char[size + 1]; // Extra byte for the '/0' character. - if (fread(data, 1, size, shaderFile) == size) - { - data[size] = '\0'; - fprintf(patchedFile, "%s%s", defines, data); - result = true; - } - - if (shaderFile) - { - fclose(shaderFile); - } - - if (patchedFile) - { - fclose(patchedFile); - } - - delete[] data; - return result ? patchedFileName : NULL; -} - -int main(int argc, char** argv) -{ - Options options; - -#if defined(_WIN32) && defined(PORTABLE) - __try - { -#endif - - if (!GetOptions(argc, argv, &options)) - { - return 1; - } - - if (options.bUseFxc) - { - char dxbcFileName[MAX_PATH_CHARS]; - char glslFileName[MAX_PATH_CHARS]; - char fullFxcCmdLine[MAX_FXC_CMD_CHARS]; - int retValue; - - if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) - { - options.shaderFile = PatchHLSLShaderFile(options.shaderFile); - if (!options.shaderFile) - { - return 1; - } - } - - sprintf_s(dxbcFileName, sizeof(dxbcFileName), "%s.dxbc", options.shaderFile); - sprintf_s(glslFileName, sizeof(glslFileName), "%s.patched", options.shaderFile); - - // Need to extract the path to the executable so we can enclose it in quotes - // in case it contains spaces. - const std::string fxcExeName = "fxc.exe"; - - // Case insensitive search - std::string::iterator fxcPos = std::search( - options.fxcCmdLine.begin(), options.fxcCmdLine.end(), - fxcExeName.begin(), fxcExeName.end(), - [](char ch1, char ch2) { return std::tolower(ch1) == std::tolower(ch2); } - ); - - if (fxcPos == options.fxcCmdLine.end()) - { - fprintf(stderr, "Could not find fxc.exe in command line"); - return 1; - } - - // Add the fxcExeName so it gets copied to the fxcExe path. - fxcPos += fxcExeName.length(); - std::string fxcExe(options.fxcCmdLine.begin(), fxcPos); - std::string fxcArguments(fxcPos, options.fxcCmdLine.end()); - -#if defined(APPLE) - fprintf(stderr, "fxc.exe cannot be executed on Mac"); - return 1; -#else - // Need an extra set of quotes around the full command line because the way "system" executes it using cmd. - sprintf_s(fullFxcCmdLine, sizeof(fullFxcCmdLine), "\"\"%s\" %s \"%s\" \"%s\"\"", fxcExe.c_str(), fxcArguments.c_str(), dxbcFileName, options.shaderFile); -#endif - - retValue = system(fullFxcCmdLine); - - if (retValue == 0) - { - GLSLShader shader; - retValue = !Run(dxbcFileName, glslFileName, options.language, options.flags, options.reflectPath, &shader, 1); - - if (retValue == 0) - { - retValue = !CombineDXBCWithGLSL(dxbcFileName, options.outputShaderFile, &shader); - FreeGLSLShader(&shader); - } - } - - remove(dxbcFileName); - remove(glslFileName); - if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) - { - // Removed the hlsl patched file that was created. - remove(options.shaderFile); - } - - return retValue; - } - - if (options.shaderFile) - { - if (!Run(options.shaderFile, options.outputShaderFile, options.language, options.flags, options.reflectPath, NULL, 0)) - { - return 1; - } - } - -#if defined(_WIN32) && defined(PORTABLE) -} -__except (FilterException(GetExceptionCode())) -{ - return 1; -} -#endif - - - return 0; -} diff --git a/Code/Tools/HLSLCrossCompiler/offline/hash.h b/Code/Tools/HLSLCrossCompiler/offline/hash.h deleted file mode 100644 index f93f3b65d3..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/hash.h +++ /dev/null @@ -1,152 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HASH_H_ -#define HASH_H_ - -/* --------------------------------------------------------------------- -mix -- mix 3 64-bit values reversibly. -mix() takes 48 machine instructions, but only 24 cycles on a superscalar - machine (like Intel's new MMX architecture). It requires 4 64-bit - registers for 4::2 parallelism. -All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of - (a,b,c), and all deltas of bottom bits were tested. All deltas were - tested both on random keys and on keys that were nearly all zero. - These deltas all cause every bit of c to change between 1/3 and 2/3 - of the time (well, only 113/400 to 287/400 of the time for some - 2-bit delta). These deltas all cause at least 80 bits to change - among (a,b,c) when the mix is run either forward or backward (yes it - is reversible). -This implies that a hash using mix64 has no funnels. There may be - characteristics with 3-bit deltas or bigger, I didn't test for - those. --------------------------------------------------------------------- -*/ -#define mix64(a, b, c) \ - { \ - a -= b; a -= c; a ^= (c >> 43); \ - b -= c; b -= a; b ^= (a << 9); \ - c -= a; c -= b; c ^= (b >> 8); \ - a -= b; a -= c; a ^= (c >> 38); \ - b -= c; b -= a; b ^= (a << 23); \ - c -= a; c -= b; c ^= (b >> 5); \ - a -= b; a -= c; a ^= (c >> 35); \ - b -= c; b -= a; b ^= (a << 49); \ - c -= a; c -= b; c ^= (b >> 11); \ - a -= b; a -= c; a ^= (c >> 12); \ - b -= c; b -= a; b ^= (a << 18); \ - c -= a; c -= b; c ^= (b >> 22); \ - } - -/* --------------------------------------------------------------------- -hash64() -- hash a variable-length key into a 64-bit value - k : the key (the unaligned variable-length array of bytes) - len : the length of the key, counting by bytes - level : can be any 8-byte value -Returns a 64-bit value. Every bit of the key affects every bit of -the return value. No funnels. Every 1-bit and 2-bit delta achieves -avalanche. About 41+5len instructions. - -The best hash table sizes are powers of 2. There is no need to do -mod a prime (mod is sooo slow!). If you need less than 64 bits, -use a bitmask. For example, if you need only 10 bits, do - h = (h & hashmask(10)); -In which case, the hash table should have hashsize(10) elements. - -If you are hashing n strings (ub1 **)k, do it like this: - for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); - -By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may -use this code any way you wish, private, educational, or commercial, -but I would appreciate if you give me credit. - -See http://burtleburtle.net/bob/hash/evahash.html -Use for hash table lookup, or anything where one collision in 2^^64 -is acceptable. Do NOT use for cryptographic purposes. --------------------------------------------------------------------- -*/ - -static uint64_t hash64(const uint8_t* k, uint32_t length, uint64_t initval) -{ - uint64_t a, b, c, len; - - /* Set up the internal state */ - len = length; - a = b = initval; /* the previous hash value */ - c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */ - - /*---------------------------------------- handle most of the key */ - while (len >= 24) - { - a += (k[0] + ((uint64_t)k[ 1] << 8) + ((uint64_t)k[ 2] << 16) + ((uint64_t)k[ 3] << 24) - + ((uint64_t)k[4 ] << 32) + ((uint64_t)k[ 5] << 40) + ((uint64_t)k[ 6] << 48) + ((uint64_t)k[ 7] << 56)); - b += (k[8] + ((uint64_t)k[ 9] << 8) + ((uint64_t)k[10] << 16) + ((uint64_t)k[11] << 24) - + ((uint64_t)k[12] << 32) + ((uint64_t)k[13] << 40) + ((uint64_t)k[14] << 48) + ((uint64_t)k[15] << 56)); - c += (k[16] + ((uint64_t)k[17] << 8) + ((uint64_t)k[18] << 16) + ((uint64_t)k[19] << 24) - + ((uint64_t)k[20] << 32) + ((uint64_t)k[21] << 40) + ((uint64_t)k[22] << 48) + ((uint64_t)k[23] << 56)); - mix64(a, b, c); - k += 24; - len -= 24; - } - - /*------------------------------------- handle the last 23 bytes */ - c += length; - switch (len) /* all the case statements fall through */ - { - case 23: - c += ((uint64_t)k[22] << 56); - case 22: - c += ((uint64_t)k[21] << 48); - case 21: - c += ((uint64_t)k[20] << 40); - case 20: - c += ((uint64_t)k[19] << 32); - case 19: - c += ((uint64_t)k[18] << 24); - case 18: - c += ((uint64_t)k[17] << 16); - case 17: - c += ((uint64_t)k[16] << 8); - /* the first byte of c is reserved for the length */ - case 16: - b += ((uint64_t)k[15] << 56); - case 15: - b += ((uint64_t)k[14] << 48); - case 14: - b += ((uint64_t)k[13] << 40); - case 13: - b += ((uint64_t)k[12] << 32); - case 12: - b += ((uint64_t)k[11] << 24); - case 11: - b += ((uint64_t)k[10] << 16); - case 10: - b += ((uint64_t)k[ 9] << 8); - case 9: - b += ((uint64_t)k[ 8]); - case 8: - a += ((uint64_t)k[ 7] << 56); - case 7: - a += ((uint64_t)k[ 6] << 48); - case 6: - a += ((uint64_t)k[ 5] << 40); - case 5: - a += ((uint64_t)k[ 4] << 32); - case 4: - a += ((uint64_t)k[ 3] << 24); - case 3: - a += ((uint64_t)k[ 2] << 16); - case 2: - a += ((uint64_t)k[ 1] << 8); - case 1: - a += ((uint64_t)k[ 0]); - /* case 0: nothing left to add */ - } - mix64(a, b, c); - /*-------------------------------------------- report the result */ - return c; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp deleted file mode 100644 index 15fe8d5b96..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "serializeReflection.h" -#include "cJSON.h" -#include <string> -#include <sstream> - -void* jsonMalloc(size_t sz) -{ - return new char[sz]; -} -void jsonFree(void* ptr) -{ - char* charPtr = static_cast<char*>(ptr); - delete [] charPtr; -} - -static void AppendIntToString(std::string& str, uint32_t num) -{ - std::stringstream ss; - ss << num; - str += ss.str(); -} - -static void WriteInOutSignature(InOutSignature* psSignature, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "SemanticName", cJSON_CreateString(psSignature->SemanticName)); - cJSON_AddItemToObject(obj, "ui32SemanticIndex", cJSON_CreateNumber(psSignature->ui32SemanticIndex)); - cJSON_AddItemToObject(obj, "eSystemValueType", cJSON_CreateNumber(psSignature->eSystemValueType)); - cJSON_AddItemToObject(obj, "eComponentType", cJSON_CreateNumber(psSignature->eComponentType)); - cJSON_AddItemToObject(obj, "ui32Register", cJSON_CreateNumber(psSignature->ui32Register)); - cJSON_AddItemToObject(obj, "ui32Mask", cJSON_CreateNumber(psSignature->ui32Mask)); - cJSON_AddItemToObject(obj, "ui32ReadWriteMask", cJSON_CreateNumber(psSignature->ui32ReadWriteMask)); -} - -static void WriteResourceBinding(ResourceBinding* psBinding, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psBinding->Name)); - cJSON_AddItemToObject(obj, "eType", cJSON_CreateNumber(psBinding->eType)); - cJSON_AddItemToObject(obj, "ui32BindPoint", cJSON_CreateNumber(psBinding->ui32BindPoint)); - cJSON_AddItemToObject(obj, "ui32BindCount", cJSON_CreateNumber(psBinding->ui32BindCount)); - cJSON_AddItemToObject(obj, "ui32Flags", cJSON_CreateNumber(psBinding->ui32Flags)); - cJSON_AddItemToObject(obj, "eDimension", cJSON_CreateNumber(psBinding->eDimension)); - cJSON_AddItemToObject(obj, "ui32ReturnType", cJSON_CreateNumber(psBinding->ui32ReturnType)); - cJSON_AddItemToObject(obj, "ui32NumSamples", cJSON_CreateNumber(psBinding->ui32NumSamples)); -} - -static void WriteShaderVar(ShaderVar* psVar, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psVar->Name)); - if(psVar->haveDefaultValue) - { - cJSON_AddItemToObject(obj, "aui32DefaultValues", cJSON_CreateIntArray((int*)psVar->pui32DefaultValues, psVar->ui32Size/4)); - } - cJSON_AddItemToObject(obj, "ui32StartOffset", cJSON_CreateNumber(psVar->ui32StartOffset)); - cJSON_AddItemToObject(obj, "ui32Size", cJSON_CreateNumber(psVar->ui32Size)); -} - -static void WriteConstantBuffer(ConstantBuffer* psCBuf, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psCBuf->Name)); - cJSON_AddItemToObject(obj, "ui32NumVars", cJSON_CreateNumber(psCBuf->ui32NumVars)); - - for(uint32_t i = 0; i < psCBuf->ui32NumVars; ++i) - { - std::string name; - name += "var"; - AppendIntToString(name, i); - - cJSON* varObj = cJSON_CreateObject(); - cJSON_AddItemToObject(obj, name.c_str(), varObj); - - WriteShaderVar(&psCBuf->asVars[i], varObj); - } - - cJSON_AddItemToObject(obj, "ui32TotalSizeInBytes", cJSON_CreateNumber(psCBuf->ui32TotalSizeInBytes)); -} - -static void WriteClassType(ClassType* psClassType, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassType->Name)); - cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassType->ui16ID)); - cJSON_AddItemToObject(obj, "ui16ConstBufStride", cJSON_CreateNumber(psClassType->ui16ConstBufStride)); - cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassType->ui16Texture)); - cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassType->ui16Sampler)); -} - -static void WriteClassInstance(ClassInstance* psClassInst, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassInst->Name)); - cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassInst->ui16ID)); - cJSON_AddItemToObject(obj, "ui16ConstBuf", cJSON_CreateNumber(psClassInst->ui16ConstBuf)); - cJSON_AddItemToObject(obj, "ui16ConstBufOffset", cJSON_CreateNumber(psClassInst->ui16ConstBufOffset)); - cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassInst->ui16Texture)); - cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassInst->ui16Sampler)); -} - -const char* SerializeReflection(ShaderInfo* psReflection) -{ - cJSON* root; - - cJSON_Hooks hooks; - hooks.malloc_fn = jsonMalloc; - hooks.free_fn = jsonFree; - cJSON_InitHooks(&hooks); - - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "ui32MajorVersion", cJSON_CreateNumber(psReflection->ui32MajorVersion)); - cJSON_AddItemToObject(root, "ui32MinorVersion", cJSON_CreateNumber(psReflection->ui32MinorVersion)); - - cJSON_AddItemToObject(root, "ui32NumInputSignatures", cJSON_CreateNumber(psReflection->ui32NumInputSignatures)); - - for(uint32_t i = 0; i < psReflection->ui32NumInputSignatures; ++i) - { - std::string name; - name += "input"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteInOutSignature(psReflection->psInputSignatures+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumOutputSignatures", cJSON_CreateNumber(psReflection->ui32NumOutputSignatures)); - - for(uint32_t i = 0; i < psReflection->ui32NumOutputSignatures; ++i) - { - std::string name; - name += "output"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteInOutSignature(psReflection->psOutputSignatures+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumResourceBindings", cJSON_CreateNumber(psReflection->ui32NumResourceBindings)); - - for(uint32_t i = 0; i < psReflection->ui32NumResourceBindings; ++i) - { - std::string name; - name += "resource"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteResourceBinding(psReflection->psResourceBindings+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumConstantBuffers", cJSON_CreateNumber(psReflection->ui32NumConstantBuffers)); - - for(uint32_t i = 0; i < psReflection->ui32NumConstantBuffers; ++i) - { - std::string name; - name += "cbuf"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteConstantBuffer(psReflection->psConstantBuffers+i, obj); - } - - //psThisPointerConstBuffer is a cache. Don't need to write this out. - //It just points to the $ThisPointer cbuffer within the psConstantBuffers array. - - for(uint32_t i = 0; i < psReflection->ui32NumClassTypes; ++i) - { - std::string name; - name += "classType"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteClassType(psReflection->psClassTypes+i, obj); - } - - for(uint32_t i = 0; i < psReflection->ui32NumClassInstances; ++i) - { - std::string name; - name += "classInst"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteClassInstance(psReflection->psClassInstances+i, obj); - } - - //psReflection->aui32TableIDToTypeID - //psReflection->aui32ConstBufferBindpointRemap - - cJSON_AddItemToObject(root, "eTessPartitioning", cJSON_CreateNumber(psReflection->eTessPartitioning)); - cJSON_AddItemToObject(root, "eTessOutPrim", cJSON_CreateNumber(psReflection->eTessOutPrim)); - - - const char* jsonString = cJSON_Print(root); - - cJSON_Delete(root); - - return jsonString; -} diff --git a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h deleted file mode 100644 index c8c4175a6a..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h +++ /dev/null @@ -1,11 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef SERIALIZE_REFLECTION_H_ -#define SERIALIZE_REFLECTION_H_ - -#include "hlslcc.h" - -const char* SerializeReflection(ShaderInfo* psReflection); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/timer.cpp b/Code/Tools/HLSLCrossCompiler/offline/timer.cpp deleted file mode 100644 index c707e1bfa8..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/timer.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "timer.h" - -void InitTimer(Timer_t* psTimer) -{ -#if defined(_WIN32) - QueryPerformanceFrequency(&psTimer->frequency); -#endif -} - -void ResetTimer(Timer_t* psTimer) -{ -#if defined(_WIN32) - QueryPerformanceCounter(&psTimer->startCount); -#else - gettimeofday(&psTimer->startCount, 0); -#endif -} - -/* Returns time in micro seconds */ -double ReadTimer(Timer_t* psTimer) -{ - double startTimeInMicroSec, endTimeInMicroSec; - -#if defined(_WIN32) - const double freq = (1000000.0 / psTimer->frequency.QuadPart); - QueryPerformanceCounter(&psTimer->endCount); - startTimeInMicroSec = psTimer->startCount.QuadPart * freq; - endTimeInMicroSec = psTimer->endCount.QuadPart * freq; -#else - gettimeofday(&psTimer->endCount, 0); - startTimeInMicroSec = (psTimer->startCount.tv_sec * 1000000.0) + psTimer->startCount.tv_usec; - endTimeInMicroSec = (psTimer->endCount.tv_sec * 1000000.0) + psTimer->endCount.tv_usec; -#endif - - return endTimeInMicroSec - startTimeInMicroSec; -} - diff --git a/Code/Tools/HLSLCrossCompiler/offline/timer.h b/Code/Tools/HLSLCrossCompiler/offline/timer.h deleted file mode 100644 index 3f4ea333fd..0000000000 --- a/Code/Tools/HLSLCrossCompiler/offline/timer.h +++ /dev/null @@ -1,29 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TIMER_H -#define TIMER_H - -#ifdef _WIN32 -#include <Windows.h> -#else -#include <sys/time.h> -#endif - -typedef struct -{ -#ifdef _WIN32 - LARGE_INTEGER frequency; - LARGE_INTEGER startCount; - LARGE_INTEGER endCount; -#else - struct timeval startCount; - struct timeval endCount; -#endif -} Timer_t; - -void InitTimer(Timer_t* psTimer); -void ResetTimer(Timer_t* psTimer); -double ReadTimer(Timer_t* psTimer); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c b/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c deleted file mode 100644 index 7b339ba93e..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c +++ /dev/null @@ -1,219 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toGLSLInstruction.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/languages.h" -#include "bstrlib.h" -#include "stdio.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "amazon_changes.h" - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wpointer-sign" -#endif - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -// These are .c files, so no C++ or C++11 for us :( -#define MAX_VARIABLE_LENGTH 16 - -// This struct is used to keep track of each valid occurance of xxxBitsToxxx(variable) and store all relevant information for fixing that instance -typedef struct ShaderCastLocation -{ - char tempVariableName[MAX_VARIABLE_LENGTH]; - char replacementVariableName[MAX_VARIABLE_LENGTH]; - unsigned int castType; - - // Since we have no stl, here's our list - struct ShaderCastLocation* next; -} ShaderCastLocation; - -// Structure used to prebuild the list of all functions that need to be replaced. -typedef struct ShaderCastType -{ - const char* functionName; - unsigned int castType; - const char* variableTypeName; // String for the variable type used when declaring a temporary variable to replace the source temp vector -} ShaderCastType; - -enum ShaderCasts -{ - CAST_UINTBITSTOFLOAT, - CAST_INTBITSTOFLOAT, - CAST_FLOATBITSTOUINT, - CAST_FLOATBITSTOINT, - CAST_NUMCASTS -}; - -// NOTICE: Order is important here because intBitsToFloat is a substring of uintBitsToFloat, so do not change the ordering here! -static const ShaderCastType s_castFunctions[CAST_NUMCASTS] = -{ - { "uintBitsToFloat", CAST_UINTBITSTOFLOAT, "uvec4" }, - { "intBitsToFloat", CAST_INTBITSTOFLOAT, "ivec4" }, - { "floatBitsToUint", CAST_FLOATBITSTOUINT, "vec4" }, - { "floatBitsToInt", CAST_FLOATBITSTOINT, "vec4" } -}; - -int IsValidUseCase( char* variableStart, char* outVariableName, ShaderCastLocation* foundShaderCastsHead, int currentType ) -{ - // Cases we have to replace (this is very strict in definition): - // 1) floatBitsToInt(Temp2) - // 2) floatBitsToInt(Temp2.x) - // 3) floatBitsToInt(Temp[0]) - // 4) floatBitsToInt(Temp[0].x) - // Cases we do not have to replace: - // 1) floatBitsToInt(vec4(Temp2)) - // 2) floatBitsToInt(Output0.x != 0.0f ? 1.0f : 0.0f) - // 3) Any other version that evaluates an expression within the () - if ( strncmp(variableStart, "Temp", 4) != 0 ) - return 0; - - unsigned int lengthOfVariable = 4; // Start at 4 for temp - - while ( 1 ) - { - char val = *(variableStart + lengthOfVariable); - - // If alphanumeric or [] (array), we have a valid variable name - if ( isalnum( val ) || (val == '[') || (val == ']') ) - { - lengthOfVariable++; - } - else if ( (val == ')') || (val == '.') ) - { - // Found end of variable - break; - } - else - { - // Found something unexpected, so abort - return 0; - } - } - - ASSERT( lengthOfVariable < MAX_VARIABLE_LENGTH ); - - // Now ensure that no duplicates of this declaration already exist - ShaderCastLocation* currentLink = foundShaderCastsHead; - while ( currentLink ) - { - // If we have the same type and the same name - if ( (currentType == currentLink->castType) && (strncmp(variableStart, currentLink->tempVariableName, lengthOfVariable) == 0) ) - return 0; // Do not add because an entry already exists for this variable and this cast function - - // Hmm...I guess this scenario is possible, but it has not shown up in any shaders. - // The only time we could ever hit this is if the same line casts a float to both an int and uint in separate calls - // Seems highly unlikely, so let's just assert for now and fix it if we have to. - if ( strncmp(variableStart, currentLink->tempVariableName, lengthOfVariable) == 0 ) - { - // TODO: Implement this case where we cast the same variable to multiple types on the same line of GLSL - ASSERT(0); - } - - currentLink = currentLink->next; - } - - // We found a unique instance, so store it - strncpy( outVariableName, variableStart, lengthOfVariable ); - return 1; -} - -void ModifyLineForQualcommReinterpretCastBug( HLSLCrossCompilerContext* psContext, bstring* originalString, bstring* overloadString ) -{ - unsigned int numFoundCasts = 0; - - ShaderCastLocation* foundShaderCastsHead = NULL; - ShaderCastLocation* currentShaderCasts = NULL; - - // Find all occurances of the *BitsTo* functions - // Note that this would be cleaner, but 'intBitsToFloat' is a substring of 'uintBitsToFloat' so parsing order is important here. - char* parsingString = bdataofs(*overloadString, 0); - while ( parsingString ) - { - char* result = NULL; - - for ( int index=0; index<CAST_NUMCASTS; ++index ) - { - result = strstr( parsingString, s_castFunctions[index].functionName ); - if ( result != NULL ) - { - // Now determine if this is a case that requires a workaround - char* variableStart = result + strlen( s_castFunctions[index].functionName ) + 1; // Add the function name + first parenthesis - char tempVariableName[MAX_VARIABLE_LENGTH]; - memset( tempVariableName, 0, MAX_VARIABLE_LENGTH ); - - // Now the next word must be Temp, or this is not a valid case - if ( IsValidUseCase( variableStart, tempVariableName, foundShaderCastsHead, index ) ) - { - // Now store the information about this cast. Allocate a new link in the list. - if ( !foundShaderCastsHead ) - { - foundShaderCastsHead = (ShaderCastLocation*)hlslcc_malloc( sizeof(ShaderCastLocation) ); - memset( foundShaderCastsHead, 0x0, sizeof(ShaderCastLocation) ); - currentShaderCasts = foundShaderCastsHead; - } - else - { - ASSERT( !currentShaderCasts->next ); - currentShaderCasts->next = (ShaderCastLocation*)hlslcc_malloc( sizeof(ShaderCastLocation) ); - memset( currentShaderCasts->next, 0x0, sizeof(ShaderCastLocation) ); - currentShaderCasts = currentShaderCasts->next; - } - - currentShaderCasts->castType = index; - strcpy( currentShaderCasts->tempVariableName, tempVariableName ); - - numFoundCasts++; - } - result += strlen( s_castFunctions[index].functionName ); - - // Break out of the loop because we have to advance the search string and start over with uintBitsToFloat again due to the problem with intBitsToFloat being a substring - break; - } - } - - parsingString = result; - } - - // If we have found no casts, then append the line to the primary string - if ( numFoundCasts == 0 ) - { - bconcat( *originalString, *overloadString ); - return; - } - - // Now we start creating our temporary variables to workaround the crash - currentShaderCasts = foundShaderCastsHead; - - // NOTE: We want a count of all variables processed for this entire shader. This could be fancier... - static unsigned int currentVariableIndex = 0; - - while ( currentShaderCasts ) - { - // Generate new variable name - sprintf( currentShaderCasts->replacementVariableName, "LYTemp%i", currentVariableIndex ); - - // Write out the new variable name declaration and initialize it - AddIndentation( psContext ); - bformata( *originalString, "%s %s=%s;\n", s_castFunctions[currentShaderCasts->castType].variableTypeName, currentShaderCasts->replacementVariableName, currentShaderCasts->tempVariableName ); - - // Now replace all instances of the variable in question with the new variable name. - // Note: We can't do a breplace on the temp variable name because the variable can still be legally used without a reinterpret cast in that line. - // Do a full replace on the xxBitsToxx(TempVar) here - bstring tempVarName = bformat( "%s(%s)", s_castFunctions[currentShaderCasts->castType].functionName, currentShaderCasts->tempVariableName ); - bstring replacementVarName = bformat( "%s(%s)", s_castFunctions[currentShaderCasts->castType].functionName, currentShaderCasts->replacementVariableName ); - bfindreplace( *overloadString, tempVarName, replacementVarName, 0 ); - - // Cleanup bstrings allocated from bformat - bdestroy( tempVarName ); - bdestroy( replacementVarName ); - - currentVariableIndex++; - currentShaderCasts = currentShaderCasts->next; - } - - // Now append our modified string to the full shader file - bconcat( *originalString, *overloadString ); -} diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c deleted file mode 100644 index 3f24fa3341..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bsafe.c - * - * This is an optional module that can be used to help enforce a safety - * standard based on pervasive usage of bstrlib. This file is not necessarily - * portable, however, it has been tested to work correctly with Intel's C/C++ - * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. - */ - -#include <stdio.h> -#include <stdlib.h> -#include "bsafe.h" diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h deleted file mode 100644 index 3a647a6ac8..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bsafe.h - * - * This is an optional module that can be used to help enforce a safety - * standard based on pervasive usage of bstrlib. This file is not necessarily - * portable, however, it has been tested to work correctly with Intel's C/C++ - * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. - */ - -#ifndef BSTRLIB_BSAFE_INCLUDE -#define BSTRLIB_BSAFE_INCLUDE - -#ifdef __cplusplus -extern "C" { -#endif - -#if !defined(__GNUC__) && !defined(__clang__) -#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310)) -/* This is caught in the linker, so its not necessary for gcc. */ -extern char * (gets) (char * buf); -#endif - -extern char * (strncpy) (char *dst, const char *src, size_t n); -extern char * (strncat) (char *dst, const char *src, size_t n); -extern char * (strtok) (char *s1, const char *s2); -extern char * (strdup) (const char *s); - -#undef strcpy -#undef strcat -#define strcpy(a,b) bsafe_strcpy(a,b) -#define strcat(a,b) bsafe_strcat(a,b) -#endif -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c deleted file mode 100644 index 2dc7b04840..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstraux.c - * - * This file is not necessarily part of the core bstring library itself, but - * is just an auxilliary module which includes miscellaneous or trivial - * functions. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> -#include "bstrlib.h" -#include "bstraux.h" - -/* bstring bTail (bstring b, int n) - * - * Return with a string of the last n characters of b. - */ -bstring bTail (bstring b, int n) { - if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; - if (n >= b->slen) return bstrcpy (b); - return bmidstr (b, b->slen - n, n); -} - -/* bstring bHead (bstring b, int n) - * - * Return with a string of the first n characters of b. - */ -bstring bHead (bstring b, int n) { - if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; - if (n >= b->slen) return bstrcpy (b); - return bmidstr (b, 0, n); -} - -/* int bFill (bstring a, char c, int len) - * - * Fill a given bstring with the character in parameter c, for a length n. - */ -int bFill (bstring b, char c, int len) { - if (b == NULL || len < 0 || (b->mlen < b->slen && b->mlen > 0)) return -__LINE__; - b->slen = 0; - return bsetstr (b, len, NULL, c); -} - -/* int bReplicate (bstring b, int n) - * - * Replicate the contents of b end to end n times and replace it in b. - */ -int bReplicate (bstring b, int n) { - return bpattern (b, n * b->slen); -} - -/* int bReverse (bstring b) - * - * Reverse the contents of b in place. - */ -int bReverse (bstring b) { -int i, n, m; -unsigned char t; - - if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; - n = b->slen; - if (2 <= n) { - m = ((unsigned)n) >> 1; - n--; - for (i=0; i < m; i++) { - t = b->data[n - i]; - b->data[n - i] = b->data[i]; - b->data[i] = t; - } - } - return 0; -} - -/* int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) - * - * Insert a repeated sequence of a given character into the string at - * position pos for a length len. - */ -int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) { - if (b == NULL || b->slen < 0 || b->mlen < b->slen || pos < 0 || len <= 0) return -__LINE__; - - if (pos > b->slen - && 0 > bsetstr (b, pos, NULL, fill)) return -__LINE__; - - if (0 > balloc (b, b->slen + len)) return -__LINE__; - if (pos < b->slen) memmove (b->data + pos + len, b->data + pos, b->slen - pos); - memset (b->data + pos, c, len); - b->slen += len; - b->data[b->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bJustifyLeft (bstring b, int space) - * - * Left justify a string. - */ -int bJustifyLeft (bstring b, int space) { -int j, i, s, t; -unsigned char c = (unsigned char) space; - - if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; - if (space != (int) c) return BSTR_OK; - - for (s=j=i=0; i < b->slen; i++) { - t = s; - s = c != (b->data[j] = b->data[i]); - j += (t|s); - } - if (j > 0 && b->data[j-1] == c) j--; - - b->data[j] = (unsigned char) '\0'; - b->slen = j; - return BSTR_OK; -} - -/* int bJustifyRight (bstring b, int width, int space) - * - * Right justify a string to within a given width. - */ -int bJustifyRight (bstring b, int width, int space) { -int ret; - if (width <= 0) return -__LINE__; - if (0 > (ret = bJustifyLeft (b, space))) return ret; - if (b->slen <= width) - return bInsertChrs (b, 0, width - b->slen, (unsigned char) space, (unsigned char) space); - return BSTR_OK; -} - -/* int bJustifyCenter (bstring b, int width, int space) - * - * Center a string's non-white space characters to within a given width by - * inserting whitespaces at the beginning. - */ -int bJustifyCenter (bstring b, int width, int space) { -int ret; - if (width <= 0) return -__LINE__; - if (0 > (ret = bJustifyLeft (b, space))) return ret; - if (b->slen <= width) - return bInsertChrs (b, 0, (width - b->slen + 1) >> 1, (unsigned char) space, (unsigned char) space); - return BSTR_OK; -} - -/* int bJustifyMargin (bstring b, int width, int space) - * - * Stretch a string to flush against left and right margins by evenly - * distributing additional white space between words. If the line is too - * long to be margin justified, it is left justified. - */ -int bJustifyMargin (bstring b, int width, int space) { -struct bstrList * sl; -int i, l, c; - - if (b == NULL || b->slen < 0 || b->mlen == 0 || b->mlen < b->slen) return -__LINE__; - if (NULL == (sl = bsplit (b, (unsigned char) space))) return -__LINE__; - for (l=c=i=0; i < sl->qty; i++) { - if (sl->entry[i]->slen > 0) { - c ++; - l += sl->entry[i]->slen; - } - } - - if (l + c >= width || c < 2) { - bstrListDestroy (sl); - return bJustifyLeft (b, space); - } - - b->slen = 0; - for (i=0; i < sl->qty; i++) { - if (sl->entry[i]->slen > 0) { - if (b->slen > 0) { - int s = (width - l + (c / 2)) / c; - bInsertChrs (b, b->slen, s, (unsigned char) space, (unsigned char) space); - l += s; - } - bconcat (b, sl->entry[i]); - c--; - if (c <= 0) break; - } - } - - bstrListDestroy (sl); - return BSTR_OK; -} - -static size_t readNothing (void *buff, size_t elsize, size_t nelem, void *parm) { - buff = buff; - elsize = elsize; - nelem = nelem; - parm = parm; - return 0; /* Immediately indicate EOF. */ -} - -/* struct bStream * bsFromBstr (const_bstring b); - * - * Create a bStream whose contents are a copy of the bstring passed in. - * This allows the use of all the bStream APIs with bstrings. - */ -struct bStream * bsFromBstr (const_bstring b) { -struct bStream * s = bsopen ((bNread) readNothing, NULL); - bsunread (s, b); /* Push the bstring data into the empty bStream. */ - return s; -} - -static size_t readRef (void *buff, size_t elsize, size_t nelem, void *parm) { -struct tagbstring * t = (struct tagbstring *) parm; -size_t tsz = elsize * nelem; - - if (tsz > (size_t) t->slen) tsz = (size_t) t->slen; - if (tsz > 0) { - memcpy (buff, t->data, tsz); - t->slen -= (int) tsz; - t->data += tsz; - return tsz / elsize; - } - return 0; -} - -/* The "by reference" version of the above function. This function puts - * a number of restrictions on the call site (the passed in struct - * tagbstring *will* be modified by this function, and the source data - * must remain alive and constant for the lifetime of the bStream). - * Hence it is not presented as an extern. - */ -static struct bStream * bsFromBstrRef (struct tagbstring * t) { - if (!t) return NULL; - return bsopen ((bNread) readRef, t); -} - -/* char * bStr2NetStr (const_bstring b) - * - * Convert a bstring to a netstring. See - * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. - * Note: 1) The value returned should be freed with a call to bcstrfree() at - * the point when it will no longer be referenced to avoid a memory - * leak. - * 2) If the returned value is non-NULL, then it also '\0' terminated - * in the character position one past the "," terminator. - */ -char * bStr2NetStr (const_bstring b) { -char strnum[sizeof (b->slen) * 3 + 1]; -bstring s; -unsigned char * buff; - - if (b == NULL || b->data == NULL || b->slen < 0) return NULL; - sprintf (strnum, "%d:", b->slen); - if (NULL == (s = bfromcstr (strnum)) - || bconcat (s, b) == BSTR_ERR || bconchar (s, (char) ',') == BSTR_ERR) { - bdestroy (s); - return NULL; - } - buff = s->data; - bcstrfree ((char *) s); - return (char *) buff; -} - -/* bstring bNetStr2Bstr (const char * buf) - * - * Convert a netstring to a bstring. See - * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. - * Note that the terminating "," *must* be present, however a following '\0' - * is *not* required. - */ -bstring bNetStr2Bstr (const char * buff) { -int i, x; -bstring b; - if (buff == NULL) return NULL; - x = 0; - for (i=0; buff[i] != ':'; i++) { - unsigned int v = buff[i] - '0'; - if (v > 9 || x > ((INT_MAX - (signed int)v) / 10)) return NULL; - x = (x * 10) + v; - } - - /* This thing has to be properly terminated */ - if (buff[i + 1 + x] != ',') return NULL; - - if (NULL == (b = bfromcstr (""))) return NULL; - if (balloc (b, x + 1) != BSTR_OK) { - bdestroy (b); - return NULL; - } - memcpy (b->data, buff + i + 1, x); - b->data[x] = (unsigned char) '\0'; - b->slen = x; - return b; -} - -static char b64ETable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* bstring bBase64Encode (const_bstring b) - * - * Generate a base64 encoding. See: RFC1341 - */ -bstring bBase64Encode (const_bstring b) { -int i, c0, c1, c2, c3; -bstring out; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - out = bfromcstr (""); - for (i=0; i + 2 < b->slen; i += 3) { - if (i && ((i % 57) == 0)) { - if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { - bdestroy (out); - return NULL; - } - } - c0 = b->data[i] >> 2; - c1 = ((b->data[i] << 4) | - (b->data[i+1] >> 4)) & 0x3F; - c2 = ((b->data[i+1] << 2) | - (b->data[i+2] >> 6)) & 0x3F; - c3 = b->data[i+2] & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, b64ETable[c2]) < 0 || - bconchar (out, b64ETable[c3]) < 0) { - bdestroy (out); - return NULL; - } - } - - if (i && ((i % 57) == 0)) { - if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { - bdestroy (out); - return NULL; - } - } - - switch (i + 2 - b->slen) { - case 0: c0 = b->data[i] >> 2; - c1 = ((b->data[i] << 4) | - (b->data[i+1] >> 4)) & 0x3F; - c2 = (b->data[i+1] << 2) & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, b64ETable[c2]) < 0 || - bconchar (out, (char) '=') < 0) { - bdestroy (out); - return NULL; - } - break; - case 1: c0 = b->data[i] >> 2; - c1 = (b->data[i] << 4) & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, (char) '=') < 0 || - bconchar (out, (char) '=') < 0) { - bdestroy (out); - return NULL; - } - break; - case 2: break; - } - - return out; -} - -#define B64_PAD (-2) -#define B64_ERR (-1) - -static int base64DecodeSymbol (unsigned char alpha) { - if ((alpha >= 'A') && (alpha <= 'Z')) return (int)(alpha - 'A'); - else if ((alpha >= 'a') && (alpha <= 'z')) - return 26 + (int)(alpha - 'a'); - else if ((alpha >= '0') && (alpha <= '9')) - return 52 + (int)(alpha - '0'); - else if (alpha == '+') return 62; - else if (alpha == '/') return 63; - else if (alpha == '=') return B64_PAD; - else return B64_ERR; -} - -/* bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) - * - * Decode a base64 block of data. All MIME headers are assumed to have been - * removed. See: RFC1341 - */ -bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) { -int i, v; -unsigned char c0, c1, c2; -bstring out; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - if (boolTruncError) *boolTruncError = 0; - out = bfromcstr (""); - i = 0; - for (;;) { - do { - if (i >= b->slen) return out; - if (b->data[i] == '=') { /* Bad "too early" truncation */ - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c0 = (unsigned char) (v << 2); - do { - if (i >= b->slen || b->data[i] == '=') { /* Bad "too early" truncation */ - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c0 |= (unsigned char) (v >> 4); - c1 = (unsigned char) (v << 4); - do { - if (i >= b->slen) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (b->data[i] == '=') { - i++; - if (i >= b->slen || b->data[i] != '=' || bconchar (out, c0) < 0) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); /* Missing "=" at the end. */ - return NULL; - } - return out; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c1 |= (unsigned char) (v >> 2); - c2 = (unsigned char) (v << 6); - do { - if (i >= b->slen) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (b->data[i] == '=') { - if (bconchar (out, c0) < 0 || bconchar (out, c1) < 0) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (boolTruncError) *boolTruncError = 0; - return out; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c2 |= (unsigned char) (v); - if (bconchar (out, c0) < 0 || - bconchar (out, c1) < 0 || - bconchar (out, c2) < 0) { - if (boolTruncError) { - *boolTruncError = -1; - return out; - } - bdestroy (out); - return NULL; - } - } -} - -#define UU_DECODE_BYTE(b) (((b) == (signed int)'`') ? 0 : (b) - (signed int)' ') - -struct bUuInOut { - bstring src, dst; - int * badlines; -}; - -#define UU_MAX_LINELEN 45 - -static int bUuDecLine (void * parm, int ofs, int len) { -struct bUuInOut * io = (struct bUuInOut *) parm; -bstring s = io->src; -bstring t = io->dst; -int i, llen, otlen, ret, c0, c1, c2, c3, d0, d1, d2, d3; - - if (len == 0) return 0; - llen = UU_DECODE_BYTE (s->data[ofs]); - ret = 0; - - otlen = t->slen; - - if (((unsigned) llen) > UU_MAX_LINELEN) { ret = -__LINE__; - goto bl; - } - - llen += t->slen; - - for (i=1; i < s->slen && t->slen < llen;i += 4) { - unsigned char outoctet[3]; - c0 = UU_DECODE_BYTE (d0 = (int) bchare (s, i+ofs+0, ' ' - 1)); - c1 = UU_DECODE_BYTE (d1 = (int) bchare (s, i+ofs+1, ' ' - 1)); - c2 = UU_DECODE_BYTE (d2 = (int) bchare (s, i+ofs+2, ' ' - 1)); - c3 = UU_DECODE_BYTE (d3 = (int) bchare (s, i+ofs+3, ' ' - 1)); - - if (((unsigned) (c0|c1) >= 0x40)) { if (!ret) ret = -__LINE__; - if (d0 > 0x60 || (d0 < (' ' - 1) && !isspace (d0)) || - d1 > 0x60 || (d1 < (' ' - 1) && !isspace (d1))) { - t->slen = otlen; - goto bl; - } - c0 = c1 = 0; - } - outoctet[0] = (unsigned char) ((c0 << 2) | ((unsigned) c1 >> 4)); - if (t->slen+1 >= llen) { - if (0 > bconchar (t, (char) outoctet[0])) return -__LINE__; - break; - } - if ((unsigned) c2 >= 0x40) { if (!ret) ret = -__LINE__; - if (d2 > 0x60 || (d2 < (' ' - 1) && !isspace (d2))) { - t->slen = otlen; - goto bl; - } - c2 = 0; - } - outoctet[1] = (unsigned char) ((c1 << 4) | ((unsigned) c2 >> 2)); - if (t->slen+2 >= llen) { - if (0 > bcatblk (t, outoctet, 2)) return -__LINE__; - break; - } - if ((unsigned) c3 >= 0x40) { if (!ret) ret = -__LINE__; - if (d3 > 0x60 || (d3 < (' ' - 1) && !isspace (d3))) { - t->slen = otlen; - goto bl; - } - c3 = 0; - } - outoctet[2] = (unsigned char) ((c2 << 6) | ((unsigned) c3)); - if (0 > bcatblk (t, outoctet, 3)) return -__LINE__; - } - if (t->slen < llen) { if (0 == ret) ret = -__LINE__; - t->slen = otlen; - } - bl:; - if (ret && io->badlines) { - (*io->badlines)++; - return 0; - } - return ret; -} - -/* bstring bUuDecodeEx (const_bstring src, int * badlines) - * - * Performs a UUDecode of a block of data. If there are errors in the - * decoding, they are counted up and returned in "badlines", if badlines is - * not NULL. It is assumed that the "begin" and "end" lines have already - * been stripped off. The potential security problem of writing the - * filename in the begin line is something that is beyond the scope of a - * portable library. - */ - -#ifdef _MSC_VER -#pragma warning(disable:4204) -#endif - -bstring bUuDecodeEx (const_bstring src, int * badlines) { -struct tagbstring t; -struct bStream * s; -struct bStream * d; -bstring b; - - if (!src) return NULL; - t = *src; /* Short lifetime alias to header of src */ - s = bsFromBstrRef (&t); /* t is undefined after this */ - if (!s) return NULL; - d = bsUuDecode (s, badlines); - b = bfromcstralloc (256, ""); - if (NULL == b || 0 > bsread (b, d, INT_MAX)) { - bdestroy (b); - bsclose (d); - bsclose (s); - return NULL; - } - return b; -} - -struct bsUuCtx { - struct bUuInOut io; - struct bStream * sInp; -}; - -static size_t bsUuDecodePart (void *buff, size_t elsize, size_t nelem, void *parm) { -static struct tagbstring eol = bsStatic ("\r\n"); -struct bsUuCtx * luuCtx = (struct bsUuCtx *) parm; -size_t tsz; -int l, lret; - - if (NULL == buff || NULL == parm) return 0; - tsz = elsize * nelem; - - CheckInternalBuffer:; - /* If internal buffer has sufficient data, just output it */ - if (((size_t) luuCtx->io.dst->slen) > tsz) { - memcpy (buff, luuCtx->io.dst->data, tsz); - bdelete (luuCtx->io.dst, 0, (int) tsz); - return nelem; - } - - DecodeMore:; - if (0 <= (l = binchr (luuCtx->io.src, 0, &eol))) { - int ol = 0; - struct tagbstring t; - bstring s = luuCtx->io.src; - luuCtx->io.src = &t; - - do { - if (l > ol) { - bmid2tbstr (t, s, ol, l - ol); - lret = bUuDecLine (&luuCtx->io, 0, t.slen); - if (0 > lret) { - luuCtx->io.src = s; - goto Done; - } - } - ol = l + 1; - if (((size_t) luuCtx->io.dst->slen) > tsz) break; - l = binchr (s, ol, &eol); - } while (BSTR_ERR != l); - bdelete (s, 0, ol); - luuCtx->io.src = s; - goto CheckInternalBuffer; - } - - if (BSTR_ERR != bsreada (luuCtx->io.src, luuCtx->sInp, bsbufflength (luuCtx->sInp, BSTR_BS_BUFF_LENGTH_GET))) { - goto DecodeMore; - } - - bUuDecLine (&luuCtx->io, 0, luuCtx->io.src->slen); - - Done:; - /* Output any lingering data that has been translated */ - if (((size_t) luuCtx->io.dst->slen) > 0) { - if (((size_t) luuCtx->io.dst->slen) > tsz) goto CheckInternalBuffer; - memcpy (buff, luuCtx->io.dst->data, luuCtx->io.dst->slen); - tsz = luuCtx->io.dst->slen / elsize; - luuCtx->io.dst->slen = 0; - if (tsz > 0) return tsz; - } - - /* Deallocate once EOF becomes triggered */ - bdestroy (luuCtx->io.dst); - bdestroy (luuCtx->io.src); - free (luuCtx); - return 0; -} - -/* bStream * bsUuDecode (struct bStream * sInp, int * badlines) - * - * Creates a bStream which performs the UUDecode of an an input stream. If - * there are errors in the decoding, they are counted up and returned in - * "badlines", if badlines is not NULL. It is assumed that the "begin" and - * "end" lines have already been stripped off. The potential security - * problem of writing the filename in the begin line is something that is - * beyond the scope of a portable library. - */ - -struct bStream * bsUuDecode (struct bStream * sInp, int * badlines) { -struct bsUuCtx * luuCtx = (struct bsUuCtx *) malloc (sizeof (struct bsUuCtx)); -struct bStream * sOut; - - if (NULL == luuCtx) return NULL; - - luuCtx->io.src = bfromcstr (""); - luuCtx->io.dst = bfromcstr (""); - if (NULL == luuCtx->io.dst || NULL == luuCtx->io.src) { - CleanUpFailureToAllocate:; - bdestroy (luuCtx->io.dst); - bdestroy (luuCtx->io.src); - free (luuCtx); - return NULL; - } - luuCtx->io.badlines = badlines; - if (badlines) *badlines = 0; - - luuCtx->sInp = sInp; - - sOut = bsopen ((bNread) bsUuDecodePart, luuCtx); - if (NULL == sOut) goto CleanUpFailureToAllocate; - return sOut; -} - -#define UU_ENCODE_BYTE(b) (char) (((b) == 0) ? '`' : ((b) + ' ')) - -/* bstring bUuEncode (const_bstring src) - * - * Performs a UUEncode of a block of data. The "begin" and "end" lines are - * not appended. - */ -bstring bUuEncode (const_bstring src) { -bstring out; -int i, j, jm; -unsigned int c0, c1, c2; - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - for (i=0; i < src->slen; i += UU_MAX_LINELEN) { - if ((jm = i + UU_MAX_LINELEN) > src->slen) jm = src->slen; - if (bconchar (out, UU_ENCODE_BYTE (jm - i)) < 0) { - bstrFree (out); - break; - } - for (j = i; j < jm; j += 3) { - c0 = (unsigned int) bchar (src, j ); - c1 = (unsigned int) bchar (src, j + 1); - c2 = (unsigned int) bchar (src, j + 2); - if (bconchar (out, UU_ENCODE_BYTE ( (c0 & 0xFC) >> 2)) < 0 || - bconchar (out, UU_ENCODE_BYTE (((c0 & 0x03) << 4) | ((c1 & 0xF0) >> 4))) < 0 || - bconchar (out, UU_ENCODE_BYTE (((c1 & 0x0F) << 2) | ((c2 & 0xC0) >> 6))) < 0 || - bconchar (out, UU_ENCODE_BYTE ( (c2 & 0x3F))) < 0) { - bstrFree (out); - goto End; - } - } - if (bconchar (out, (char) '\r') < 0 || bconchar (out, (char) '\n') < 0) { - bstrFree (out); - break; - } - } - End:; - return out; -} - -/* bstring bYEncode (const_bstring src) - * - * Performs a YEncode of a block of data. No header or tail info is - * appended. See: http://www.yenc.org/whatis.htm and - * http://www.yenc.org/yenc-draft.1.3.txt - */ -bstring bYEncode (const_bstring src) { -int i; -bstring out; -unsigned char c; - - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - for (i=0; i < src->slen; i++) { - c = (unsigned char)(src->data[i] + 42); - if (c == '=' || c == '\0' || c == '\r' || c == '\n') { - if (0 > bconchar (out, (char) '=')) { - bdestroy (out); - return NULL; - } - c += (unsigned char) 64; - } - if (0 > bconchar (out, c)) { - bdestroy (out); - return NULL; - } - } - return out; -} - -/* bstring bYDecode (const_bstring src) - * - * Performs a YDecode of a block of data. See: - * http://www.yenc.org/whatis.htm and http://www.yenc.org/yenc-draft.1.3.txt - */ -#define MAX_OB_LEN (64) - -bstring bYDecode (const_bstring src) { -int i; -bstring out; -unsigned char c; -unsigned char octetbuff[MAX_OB_LEN]; -int obl; - - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - - obl = 0; - - for (i=0; i < src->slen; i++) { - if ('=' == (c = src->data[i])) { /* The = escape mode */ - i++; - if (i >= src->slen) { - bdestroy (out); - return NULL; - } - c = (unsigned char) (src->data[i] - 64); - } else { - if ('\0' == c) { - bdestroy (out); - return NULL; - } - - /* Extraneous CR/LFs are to be ignored. */ - if (c == '\r' || c == '\n') continue; - } - - octetbuff[obl] = (unsigned char) ((int) c - 42); - obl++; - - if (obl >= MAX_OB_LEN) { - if (0 > bcatblk (out, octetbuff, obl)) { - bdestroy (out); - return NULL; - } - obl = 0; - } - } - - if (0 > bcatblk (out, octetbuff, obl)) { - bdestroy (out); - out = NULL; - } - return out; -} - -/* bstring bStrfTime (const char * fmt, const struct tm * timeptr) - * - * Takes a format string that is compatible with strftime and a struct tm - * pointer, formats the time according to the format string and outputs - * the bstring as a result. Note that if there is an early generation of a - * '\0' character, the bstring will be truncated to this end point. - */ -bstring bStrfTime (const char * fmt, const struct tm * timeptr) { -#if defined (__TURBOC__) && !defined (__BORLANDC__) -static struct tagbstring ns = bsStatic ("bStrfTime Not supported"); - fmt = fmt; - timeptr = timeptr; - return &ns; -#else -bstring buff; -int n; -size_t r; - - if (fmt == NULL) return NULL; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "strftime" call on increasing - potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < 16) n = 16; - buff = bfromcstralloc (n+2, ""); - - for (;;) { - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return NULL; - } - - r = strftime ((char *) buff->data, n + 1, fmt, timeptr); - - if (r > 0) { - buff->slen = (int) r; - break; - } - - n += n; - } - - return buff; -#endif -} - -/* int bSetCstrChar (bstring a, int pos, char c) - * - * Sets the character at position pos to the character c in the bstring a. - * If the character c is NUL ('\0') then the string is truncated at this - * point. Note: this does not enable any other '\0' character in the bstring - * as terminator indicator for the string. pos must be in the position - * between 0 and b->slen inclusive, otherwise BSTR_ERR will be returned. - */ -int bSetCstrChar (bstring b, int pos, char c) { - if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) - return BSTR_ERR; - if (pos < 0 || pos > b->slen) return BSTR_ERR; - - if (pos == b->slen) { - if ('\0' != c) return bconchar (b, c); - return 0; - } - - b->data[pos] = (unsigned char) c; - if ('\0' == c) b->slen = pos; - - return 0; -} - -/* int bSetChar (bstring b, int pos, char c) - * - * Sets the character at position pos to the character c in the bstring a. - * The string is not truncated if the character c is NUL ('\0'). pos must - * be in the position between 0 and b->slen inclusive, otherwise BSTR_ERR - * will be returned. - */ -int bSetChar (bstring b, int pos, char c) { - if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) - return BSTR_ERR; - if (pos < 0 || pos > b->slen) return BSTR_ERR; - - if (pos == b->slen) { - return bconchar (b, c); - } - - b->data[pos] = (unsigned char) c; - return 0; -} - -#define INIT_SECURE_INPUT_LENGTH (256) - -/* bstring bSecureInput (int maxlen, int termchar, - * bNgetc vgetchar, void * vgcCtx) - * - * Read input from an abstracted input interface, for a length of at most - * maxlen characters. If maxlen <= 0, then there is no length limit put - * on the input. The result is terminated early if vgetchar() return EOF - * or the user specified value termchar. - * - */ -bstring bSecureInput (int maxlen, int termchar, bNgetc vgetchar, void * vgcCtx) { -int i, m, c; -bstring b, t; - - if (!vgetchar) return NULL; - - b = bfromcstralloc (INIT_SECURE_INPUT_LENGTH, ""); - if ((c = UCHAR_MAX + 1) == termchar) c++; - - for (i=0; ; i++) { - if (termchar == c || (maxlen > 0 && i >= maxlen)) c = EOF; - else c = vgetchar (vgcCtx); - - if (EOF == c) break; - - if (i+1 >= b->mlen) { - - /* Double size, but deal with unusual case of numeric - overflows */ - - if ((m = b->mlen << 1) <= b->mlen && - (m = b->mlen + 1024) <= b->mlen && - (m = b->mlen + 16) <= b->mlen && - (m = b->mlen + 1) <= b->mlen) t = NULL; - else t = bfromcstralloc (m, ""); - - if (t) memcpy (t->data, b->data, i); - bSecureDestroy (b); /* Cleanse previous buffer */ - b = t; - if (!b) return b; - } - - b->data[i] = (unsigned char) c; - } - - b->slen = i; - b->data[i] = (unsigned char) '\0'; - return b; -} - -#define BWS_BUFF_SZ (1024) - -struct bwriteStream { - bstring buff; /* Buffer for underwrites */ - void * parm; /* The stream handle for core stream */ - bNwrite writeFn; /* fwrite work-a-like fnptr for core stream */ - int isEOF; /* track stream's EOF state */ - int minBuffSz; -}; - -/* struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) - * - * Wrap a given open stream (described by a fwrite work-a-like function - * pointer and stream handle) into an open bwriteStream suitable for write - * streaming functions. - */ -struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) { -struct bwriteStream * ws; - - if (NULL == writeFn) return NULL; - ws = (struct bwriteStream *) malloc (sizeof (struct bwriteStream)); - if (ws) { - if (NULL == (ws->buff = bfromcstr (""))) { - free (ws); - ws = NULL; - } else { - ws->parm = parm; - ws->writeFn = writeFn; - ws->isEOF = 0; - ws->minBuffSz = BWS_BUFF_SZ; - } - } - return ws; -} - -#define internal_bwswriteout(ws,b) { \ - if ((b)->slen > 0) { \ - if (1 != (ws->writeFn ((b)->data, (b)->slen, 1, ws->parm))) { \ - ws->isEOF = 1; \ - return BSTR_ERR; \ - } \ - } \ -} - -/* int bwsWriteFlush (struct bwriteStream * ws) - * - * Force any pending data to be written to the core stream. - */ -int bwsWriteFlush (struct bwriteStream * ws) { - if (NULL == ws || ws->isEOF || 0 >= ws->minBuffSz || - NULL == ws->writeFn || NULL == ws->buff) return BSTR_ERR; - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - return 0; -} - -/* int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) - * - * Send a bstring to a bwriteStream. If the stream is at EOF BSTR_ERR is - * returned. Note that there is no deterministic way to determine the exact - * cut off point where the core stream stopped accepting data. - */ -int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) { -struct tagbstring t; -int l; - - if (NULL == ws || NULL == b || NULL == ws->buff || - ws->isEOF || 0 >= ws->minBuffSz || NULL == ws->writeFn) - return BSTR_ERR; - - /* Buffer prepacking optimization */ - if (b->slen > 0 && ws->buff->mlen - ws->buff->slen > b->slen) { - static struct tagbstring empty = bsStatic (""); - if (0 > bconcat (ws->buff, b)) return BSTR_ERR; - return bwsWriteBstr (ws, &empty); - } - - if (0 > (l = ws->minBuffSz - ws->buff->slen)) { - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - l = ws->minBuffSz; - } - - if (b->slen < l) return bconcat (ws->buff, b); - - if (0 > bcatblk (ws->buff, b->data, l)) return BSTR_ERR; - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - - bmid2tbstr (t, (bstring) b, l, b->slen); - - if (t.slen >= ws->minBuffSz) { - internal_bwswriteout (ws, &t); - return 0; - } - - return bassign (ws->buff, &t); -} - -/* int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) - * - * Send a block of data a bwriteStream. If the stream is at EOF BSTR_ERR is - * returned. - */ -int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) { -struct tagbstring t; - if (NULL == blk || len < 0) return BSTR_ERR; - blk2tbstr (t, blk, len); - return bwsWriteBstr (ws, &t); -} - -/* int bwsIsEOF (const struct bwriteStream * ws) - * - * Returns 0 if the stream is currently writable, 1 if the core stream has - * responded by not accepting the previous attempted write. - */ -int bwsIsEOF (const struct bwriteStream * ws) { - if (NULL == ws || NULL == ws->buff || 0 > ws->minBuffSz || - NULL == ws->writeFn) return BSTR_ERR; - return ws->isEOF; -} - -/* int bwsBuffLength (struct bwriteStream * ws, int sz) - * - * Set the length of the buffer used by the bwsStream. If sz is zero, the - * length is not set. This function returns with the previous length. - */ -int bwsBuffLength (struct bwriteStream * ws, int sz) { -int oldSz; - if (ws == NULL || sz < 0) return BSTR_ERR; - oldSz = ws->minBuffSz; - if (sz > 0) ws->minBuffSz = sz; - return oldSz; -} - -/* void * bwsClose (struct bwriteStream * s) - * - * Close the bwriteStream, and return the handle to the stream that was - * originally used to open the given stream. Note that even if the stream - * is at EOF it still needs to be closed with a call to bwsClose. - */ -void * bwsClose (struct bwriteStream * ws) { -void * parm; - if (NULL == ws || NULL == ws->buff || 0 >= ws->minBuffSz || - NULL == ws->writeFn) return NULL; - bwsWriteFlush (ws); - parm = ws->parm; - ws->parm = NULL; - ws->minBuffSz = -1; - ws->writeFn = NULL; - bstrFree (ws->buff); - free (ws); - return parm; -} - diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h deleted file mode 100644 index e10c6e1a68..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstraux.h - * - * This file is not a necessary part of the core bstring library itself, but - * is just an auxilliary module which includes miscellaneous or trivial - * functions. - */ - -#ifndef BSTRAUX_INCLUDE -#define BSTRAUX_INCLUDE - -#include <time.h> -#include "bstrlib.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Safety mechanisms */ -#define bstrDeclare(b) bstring (b) = NULL; -#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }} - -/* Backward compatibilty with previous versions of Bstrlib */ -#define bAssign(a,b) ((bassign)((a), (b))) -#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) -#define bStrchr(b,c) ((bstrchr)((b), (c))) -#define bStrchrFast(b,c) ((bstrchr)((b), (c))) -#define bCatCstr(b,s) ((bcatcstr)((b), (s))) -#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) -#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1) -#define bTrunc(b,n) ((btrunc)((b), (n))) -#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos))) -#define bUppercase(b) ((btoupper)(b)) -#define bLowercase(b) ((btolower)(b)) -#define bCaselessCmp(a,b) ((bstricmp)((a), (b))) -#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n))) -#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL)) -#define bUuDecode(b) (bUuDecodeEx ((b), NULL)) - -/* Unusual functions */ -extern struct bStream * bsFromBstr (const_bstring b); -extern bstring bTail (bstring b, int n); -extern bstring bHead (bstring b, int n); -extern int bSetCstrChar (bstring a, int pos, char c); -extern int bSetChar (bstring b, int pos, char c); -extern int bFill (bstring a, char c, int len); -extern int bReplicate (bstring b, int n); -extern int bReverse (bstring b); -extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill); -extern bstring bStrfTime (const char * fmt, const struct tm * timeptr); -#define bAscTime(t) (bStrfTime ("%c\n", (t))) -#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL) - -/* Spacing formatting */ -extern int bJustifyLeft (bstring b, int space); -extern int bJustifyRight (bstring b, int width, int space); -extern int bJustifyMargin (bstring b, int width, int space); -extern int bJustifyCenter (bstring b, int width, int space); - -/* Esoteric standards specific functions */ -extern char * bStr2NetStr (const_bstring b); -extern bstring bNetStr2Bstr (const char * buf); -extern bstring bBase64Encode (const_bstring b); -extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError); -extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines); -extern bstring bUuDecodeEx (const_bstring src, int * badlines); -extern bstring bUuEncode (const_bstring src); -extern bstring bYEncode (const_bstring src); -extern bstring bYDecode (const_bstring src); - -/* Writable stream */ -typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm); - -struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm); -int bwsWriteBstr (struct bwriteStream * stream, const_bstring b); -int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len); -int bwsWriteFlush (struct bwriteStream * stream); -int bwsIsEOF (const struct bwriteStream * stream); -int bwsBuffLength (struct bwriteStream * stream, int sz); -void * bwsClose (struct bwriteStream * stream); - -/* Security functions */ -#define bSecureDestroy(b) { \ -bstring bstr__tmp = (b); \ - if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \ - (void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \ - bdestroy (bstr__tmp); \ - } \ -} -#define bSecureWriteProtect(t) { \ - if ((t).mlen >= 0) { \ - if ((t).mlen > (t).slen)) { \ - (void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \ - } \ - (t).mlen = -1; \ - } \ -} -extern bstring bSecureInput (int maxlen, int termchar, - bNgetc vgetchar, void * vgcCtx); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c deleted file mode 100644 index 7c233454ba..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c +++ /dev/null @@ -1,2976 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstrlib.c - * - * This file is the core module for implementing the bstring functions. - */ - -#include <stdio.h> -#include <stddef.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "bstrlib.h" -#include "../internal_includes/hlslcc_malloc.h" - -/* Optionally include a mechanism for debugging memory */ - -#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) -#include "memdbg.h" -#endif - -#ifndef bstr__alloc -#define bstr__alloc(x) malloc (x) -#endif - -#ifndef bstr__free -#define bstr__free(p) free (p) -#endif - -#ifndef bstr__realloc -#define bstr__realloc(p,x) realloc ((p), (x)) -#endif - -#ifndef bstr__memcpy -#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) -#endif - -#ifndef bstr__memmove -#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) -#endif - -#ifndef bstr__memset -#define bstr__memset(d,c,l) memset ((d), (c), (l)) -#endif - -#ifndef bstr__memcmp -#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) -#endif - -#ifndef bstr__memchr -#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) -#endif - -/* Just a length safe wrapper for memmove. */ - -#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } - -/* Compute the snapped size for a given requested size. By snapping to powers - of 2 like this, repeated reallocations are avoided. */ -static int snapUpSize (int i) { - if (i < 8) { - i = 8; - } else { - unsigned int j; - j = (unsigned int) i; - - j |= (j >> 1); - j |= (j >> 2); - j |= (j >> 4); - j |= (j >> 8); /* Ok, since int >= 16 bits */ -#if (UINT_MAX != 0xffff) - j |= (j >> 16); /* For 32 bit int systems */ -#if (UINT_MAX > 0xffffffffUL) - j |= (j >> 32); /* For 64 bit int systems */ -#endif -#endif - /* Least power of two greater than i */ - j++; - if ((int) j >= i) i = (int) j; - } - return i; -} - -/* int balloc (bstring b, int len) - * - * Increase the size of the memory backing the bstring b to at least len. - */ -int balloc (bstring b, int olen) { - int len; - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || - b->mlen < b->slen || olen <= 0) { - return BSTR_ERR; - } - - if (olen >= b->mlen) { - unsigned char * x; - - if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; - - /* Assume probability of a non-moving realloc is 0.125 */ - if (7 * b->mlen < 8 * b->slen) { - - /* If slen is close to mlen in size then use realloc to reduce - the memory defragmentation */ - - reallocStrategy:; - - x = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (x == NULL) { - - /* Since we failed, try allocating the tighest possible - allocation */ - - if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { - return BSTR_ERR; - } - } - } else { - - /* If slen is not close to mlen then avoid the penalty of copying - the extra bytes that are allocated, but not considered part of - the string */ - - if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { - - /* Perhaps there is no available memory for the two - allocations to be in memory at once */ - - goto reallocStrategy; - - } else { - if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); - bstr__free (b->data); - } - } - b->data = x; - b->mlen = len; - b->data[b->slen] = (unsigned char) '\0'; - } - - return BSTR_OK; -} - -/* int ballocmin (bstring b, int len) - * - * Set the size of the memory backing the bstring b to len or b->slen+1, - * whichever is larger. Note that repeated use of this function can degrade - * performance. - */ -int ballocmin (bstring b, int len) { - unsigned char * s; - - if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || - b->mlen < b->slen || len <= 0) { - return BSTR_ERR; - } - - if (len < b->slen + 1) len = b->slen + 1; - - if (len != b->mlen) { - s = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (NULL == s) return BSTR_ERR; - s[b->slen] = (unsigned char) '\0'; - b->data = s; - b->mlen = len; - } - - return BSTR_OK; -} - -/* bstring bfromcstr (const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. - */ -bstring bfromcstr (const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; - b->slen = (int) j; - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring bfromcstralloc (int mlen, const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. The memory buffer backing the string is at least len - * characters in length. - */ -bstring bfromcstralloc (int mlen, const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = (int) j; - if (i < mlen) i = mlen; - - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring blk2bstr (const void * blk, int len) - * - * Create a bstring which contains the content of the block blk of length - * len. - */ -bstring blk2bstr (const void * blk, int len) { -bstring b; -int i; - - if (blk == NULL || len < 0) return NULL; - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = len; - - i = len + (2 - (len != 0)); - i = snapUpSize (i); - - b->mlen = i; - - b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); - b->data[len] = (unsigned char) '\0'; - - return b; -} - -/* char * bstr2cstr (const_bstring s, char z) - * - * Create a '\0' terminated char * buffer which is equal to the contents of - * the bstring s, except that any contained '\0' characters are converted - * to the character in z. This returned value should be freed with a - * bcstrfree () call, by the calling application. - */ -char * bstr2cstr (const_bstring b, char z) { -int i, l; -char * r; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - l = b->slen; - r = (char *) bstr__alloc ((size_t) (l + 1)); - if (r == NULL) return r; - - for (i=0; i < l; i ++) { - r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); - } - - r[l] = (unsigned char) '\0'; - - return r; -} - -/* int bcstrfree (char * s) - * - * Frees a C-string generated by bstr2cstr (). This is normally unnecessary - * since it just wraps a call to bstr__free (), however, if bstr__alloc () - * and bstr__free () have been redefined as a macros within the bstrlib - * module (via defining them in memdbg.h after defining - * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std - * library functions, then this allows a correct way of freeing the memory - * that allows higher level code to be independent from these macro - * redefinitions. - */ -int bcstrfree (char * s) { - if (s) { - bstr__free (s); - return BSTR_OK; - } - return BSTR_ERR; -} - -/* int bconcat (bstring b0, const_bstring b1) - * - * Concatenate the bstring b1 to the bstring b0. - */ -int bconcat (bstring b0, const_bstring b1) { -int len, d; -bstring aux = (bstring) b1; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; - - d = b0->slen; - len = b1->slen; - if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; - - if (b0->mlen <= d + len + 1) { - ptrdiff_t pd = b1->data - b0->data; - if (0 <= pd && pd < b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - if (balloc (b0, d + len + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - } - - bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); - b0->data[d + len] = (unsigned char) '\0'; - b0->slen = d + len; - if (aux != b1) bdestroy (aux); - return BSTR_OK; -} - -/* int bconchar (bstring b, char c) -/ * - * Concatenate the single character c to the bstring b. - */ -int bconchar (bstring b, char c) { -int d; - - if (b == NULL) return BSTR_ERR; - d = b->slen; - if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - b->data[d] = (unsigned char) c; - b->data[d + 1] = (unsigned char) '\0'; - b->slen++; - return BSTR_OK; -} - -/* int bcatcstr (bstring b, const char * s) - * - * Concatenate a char * string to a bstring. - */ -int bcatcstr (bstring b, const char * s) { -char * d; -int i, l; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL) return BSTR_ERR; - - /* Optimistically concatenate directly */ - l = b->mlen - b->slen; - d = (char *) &b->data[b->slen]; - for (i=0; i < l; i++) { - if ((*d++ = *s++) == '\0') { - b->slen += i; - return BSTR_OK; - } - } - b->slen += i; - - /* Need to explicitely resize and concatenate tail */ - return bcatblk (b, (const void *) s, (int) strlen (s)); -} - -/* int bcatblk (bstring b, const void * s, int len) - * - * Concatenate a fixed length buffer to a bstring. - */ -int bcatblk (bstring b, const void * s, int len) { -int nl; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; - - if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ - if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; - - bBlockCopy (&b->data[b->slen], s, (size_t) len); - b->slen = nl; - b->data[nl] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bstrcpy (const_bstring b) - * - * Create a copy of the bstring b. - */ -bstring bstrcpy (const_bstring b) { -bstring b0; -int i,j; - - /* Attempted to copy an invalid string? */ - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b0 == NULL) { - /* Unable to allocate memory for string header */ - return NULL; - } - - i = b->slen; - j = snapUpSize (i + 1); - - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - j = i + 1; - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - /* Unable to allocate memory for string data */ - bstr__free (b0); - return NULL; - } - } - - b0->mlen = j; - b0->slen = i; - - if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); - b0->data[b0->slen] = (unsigned char) '\0'; - - return b0; -} - -/* int bassign (bstring a, const_bstring b) - * - * Overwrite the string a with the contents of string b. - */ -int bassign (bstring a, const_bstring b) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - if (b->slen != 0) { - if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data, b->slen); - } else { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - } - a->data[b->slen] = (unsigned char) '\0'; - a->slen = b->slen; - return BSTR_OK; -} - -/* int bassignmidstr (bstring a, const_bstring b, int left, int len) - * - * Overwrite the string a with the middle of contents of string b - * starting from position left and running for a length len. left and - * len are clamped to the ends of b as with the function bmidstr. - */ -int bassignmidstr (bstring a, const_bstring b, int left, int len) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - - if (len > 0) { - if (balloc (a, len) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data + left, len); - a->slen = len; - } else { - a->slen = 0; - } - a->data[a->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bassigncstr (bstring a, const char * str) - * - * Overwrite the string a with the contents of char * string str. Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned however a may be partially overwritten. - */ -int bassigncstr (bstring a, const char * str) { -int i; -size_t len; - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == str) - return BSTR_ERR; - - for (i=0; i < a->mlen; i++) { - if ('\0' == (a->data[i] = str[i])) { - a->slen = i; - return BSTR_OK; - } - } - - a->slen = i; - len = strlen (str + i); - if (len > INT_MAX || i + len + 1 > INT_MAX || - 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; - bBlockCopy (a->data + i, str + i, (size_t) len + 1); - a->slen += (int) len; - return BSTR_OK; -} - -/* int bassignblk (bstring a, const void * s, int len) - * - * Overwrite the string a with the contents of the block (s, len). Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned and a is not overwritten. - */ -int bassignblk (bstring a, const void * s, int len) { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) - return BSTR_ERR; - if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; - bBlockCopy (a->data, s, (size_t) len); - a->data[len] = (unsigned char) '\0'; - a->slen = len; - return BSTR_OK; -} - -/* int btrunc (bstring b, int n) - * - * Truncate the bstring to at most n characters. - */ -int btrunc (bstring b, int n) { - if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - if (b->slen > n) { - b->slen = n; - b->data[n] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -#define upcase(c) (toupper ((unsigned char) c)) -#define downcase(c) (tolower ((unsigned char) c)) -#define wspace(c) (isspace ((unsigned char) c)) - -/* int btoupper (bstring b) - * - * Convert contents of bstring to upper case. - */ -int btoupper (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) upcase (b->data[i]); - } - return BSTR_OK; -} - -/* int btolower (bstring b) - * - * Convert contents of bstring to lower case. - */ -int btolower (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) downcase (b->data[i]); - } - return BSTR_OK; -} - -/* int bstricmp (const_bstring b0, const_bstring b1) - * - * Compare two strings without differentiating between case. The return - * value is the difference of the values of the characters where the two - * strings first differ after lower case transformation, otherwise 0 is - * returned indicating that the strings are equal. If the lengths are - * different, then a difference from 0 is given, but if the first extra - * character is '\0', then it is taken to be the value UCHAR_MAX+1. - */ -int bstricmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; - if ((n = b0->slen) > b1->slen) n = b1->slen; - else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = (char) downcase (b0->data[i]) - - (char) downcase (b1->data[i]); - if (0 != v) return v; - } - - if (b0->slen > n) { - v = (char) downcase (b0->data[n]); - if (v) return v; - return UCHAR_MAX + 1; - } - if (b1->slen > n) { - v = - (char) downcase (b1->data[n]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); - } - return BSTR_OK; -} - -/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) - * - * Compare two strings without differentiating between case for at most n - * characters. If the position where the two strings first differ is - * before the nth position, the return value is the difference of the values - * of the characters, otherwise 0 is returned. If the lengths are different - * and less than n characters, then a difference from 0 is given, but if the - * first extra character is '\0', then it is taken to be the value - * UCHAR_MAX+1. - */ -int bstrnicmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = (char) downcase (b0->data[i]); - v -= (char) downcase (b1->data[i]); - if (v != 0) return b0->data[i] - b1->data[i]; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) { - v = (char) downcase (b0->data[m]); - if (v) return v; - return UCHAR_MAX + 1; - } - - v = - (char) downcase (b1->data[m]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); -} - -/* int biseqcaseless (const_bstring b0, const_bstring b1) - * - * Compare two strings for equality without differentiating between case. - * If the strings differ other than in case, 0 is returned, if the strings - * are the same, 1 is returned, if there is an error, -1 is returned. If - * the length of the strings are different, this function is O(1). '\0' - * termination characters are not treated in any special way. - */ -int biseqcaseless (const_bstring b0, const_bstring b1) { -int i, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - for (i=0, n=b0->slen; i < n; i++) { - if (b0->data[i] != b1->data[i]) { - unsigned char c = (unsigned char) downcase (b0->data[i]); - if (c != (unsigned char) downcase (b1->data[i])) return 0; - } - } - return 1; -} - -/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len - * without differentiating between case for equality. If the beginning of b0 - * differs from the memory block other than in case (or if b0 is too short), - * 0 is returned, if the strings are the same, 1 is returned, if there is an - * error, -1 is returned. '\0' characters are not treated in any special - * way. - */ -int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) { - if (downcase (b0->data[i]) != - downcase (((const unsigned char *) blk)[i])) return 0; - } - } - return 1; -} - -/* - * int bltrimws (bstring b) - * - * Delete whitespace contiguous from the left end of the string. - */ -int bltrimws (bstring b) { -int i, len; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (len = b->slen, i = 0; i < len; i++) { - if (!wspace (b->data[i])) { - return bdelete (b, 0, i); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int brtrimws (bstring b) - * - * Delete whitespace contiguous from the right end of the string. - */ -int brtrimws (bstring b) { -int i; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - return BSTR_OK; - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int btrimws (bstring b) - * - * Delete whitespace contiguous from both ends of the string. - */ -int btrimws (bstring b) { -int i, j; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - for (j = 0; wspace (b->data[j]); j++) {} - return bdelete (b, 0, j); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* int biseq (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If the strings differ, 0 is returned, if - * the strings are the same, 1 is returned, if there is an error, -1 is - * returned. If the length of the strings are different, this function is - * O(1). '\0' termination characters are not treated in any special way. - */ -int biseq (const_bstring b0, const_bstring b1) { - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - return !bstr__memcmp (b0->data, b1->data, b0->slen); -} - -/* int bisstemeqblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len for - * equality. If the beginning of b0 differs from the memory block (or if b0 - * is too short), 0 is returned, if the strings are the same, 1 is returned, - * if there is an error, -1 is returned. '\0' characters are not treated in - * any special way. - */ -int bisstemeqblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; - } - return 1; -} - -/* int biseqcstr (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical with the bstring b with no '\0' - * characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal when comparing them in the same format after converting one or the - * other. If the strings are equal 1 is returned, if they are unequal 0 is - * returned and if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstr (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int biseqcstrcaseless (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical except for case with the bstring b with - * no '\0' characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal ignoring case when comparing them in the same format after - * converting one or the other. If the strings are equal, except for case, - * 1 is returned, if they are unequal regardless of case 0 is returned and - * if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstrcaseless (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || - (b->data[i] != (unsigned char) s[i] && - downcase (b->data[i]) != (unsigned char) downcase (s[i]))) - return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int bstrcmp (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, - * otherwise a value less than or greater than zero, indicating that the - * string pointed to by b0 is lexicographically less than or greater than - * the string pointed to by b1 is returned. If the the string lengths are - * unequal but the characters up until the length of the shorter are equal - * then a value less than, or greater than zero, indicating that the string - * pointed to by b0 is shorter or longer than the string pointed to by b1 is - * returned. 0 is returned if and only if the two strings are the same. If - * the length of the strings are different, this function is O(n). Like its - * standard C library counter part strcmp, the comparison does not proceed - * past any '\0' termination characters encountered. - */ -int bstrcmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - n = b0->slen; if (n > b1->slen) n = b1->slen; - if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) - return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - - if (b0->slen > n) return 1; - if (b1->slen > n) return -1; - return BSTR_OK; -} - -/* int bstrncmp (const_bstring b0, const_bstring b1, int n) - * - * Compare the string b0 and b1 for at most n characters. If there is an - * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and - * b1 were first truncated to at most n characters then bstrcmp was called - * with these new strings are paremeters. If the length of the strings are - * different, this function is O(n). Like its standard C library counter - * part strcmp, the comparison does not proceed past any '\0' termination - * characters encountered. - */ -int bstrncmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) return 1; - return -1; -} - -/* bstring bmidstr (const_bstring b, int left, int len) - * - * Create a bstring which is the substring of b starting from position left - * and running for a length len (clamped by the end of the bstring b.) If - * b is detectably invalid, then NULL is returned. The section described - * by (left, len) is clamped to the boundaries of b. - */ -bstring bmidstr (const_bstring b, int left, int len) { - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (len <= 0) return bfromcstr (""); - return blk2bstr (b->data + left, len); -} - -/* int bdelete (bstring b, int pos, int len) - * - * Removes characters from pos to pos+len-1 inclusive and shifts the tail of - * the bstring starting from pos+len to pos. len must be positive for this - * call to have any effect. The section of the string described by (pos, - * len) is clamped to boundaries of the bstring b. - */ -int bdelete (bstring b, int pos, int len) { - /* Clamp to left side of bstring */ - if (pos < 0) { - len += pos; - pos = 0; - } - - if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || - b->mlen < b->slen || b->mlen <= 0) - return BSTR_ERR; - if (len > 0 && pos < b->slen) { - if (pos + len >= b->slen) { - b->slen = pos; - } else { - bBlockCopy ((char *) (b->data + pos), - (char *) (b->data + pos + len), - b->slen - (pos+len)); - b->slen -= len; - } - b->data[b->slen] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -/* int bdestroy (bstring b) - * - * Free up the bstring. Note that if b is detectably invalid or not writable - * then no action is performed and BSTR_ERR is returned. Like a freed memory - * allocation, dereferences, writes or any other action on b after it has - * been bdestroyed is undefined. - */ -int bdestroy (bstring b) { - if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || - b->data == NULL) - return BSTR_ERR; - - bstr__free (b->data); - - /* In case there is any stale usage, there is one more chance to - notice this error. */ - - b->slen = -1; - b->mlen = -__LINE__; - b->data = NULL; - - bstr__free (b); - return BSTR_OK; -} - -/* int binstr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstr (const_bstring b1, int pos, const_bstring b2) { -int j, ii, ll, lf; -unsigned char * d0; -unsigned char c0; -register unsigned char * d1; -register unsigned char c1; -register int i; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* No space to find such a string? */ - if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return 0; - - i = pos; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - /* Peel off the b2->slen == 1 case */ - c0 = d0[0]; - if (1 == ll) { - for (;i < lf; i++) if (c0 == d1[i]) return i; - return BSTR_ERR; - } - - c1 = c0; - j = 0; - lf = b1->slen - 1; - - ii = -1; - if (i < lf) do { - /* Unrolled current character test */ - if (c1 != d1[i]) { - if (c1 != d1[1+i]) { - i += 2; - continue; - } - i++; - } - - /* Take note if this is the start of a potential match */ - if (0 == j) ii = i; - - /* Shift the test character down by one */ - j++; - i++; - - /* If this isn't past the last character continue */ - if (j < ll) { - c1 = d0[j]; - continue; - } - - N0:; - - /* If no characters mismatched, then we matched */ - if (i == ii+j) return ii; - - /* Shift back to the beginning */ - i -= j; - j = 0; - c1 = c0; - } while (i < lf); - - /* Deal with last case if unrolling caused a misalignment */ - if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; - - return BSTR_ERR; -} - -/* int binstrr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstrr (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j]) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l, ll; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - l = b1->slen - b2->slen + 1; - - /* No space to find such a string? */ - if (l <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return BSTR_OK; - - i = pos; - j = 0; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= ll) return i; - } else { - i ++; - if (i >= l) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - - -/* int bstrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b forwards from the position pos - * (inclusive). - */ -int bstrchrp (const_bstring b, int c, int pos) { -unsigned char * p; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); - if (p) return (int) (p - b->data); - return BSTR_ERR; -} - -/* int bstrrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b backwards from the position pos in string - * (inclusive). - */ -int bstrrchrp (const_bstring b, int c, int pos) { -int i; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - for (i=pos; i >= 0; i--) { - if (b->data[i] == (unsigned char) c) return i; - } - return BSTR_ERR; -} - -#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) -#define LONG_LOG_BITS_QTY (3) -#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) -#define LONG_TYPE unsigned char - -#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) -struct charField { LONG_TYPE content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) -#define setInCharField(cf,idx) { \ - unsigned int c = (unsigned int) (idx); \ - (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ -} - -#else - -#define CFCLEN (1 << CHAR_BIT) -struct charField { unsigned char content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) -#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 - -#endif - -/* Convert a bstring to charField */ -static int buildCharField (struct charField * cf, const_bstring b) { -int i; - if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; - memset ((void *) cf->content, 0, sizeof (struct charField)); - for (i=0; i < b->slen; i++) { - setInCharField (cf, b->data[i]); - } - return BSTR_OK; -} - -static void invertCharField (struct charField * cf) { -int i; - for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; -} - -/* Inner engine for binchr */ -static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { -int i; - for (i=pos; i < len; i++) { - unsigned char c = (unsigned char) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * one of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int binchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* Inner engine for binchrr */ -static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { -int i; - for (i=pos; i >= 0; i--) { - unsigned int c = (unsigned int) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which one of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int binchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bninchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * none of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int bninchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* int bninchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which none of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int bninchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) - * - * Overwrite the string b0 starting at position pos with the string b1. If - * the position pos is past the end of b0, then the character "fill" is - * appended as necessary to make up the gap between the end of b0 and pos. - * If b1 is NULL, it behaves as if it were a 0-length string. - */ -int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { -int d, newlen; -ptrdiff_t pd; -bstring aux = (bstring) b1; - - if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || - b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; - if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; - - d = pos; - - /* Aliasing case */ - if (NULL != aux) { - if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - d += aux->slen; - } - - /* Increase memory size if necessary */ - if (balloc (b0, d + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - - newlen = b0->slen; - - /* Fill in "fill" character as necessary */ - if (pos > newlen) { - bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); - newlen = pos; - } - - /* Copy b1 to position pos in b0. */ - if (aux != NULL) { - bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); - if (aux != b1) bdestroy (aux); - } - - /* Indicate the potentially increased size of b0 */ - if (d > newlen) newlen = d; - - b0->slen = newlen; - b0->data[newlen] = (unsigned char) '\0'; - - return BSTR_OK; -} - -/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) - * - * Inserts the string b2 into b1 at position pos. If the position pos is - * past the end of b1, then the character "fill" is appended as necessary to - * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert - * does not allow b2 to be NULL. - */ -int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { -int d, l; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || - b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - /* Compute the two possible end pointers */ - d = b1->slen + aux->slen; - l = pos + aux->slen; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b1, l + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); - b1->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b1, d + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bBlockCopy (b1->data + l, b1->data + pos, d - l); - b1->slen = d; - } - bBlockCopy (b1->data + pos, aux->data, aux->slen); - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* int breplace (bstring b1, int pos, int len, bstring b2, - * unsigned char fill) - * - * Replace a section of a string from pos for a length len with the string b2. - * fill is used is pos > b1->slen. - */ -int breplace (bstring b1, int pos, int len, const_bstring b2, - unsigned char fill) { -int pl, ret; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || - b2 == NULL || b1->data == NULL || b2->data == NULL || - b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || - b1->mlen <= 0) return BSTR_ERR; - - /* Straddles the end? */ - if (pl >= b1->slen) { - if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; - if (pos + b2->slen < b1->slen) { - b1->slen = pos + b2->slen; - b1->data[b1->slen] = (unsigned char) '\0'; - } - return ret; - } - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - if (aux->slen > len) { - if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - } - - if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); - bstr__memcpy (b1->data + pos, aux->data, aux->slen); - b1->slen += aux->slen - len; - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* - * findreplaceengine is used to implement bfindreplace and - * bfindreplacecaseless. It works by breaking the three cases of - * expansion, reduction and replacement, and solving each of these - * in the most efficient way possible. - */ - -typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); - -#define INITIAL_STATIC_FIND_INDEX_COUNT 32 - -static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { -int i, ret, slen, mlen, delta, acc; -int * d; -int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */ -ptrdiff_t pd; -bstring auxf = (bstring) find; -bstring auxr = (bstring) repl; - - if (b == NULL || b->data == NULL || find == NULL || - find->data == NULL || repl == NULL || repl->data == NULL || - pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || - b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; - if (pos > b->slen - find->slen) return BSTR_OK; - - /* Alias with find string */ - pd = (ptrdiff_t) (find->data - b->data); - if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; - } - - /* Alias with repl string */ - pd = (ptrdiff_t) (repl->data - b->data); - if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxr = bstrcpy (repl))) { - if (auxf != find) bdestroy (auxf); - return BSTR_ERR; - } - } - - delta = auxf->slen - auxr->slen; - - /* in-place replacement since find and replace strings are of equal - length */ - if (delta == 0) { - while ((pos = instr (b, pos, auxf)) >= 0) { - bstr__memcpy (b->data + pos, auxr->data, auxr->slen); - pos += auxf->slen; - } - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* shrinking replacement since auxf->slen > auxr->slen */ - if (delta > 0) { - acc = 0; - - while ((i = instr (b, pos, auxf)) >= 0) { - if (acc && i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - if (auxr->slen) - bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); - acc += delta; - pos = i + auxf->slen; - } - - if (acc) { - i = b->slen; - if (i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - b->slen -= acc; - b->data[b->slen] = (unsigned char) '\0'; - } - - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* expanding replacement since find->slen < repl->slen. Its a lot - more complicated. This works by first finding all the matches and - storing them to a growable array, then doing at most one resize of - the destination bstring and then performing the direct memory transfers - of the string segment pieces to form the final result. The growable - array of matches uses a deferred doubling reallocing strategy. What - this means is that it starts as a reasonably fixed sized auto array in - the hopes that many if not most cases will never need to grow this - array. But it switches as soon as the bounds of the array will be - exceeded. An extra find result is always appended to this array that - corresponds to the end of the destination string, so slen is checked - against mlen - 1 rather than mlen before resizing. - */ - - mlen = INITIAL_STATIC_FIND_INDEX_COUNT; - d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ - acc = slen = 0; - - while ((pos = instr (b, pos, auxf)) >= 0) { - if (slen >= mlen - 1) { - int sl, *t; - - mlen += mlen; - sl = sizeof (int *) * mlen; - if (static_d == d) d = NULL; /* static_d cannot be realloced */ - if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { - ret = BSTR_ERR; - goto done; - } - if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); - d = t; - } - d[slen] = pos; - slen++; - acc -= delta; - pos += auxf->slen; - if (pos < 0 || acc < 0) { - ret = BSTR_ERR; - goto done; - } - } - - /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ - d[slen] = b->slen; - - if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { - b->slen += acc; - for (i = slen-1; i >= 0; i--) { - int s, l; - s = d[i] + auxf->slen; - l = d[i+1] - s; /* d[slen] may be accessed here. */ - if (l) { - bstr__memmove (b->data + s + acc, b->data + s, l); - } - if (auxr->slen) { - bstr__memmove (b->data + s + acc - auxr->slen, - auxr->data, auxr->slen); - } - acc += delta; - } - b->data[b->slen] = (unsigned char) '\0'; - } - - done:; - if (static_d == d) d = NULL; - bstr__free (d); - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return ret; -} - -/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string with a replace string after a - * given point in a bstring. - */ -int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstr); -} - -/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string, ignoring case, with a replace - * string after a given point in a bstring. - */ -int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstrcaseless); -} - -/* int binsertch (bstring b, int pos, int len, unsigned char fill) - * - * Inserts the character fill repeatedly into b at position pos for a - * length len. If the position pos is past the end of b, then the - * character "fill" is appended as necessary to make up the gap between the - * end of b and the position pos + len. - */ -int binsertch (bstring b, int pos, int len, unsigned char fill) { -int d, l, i; - - if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || len < 0) return BSTR_ERR; - - /* Compute the two possible end pointers */ - d = b->slen + len; - l = pos + len; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; - pos = b->slen; - b->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; - for (i = d - 1; i >= l; i--) { - b->data[i] = b->data[i - len]; - } - b->slen = d; - } - - for (i=pos; i < l; i++) b->data[i] = fill; - b->data[b->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bpattern (bstring b, int len) - * - * Replicate the bstring, b in place, end to end repeatedly until it - * surpasses len characters, then chop the result to exactly len characters. - * This function operates in-place. The function will return with BSTR_ERR - * if b is NULL or of length 0, otherwise BSTR_OK is returned. - */ -int bpattern (bstring b, int len) { -int i, d; - - d = blength (b); - if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; - if (len > 0) { - if (d == 1) return bsetstr (b, len, NULL, b->data[0]); - for (i = d; i < len; i++) b->data[i] = b->data[i - d]; - } - b->data[len] = (unsigned char) '\0'; - b->slen = len; - return BSTR_OK; -} - -#define BS_BUFF_SZ (1024) - -/* int breada (bstring b, bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to concatenate to the - * bstring b the entire contents of file-like source data in a roughly - * efficient way. - */ -int breada (bstring b, bNread readPtr, void * parm) { -int i, l, n; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; - - i = b->slen; - for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { - if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; - l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); - i += l; - b->slen = i; - if (i < n) break; - } - - b->data[i] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bread (bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to create a bstring - * filled with the entire contents of file-like source data in a roughly - * efficient way. - */ -bstring bread (bNread readPtr, void * parm) { -bstring buff; - - if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { - bdestroy (buff); - return NULL; - } - return buff; -} - -/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result in b. If there is an empty partial - * result, 1 is returned. If no characters are read, or there is some other - * detectable error, BSTR_ERR is returned. - */ -int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = 0; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result concatentated to b. If there is - * an empty partial result, 1 is returned. If no characters are read, or - * there is some other detectable error, BSTR_ERR is returned. - */ -int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = b->slen; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* bstring bgets (bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated into a bstring. - * The stream read is terminated by the passed in terminator function. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * result obtained thus far is returned. If no characters are read, or - * there is some other detectable error, NULL is returned. - */ -bstring bgets (bNgetc getcPtr, void * parm, char terminator) { -bstring buff; - - if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { - bdestroy (buff); - buff = NULL; - } - return buff; -} - -struct bStream { - bstring buff; /* Buffer for over-reads */ - void * parm; /* The stream handle for core stream */ - bNread readFnPtr; /* fread compatible fnptr for core stream */ - int isEOF; /* track file's EOF state */ - int maxBuffSz; -}; - -/* struct bStream * bsopen (bNread readPtr, void * parm) - * - * Wrap a given open stream (described by a fread compatible function - * pointer and stream handle) into an open bStream suitable for the bstring - * library streaming functions. - */ -struct bStream * bsopen (bNread readPtr, void * parm) { -struct bStream * s; - - if (readPtr == NULL) return NULL; - s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); - if (s == NULL) return NULL; - s->parm = parm; - s->buff = bfromcstr (""); - s->readFnPtr = readPtr; - s->maxBuffSz = BS_BUFF_SZ; - s->isEOF = 0; - return s; -} - -/* int bsbufflength (struct bStream * s, int sz) - * - * Set the length of the buffer used by the bStream. If sz is zero, the - * length is not set. This function returns with the previous length. - */ -int bsbufflength (struct bStream * s, int sz) { -int oldSz; - if (s == NULL || sz < 0) return BSTR_ERR; - oldSz = s->maxBuffSz; - if (sz > 0) s->maxBuffSz = sz; - return oldSz; -} - -int bseof (const struct bStream * s) { - if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; - return s->isEOF && (s->buff->slen == 0); -} - -/* void * bsclose (struct bStream * s) - * - * Close the bStream, and return the handle to the stream that was originally - * used to open the given stream. - */ -void * bsclose (struct bStream * s) { -void * parm; - if (s == NULL) return NULL; - s->readFnPtr = NULL; - if (s->buff) bdestroy (s->buff); - s->buff = NULL; - parm = s->parm; - s->parm = NULL; - s->isEOF = 1; - bstr__free (s); - return parm; -} - -/* int bsreadlna (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadlna (bstring r, struct bStream * s, char terminator) { -int i, l, ret, rlo; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || - r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - /* First check if the current buffer holds the terminator */ - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { -int i, l, ret, rlo; -unsigned char * b; -struct tagbstring x; -struct charField cf; - - if (s == NULL || s->buff == NULL || r == NULL || term == NULL || - term->data == NULL || r->mlen <= 0 || r->slen < 0 || - r->mlen < r->slen) return BSTR_ERR; - if (term->slen == 1) return bsreadlna (r, s, term->data[0]); - if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; - - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) s->buff->data; - x.data = b; - - /* First check if the current buffer holds the terminator */ - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreada (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsreada (bstring r, struct bStream * s, int n) { -int l, ret, orslen; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; - - n += r->slen; - if (n <= 0) return BSTR_ERR; - - l = s->buff->slen; - - orslen = r->slen; - - if (0 == l) { - if (s->isEOF) return BSTR_ERR; - if (r->mlen > n) { - l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); - if (0 >= l || l > n - r->slen) { - s->isEOF = 1; - return BSTR_ERR; - } - r->slen += l; - r->data[r->slen] = (unsigned char) '\0'; - return 0; - } - } - - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - do { - if (l + r->slen >= n) { - x.slen = n - r->slen; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); - return BSTR_ERR & -(r->slen == orslen); - } - - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) break; - - l = n - r->slen; - if (l > s->maxBuffSz) l = s->maxBuffSz; - - l = (int) s->readFnPtr (b, 1, l, s->parm); - - } while (l > 0); - if (l < 0) l = 0; - if (l == 0) s->isEOF = 1; - s->buff->slen = l; - return BSTR_ERR & -(r->slen == orslen); -} - -/* int bsreadln (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadln (bstring r, struct bStream * s, char terminator) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) - return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlna (r, s, terminator); -} - -/* int bsreadlns (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlns (bstring r, struct bStream * s, const_bstring term) { - if (s == NULL || s->buff == NULL || r == NULL || term == NULL - || term->data == NULL || r->mlen <= 0) return BSTR_ERR; - if (term->slen == 1) return bsreadln (r, s, term->data[0]); - if (term->slen < 1) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlnsa (r, s, term); -} - -/* int bsread (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsread (bstring r, struct bStream * s, int n) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || n <= 0) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreada (r, s, n); -} - -/* int bsunread (struct bStream * s, const_bstring b) - * - * Insert a bstring into the bStream at the current position. These - * characters will be read prior to those that actually come from the core - * stream. - */ -int bsunread (struct bStream * s, const_bstring b) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return binsert (s->buff, 0, b, (unsigned char) '?'); -} - -/* int bspeek (bstring r, const struct bStream * s) - * - * Return the currently buffered characters from the bStream that will be - * read prior to reads from the core stream. - */ -int bspeek (bstring r, const struct bStream * s) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return bassign (r, s->buff); -} - -/* bstring bjoin (const struct bstrList * bl, const_bstring sep); - * - * Join the entries of a bstrList into one bstring by sequentially - * concatenating them with the sep string in between. If there is an error - * NULL is returned, otherwise a bstring with the correct result is returned. - */ -bstring bjoin (const struct bstrList * bl, const_bstring sep) { -bstring b; -int i, c, v; - - if (bl == NULL || bl->qty < 0) return NULL; - if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; - - for (i = 0, c = 1; i < bl->qty; i++) { - v = bl->entry[i]->slen; - if (v < 0) return NULL; /* Invalid input */ - c += v; - if (c < 0) return NULL; /* Wrap around ?? */ - } - - if (sep != NULL) c += (bl->qty - 1) * sep->slen; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; /* Out of memory */ - b->data = (unsigned char *) bstr__alloc (c); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - b->mlen = c; - b->slen = c-1; - - for (i = 0, c = 0; i < bl->qty; i++) { - if (i > 0 && sep != NULL) { - bstr__memcpy (b->data + c, sep->data, sep->slen); - c += sep->slen; - } - v = bl->entry[i]->slen; - bstr__memcpy (b->data + c, bl->entry[i]->data, v); - c += v; - } - b->data[c] = (unsigned char) '\0'; - return b; -} - -#define BSSSC_BUFF_LEN (256) - -/* int bssplitscb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by any of the characters in splitStr. An empty splitStr causes - * the whole stream to be iterated once. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -struct charField chrs; -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; - if ((ret = cb (parm, 0, buff)) > 0) - ret = 0; - } else { - buildCharField (&chrs, splitStr); - ret = p = i = 0; - for (;;) { - if (i >= buff->slen) { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (i >= buff->slen) { - if (0 < (ret = cb (parm, p, buff))) ret = 0; - break; - } - } - if (testInCharField (&chrs, buff->data[i])) { - struct tagbstring t; - unsigned char c; - - blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); - if ((ret = bsunread (s, &t)) < 0) break; - buff->slen = i; - c = buff->data[i]; - buff->data[i] = (unsigned char) '\0'; - if ((ret = cb (parm, p, buff)) < 0) break; - buff->data[i] = c; - buff->slen = 0; - p += i + 1; - i = -1; - } - i++; - } - } - - bdestroy (buff); - return ret; -} - -/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by the entire substring splitStr. An empty splitStr causes - * each character of the stream to be iterated. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { - if ((ret = cb (parm, 0, buff)) < 0) { - bdestroy (buff); - return ret; - } - buff->slen = 0; - } - return BSTR_OK; - } else { - ret = p = i = 0; - for (i=p=0;;) { - if ((ret = binstr (buff, 0, splitStr)) >= 0) { - struct tagbstring t; - blk2tbstr (t, buff->data, ret); - i = ret + splitStr->slen; - if ((ret = cb (parm, p, &t)) < 0) break; - p += i; - bdelete (buff, 0, i); - } else { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (bseof (s)) { - if ((ret = cb (parm, p, buff)) > 0) ret = 0; - break; - } - } - } - } - - bdestroy (buff); - return ret; -} - -/* int bstrListCreate (void) - * - * Create a bstrList. - */ -struct bstrList * bstrListCreate (void) { -struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (sl) { - sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); - if (!sl->entry) { - bstr__free (sl); - sl = NULL; - } else { - sl->qty = 0; - sl->mlen = 1; - } - } - return sl; -} - -/* int bstrListDestroy (struct bstrList * sl) - * - * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. - */ -int bstrListDestroy (struct bstrList * sl) { -int i; - if (sl == NULL || sl->qty < 0) return BSTR_ERR; - for (i=0; i < sl->qty; i++) { - if (sl->entry[i]) { - bdestroy (sl->entry[i]); - sl->entry[i] = NULL; - } - } - sl->qty = -1; - sl->mlen = -1; - bstr__free (sl->entry); - sl->entry = NULL; - bstr__free (sl); - return BSTR_OK; -} - -/* int bstrListAlloc (struct bstrList * sl, int msz) - * - * Ensure that there is memory for at least msz number of entries for the - * list. - */ -int bstrListAlloc (struct bstrList * sl, int msz) { -bstring * l; -int smsz; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (sl->mlen >= msz) return BSTR_OK; - smsz = snapUpSize (msz); - nsz = ((size_t) smsz) * sizeof (bstring); - if (nsz < (size_t) smsz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) { - smsz = msz; - nsz = ((size_t) smsz) * sizeof (bstring); - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - } - sl->mlen = smsz; - sl->entry = l; - return BSTR_OK; -} - -/* int bstrListAllocMin (struct bstrList * sl, int msz) - * - * Try to allocate the minimum amount of memory for the list to include at - * least msz entries or sl->qty whichever is greater. - */ -int bstrListAllocMin (struct bstrList * sl, int msz) { -bstring * l; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (msz < sl->qty) msz = sl->qty; - if (sl->mlen == msz) return BSTR_OK; - nsz = ((size_t) msz) * sizeof (bstring); - if (nsz < (size_t) msz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - sl->mlen = msz; - sl->entry = l; - return BSTR_OK; -} - -/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * character in splitChar. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitcb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitcb will continue in an undefined manner. - */ -int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) - return BSTR_ERR; - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (str->data[i] == splitChar) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by any - * of the characters in splitStr. An empty splitStr causes the whole str to - * be iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitscb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -struct charField chrs; -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - if (splitStr->slen == 0) { - if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; - return ret; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - buildCharField (&chrs, splitStr); - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (testInCharField (&chrs, str->data[i])) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * substring splitStr. An empty splitStr causes the whole str to be - * iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitstrcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (0 == splitStr->slen) { - for (i=pos; i < str->slen; i++) { - if ((ret = cb (parm, i, 1)) < 0) return ret; - } - return BSTR_OK; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - for (i=p=pos; i <= str->slen - splitStr->slen; i++) { - if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { - if ((ret = cb (parm, p, i - p)) < 0) return ret; - i += splitStr->slen; - p = i; - } - } - if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; - return BSTR_OK; -} - -struct genBstrList { - bstring b; - struct bstrList * bl; -}; - -static int bscb (void * parm, int ofs, int len) { -struct genBstrList * g = (struct genBstrList *) parm; - if (g->bl->qty >= g->bl->mlen) { - int mlen = g->bl->mlen * 2; - bstring * tbl; - - while (g->bl->qty >= mlen) { - if (mlen < g->bl->mlen) return BSTR_ERR; - mlen += mlen; - } - - tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); - if (tbl == NULL) return BSTR_ERR; - - g->bl->entry = tbl; - g->bl->mlen = mlen; - } - - g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); - g->bl->qty++; - return BSTR_OK; -} - -/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) - * - * Create an array of sequential substrings from str divided by the character - * splitChar. - */ -struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) - * - * Create an array of sequential substrings from str divided by the entire - * substring splitStr. - */ -struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplits (const_bstring str, bstring splitStr) - * - * Create an array of sequential substrings from str divided by any of the - * characters in splitStr. An empty splitStr causes a single entry bstrList - * containing a copy of str to be returned. - */ -struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if ( str == NULL || str->slen < 0 || str->data == NULL || - splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) - return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - g.b = (bstring) str; - g.bl->qty = 0; - - if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -#if defined (__TURBOC__) && !defined (__BORLANDC__) -# ifndef BSTRLIB_NOVSNP -# define BSTRLIB_NOVSNP -# endif -#endif - -/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ -#if defined(__WATCOMC__) || defined(_MSC_VER) -#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} -#else -#ifdef BSTRLIB_NOVSNP -/* This is just a hack. If you are using a system without a vsnprintf, it is - not recommended that bformat be used at all. */ -#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} -#define START_VSNBUFF (256) -#else - -#if defined(__GNUC__) && !defined(__clang__) -/* Something is making gcc complain about this prototype not being here, so - I've just gone ahead and put it in. */ -extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); -#endif - -#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} -#endif -#endif - -#if !defined (BSTRLIB_NOVSNP) - -#ifndef START_VSNBUFF -#define START_VSNBUFF (16) -#endif - -/* On IRIX vsnprintf returns n-1 when the operation would overflow the target - buffer, WATCOM and MSVC both return -1, while C99 requires that the - returned value be exactly what the length would be if the buffer would be - large enough. This leads to the idea that if the return value is larger - than n, then changing n to the return value will reduce the number of - iterations required. */ - -/* int bformata (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it appends the results to - * a bstring which contains what would have been output. Note that if there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bformata (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bconcat (b, buff); - bdestroy (buff); - return r; -} - -/* int bassignformat (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it outputs the results to - * the bstring parameter b. Note that if there is an early generation of a - * '\0' character, the bstring will be truncated to this end point. - */ -int bassignformat (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bassign (b, buff); - bdestroy (buff); - return r; -} - -/* bstring bformat (const char * fmt, ...) - * - * Takes the same parameters as printf (), but rather than outputting results - * to stdio, it forms a bstring which contains what would have been output. - * Note that if there is an early generation of a '\0' character, the - * bstring will be truncated to this end point. - */ -bstring bformat (const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (fmt == NULL) return NULL; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return NULL; - } - } - - return buff; -} - -/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) - * - * The bvcformata function formats data under control of the format control - * string fmt and attempts to append the result to b. The fmt parameter is - * the same as that of the printf function. The variable argument list is - * replaced with arglist, which has been initialized by the va_start macro. - * The size of the appended output is upper bounded by count. If the - * required output exceeds count, the string b is not augmented with any - * contents and a value below BSTR_ERR is returned. If a value below -count - * is returned then it is recommended that the negative of this value be - * used as an update to the count in a subsequent pass. On other errors, - * such as running out of memory, parameter errors or numeric wrap around - * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully - * generated and appended to b. - * - * Note: There is no sanity checking of arglist, and this function is - * destructive of the contents of b from the b->slen point onward. If there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bvcformata (bstring b, int count, const char * fmt, va_list arg) { -int n, r, l; - - if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL - || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - if (count > (n = b->slen + count) + 2) return BSTR_ERR; - if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; - - exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); - - /* Did the operation complete successfully within bounds? */ - for (l = b->slen; l <= n; l++) { - if ('\0' == b->data[l]) { - b->slen = l; - return BSTR_OK; - } - } - - /* Abort, since the buffer was not large enough. The return value - tries to help set what the retry length should be. */ - - b->data[b->slen] = '\0'; - if (r > count + 1) { /* Does r specify a particular target length? */ - n = r; - } else { - n = count + count; /* If not, just double the size of count */ - if (count > n) n = INT_MAX; - } - n = -n; - - if (n > BSTR_ERR-1) n = BSTR_ERR-1; - return n; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h deleted file mode 100644 index edf8c00fc6..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstrlib.h - * - * This file is the header file for the core module for implementing the - * bstring functions. - */ - -#ifndef BSTRLIB_INCLUDE -#define BSTRLIB_INCLUDE - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdarg.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> - -#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) -# if defined (__TURBOC__) && !defined (__BORLANDC__) -# define BSTRLIB_NOVSNP -# endif -#endif - -#define BSTR_ERR (-1) -#define BSTR_OK (0) -#define BSTR_BS_BUFF_LENGTH_GET (0) - -typedef struct tagbstring * bstring; -typedef const struct tagbstring * const_bstring; - -/* Copy functions */ -#define cstr2bstr bfromcstr -extern bstring bfromcstr (const char * str); -extern bstring bfromcstralloc (int mlen, const char * str); -extern bstring blk2bstr (const void * blk, int len); -extern char * bstr2cstr (const_bstring s, char z); -extern int bcstrfree (char * s); -extern bstring bstrcpy (const_bstring b1); -extern int bassign (bstring a, const_bstring b); -extern int bassignmidstr (bstring a, const_bstring b, int left, int len); -extern int bassigncstr (bstring a, const char * str); -extern int bassignblk (bstring a, const void * s, int len); - -/* Destroy function */ -extern int bdestroy (bstring b); - -/* Space allocation hinting functions */ -extern int balloc (bstring s, int len); -extern int ballocmin (bstring b, int len); - -/* Substring extraction */ -extern bstring bmidstr (const_bstring b, int left, int len); - -/* Various standard manipulations */ -extern int bconcat (bstring b0, const_bstring b1); -extern int bconchar (bstring b0, char c); -extern int bcatcstr (bstring b, const char * s); -extern int bcatblk (bstring b, const void * s, int len); -extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); -extern int binsertch (bstring s1, int pos, int len, unsigned char fill); -extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); -extern int bdelete (bstring s1, int pos, int len); -extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); -extern int btrunc (bstring b, int n); - -/* Scan/search functions */ -extern int bstricmp (const_bstring b0, const_bstring b1); -extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); -extern int biseqcaseless (const_bstring b0, const_bstring b1); -extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); -extern int biseq (const_bstring b0, const_bstring b1); -extern int bisstemeqblk (const_bstring b0, const void * blk, int len); -extern int biseqcstr (const_bstring b, const char * s); -extern int biseqcstrcaseless (const_bstring b, const char * s); -extern int bstrcmp (const_bstring b0, const_bstring b1); -extern int bstrncmp (const_bstring b0, const_bstring b1, int n); -extern int binstr (const_bstring s1, int pos, const_bstring s2); -extern int binstrr (const_bstring s1, int pos, const_bstring s2); -extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int bstrchrp (const_bstring b, int c, int pos); -extern int bstrrchrp (const_bstring b, int c, int pos); -#define bstrchr(b,c) bstrchrp ((b), (c), 0) -#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) -extern int binchr (const_bstring b0, int pos, const_bstring b1); -extern int binchrr (const_bstring b0, int pos, const_bstring b1); -extern int bninchr (const_bstring b0, int pos, const_bstring b1); -extern int bninchrr (const_bstring b0, int pos, const_bstring b1); -extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); -extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); - -/* List of string container functions */ -struct bstrList { - int qty, mlen; - bstring * entry; -}; -extern struct bstrList * bstrListCreate (void); -extern int bstrListDestroy (struct bstrList * sl); -extern int bstrListAlloc (struct bstrList * sl, int msz); -extern int bstrListAllocMin (struct bstrList * sl, int msz); - -/* String split and join functions */ -extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); -extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); -extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); -extern bstring bjoin (const struct bstrList * bl, const_bstring sep); -extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - -/* Miscellaneous functions */ -extern int bpattern (bstring b, int len); -extern int btoupper (bstring b); -extern int btolower (bstring b); -extern int bltrimws (bstring b); -extern int brtrimws (bstring b); -extern int btrimws (bstring b); - -/* <*>printf format functions */ -#if !defined (BSTRLIB_NOVSNP) -extern bstring bformat (const char * fmt, ...); -extern int bformata (bstring b, const char * fmt, ...); -extern int bassignformat (bstring b, const char * fmt, ...); -extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); - -#define bvformata(ret, b, fmt, lastarg) { \ -bstring bstrtmp_b = (b); \ -const char * bstrtmp_fmt = (fmt); \ -int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ - for (;;) { \ - va_list bstrtmp_arglist; \ - va_start (bstrtmp_arglist, lastarg); \ - bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ - va_end (bstrtmp_arglist); \ - if (bstrtmp_r >= 0) { /* Everything went ok */ \ - bstrtmp_r = BSTR_OK; \ - break; \ - } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ - bstrtmp_r = BSTR_ERR; \ - break; \ - } \ - bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ - } \ - ret = bstrtmp_r; \ -} - -#endif - -typedef int (*bNgetc) (void *parm); -typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); - -/* Input functions */ -extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); -extern bstring bread (bNread readPtr, void * parm); -extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int breada (bstring b, bNread readPtr, void * parm); - -/* Stream functions */ -extern struct bStream * bsopen (bNread readPtr, void * parm); -extern void * bsclose (struct bStream * s); -extern int bsbufflength (struct bStream * s, int sz); -extern int bsreadln (bstring b, struct bStream * s, char terminator); -extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); -extern int bsread (bstring b, struct bStream * s, int n); -extern int bsreadlna (bstring b, struct bStream * s, char terminator); -extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); -extern int bsreada (bstring b, struct bStream * s, int n); -extern int bsunread (struct bStream * s, const_bstring b); -extern int bspeek (bstring r, const struct bStream * s); -extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bseof (const struct bStream * s); - -struct tagbstring { - int mlen; - int slen; - unsigned char * data; -}; - -/* Accessor macros */ -#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) -#define blength(b) (blengthe ((b), 0)) -#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) -#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) -#define bdatae(b, e) (bdataofse (b, 0, e)) -#define bdata(b) (bdataofs (b, 0)) -#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) -#define bchar(b, p) bchare ((b), (p), '\0') - -/* Static constant string initialization macro */ -#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} -#if defined(_MSC_VER) -/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ -# define bsStatic(q) bsStaticMlen(q,-32) -#endif -#ifndef bsStatic -# define bsStatic(q) bsStaticMlen(q,-__LINE__) -#endif - -/* Static constant block parameter pair */ -#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) - -/* Reference building macros */ -#define cstr2tbstr btfromcstr -#define btfromcstr(t,s) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ - (t).mlen = -1; \ -} -#define blk2tbstr(t,s,l) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = l; \ - (t).mlen = -1; \ -} -#define btfromblk(t,s,l) blk2tbstr(t,s,l) -#define bmid2tbstr(t,b,p,l) { \ - const_bstring bstrtmp_s = (b); \ - if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ - int bstrtmp_left = (p); \ - int bstrtmp_len = (l); \ - if (bstrtmp_left < 0) { \ - bstrtmp_len += bstrtmp_left; \ - bstrtmp_left = 0; \ - } \ - if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ - bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ - if (bstrtmp_len <= 0) { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } else { \ - (t).data = bstrtmp_s->data + bstrtmp_left; \ - (t).slen = bstrtmp_len; \ - } \ - } else { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } \ - (t).mlen = -__LINE__; \ -} -#define btfromblkltrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l); \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} -#define btfromblkrtrimws(t,s,l) { \ - int bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_len >= 0; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s; \ - (t).slen = bstrtmp_len + 1; \ - (t).mlen = -__LINE__; \ -} -#define btfromblktrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} - -/* Write protection macros */ -#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } -#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } -#define biswriteprotected(t) ((t).mlen <= 0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt deleted file mode 100644 index 8ebb188853..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt +++ /dev/null @@ -1,3201 +0,0 @@ -Better String library ---------------------- - -by Paul Hsieh - -The bstring library is an attempt to provide improved string processing -functionality to the C and C++ language. At the heart of the bstring library -(Bstrlib for short) is the management of "bstring"s which are a significant -improvement over '\0' terminated char buffers. - -=============================================================================== - -Motivation ----------- - -The standard C string library has serious problems: - - 1) Its use of '\0' to denote the end of the string means knowing a - string's length is O(n) when it could be O(1). - 2) It imposes an interpretation for the character value '\0'. - 3) gets() always exposes the application to a buffer overflow. - 4) strtok() modifies the string its parsing and thus may not be usable in - programs which are re-entrant or multithreaded. - 5) fgets has the unusual semantic of ignoring '\0's that occur before - '\n's are consumed. - 6) There is no memory management, and actions performed such as strcpy, - strcat and sprintf are common places for buffer overflows. - 7) strncpy() doesn't '\0' terminate the destination in some cases. - 8) Passing NULL to C library string functions causes an undefined NULL - pointer access. - 9) Parameter aliasing (overlapping, or self-referencing parameters) - within most C library functions has undefined behavior. - 10) Many C library string function calls take integer parameters with - restricted legal ranges. Parameters passed outside these ranges are - not typically detected and cause undefined behavior. - -So the desire is to create an alternative string library that does not suffer -from the above problems and adds in the following functionality: - - 1) Incorporate string functionality seen from other languages. - a) MID$() - from BASIC - b) split()/join() - from Python - c) string/char x n - from Perl - 2) Implement analogs to functions that combine stream IO and char buffers - without creating a dependency on stream IO functionality. - 3) Implement the basic text editor-style functions insert, delete, find, - and replace. - 4) Implement reference based sub-string access (as a generalization of - pointer arithmetic.) - 5) Implement runtime write protection for strings. - -There is also a desire to avoid "API-bloat". So functionality that can be -implemented trivially in other functionality is omitted. So there is no -left$() or right$() or reverse() or anything like that as part of the core -functionality. - -Explaining Bstrings -------------------- - -A bstring is basically a header which wraps a pointer to a char buffer. Lets -start with the declaration of a struct tagbstring: - - struct tagbstring { - int mlen; - int slen; - unsigned char * data; - }; - -This definition is considered exposed, not opaque (though it is neither -necessary nor recommended that low level maintenance of bstrings be performed -whenever the abstract interfaces are sufficient). The mlen field (usually) -describes a lower bound for the memory allocated for the data field. The -slen field describes the exact length for the bstring. The data field is a -single contiguous buffer of unsigned chars. Note that the existence of a '\0' -character in the unsigned char buffer pointed to by the data field does not -necessarily denote the end of the bstring. - -To be a well formed modifiable bstring the mlen field must be at least the -length of the slen field, and slen must be non-negative. Furthermore, the -data field must point to a valid buffer in which access to the first mlen -characters has been acquired. So the minimal check for correctness is: - - (slen >= 0 && mlen >= slen && data != NULL) - -bstrings returned by bstring functions can be assumed to be either NULL or -satisfy the above property. (When bstrings are only readable, the mlen >= -slen restriction is not required; this is discussed later in this section.) -A bstring itself is just a pointer to a struct tagbstring: - - typedef struct tagbstring * bstring; - -Note that use of the prefix "tag" in struct tagbstring is required to work -around the inconsistency between C and C++'s struct namespace usage. This -definition is also considered exposed. - -Bstrlib basically manages bstrings allocated as a header and an associated -data-buffer. Since the implementation is exposed, they can also be -constructed manually. Functions which mutate bstrings assume that the header -and data buffer have been malloced; the bstring library may perform free() or -realloc() on both the header and data buffer of any bstring parameter. -Functions which return bstring's create new bstrings. The string memory is -freed by a bdestroy() call (or using the bstrFree macro). - -The following related typedef is also provided: - - typedef const struct tagbstring * const_bstring; - -which is also considered exposed. These are directly bstring compatible (no -casting required) but are just used for parameters which are meant to be -non-mutable. So in general, bstring parameters which are read as input but -not meant to be modified will be declared as const_bstring, and bstring -parameters which may be modified will be declared as bstring. This convention -is recommended for user written functions as well. - -Since bstrings maintain interoperability with C library char-buffer style -strings, all functions which modify, update or create bstrings also append a -'\0' character into the position slen + 1. This trailing '\0' character is -not required for bstrings input to the bstring functions; this is provided -solely as a convenience for interoperability with standard C char-buffer -functionality. - -Analogs for the ANSI C string library functions have been created when they -are necessary, but have also been left out when they are not. In particular -there are no functions analogous to fwrite, or puts just for the purposes of -bstring. The ->data member of any string is exposed, and therefore can be -used just as easily as char buffers for C functions which read strings. - -For those that wish to hand construct bstrings, the following should be kept -in mind: - - 1) While bstrlib can accept constructed bstrings without terminating - '\0' characters, the rest of the C language string library will not - function properly on such non-terminated strings. This is obvious - but must be kept in mind. - 2) If it is intended that a constructed bstring be written to by the - bstring library functions then the data portion should be allocated - by the malloc function and the slen and mlen fields should be entered - properly. The struct tagbstring header is not reallocated, and only - freed by bdestroy. - 3) Writing arbitrary '\0' characters at various places in the string - will not modify its length as perceived by the bstring library - functions. In fact, '\0' is a legitimate non-terminating character - for a bstring to contain. - 4) For read only parameters, bstring functions do not check the mlen. - I.e., the minimal correctness requirements are reduced to: - - (slen >= 0 && data != NULL) - -Better pointer arithmetic -------------------------- - -One built-in feature of '\0' terminated char * strings, is that its very easy -and fast to obtain a reference to the tail of any string using pointer -arithmetic. Bstrlib does one better by providing a way to get a reference to -any substring of a bstring (or any other length delimited block of memory.) -So rather than just having pointer arithmetic, with bstrlib one essentially -has segment arithmetic. This is achieved using the macro blk2tbstr() which -builds a reference to a block of memory and the macro bmid2tbstr() which -builds a reference to a segment of a bstring. Bstrlib also includes -functions for direct consumption of memory blocks into bstrings, namely -bcatblk () and blk2bstr (). - -One scenario where this can be extremely useful is when string contains many -substrings which one would like to pass as read-only reference parameters to -some string consuming function without the need to allocate entire new -containers for the string data. More concretely, imagine parsing a command -line string whose parameters are space delimited. This can only be done for -tails of the string with '\0' terminated char * strings. - -Improved NULL semantics and error handling ------------------------------------------- - -Unless otherwise noted, if a NULL pointer is passed as a bstring or any other -detectably illegal parameter, the called function will return with an error -indicator (either NULL or BSTR_ERR) rather than simply performing a NULL -pointer access, or having undefined behavior. - -To illustrate the value of this, consider the following example: - - strcpy (p = malloc (13 * sizeof (char)), "Hello,"); - strcat (p, " World"); - -This is not correct because malloc may return NULL (due to an out of memory -condition), and the behaviour of strcpy is undefined if either of its -parameters are NULL. However: - - bstrcat (p = bfromcstr ("Hello,"), q = bfromcstr (" World")); - bdestroy (q); - -is well defined, because if either p or q are assigned NULL (indicating a -failure to allocate memory) both bstrcat and bdestroy will recognize it and -perform no detrimental action. - -Note that it is not necessary to check any of the members of a returned -bstring for internal correctness (in particular the data member does not need -to be checked against NULL when the header is non-NULL), since this is -assured by the bstring library itself. - -bStreams --------- - -In addition to the bgets and bread functions, bstrlib can abstract streams -with a high performance read only stream called a bStream. In general, the -idea is to open a core stream (with something like fopen) then pass its -handle as well as a bNread function pointer (like fread) to the bsopen -function which will return a handle to an open bStream. Then the functions -bsread, bsreadln or bsreadlns can be called to read portions of the stream. -Finally, the bsclose function is called to close the bStream -- it will -return a handle to the original (core) stream. So bStreams, essentially, -wrap other streams. - -The bStreams have two main advantages over the bgets and bread (as well as -fgets/ungetc) paradigms: - -1) Improved functionality via the bunread function which allows a stream to - unread characters, giving the bStream stack-like functionality if so - desired. -2) A very high performance bsreadln function. The C library function fgets() - (and the bgets function) can typically be written as a loop on top of - fgetc(), thus paying all of the overhead costs of calling fgetc on a per - character basis. bsreadln will read blocks at a time, thus amortizing the - overhead of fread calls over many characters at once. - -However, clearly bStreams are suboptimal or unusable for certain kinds of -streams (stdin) or certain usage patterns (a few spotty, or non-sequential -reads from a slow stream.) For those situations, using bgets will be more -appropriate. - -The semantics of bStreams allows practical construction of layerable data -streams. What this means is that by writing a bNread compatible function on -top of a bStream, one can construct a new bStream on top of it. This can be -useful for writing multi-pass parsers that don't actually read the entire -input more than once and don't require the use of intermediate storage. - -Aliasing --------- - -Aliasing occurs when a function is given two parameters which point to data -structures which overlap in the memory they occupy. While this does not -disturb read only functions, for many libraries this can make functions that -write to these memory locations malfunction. This is a common problem of the -C standard library and especially the string functions in the C standard -library. - -The C standard string library is entirely char by char oriented (as is -bstring) which makes conforming implementations alias safe for some -scenarios. However no actual detection of aliasing is typically performed, -so it is easy to find cases where the aliasing will cause anomolous or -undesirable behaviour (consider: strcat (p, p).) The C99 standard includes -the "restrict" pointer modifier which allows the compiler to document and -assume a no-alias condition on usage. However, only the most trivial cases -can be caught (if at all) by the compiler at compile time, and thus there is -no actual enforcement of non-aliasing. - -Bstrlib, by contrast, permits aliasing and is completely aliasing safe, in -the C99 sense of aliasing. That is to say, under the assumption that -pointers of incompatible types from distinct objects can never alias, bstrlib -is completely aliasing safe. (In practice this means that the data buffer -portion of any bstring and header of any bstring are assumed to never alias.) -With the exception of the reference building macros, the library behaves as -if all read-only parameters are first copied and replaced by temporary -non-aliased parameters before any writing to any output bstring is performed -(though actual copying is extremely rarely ever done.) - -Besides being a useful safety feature, bstring searching/comparison -functions can improve to O(1) execution when aliasing is detected. - -Note that aliasing detection and handling code in Bstrlib is generally -extremely cheap. There is almost never any appreciable performance penalty -for using aliased parameters. - -Reenterancy ------------ - -Nearly every function in Bstrlib is a leaf function, and is completely -reenterable with the exception of writing to common bstrings. The split -functions which use a callback mechanism requires only that the source string -not be destroyed by the callback function unless the callback function returns -with an error status (note that Bstrlib functions which return an error do -not modify the string in any way.) The string can in fact be modified by the -callback and the behaviour is deterministic. See the documentation of the -various split functions for more details. - -Undefined scenarios -------------------- - -One of the basic important premises for Bstrlib is to not to increase the -propogation of undefined situations from parameters that are otherwise legal -in of themselves. In particular, except for extremely marginal cases, usages -of bstrings that use the bstring library functions alone cannot lead to any -undefined action. But due to C/C++ language and library limitations, there -is no way to define a non-trivial library that is completely without -undefined operations. All such possible undefined operations are described -below: - -1) bstrings or struct tagbstrings that are not explicitely initialized cannot - be passed as a parameter to any bstring function. -2) The members of the NULL bstring cannot be accessed directly. (Though all - APIs and macros detect the NULL bstring.) -3) A bstring whose data member has not been obtained from a malloc or - compatible call and which is write accessible passed as a writable - parameter will lead to undefined results. (i.e., do not writeAllow any - constructed bstrings unless the data portion has been obtained from the - heap.) -4) If the headers of two strings alias but are not identical (which can only - happen via a defective manual construction), then passing them to a - bstring function in which one is writable is not defined. -5) If the mlen member is larger than the actual accessible length of the data - member for a writable bstring, or if the slen member is larger than the - readable length of the data member for a readable bstring, then the - corresponding bstring operations are undefined. -6) Any bstring definition whose header or accessible data portion has been - assigned to inaccessible or otherwise illegal memory clearly cannot be - acted upon by the bstring library in any way. -7) Destroying the source of an incremental split from within the callback - and not returning with a negative value (indicating that it should abort) - will lead to undefined behaviour. (Though *modifying* or adjusting the - state of the source data, even if those modification fail within the - bstrlib API, has well defined behavior.) -8) Modifying a bstring which is write protected by direct access has - undefined behavior. - -While this may seem like a long list, with the exception of invalid uses of -the writeAllow macro, and source destruction during an iterative split -without an accompanying abort, no usage of the bstring API alone can cause -any undefined scenario to occurr. I.e., the policy of restricting usage of -bstrings to the bstring API can significantly reduce the risk of runtime -errors (in practice it should eliminate them) related to string manipulation -due to undefined action. - -C++ wrapper ------------ - -A C++ wrapper has been created to enable bstring functionality for C++ in the -most natural (for C++ programers) way possible. The mandate for the C++ -wrapper is different from the base C bstring library. Since the C++ language -has far more abstracting capabilities, the CBString structure is considered -fully abstracted -- i.e., hand generated CBStrings are not supported (though -conversion from a struct tagbstring is allowed) and all detectable errors are -manifest as thrown exceptions. - -- The C++ class definitions are all under the namespace Bstrlib. bstrwrap.h - enables this namespace (with a using namespace Bstrlib; directive at the - end) unless the macro BSTRLIB_DONT_ASSUME_NAMESPACE has been defined before - it is included. - -- Erroneous accesses results in an exception being thrown. The exception - parameter is of type "struct CBStringException" which is derived from - std::exception if STL is used. A verbose description of the error message - can be obtained from the what() method. - -- CBString is a C++ structure derived from a struct tagbstring. An address - of a CBString cast to a bstring must not be passed to bdestroy. The bstring - C API has been made C++ safe and can be used directly in a C++ project. - -- It includes constructors which can take a char, '\0' terminated char - buffer, tagbstring, (char, repeat-value), a length delimited buffer or a - CBStringList to initialize it. - -- Concatenation is performed with the + and += operators. Comparisons are - done with the ==, !=, <, >, <= and >= operators. Note that == and != use - the biseq call, while <, >, <= and >= use bstrcmp. - -- CBString's can be directly cast to const character buffers. - -- CBString's can be directly cast to double, float, int or unsigned int so - long as the CBString are decimal representations of those types (otherwise - an exception will be thrown). Converting the other way should be done with - the format(a) method(s). - -- CBString contains the length, character and [] accessor methods. The - character and [] accessors are aliases of each other. If the bounds for - the string are exceeded, an exception is thrown. To avoid the overhead for - this check, first cast the CBString to a (const char *) and use [] to - dereference the array as normal. Note that the character and [] accessor - methods allows both reading and writing of individual characters. - -- The methods: format, formata, find, reversefind, findcaseless, - reversefindcaseless, midstr, insert, insertchrs, replace, findreplace, - findreplacecaseless, remove, findchr, nfindchr, alloc, toupper, tolower, - gets, read are analogous to the functions that can be found in the C API. - -- The caselessEqual and caselessCmp methods are analogous to biseqcaseless - and bstricmp functions respectively. - -- Note that just like the bformat function, the format and formata methods do - not automatically cast CBStrings into char * strings for "%s"-type - substitutions: - - CBString w("world"); - CBString h("Hello"); - CBString hw; - - /* The casts are necessary */ - hw.format ("%s, %s", (const char *)h, (const char *)w); - -- The methods trunc and repeat have been added instead of using pattern. - -- ltrim, rtrim and trim methods have been added. These remove characters - from a given character string set (defaulting to the whitespace characters) - from either the left, right or both ends of the CBString, respectively. - -- The method setsubstr is also analogous in functionality to bsetstr, except - that it cannot be passed NULL. Instead the method fill and the fill-style - constructor have been supplied to enable this functionality. - -- The writeprotect(), writeallow() and iswriteprotected() methods are - analogous to the bwriteprotect(), bwriteallow() and biswriteprotected() - macros in the C API. Write protection semantics in CBString are stronger - than with the C API in that indexed character assignment is checked for - write protection. However, unlike with the C API, a write protected - CBString can be destroyed by the destructor. - -- CBStream is a C++ structure which wraps a struct bStream (its not derived - from it, since destruction is slightly different). It is constructed by - passing in a bNread function pointer and a stream parameter cast to void *. - This structure includes methods for detecting eof, setting the buffer - length, reading the whole stream or reading entries line by line or block - by block, an unread function, and a peek function. - -- If STL is available, the CBStringList structure is derived from a vector of - CBString with various split methods. The split method has been overloaded - to accept either a character or CBString as the second parameter (when the - split parameter is a CBString any character in that CBString is used as a - seperator). The splitstr method takes a CBString as a substring seperator. - Joins can be performed via a CBString constructor which takes a - CBStringList as a parameter, or just using the CBString::join() method. - -- If there is proper support for std::iostreams, then the >> and << operators - and the getline() function have been added (with semantics the same as - those for std::string). - -Multithreading --------------- - -A mutable bstring is kind of analogous to a small (two entry) linked list -allocated by malloc, with all aliasing completely under programmer control. -I.e., manipulation of one bstring will never affect any other distinct -bstring unless explicitely constructed to do so by the programmer via hand -construction or via building a reference. Bstrlib also does not use any -static or global storage, so there are no hidden unremovable race conditions. -Bstrings are also clearly not inherently thread local. So just like -char *'s, bstrings can be passed around from thread to thread and shared and -so on, so long as modifications to a bstring correspond to some kind of -exclusive access lock as should be expected (or if the bstring is read-only, -which can be enforced by bstring write protection) for any sort of shared -object in a multithreaded environment. - -Bsafe module ------------- - -For convenience, a bsafe module has been included. The idea is that if this -module is included, inadvertant usage of the most dangerous C functions will -be overridden and lead to an immediate run time abort. Of course, it should -be emphasized that usage of this module is completely optional. The -intention is essentially to provide an option for creating project safety -rules which can be enforced mechanically rather than socially. This is -useful for larger, or open development projects where its more difficult to -enforce social rules or "coding conventions". - -Problems not solved -------------------- - -Bstrlib is written for the C and C++ languages, which have inherent weaknesses -that cannot be easily solved: - -1. Memory leaks: Forgetting to call bdestroy on a bstring that is about to be - unreferenced, just as forgetting to call free on a heap buffer that is - about to be dereferenced. Though bstrlib itself is leak free. -2. Read before write usage: In C, declaring an auto bstring does not - automatically fill it with legal/valid contents. This problem has been - somewhat mitigated in C++. (The bstrDeclare and bstrFree macros from - bstraux can be used to help mitigate this problem.) - -Other problems not addressed: - -3. Built-in mutex usage to automatically avoid all bstring internal race - conditions in multitasking environments: The problem with trying to - implement such things at this low a level is that it is typically more - efficient to use locks in higher level primitives. There is also no - platform independent way to implement locks or mutexes. -4. Unicode/widecharacter support. - -Note that except for spotty support of wide characters, the default C -standard library does not address any of these problems either. - -Configurable compilation options --------------------------------- - -All configuration options are meant solely for the purpose of compiler -compatibility. Configuration options are not meant to change the semantics -or capabilities of the library, except where it is unavoidable. - -Since some C++ compilers don't include the Standard Template Library and some -have the options of disabling exception handling, a number of macros can be -used to conditionally compile support for each of this: - -BSTRLIB_CAN_USE_STL - - - defining this will enable the used of the Standard Template Library. - Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. - -BSTRLIB_CANNOT_USE_STL - - - defining this will disable the use of the Standard Template Library. - Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. - -BSTRLIB_CAN_USE_IOSTREAM - - - defining this will enable the used of streams from class std. Defining - BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. - -BSTRLIB_CANNOT_USE_IOSTREAM - - - defining this will disable the use of streams from class std. Defining - BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. - -BSTRLIB_THROWS_EXCEPTIONS - - - defining this will enable the exception handling within bstring. - Defining BSTRLIB_THROWS_EXCEPTIONS overrides the - BSTRLIB_DOESNT_THROWS_EXCEPTIONS macro. - -BSTRLIB_DOESNT_THROW_EXCEPTIONS - - - defining this will disable the exception handling within bstring. - Defining BSTRLIB_THROWS_EXCEPTIONS overrides the - BSTRLIB_DOESNT_THROW_EXCEPTIONS macro. - -Note that these macros must be defined consistently throughout all modules -that use CBStrings including bstrwrap.cpp. - -Some older C compilers do not support functions such as vsnprintf. This is -handled by the following macro variables: - -BSTRLIB_NOVSNP - - - defining this indicates that the compiler does not support vsnprintf. - This will cause bformat and bformata to not be declared. Note that - for some compilers, such as Turbo C, this is set automatically. - Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. - -BSTRLIB_VSNP_OK - - - defining this will disable the autodetection of compilers the do not - support of compilers that do not support vsnprintf. - Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. - -Semantic compilation options ----------------------------- - -Bstrlib comes with very few compilation options for changing the semantics of -of the library. These are described below. - -BSTRLIB_DONT_ASSUME_NAMESPACE - - - Defining this before including bstrwrap.h will disable the automatic - enabling of the Bstrlib namespace for the C++ declarations. - -BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR - - - Defining this will make the CBString destructor non-virtual. - -BSTRLIB_MEMORY_DEBUG - - - Defining this will cause the bstrlib modules bstrlib.c and bstrwrap.cpp - to invoke a #include "memdbg.h". memdbg.h has to be supplied by the user. - -Note that these macros must be defined consistently throughout all modules -that use bstrings or CBStrings including bstrlib.c, bstraux.c and -bstrwrap.cpp. - -=============================================================================== - -Files ------ - -bstrlib.c - C implementaion of bstring functions. -bstrlib.h - C header file for bstring functions. -bstraux.c - C example that implements trivial additional functions. -bstraux.h - C header for bstraux.c -bstest.c - C unit/regression test for bstrlib.c - -bstrwrap.cpp - C++ implementation of CBString. -bstrwrap.h - C++ header file for CBString. -test.cpp - C++ unit/regression test for bstrwrap.cpp - -bsafe.c - C runtime stubs to abort usage of unsafe C functions. -bsafe.h - C header file for bsafe.c functions. - -C projects need only include bstrlib.h and compile/link bstrlib.c to use the -bstring library. C++ projects need to additionally include bstrwrap.h and -compile/link bstrwrap.cpp. For both, there may be a need to make choices -about feature configuration as described in the "Configurable compilation -options" in the section above. - -Other files that are included in this archive are: - -license.txt - The 3 clause BSD license for Bstrlib -gpl.txt - The GPL version 2 -security.txt - A security statement useful for auditting Bstrlib -porting.txt - A guide to porting Bstrlib -bstrlib.txt - This file - -=============================================================================== - -The functions -------------- - - extern bstring bfromcstr (const char * str); - - Take a standard C library style '\0' terminated char buffer and generate - a bstring with the same contents as the char buffer. If an error occurs - NULL is returned. - - So for example: - - bstring b = bfromcstr ("Hello"); - if (!b) { - fprintf (stderr, "Out of memory"); - } else { - puts ((char *) b->data); - } - - .......................................................................... - - extern bstring bfromcstralloc (int mlen, const char * str); - - Create a bstring which contains the contents of the '\0' terminated - char * buffer str. The memory buffer backing the bstring is at least - mlen characters in length. If an error occurs NULL is returned. - - So for example: - - bstring b = bfromcstralloc (64, someCstr); - if (b) b->data[63] = 'x'; - - The idea is that this will set the 64th character of b to 'x' if it is at - least 64 characters long otherwise do nothing. And we know this is well - defined so long as b was successfully created, since it will have been - allocated with at least 64 characters. - - .......................................................................... - - extern bstring blk2bstr (const void * blk, int len); - - Create a bstring whose contents are described by the contiguous buffer - pointing to by blk with a length of len bytes. Note that this function - creates a copy of the data in blk, rather than simply referencing it. - Compare with the blk2tbstr macro. If an error occurs NULL is returned. - - .......................................................................... - - extern char * bstr2cstr (const_bstring s, char z); - - Create a '\0' terminated char buffer which contains the contents of the - bstring s, except that any contained '\0' characters are converted to the - character in z. This returned value should be freed with bcstrfree(), by - the caller. If an error occurs NULL is returned. - - .......................................................................... - - extern int bcstrfree (char * s); - - Frees a C-string generated by bstr2cstr (). This is normally unnecessary - since it just wraps a call to free (), however, if malloc () and free () - have been redefined as a macros within the bstrlib module (via macros in - the memdbg.h backdoor) with some difference in behaviour from the std - library functions, then this allows a correct way of freeing the memory - that allows higher level code to be independent from these macro - redefinitions. - - .......................................................................... - - extern bstring bstrcpy (const_bstring b1); - - Make a copy of the passed in bstring. The copied bstring is returned if - there is no error, otherwise NULL is returned. - - .......................................................................... - - extern int bassign (bstring a, const_bstring b); - - Overwrite the bstring a with the contents of bstring b. Note that the - bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - int bassigncstr (bstring a, const char * str); - - Overwrite the string a with the contents of char * string str. Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a may be partially overwritten. - - .......................................................................... - - int bassignblk (bstring a, const void * s, int len); - - Overwrite the string a with the contents of the block (s, len). Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - extern int bassignmidstr (bstring a, const_bstring b, int left, int len); - - Overwrite the bstring a with the middle of contents of bstring b - starting from position left and running for a length len. left and - len are clamped to the ends of b as with the function bmidstr. Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - extern bstring bmidstr (const_bstring b, int left, int len); - - Create a bstring which is the substring of b starting from position left - and running for a length len (clamped by the end of the bstring b.) If - there was no error, the value of this constructed bstring is returned - otherwise NULL is returned. - - .......................................................................... - - extern int bdelete (bstring s1, int pos, int len); - - Removes characters from pos to pos+len-1 and shifts the tail of the - bstring starting from pos+len to pos. len must be positive for this call - to have any effect. The section of the bstring described by (pos, len) - is clamped to boundaries of the bstring b. The value BSTR_OK is returned - if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int bconcat (bstring b0, const_bstring b1); - - Concatenate the bstring b1 to the end of bstring b0. The value BSTR_OK - is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bconchar (bstring b, char c); - - Concatenate the character c to the end of bstring b. The value BSTR_OK - is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bcatcstr (bstring b, const char * s); - - Concatenate the char * string s to the end of bstring b. The value - BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bcatblk (bstring b, const void * s, int len); - - Concatenate a fixed length buffer (s, len) to the end of bstring b. The - value BSTR_OK is returned if the operation is successful, otherwise - BSTR_ERR is returned. - - .......................................................................... - - extern int biseq (const_bstring b0, const_bstring b1); - - Compare the bstring b0 and b1 for equality. If the bstrings differ, 0 - is returned, if the bstrings are the same, 1 is returned, if there is an - error, -1 is returned. If the length of the bstrings are different, this - function has O(1) complexity. Contained '\0' characters are not treated - as a termination character. - - Note that the semantics of biseq are not completely compatible with - bstrcmp because of its different treatment of the '\0' character. - - .......................................................................... - - extern int bisstemeqblk (const_bstring b, const void * blk, int len); - - Compare beginning of bstring b0 with a block of memory of length len for - equality. If the beginning of b0 differs from the memory block (or if b0 - is too short), 0 is returned, if the bstrings are the same, 1 is returned, - if there is an error, -1 is returned. - - .......................................................................... - - extern int biseqcaseless (const_bstring b0, const_bstring b1); - - Compare two bstrings for equality without differentiating between case. - If the bstrings differ other than in case, 0 is returned, if the bstrings - are the same, 1 is returned, if there is an error, -1 is returned. If - the length of the bstrings are different, this function is O(1). '\0' - termination characters are not treated in any special way. - - .......................................................................... - - extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); - - Compare beginning of bstring b0 with a block of memory of length len - without differentiating between case for equality. If the beginning of b0 - differs from the memory block other than in case (or if b0 is too short), - 0 is returned, if the bstrings are the same, 1 is returned, if there is an - error, -1 is returned. - - .......................................................................... - - extern int biseqcstr (const_bstring b, const char *s); - - Compare the bstring b and char * bstring s. The C string s must be '\0' - terminated at exactly the length of the bstring b, and the contents - between the two must be identical with the bstring b with no '\0' - characters for the two contents to be considered equal. This is - equivalent to the condition that their current contents will be always be - equal when comparing them in the same format after converting one or the - other. If they are equal 1 is returned, if they are unequal 0 is - returned and if there is a detectable error BSTR_ERR is returned. - - .......................................................................... - - extern int biseqcstrcaseless (const_bstring b, const char *s); - - Compare the bstring b and char * string s. The C string s must be '\0' - terminated at exactly the length of the bstring b, and the contents - between the two must be identical except for case with the bstring b with - no '\0' characters for the two contents to be considered equal. This is - equivalent to the condition that their current contents will be always be - equal ignoring case when comparing them in the same format after - converting one or the other. If they are equal, except for case, 1 is - returned, if they are unequal regardless of case 0 is returned and if - there is a detectable error BSTR_ERR is returned. - - .......................................................................... - - extern int bstrcmp (const_bstring b0, const_bstring b1); - - Compare the bstrings b0 and b1 for ordering. If there is an error, - SHRT_MIN is returned, otherwise a value less than or greater than zero, - indicating that the bstring pointed to by b0 is lexicographically less - than or greater than the bstring pointed to by b1 is returned. If the - bstring lengths are unequal but the characters up until the length of the - shorter are equal then a value less than, or greater than zero, - indicating that the bstring pointed to by b0 is shorter or longer than the - bstring pointed to by b1 is returned. 0 is returned if and only if the - two bstrings are the same. If the length of the bstrings are different, - this function is O(n). Like its standard C library counter part, the - comparison does not proceed past any '\0' termination characters - encountered. - - The seemingly odd error return value, merely provides slightly more - granularity than the undefined situation given in the C library function - strcmp. The function otherwise behaves very much like strcmp(). - - Note that the semantics of bstrcmp are not completely compatible with - biseq because of its different treatment of the '\0' termination - character. - - .......................................................................... - - extern int bstrncmp (const_bstring b0, const_bstring b1, int n); - - Compare the bstrings b0 and b1 for ordering for at most n characters. If - there is an error, SHRT_MIN is returned, otherwise a value is returned as - if b0 and b1 were first truncated to at most n characters then bstrcmp - was called with these new bstrings are paremeters. If the length of the - bstrings are different, this function is O(n). Like its standard C - library counter part, the comparison does not proceed past any '\0' - termination characters encountered. - - The seemingly odd error return value, merely provides slightly more - granularity than the undefined situation given in the C library function - strncmp. The function otherwise behaves very much like strncmp(). - - .......................................................................... - - extern int bstricmp (const_bstring b0, const_bstring b1); - - Compare two bstrings without differentiating between case. The return - value is the difference of the values of the characters where the two - bstrings first differ, otherwise 0 is returned indicating that the - bstrings are equal. If the lengths are different, then a difference from - 0 is given, but if the first extra character is '\0', then it is taken to - be the value UCHAR_MAX+1. - - .......................................................................... - - extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); - - Compare two bstrings without differentiating between case for at most n - characters. If the position where the two bstrings first differ is - before the nth position, the return value is the difference of the values - of the characters, otherwise 0 is returned. If the lengths are different - and less than n characters, then a difference from 0 is given, but if the - first extra character is '\0', then it is taken to be the value - UCHAR_MAX+1. - - .......................................................................... - - extern int bdestroy (bstring b); - - Deallocate the bstring passed. Passing NULL in as a parameter will have - no effect. Note that both the header and the data portion of the bstring - will be freed. No other bstring function which modifies one of its - parameters will free or reallocate the header. Because of this, in - general, bdestroy cannot be called on any declared struct tagbstring even - if it is not write protected. A bstring which is write protected cannot - be destroyed via the bdestroy call. Any attempt to do so will result in - no action taken, and BSTR_ERR will be returned. - - Note to C++ users: Passing in a CBString cast to a bstring will lead to - undefined behavior (free will be called on the header, rather than the - CBString destructor.) Instead just use the ordinary C++ language - facilities to dealloc a CBString. - - .......................................................................... - - extern int binstr (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - forward (increasing) direction. If it is found then it returns with the - first position after pos where it is found, otherwise it returns BSTR_ERR. - The algorithm used is brute force; O(m*n). - - .......................................................................... - - extern int binstrr (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - backward (decreasing) direction. If it is found then it returns with the - first position after pos where it is found, otherwise return BSTR_ERR. - Note that the current position at pos is tested as well -- so to be - disjoint from a previous forward search it is recommended that the - position be backed up (decremented) by one position. The algorithm used - is brute force; O(m*n). - - .......................................................................... - - extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - forward (increasing) direction but without regard to case. If it is - found then it returns with the first position after pos where it is - found, otherwise it returns BSTR_ERR. The algorithm used is brute force; - O(m*n). - - .......................................................................... - - extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - backward (decreasing) direction but without regard to case. If it is - found then it returns with the first position after pos where it is - found, otherwise return BSTR_ERR. Note that the current position at pos - is tested as well -- so to be disjoint from a previous forward search it - is recommended that the position be backed up (decremented) by one - position. The algorithm used is brute force; O(m*n). - - .......................................................................... - - extern int binchr (const_bstring b0, int pos, const_bstring b1); - - Search for the first position in b0 starting from pos or after, in which - one of the characters in b1 is found. This function has an execution - time of O(b0->slen + b1->slen). If such a position does not exist in b0, - then BSTR_ERR is returned. - - .......................................................................... - - extern int binchrr (const_bstring b0, int pos, const_bstring b1); - - Search for the last position in b0 no greater than pos, in which one of - the characters in b1 is found. This function has an execution time - of O(b0->slen + b1->slen). If such a position does not exist in b0, - then BSTR_ERR is returned. - - .......................................................................... - - extern int bninchr (const_bstring b0, int pos, const_bstring b1); - - Search for the first position in b0 starting from pos or after, in which - none of the characters in b1 is found and return it. This function has - an execution time of O(b0->slen + b1->slen). If such a position does - not exist in b0, then BSTR_ERR is returned. - - .......................................................................... - - extern int bninchrr (const_bstring b0, int pos, const_bstring b1); - - Search for the last position in b0 no greater than pos, in which none of - the characters in b1 is found and return it. This function has an - execution time of O(b0->slen + b1->slen). If such a position does not - exist in b0, then BSTR_ERR is returned. - - .......................................................................... - - extern int bstrchr (const_bstring b, int c); - - Search for the character c in the bstring b forwards from the start of - the bstring. Returns the position of the found character or BSTR_ERR if - it is not found. - - NOTE: This has been implemented as a macro on top of bstrchrp (). - - .......................................................................... - - extern int bstrrchr (const_bstring b, int c); - - Search for the character c in the bstring b backwards from the end of the - bstring. Returns the position of the found character or BSTR_ERR if it is - not found. - - NOTE: This has been implemented as a macro on top of bstrrchrp (). - - .......................................................................... - - extern int bstrchrp (const_bstring b, int c, int pos); - - Search for the character c in b forwards from the position pos - (inclusive). Returns the position of the found character or BSTR_ERR if - it is not found. - - .......................................................................... - - extern int bstrrchrp (const_bstring b, int c, int pos); - - Search for the character c in b backwards from the position pos in bstring - (inclusive). Returns the position of the found character or BSTR_ERR if - it is not found. - - .......................................................................... - - extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); - - Overwrite the bstring b0 starting at position pos with the bstring b1. If - the position pos is past the end of b0, then the character "fill" is - appended as necessary to make up the gap between the end of b0 and pos. - If b1 is NULL, it behaves as if it were a 0-length bstring. The value - BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); - - Inserts the bstring s2 into s1 at position pos. If the position pos is - past the end of s1, then the character "fill" is appended as necessary to - make up the gap between the end of s1 and pos. The value BSTR_OK is - returned if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int binsertch (bstring s1, int pos, int len, unsigned char fill); - - Inserts the character fill repeatedly into s1 at position pos for a - length len. If the position pos is past the end of s1, then the - character "fill" is appended as necessary to make up the gap between the - end of s1 and the position pos + len (exclusive). The value BSTR_OK is - returned if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int breplace (bstring b1, int pos, int len, const_bstring b2, - unsigned char fill); - - Replace a section of a bstring from pos for a length len with the bstring - b2. If the position pos is past the end of b1 then the character "fill" - is appended as necessary to make up the gap between the end of b1 and - pos. - - .......................................................................... - - extern int bfindreplace (bstring b, const_bstring find, - const_bstring replace, int position); - - Replace all occurrences of the find substring with a replace bstring - after a given position in the bstring b. The find bstring must have a - length > 0 otherwise BSTR_ERR is returned. This function does not - perform recursive per character replacement; that is to say successive - searches resume at the position after the last replace. - - So for example: - - bfindreplace (a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"), - a2 = bfromcstr("aa"), 0); - - Should result in changing a0 to "aaaabaaAb". - - This function performs exactly (b->slen - position) bstring comparisons, - and data movement is bounded above by character volume equivalent to size - of the output bstring. - - .......................................................................... - - extern int bfindreplacecaseless (bstring b, const_bstring find, - const_bstring replace, int position); - - Replace all occurrences of the find substring, ignoring case, with a - replace bstring after a given position in the bstring b. The find bstring - must have a length > 0 otherwise BSTR_ERR is returned. This function - does not perform recursive per character replacement; that is to say - successive searches resume at the position after the last replace. - - So for example: - - bfindreplacecaseless (a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"), - a2 = bfromcstr("aa"), 0); - - Should result in changing a0 to "aaaabaaaab". - - This function performs exactly (b->slen - position) bstring comparisons, - and data movement is bounded above by character volume equivalent to size - of the output bstring. - - .......................................................................... - - extern int balloc (bstring b, int length); - - Increase the allocated memory backing the data buffer for the bstring b - to a length of at least length. If the memory backing the bstring b is - already large enough, not action is performed. This has no effect on the - bstring b that is visible to the bstring API. Usually this function will - only be used when a minimum buffer size is required coupled with a direct - access to the ->data member of the bstring structure. - - Be warned that like any other bstring function, the bstring must be well - defined upon entry to this function. I.e., doing something like: - - b->slen *= 2; /* ?? Most likely incorrect */ - balloc (b, b->slen); - - is invalid, and should be implemented as: - - int t; - if (BSTR_OK == balloc (b, t = (b->slen * 2))) b->slen = t; - - This function will return with BSTR_ERR if b is not detected as a valid - bstring or length is not greater than 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int ballocmin (bstring b, int length); - - Change the amount of memory backing the bstring b to at least length. - This operation will never truncate the bstring data including the - extra terminating '\0' and thus will not decrease the length to less than - b->slen + 1. Note that repeated use of this function may cause - performance problems (realloc may be called on the bstring more than - the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b - is not detected as a valid bstring or length is not greater than 0, - otherwise BSTR_OK is returned. - - So for example: - - if (BSTR_OK == ballocmin (b, 64)) b->data[63] = 'x'; - - The idea is that this will set the 64th character of b to 'x' if it is at - least 64 characters long otherwise do nothing. And we know this is well - defined so long as the ballocmin call was successfully, since it will - ensure that b has been allocated with at least 64 characters. - - .......................................................................... - - int btrunc (bstring b, int n); - - Truncate the bstring to at most n characters. This function will return - with BSTR_ERR if b is not detected as a valid bstring or n is less than - 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bpattern (bstring b, int len); - - Replicate the starting bstring, b, end to end repeatedly until it - surpasses len characters, then chop the result to exactly len characters. - This function operates in-place. This function will return with BSTR_ERR - if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int btoupper (bstring b); - - Convert contents of bstring to upper case. This function will return with - BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int btolower (bstring b); - - Convert contents of bstring to lower case. This function will return with - BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bltrimws (bstring b); - - Delete whitespace contiguous from the left end of the bstring. This - function will return with BSTR_ERR if b is NULL or of length 0, otherwise - BSTR_OK is returned. - - .......................................................................... - - extern int brtrimws (bstring b); - - Delete whitespace contiguous from the right end of the bstring. This - function will return with BSTR_ERR if b is NULL or of length 0, otherwise - BSTR_OK is returned. - - .......................................................................... - - extern int btrimws (bstring b); - - Delete whitespace contiguous from both ends of the bstring. This function - will return with BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK - is returned. - - .......................................................................... - - extern int bstrListCreate (void); - - Create an empty struct bstrList. The struct bstrList output structure is - declared as follows: - - struct bstrList { - int qty, mlen; - bstring * entry; - }; - - The entry field actually is an array with qty number entries. The mlen - record counts the maximum number of bstring's for which there is memory - in the entry record. - - The Bstrlib API does *NOT* include a comprehensive set of functions for - full management of struct bstrList in an abstracted way. The reason for - this is because aliasing semantics of the list are best left to the user - of this function, and performance varies wildly depending on the - assumptions made. For a complete list of bstring data type it is - recommended that the C++ public std::vector<CBString> be used, since its - semantics are usage are more standard. - - .......................................................................... - - extern int bstrListDestroy (struct bstrList * sl); - - Destroy a struct bstrList structure that was returned by the bsplit - function. Note that this will destroy each bstring in the ->entry array - as well. See bstrListCreate() above for structure of struct bstrList. - - .......................................................................... - - extern int bstrListAlloc (struct bstrList * sl, int msz); - - Ensure that there is memory for at least msz number of entries for the - list. - - .......................................................................... - - extern int bstrListAllocMin (struct bstrList * sl, int msz); - - Try to allocate the minimum amount of memory for the list to include at - least msz entries or sl->qty whichever is greater. - - .......................................................................... - - extern struct bstrList * bsplit (bstring str, unsigned char splitChar); - - Create an array of sequential substrings from str divided by the - character splitChar. Successive occurrences of the splitChar will be - divided by empty bstring entries, following the semantics from the Python - programming language. To reclaim the memory from this output structure, - bstrListDestroy () should be called. See bstrListCreate() above for - structure of struct bstrList. - - .......................................................................... - - extern struct bstrList * bsplits (bstring str, const_bstring splitStr); - - Create an array of sequential substrings from str divided by any - character contained in splitStr. An empty splitStr causes a single entry - bstrList containing a copy of str to be returned. See bstrListCreate() - above for structure of struct bstrList. - - .......................................................................... - - extern struct bstrList * bsplitstr (bstring str, const_bstring splitStr); - - Create an array of sequential substrings from str divided by the entire - substring splitStr. An empty splitStr causes a single entry bstrList - containing a copy of str to be returned. See bstrListCreate() above for - structure of struct bstrList. - - .......................................................................... - - extern bstring bjoin (const struct bstrList * bl, const_bstring sep); - - Join the entries of a bstrList into one bstring by sequentially - concatenating them with the sep bstring in between. If sep is NULL, it - is treated as if it were the empty bstring. Note that: - - bjoin (l = bsplit (b, s->data[0]), s); - - should result in a copy of b, if s->slen is 1. If there is an error NULL - is returned, otherwise a bstring with the correct result is returned. - See bstrListCreate() above for structure of struct bstrList. - - .......................................................................... - - extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by the character splitChar. The parm passed to - bsplitcb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitcb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitcb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitcb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplit that is - abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by any of the characters in splitStr. An empty - splitStr causes the whole str to be iterated once. The parm passed to - bsplitcb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitscb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitscb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitscb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplits that - is abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by the entire substring splitStr. An empty splitStr - causes each character of str to be iterated. The parm passed to bsplitcb - is passed on to cb. If the function cb returns a value < 0, then further - iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitstrcb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitstrcb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitscb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplitstr that - is abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern bstring bformat (const char * fmt, ...); - - Takes the same parameters as printf (), but rather than outputting - results to stdio, it forms a bstring which contains what would have been - output. Note that if there is an early generation of a '\0' character, - the bstring will be truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - b0 = bformat ("Hello, %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bformat function is not present. - - .......................................................................... - - extern int bformata (bstring b, const char * fmt, ...); - - In addition to the initial output buffer b, bformata takes the same - parameters as printf (), but rather than outputting results to stdio, it - appends the results to the initial bstring parameter. Note that if - there is an early generation of a '\0' character, the bstring will be - truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bformata function is not present. - - .......................................................................... - - extern int bassignformat (bstring b, const char * fmt, ...); - - After the first parameter, it takes the same parameters as printf (), but - rather than outputting results to stdio, it outputs the results to - the bstring parameter b. Note that if there is an early generation of a - '\0' character, the bstring will be truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bassignformat function is not present. - - .......................................................................... - - extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); - - The bvcformata function formats data under control of the format control - string fmt and attempts to append the result to b. The fmt parameter is - the same as that of the printf function. The variable argument list is - replaced with arglist, which has been initialized by the va_start macro. - The size of the output is upper bounded by count. If the required output - exceeds count, the string b is not augmented with any contents and a value - below BSTR_ERR is returned. If a value below -count is returned then it - is recommended that the negative of this value be used as an update to the - count in a subsequent pass. On other errors, such as running out of - memory, parameter errors or numeric wrap around BSTR_ERR is returned. - BSTR_OK is returned when the output is successfully generated and - appended to b. - - Note: There is no sanity checking of arglist, and this function is - destructive of the contents of b from the b->slen point onward. If there - is an early generation of a '\0' character, the bstring will be truncated - to this end point. - - Although this function is part of the external API for Bstrlib, the - interface and semantics (length limitations, and unusual return codes) - are fairly atypical. The real purpose for this function is to provide an - engine for the bvformata macro. - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bvcformata function is not present. - - .......................................................................... - - extern bstring bread (bNread readPtr, void * parm); - typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, - void *parm); - - Read an entire stream into a bstring, verbatum. The readPtr function - pointer is compatible with fread sematics, except that it need not obtain - the stream data from a file. The intention is that parm would contain - the stream data context/state required (similar to the role of the FILE* - I/O stream parameter of fread.) - - Abstracting the block read function allows for block devices other than - file streams to be read if desired. Note that there is an ANSI - compatibility issue if "fread" is used directly; see the ANSI issues - section below. - - .......................................................................... - - extern int breada (bstring b, bNread readPtr, void * parm); - - Read an entire stream and append it to a bstring, verbatum. Behaves - like bread, except that it appends it results to the bstring b. - BSTR_ERR is returned on error, otherwise 0 is returned. - - .......................................................................... - - extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); - typedef int (* bNgetc) (void * parm); - - Read a bstring from a stream. As many bytes as is necessary are read - until the terminator is consumed or no more characters are available from - the stream. If read from the stream, the terminator character will be - appended to the end of the returned bstring. The getcPtr function must - have the same semantics as the fgetc C library function (i.e., returning - an integer whose value is negative when there are no more characters - available, otherwise the value of the next available unsigned character - from the stream.) The intention is that parm would contain the stream - data context/state required (similar to the role of the FILE* I/O stream - parameter of fgets.) If no characters are read, or there is some other - detectable error, NULL is returned. - - bgets will never call the getcPtr function more often than necessary to - construct its output (including a single call, if required, to determine - that the stream contains no more characters.) - - Abstracting the character stream function and terminator character allows - for different stream devices and string formats other than '\n' - terminated lines in a file if desired (consider \032 terminated email - messages, in a UNIX mailbox for example.) - - For files, this function can be used analogously as fgets as follows: - - fp = fopen ( ... ); - if (fp) b = bgets ((bNgetc) fgetc, fp, '\n'); - - (Note that only one terminator character can be used, and that '\0' is - not assumed to terminate the stream in addition to the terminator - character. This is consistent with the semantics of fgets.) - - .......................................................................... - - extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); - - Read from a stream and concatenate to a bstring. Behaves like bgets, - except that it appends it results to the bstring b. The value 1 is - returned if no characters are read before a negative result is returned - from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned - in other normal cases. - - .......................................................................... - - extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); - - Read from a stream and concatenate to a bstring. Behaves like bgets, - except that it assigns the results to the bstring b. The value 1 is - returned if no characters are read before a negative result is returned - from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned - in other normal cases. - - .......................................................................... - - extern struct bStream * bsopen (bNread readPtr, void * parm); - - Wrap a given open stream (described by a fread compatible function - pointer and stream handle) into an open bStream suitable for the bstring - library streaming functions. - - .......................................................................... - - extern void * bsclose (struct bStream * s); - - Close the bStream, and return the handle to the stream that was - originally used to open the given stream. If s is NULL or detectably - invalid, NULL will be returned. - - .......................................................................... - - extern int bsbufflength (struct bStream * s, int sz); - - Set the length of the buffer used by the bStream. If sz is the macro - BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not set. If s is - NULL or sz is negative, the function will return with BSTR_ERR, otherwise - this function returns with the previous length. - - .......................................................................... - - extern int bsreadln (bstring r, struct bStream * s, char terminator); - - Read a bstring terminated by the terminator character or the end of the - stream from the bStream (s) and return it into the parameter r. The - matched terminator, if found, appears at the end of the line read. If - the stream has been exhausted of all available data, before any can be - read, BSTR_ERR is returned. This function may read additional characters - into the stream buffer from the core stream that are not returned, but - will be retained for subsequent read operations. When reading from high - speed streams, this function can perform significantly faster than bgets. - - .......................................................................... - - extern int bsreadlna (bstring r, struct bStream * s, char terminator); - - Read a bstring terminated by the terminator character or the end of the - stream from the bStream (s) and concatenate it to the parameter r. The - matched terminator, if found, appears at the end of the line read. If - the stream has been exhausted of all available data, before any can be - read, BSTR_ERR is returned. This function may read additional characters - into the stream buffer from the core stream that are not returned, but - will be retained for subsequent read operations. When reading from high - speed streams, this function can perform significantly faster than bgets. - - .......................................................................... - - extern int bsreadlns (bstring r, struct bStream * s, bstring terminators); - - Read a bstring terminated by any character in the terminators bstring or - the end of the stream from the bStream (s) and return it into the - parameter r. This function may read additional characters from the core - stream that are not returned, but will be retained for subsequent read - operations. - - .......................................................................... - - extern int bsreadlnsa (bstring r, struct bStream * s, bstring terminators); - - Read a bstring terminated by any character in the terminators bstring or - the end of the stream from the bStream (s) and concatenate it to the - parameter r. If the stream has been exhausted of all available data, - before any can be read, BSTR_ERR is returned. This function may read - additional characters from the core stream that are not returned, but - will be retained for subsequent read operations. - - .......................................................................... - - extern int bsread (bstring r, struct bStream * s, int n); - - Read a bstring of length n (or, if it is fewer, as many bytes as is - remaining) from the bStream. This function will read the minimum - required number of additional characters from the core stream. When the - stream is at the end of the file BSTR_ERR is returned, otherwise BSTR_OK - is returned. - - .......................................................................... - - extern int bsreada (bstring r, struct bStream * s, int n); - - Read a bstring of length n (or, if it is fewer, as many bytes as is - remaining) from the bStream and concatenate it to the parameter r. This - function will read the minimum required number of additional characters - from the core stream. When the stream is at the end of the file BSTR_ERR - is returned, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bsunread (struct bStream * s, const_bstring b); - - Insert a bstring into the bStream at the current position. These - characters will be read prior to those that actually come from the core - stream. - - .......................................................................... - - extern int bspeek (bstring r, const struct bStream * s); - - Return the number of currently buffered characters from the bStream that - will be read prior to reads from the core stream, and append it to the - the parameter r. - - .......................................................................... - - extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); - - Iterate the set of disjoint sequential substrings over the stream s - divided by any character from the bstring splitStr. The parm passed to - bssplitscb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this return value is returned by - bssplitscb. - - Note: At the point of calling the cb function, the bStream pointer is - pointed exactly at the position right after having read the split - character. The cb function can act on the stream by causing the bStream - pointer to move, and bssplitscb will continue by starting the next split - at the position of the pointer after the return from cb. - - However, if the cb causes the bStream s to be destroyed then the cb must - return with a negative value, otherwise bssplitscb will continue in an - undefined manner. - - This function is provided as way to incrementally parse through a file - or other generic stream that in total size may otherwise exceed the - practical or desired memory available. As with the other split callback - based functions this is abortable and does not impose additional memory - allocation. - - .......................................................................... - - extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); - - Iterate the set of disjoint sequential substrings over the stream s - divided by the entire substring splitStr. The parm passed to - bssplitstrcb is passed on to cb. If the function cb returns a - value < 0, then further iterating is halted and this return value is - returned by bssplitstrcb. - - Note: At the point of calling the cb function, the bStream pointer is - pointed exactly at the position right after having read the split - character. The cb function can act on the stream by causing the bStream - pointer to move, and bssplitstrcb will continue by starting the next - split at the position of the pointer after the return from cb. - - However, if the cb causes the bStream s to be destroyed then the cb must - return with a negative value, otherwise bssplitscb will continue in an - undefined manner. - - This function is provided as way to incrementally parse through a file - or other generic stream that in total size may otherwise exceed the - practical or desired memory available. As with the other split callback - based functions this is abortable and does not impose additional memory - allocation. - - .......................................................................... - - extern int bseof (const struct bStream * s); - - Return the defacto "EOF" (end of file) state of a stream (1 if the - bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or - detectably erroneous.) When the readPtr callback returns a value <= 0 - the stream reaches its "EOF" state. Note that bunread with non-empty - content will essentially turn off this state, and the stream will not be - in its "EOF" state so long as its possible to read more data out of it. - - Also note that the semantics of bseof() are slightly different from - something like feof(). I.e., reaching the end of the stream does not - necessarily guarantee that bseof() will return with a value indicating - that this has happened. bseof() will only return indicating that it has - reached the "EOF" and an attempt has been made to read past the end of - the bStream. - -The macros ----------- - - The macros described below are shown in a prototype form indicating their - intended usage. Note that the parameters passed to these macros will be - referenced multiple times. As with all macros, programmer care is - required to guard against unintended side effects. - - int blengthe (const_bstring b, int err); - - Returns the length of the bstring. If the bstring is NULL err is - returned. - - .......................................................................... - - int blength (const_bstring b); - - Returns the length of the bstring. If the bstring is NULL, the length - returned is 0. - - .......................................................................... - - int bchare (const_bstring b, int p, int c); - - Returns the p'th character of the bstring b. If the position p refers to - a position that does not exist in the bstring or the bstring is NULL, - then c is returned. - - .......................................................................... - - char bchar (const_bstring b, int p); - - Returns the p'th character of the bstring b. If the position p refers to - a position that does not exist in the bstring or the bstring is NULL, - then '\0' is returned. - - .......................................................................... - - char * bdatae (bstring b, char * err); - - Returns the char * data portion of the bstring b. If b is NULL, err is - returned. - - .......................................................................... - - char * bdata (bstring b); - - Returns the char * data portion of the bstring b. If b is NULL, NULL is - returned. - - .......................................................................... - - char * bdataofse (bstring b, int ofs, char * err); - - Returns the char * data portion of the bstring b offset by ofs. If b is - NULL, err is returned. - - .......................................................................... - - char * bdataofs (bstring b, int ofs); - - Returns the char * data portion of the bstring b offset by ofs. If b is - NULL, NULL is returned. - - .......................................................................... - - struct tagbstring var = bsStatic ("..."); - - The bsStatic macro allows for static declarations of literal string - constants as struct tagbstring structures. The resulting tagbstring does - not need to be freed or destroyed. Note that this macro is only well - defined for string literal arguments. For more general string pointers, - use the btfromcstr macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - <void * blk, int len> <- bsStaticBlkParms ("...") - - The bsStaticBlkParms macro emits a pair of comma seperated parameters - corresponding to the block parameters for the block functions in Bstrlib - (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk.) - Note that this macro is only well defined for string literal arguments. - - Examples: - - bstring b = blk2bstr (bsStaticBlkParms ("Fast init. ")); - bcatblk (b, bsStaticBlkParms ("No frills fast concatenation.")); - - These are faster than using bfromcstr() and bcatcstr() respectively - because the length of the inline string is known as a compile time - constant. Also note that seperate struct tagbstring declarations for - holding the output of a bsStatic() macro are not required. - - .......................................................................... - - void btfromcstr (struct tagbstring& t, const char * s); - - Fill in the tagbstring t with the '\0' terminated char buffer s. This - action is purely reference oriented; no memory management is done. The - data member is just assigned s, and slen is assigned the strlen of s. - The s parameter is accessed exactly once in this macro. - - The resulting struct tagbstring is initially write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoke the - bwriteallow on this struct tagbstring to make it writeable (though this - requires that s be obtained from a function compatible with malloc.) - - .......................................................................... - - void btfromblk (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len. This - action is purely reference oriented; no memory management is done. The - data member of t is just assigned s, and slen is assigned len. Note that - the buffer is not appended with a '\0' character. The s and len - parameters are accessed exactly once each in this macro. - - The resulting struct tagbstring is initially write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoke the - bwriteallow on this struct tagbstring to make it writeable (though this - requires that s be obtained from a function compatible with malloc.) - - .......................................................................... - - void btfromblkltrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been left trimmed. This action is purely reference oriented; no - memory management is done. The data member of t is just assigned to a - pointer inside the buffer s. Note that the buffer is not appended with a - '\0' character. The s and len parameters are accessed exactly once each - in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void btfromblkrtrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been right trimmed. This action is purely reference oriented; no - memory management is done. The data member of t is just assigned to a - pointer inside the buffer s. Note that the buffer is not appended with a - '\0' character. The s and len parameters are accessed exactly once each - in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void btfromblktrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been left and right trimmed. This action is purely reference - oriented; no memory management is done. The data member of t is just - assigned to a pointer inside the buffer s. Note that the buffer is not - appended with a '\0' character. The s and len parameters are accessed - exactly once each in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void bmid2tbstr (struct tagbstring& t, bstring b, int pos, int len); - - Fill the tagbstring t with the substring from b, starting from position - pos with a length len. The segment is clamped by the boundaries of - the bstring b. This action is purely reference oriented; no memory - management is done. Note that the buffer is not appended with a '\0' - character. Note that the t parameter to this macro may be accessed - multiple times. Note that the contents of t will become undefined - if the contents of b change or are destroyed. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoking the - bwriteallow macro on this struct tagbstring will have no effect. - - .......................................................................... - - void bvformata (int& ret, bstring b, const char * format, lastarg); - - Append the bstring b with printf like formatting with the format control - string, and the arguments taken from the ... list of arguments after - lastarg passed to the containing function. If the containing function - does not have ... parameters or lastarg is not the last named parameter - before the ... then the results are undefined. If successful, the - results are appended to b and BSTR_OK is assigned to ret. Otherwise - BSTR_ERR is assigned to ret. - - Example: - - void dbgerror (FILE * fp, const char * fmt, ...) { - int ret; - bstring b; - bvformata (ret, b = bfromcstr ("DBG: "), fmt, fmt); - if (BSTR_OK == ret) fputs ((char *) bdata (b), fp); - bdestroy (b); - } - - Note that if the BSTRLIB_NOVSNP macro was set when bstrlib had been - compiled the bvformata macro will not link properly. If the - BSTRLIB_NOVSNP macro has been set, the bvformata macro will not be - available. - - .......................................................................... - - void bwriteprotect (struct tagbstring& t); - - Disallow bstring from being written to via the bstrlib API. Attempts to - write to the resulting tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. - - Note: bstrings which are write protected cannot be destroyed via bdestroy. - - Note to C++ users: Setting a CBString as write protected will not prevent - it from being destroyed by the destructor. - - .......................................................................... - - void bwriteallow (struct tagbstring& t); - - Allow bstring to be written to via the bstrlib API. Note that such an - action makes the bstring both writable and destroyable. If the bstring is - not legitimately writable (as is the case for struct tagbstrings - initialized with a bsStatic value), the results of this are undefined. - - Note that invoking the bwriteallow macro may increase the number of - reallocs by one more than necessary for every call to bwriteallow - interleaved with any bstring API which writes to this bstring. - - .......................................................................... - - int biswriteprotected (struct tagbstring& t); - - Returns 1 if the bstring is write protected, otherwise 0 is returned. - -=============================================================================== - -The bstest module ------------------ - -The bstest module is just a unit test for the bstrlib module. For correct -implementations of bstrlib, it should execute with 0 failures being reported. -This test should be utilized if modifications/customizations to bstrlib have -been performed. It tests each core bstrlib function with bstrings of every -mode (read-only, NULL, static and mutable) and ensures that the expected -semantics are observed (including results that should indicate an error). It -also tests for aliasing support. Passing bstest is a necessary but not a -sufficient condition for ensuring the correctness of the bstrlib module. - - -The test module ---------------- - -The test module is just a unit test for the bstrwrap module. For correct -implementations of bstrwrap, it should execute with 0 failures being -reported. This test should be utilized if modifications/customizations to -bstrwrap have been performed. It tests each core bstrwrap function with -CBStrings write protected or not and ensures that the expected semantics are -observed (including expected exceptions.) Note that exceptions cannot be -disabled to run this test. Passing test is a necessary but not a sufficient -condition for ensuring the correctness of the bstrwrap module. - -=============================================================================== - -Using Bstring and CBString as an alternative to the C library -------------------------------------------------------------- - -First let us give a table of C library functions and the alternative bstring -functions and CBString methods that should be used instead of them. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -gets bgets ::gets -strcpy bassign = operator -strncpy bassignmidstr ::midstr -strcat bconcat += operator -strncat bconcat + btrunc += operator + ::trunc -strtok bsplit, bsplits ::split -sprintf b(assign)format ::format -snprintf b(assign)format + btrunc ::format + ::trunc -vsprintf bvformata bvformata - -vsnprintf bvformata + btrunc bvformata + btrunc -vfprintf bvformata + fputs use bvformata + fputs -strcmp biseq, bstrcmp comparison operators. -strncmp bstrncmp, memcmp bstrncmp, memcmp -strlen ->slen, blength ::length -strdup bstrcpy constructor -strset bpattern ::fill -strstr binstr ::find -strpbrk binchr ::findchr -stricmp bstricmp cast & use bstricmp -strlwr btolower cast & use btolower -strupr btoupper cast & use btoupper -strrev bReverse (aux module) cast & use bReverse -strchr bstrchr cast & use bstrchr -strspnp use strspn use strspn -ungetc bsunread bsunread - -The top 9 C functions listed here are troublesome in that they impose memory -management in the calling function. The Bstring and CBstring interfaces have -built-in memory management, so there is far less code with far less potential -for buffer overrun problems. strtok can only be reliably called as a "leaf" -calculation, since it (quite bizarrely) maintains hidden internal state. And -gets is well known to be broken no matter what. The Bstrlib alternatives do -not suffer from those sorts of problems. - -The substitute for strncat can be performed with higher performance by using -the blk2tbstr macro to create a presized second operand for bconcat. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -strspn strspn acceptable strspn acceptable -strcspn strcspn acceptable strcspn acceptable -strnset strnset acceptable strnset acceptable -printf printf acceptable printf acceptable -puts puts acceptable puts acceptable -fprintf fprintf acceptable fprintf acceptable -fputs fputs acceptable fputs acceptable -memcmp memcmp acceptable memcmp acceptable - -Remember that Bstring (and CBstring) functions will automatically append the -'\0' character to the character data buffer. So by simply accessing the data -buffer directly, ordinary C string library functions can be called directly -on them. Note that bstrcmp is not the same as memcmp in exactly the same way -that strcmp is not the same as memcmp. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -fread balloc + fread ::alloc + fread -fgets balloc + fgets ::alloc + fgets - -These are odd ones because of the exact sizing of the buffer required. The -Bstring and CBString alternatives requires that the buffers are forced to -hold at least the prescribed length, then just use fread or fgets directly. -However, typically the automatic memory management of Bstring and CBstring -will make the typical use of fgets and fread to read specifically sized -strings unnecessary. - -Implementation Choices ----------------------- - -Overhead: -......... - -The bstring library has more overhead versus straight char buffers for most -functions. This overhead is essentially just the memory management and -string header allocation. This overhead usually only shows up for small -string manipulations. The performance loss has to be considered in -light of the following: - -1) What would be the performance loss of trying to write this management - code in one's own application? -2) Since the bstring library source code is given, a sufficiently powerful - modern inlining globally optimizing compiler can remove function call - overhead. - -Since the data type is exposed, a developer can replace any unsatisfactory -function with their own inline implementation. And that is besides the main -point of what the better string library is mainly meant to provide. Any -overhead lost has to be compared against the value of the safe abstraction -for coupling memory management and string functionality. - -Performance of the C interface: -............................... - -The algorithms used have performance advantages versus the analogous C -library functions. For example: - -1. bfromcstr/blk2str/bstrcpy versus strcpy/strdup. By using memmove instead - of strcpy, the break condition of the copy loop is based on an independent - counter (that should be allocated in a register) rather than having to - check the results of the load. Modern out-of-order executing CPUs can - parallelize the final branch mis-predict penality with the loading of the - source string. Some CPUs will also tend to have better built-in hardware - support for counted memory moves than load-compare-store. (This is a - minor, but non-zero gain.) -2. biseq versus strcmp. If the strings are unequal in length, bsiseq will - return in O(1) time. If the strings are aliased, or have aliased data - buffers, biseq will return in O(1) time. strcmp will always be O(k), - where k is the length of the common prefix or the whole string if they are - identical. -3. ->slen versus strlen. ->slen is obviously always O(1), while strlen is - always O(n) where n is the length of the string. -4. bconcat versus strcat. Both rely on precomputing the length of the - destination string argument, which will favor the bstring library. On - iterated concatenations the performance difference can be enormous. -5. bsreadln versus fgets. The bsreadln function reads large blocks at a time - from the given stream, then parses out lines from the buffers directly. - Some C libraries will implement fgets as a loop over single fgetc calls. - Testing indicates that the bsreadln approach can be several times faster - for fast stream devices (such as a file that has been entirely cached.) -6. bsplits/bsplitscb versus strspn. Accelerators for the set of match - characters are generated only once. -7. binstr versus strstr. The binstr implementation unrolls the loops to - help reduce loop overhead. This will matter if the target string is - long and source string is not found very early in the target string. - With strstr, while it is possible to unroll the source contents, it is - not possible to do so with the destination contents in a way that is - effective because every destination character must be tested against - '\0' before proceeding to the next character. -8. bReverse versus strrev. The C function must find the end of the string - first before swaping character pairs. -9. bstrrchr versus no comparable C function. Its not hard to write some C - code to search for a character from the end going backwards. But there - is no way to do this without computing the length of the string with - strlen. - -Practical testing indicates that in general Bstrlib is never signifcantly -slower than the C library for common operations, while very often having a -performance advantage that ranges from significant to massive. Even for -functions like b(n)inchr versus str(c)spn() (where, in theory, there is no -advantage for the Bstrlib architecture) the performance of Bstrlib is vastly -superior to most tested C library implementations. - -Some of Bstrlib's extra functionality also lead to inevitable performance -advantages over typical C solutions. For example, using the blk2tbstr macro, -one can (in O(1) time) generate an internal substring by reference while not -disturbing the original string. If disturbing the original string is not an -option, typically, a comparable char * solution would have to make a copy of -the substring to provide similar functionality. Another example is reverse -character set scanning -- the str(c)spn functions only scan in a forward -direction which can complicate some parsing algorithms. - -Where high performance char * based algorithms are available, Bstrlib can -still leverage them by accessing the ->data field on bstrings. So -realistically Bstrlib can never be significantly slower than any standard -'\0' terminated char * based solutions. - -Performance of the C++ interface: -................................. - -The C++ interface has been designed with an emphasis on abstraction and safety -first. However, since it is substantially a wrapper for the C bstring -functions, for longer strings the performance comments described in the -"Performance of the C interface" section above still apply. Note that the -(CBString *) type can be directly cast to a (bstring) type, and passed as -parameters to the C functions (though a CBString must never be passed to -bdestroy.) - -Probably the most controversial choice is performing full bounds checking on -the [] operator. This decision was made because 1) the fast alternative of -not bounds checking is still available by first casting the CBString to a -(const char *) buffer or to a (struct tagbstring) then derefencing .data and -2) because the lack of bounds checking is seen as one of the main weaknesses -of C/C++ versus other languages. This check being done on every access leads -to individual character extraction being actually slower than other languages -in this one respect (other language's compilers will normally dedicate more -resources on hoisting or removing bounds checking as necessary) but otherwise -bring C++ up to the level of other languages in terms of functionality. - -It is common for other C++ libraries to leverage the abstractions provided by -C++ to use reference counting and "copy on write" policies. While these -techniques can speed up some scenarios, they impose a problem with respect to -thread safety. bstrings and CBStrings can be properly protected with -"per-object" mutexes, meaning that two bstrlib calls can be made and execute -simultaneously, so long as the bstrings and CBstrings are distinct. With a -reference count and alias before copy on write policy, global mutexes are -required that prevent multiple calls to the strings library to execute -simultaneously regardless of whether or not the strings represent the same -string. - -One interesting trade off in CBString is that the default constructor is not -trivial. I.e., it always prepares a ready to use memory buffer. The purpose -is to ensure that there is a uniform internal composition for any functioning -CBString that is compatible with bstrings. It also means that the other -methods in the class are not forced to perform "late initialization" checks. -In the end it means that construction of CBStrings are slower than other -comparable C++ string classes. Initial testing, however, indicates that -CBString outperforms std::string and MFC's CString, for example, in all other -operations. So to work around this weakness it is recommended that CBString -declarations be pushed outside of inner loops. - -Practical testing indicates that with the exception of the caveats given -above (constructors and safe index character manipulations) the C++ API for -Bstrlib generally outperforms popular standard C++ string classes. Amongst -the standard libraries and compilers, the quality of concatenation operations -varies wildly and very little care has gone into search functions. Bstrlib -dominates those performance benchmarks. - -Memory management: -.................. - -The bstring functions which write and modify bstrings will automatically -reallocate the backing memory for the char buffer whenever it is required to -grow. The algorithm for resizing chosen is to snap up to sizes that are a -power of two which are sufficient to hold the intended new size. Memory -reallocation is not performed when the required size of the buffer is -decreased. This behavior can be relied on, and is necessary to make the -behaviour of balloc deterministic. This trades off additional memory usage -for decreasing the frequency for required reallocations: - -1. For any bstring whose size never exceeds n, its buffer is not ever - reallocated more than log_2(n) times for its lifetime. -2. For any bstring whose size never exceeds n, its buffer is never more than - 2*(n+1) in length. (The extra characters beyond 2*n are to allow for the - implicit '\0' which is always added by the bstring modifying functions.) - -Decreasing the buffer size when the string decreases in size would violate 1) -above and in real world case lead to pathological heap thrashing. Similarly, -allocating more tightly than "least power of 2 greater than necessary" would -lead to a violation of 1) and have the same potential for heap thrashing. - -Property 2) needs emphasizing. Although the memory allocated is always a -power of 2, for a bstring that grows linearly in size, its buffer memory also -grows linearly, not exponentially. The reason is that the amount of extra -space increases with each reallocation, which decreases the frequency of -future reallocations. - -Obviously, given that bstring writing functions may reallocate the data -buffer backing the target bstring, one should not attempt to cache the data -buffer address and use it after such bstring functions have been called. -This includes making reference struct tagbstrings which alias to a writable -bstring. - -balloc or bfromcstralloc can be used to preallocate the minimum amount of -space used for a given bstring. This will reduce even further the number of -times the data portion is reallocated. If the length of the string is never -more than one less than the memory length then there will be no further -reallocations. - -Note that invoking the bwriteallow macro may increase the number of reallocs -by one more than necessary for every call to bwriteallow interleaved with any -bstring API which writes to this bstring. - -The library does not use any mechanism for automatic clean up for the C API. -Thus explicit clean up via calls to bdestroy() are required to avoid memory -leaks. - -Constant and static tagbstrings: -................................ - -A struct tagbstring can be write protected from any bstrlib function using -the bwriteprotect macro. A write protected struct tagbstring can then be -reset to being writable via the bwriteallow macro. There is, of course, no -protection from attempts to directly access the bstring members. Modifying a -bstring which is write protected by direct access has undefined behavior. - -static struct tagbstrings can be declared via the bsStatic macro. They are -considered permanently unwritable. Such struct tagbstrings's are declared -such that attempts to write to it are not well defined. Invoking either -bwriteallow or bwriteprotect on static struct tagbstrings has no effect. - -struct tagbstring's initialized via btfromcstr or blk2tbstr are protected by -default but can be made writeable via the bwriteallow macro. If bwriteallow -is called on such struct tagbstring's, it is the programmer's responsibility -to ensure that: - -1) the buffer supplied was allocated from the heap. -2) bdestroy is not called on this tagbstring (unless the header itself has - also been allocated from the heap.) -3) free is called on the buffer to reclaim its memory. - -bwriteallow and bwriteprotect can be invoked on ordinary bstrings (they have -to be dereferenced with the (*) operator to get the levels of indirection -correct) to give them write protection. - -Buffer declaration: -................... - -The memory buffer is actually declared "unsigned char *" instead of "char *". -The reason for this is to trigger compiler warnings whenever uncasted char -buffers are assigned to the data portion of a bstring. This will draw more -diligent programmers into taking a second look at the code where they -have carelessly left off the typically required cast. (Research from -AT&T/Lucent indicates that additional programmer eyeballs is one of the most -effective mechanisms at ferreting out bugs.) - -Function pointers: -.................. - -The bgets, bread and bStream functions use function pointers to obtain -strings from data streams. The function pointer declarations have been -specifically chosen to be compatible with the fgetc and fread functions. -While this may seem to be a convoluted way of implementing fgets and fread -style functionality, it has been specifically designed this way to ensure -that there is no dependency on a single narrowly defined set of device -interfaces, such as just stream I/O. In the embedded world, its quite -possible to have environments where such interfaces may not exist in the -standard C library form. Furthermore, the generalization that this opens up -allows for more sophisticated uses for these functions (performing an fgets -like function on a socket, for example.) By using function pointers, it also -allows such abstract stream interfaces to be created using the bstring library -itself while not creating a circular dependency. - -Use of int's for sizes: -....................... - -This is just a recognition that 16bit platforms with requirements for strings -that are larger than 64K and 32bit+ platforms with requirements for strings -that are larger than 4GB are pretty marginal. The main focus is for 32bit -platforms, and emerging 64bit platforms with reasonable < 4GB string -requirements. Using ints allows for negative values which has meaning -internally to bstrlib. - -Semantic consideration: -....................... - -Certain care needs to be taken when copying and aliasing bstrings. A bstring -is essentially a pointer type which points to a multipart abstract data -structure. Thus usage, and lifetime of bstrings have semantics that follow -these considerations. For example: - - bstring a, b; - struct tagbstring t; - - a = bfromcstr("Hello"); /* Create new bstring and copy "Hello" into it. */ - b = a; /* Alias b to the contents of a. */ - t = *a; /* Create a current instance pseudo-alias of a. */ - bconcat (a, b); /* Double a and b, t is now undefined. */ - bdestroy (a); /* Destroy the contents of both a and b. */ - -Variables of type bstring are really just references that point to real -bstring objects. The equal operator (=) creates aliases, and the asterisk -dereference operator (*) creates a kind of alias to the current instance (which -is generally not useful for any purpose.) Using bstrcpy() is the correct way -of creating duplicate instances. The ampersand operator (&) is useful for -creating aliases to struct tagbstrings (remembering that constructed struct -tagbstrings are not writable by default.) - -CBStrings use complete copy semantics for the equal operator (=), and thus do -not have these sorts of issues. - -Debugging: -.......... - -Bstrings have a simple, exposed definition and construction, and the library -itself is open source. So most debugging is going to be fairly straight- -forward. But the memory for bstrings come from the heap, which can often be -corrupted indirectly, and it might not be obvious what has happened even from -direct examination of the contents in a debugger or a core dump. There are -some tools such as Purify, Insure++ and Electric Fence which can help solve -such problems, however another common approach is to directly instrument the -calls to malloc, realloc, calloc, free, memcpy, memmove and/or other calls -by overriding them with macro definitions. - -Although the user could hack on the Bstrlib sources directly as necessary to -perform such an instrumentation, Bstrlib comes with a built-in mechanism for -doing this. By defining the macro BSTRLIB_MEMORY_DEBUG and providing an -include file named memdbg.h this will force the core Bstrlib modules to -attempt to include this file. In such a file, macros could be defined which -overrides Bstrlib's useage of the C standard library. - -Rather than calling malloc, realloc, free, memcpy or memmove directly, Bstrlib -emits the macros bstr__alloc, bstr__realloc, bstr__free, bstr__memcpy and -bstr__memmove in their place respectively. By default these macros are simply -assigned to be equivalent to their corresponding C standard library function -call. However, if they are given earlier macro definitions (via the back -door include file) they will not be given their default definition. In this -way Bstrlib's interface to the standard library can be changed but without -having to directly redefine or link standard library symbols (both of which -are not strictly ANSI C compliant.) - -An example definition might include: - - #define bstr__alloc(sz) X_malloc ((sz), __LINE__, __FILE__) - -which might help contextualize heap entries in a debugging environment. - -The NULL parameter and sanity checking of bstrings is part of the Bstrlib -API, and thus Bstrlib itself does not present any different modes which would -correspond to "Debug" or "Release" modes. Bstrlib always contains mechanisms -which one might think of as debugging features, but retains the performance -and small memory footprint one would normally associate with release mode -code. - -Integration Microsoft's Visual Studio debugger: -............................................... - -Microsoft's Visual Studio debugger has a capability of customizable mouse -float over data type descriptions. This is accomplished by editting the -AUTOEXP.DAT file to include the following: - - ; new for CBString - tagbstring =slen=<slen> mlen=<mlen> <data,st> - Bstrlib::CBStringList =count=<size()> - -In Visual C++ 6.0 this file is located in the directory: - - C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin - -and in Visual Studio .NET 2003 its located here: - - C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger - -This will improve the ability of debugging with Bstrlib under Visual Studio. - -Security --------- - -Bstrlib does not come with explicit security features outside of its fairly -comprehensive error detection, coupled with its strict semantic support. -That is to say that certain common security problems, such as buffer overrun, -constant overwrite, arbitrary truncation etc, are far less likely to happen -inadvertently. Where it does help, Bstrlib maximizes its advantage by -providing developers a simple adoption path that lets them leave less secure -string mechanisms behind. The library will not leave developers wanting, so -they will be less likely to add new code using a less secure string library -to add functionality that might be missing from Bstrlib. - -That said there are a number of security ideas not addressed by Bstrlib: - -1. Race condition exploitation (i.e., verifying a string's contents, then -raising the privilege level and execute it as a shell command as two -non-atomic steps) is well beyond the scope of what Bstrlib can provide. It -should be noted that MFC's built-in string mutex actually does not solve this -problem either -- it just removes immediate data corruption as a possible -outcome of such exploit attempts (it can be argued that this is worse, since -it will leave no trace of the exploitation). In general race conditions have -to be dealt with by careful design and implementation; it cannot be assisted -by a string library. - -2. Any kind of access control or security attributes to prevent usage in -dangerous interfaces such as system(). Perl includes a "trust" attribute -which can be endowed upon strings that are intended to be passed to such -dangerous interfaces. However, Perl's solution reflects its own limitations --- notably that it is not a strongly typed language. In the example code for -Bstrlib, there is a module called taint.cpp. It demonstrates how to write a -simple wrapper class for managing "untainted" or trusted strings using the -type system to prevent questionable mixing of ordinary untrusted strings with -untainted ones then passing them to dangerous interfaces. In this way the -security correctness of the code reduces to auditing the direct usages of -dangerous interfaces or promotions of tainted strings to untainted ones. - -3. Encryption of string contents is way beyond the scope of Bstrlib. -Maintaining encrypted string contents in the futile hopes of thwarting things -like using system-level debuggers to examine sensitive string data is likely -to be a wasted effort (imagine a debugger that runs at a higher level than a -virtual processor where the application runs). For more standard encryption -usages, since the bstring contents are simply binary blocks of data, this -should pose no problem for usage with other standard encryption libraries. - -Compatibility -------------- - -The Better String Library is known to compile and function correctly with the -following compilers: - - - Microsoft Visual C++ - - Watcom C/C++ - - Intel's C/C++ compiler (Windows) - - The GNU C/C++ compiler (cygwin and Linux on PPC64) - - Borland C - - Turbo C - -Setting of configuration options should be unnecessary for these compilers -(unless exceptions are being disabled or STLport has been added to WATCOM -C/C++). Bstrlib has been developed with an emphasis on portability. As such -porting it to other compilers should be straight forward. This package -includes a porting guide (called porting.txt) which explains what issues may -exist for porting Bstrlib to different compilers and environments. - -ANSI issues ------------ - -1. The function pointer types bNgetc and bNread have prototypes which are very -similar to, but not exactly the same as fgetc and fread respectively. -Basically the FILE * parameter is replaced by void *. The purpose of this -was to allow one to create other functions with fgetc and fread like -semantics without being tied to ANSI C's file streaming mechanism. I.e., one -could very easily adapt it to sockets, or simply reading a block of memory, -or procedurally generated strings (for fractal generation, for example.) - -The problem is that invoking the functions (bNgetc)fgetc and (bNread)fread is -not technically legal in ANSI C. The reason being that the compiler is only -able to coerce the function pointers themselves into the target type, however -are unable to perform any cast (implicit or otherwise) on the parameters -passed once invoked. I.e., if internally void * and FILE * need some kind of -mechanical coercion, the compiler will not properly perform this conversion -and thus lead to undefined behavior. - -Apparently a platform from Data General called "Eclipse" and another from -Tandem called "NonStop" have a different representation for pointers to bytes -and pointers to words, for example, where coercion via casting is necessary. -(Actual confirmation of the existence of such machines is hard to come by, so -it is prudent to be skeptical about this information.) However, this is not -an issue for any known contemporary platforms. One may conclude that such -platforms are effectively apocryphal even if they do exist. - -To correctly work around this problem to the satisfaction of the ANSI -limitations, one needs to create wrapper functions for fgets and/or -fread with the prototypes of bNgetc and/or bNread respectively which performs -no other action other than to explicitely cast the void * parameter to a -FILE *, and simply pass the remaining parameters straight to the function -pointer call. - -The wrappers themselves are trivial: - - size_t freadWrap (void * buff, size_t esz, size_t eqty, void * parm) { - return fread (buff, esz, eqty, (FILE *) parm); - } - - int fgetcWrap (void * parm) { - return fgetc ((FILE *) parm); - } - -These have not been supplied in bstrlib or bstraux to prevent unnecessary -linking with file I/O functions. - -2. vsnprintf is not available on all compilers. Because of this, the bformat -and bformata functions (and format and formata methods) are not guaranteed to -work properly. For those compilers that don't have vsnprintf, the -BSTRLIB_NOVSNP macro should be set before compiling bstrlib, and the format -functions/method will be disabled. - -The more recent ANSI C standards have specified the required inclusion of a -vsnprintf function. - -3. The bstrlib function names are not unique in the first 6 characters. This -is only an issue for older C compiler environments which do not store more -than 6 characters for function names. - -4. The bsafe module defines macros and function names which are part of the -C library. This simply overrides the definition as expected on all platforms -tested, however it is not sanctioned by the ANSI standard. This module is -clearly optional and should be omitted on platforms which disallow its -undefined semantics. - -In practice the real issue is that some compilers in some modes of operation -can/will inline these standard library functions on a module by module basis -as they appear in each. The linker will thus have no opportunity to override -the implementation of these functions for those cases. This can lead to -inconsistent behaviour of the bsafe module on different platforms and -compilers. - -=============================================================================== - -Comparison with Microsoft's CString class ------------------------------------------ - -Although developed independently, CBStrings have very similar functionality to -Microsoft's CString class. However, the bstring library has significant -advantages over CString: - -1. Bstrlib is a C-library as well as a C++ library (using the C++ wrapper). - - - Thus it is compatible with more programming environments and - available to a wider population of programmers. - -2. The internal structure of a bstring is considered exposed. - - - A single contiguous block of data can be cut into read-only pieces by - simply creating headers, without allocating additional memory to create - reference copies of each of these sub-strings. - - In this way, using bstrings in a totally abstracted way becomes a choice - rather than an imposition. Further this choice can be made differently - at different layers of applications that use it. - -3. Static declaration support precludes the need for constructor - invocation. - - - Allows for static declarations of constant strings that has no - additional constructor overhead. - -4. Bstrlib is not attached to another library. - - - Bstrlib is designed to be easily plugged into any other library - collection, without dependencies on other libraries or paradigms (such - as "MFC".) - -The bstring library also comes with a few additional functions that are not -available in the CString class: - - - bsetstr - - bsplit - - bread - - breplace (this is different from CString::Replace()) - - Writable indexed characters (for example a[i]='x') - -Interestingly, although Microsoft did implement mid$(), left$() and right$() -functional analogues (these are functions from GWBASIC) they seem to have -forgotten that mid$() could be also used to write into the middle of a string. -This functionality exists in Bstrlib with the bsetstr() and breplace() -functions. - -Among the disadvantages of Bstrlib is that there is no special support for -localization or wide characters. Such things are considered beyond the scope -of what bstrings are trying to deliver. CString essentially supports the -older UCS-2 version of Unicode via widechar_t as an application-wide compile -time switch. - -CString's also use built-in mechanisms for ensuring thread safety under all -situations. While this makes writing thread safe code that much easier, this -built-in safety feature has a price -- the inner loops of each CString method -runs in its own critical section (grabbing and releasing a light weight mutex -on every operation.) The usual way to decrease the impact of a critical -section performance penalty is to amortize more operations per critical -section. But since the implementation of CStrings is fixed as a one critical -section per-operation cost, there is no way to leverage this common -performance enhancing idea. - -The search facilities in Bstrlib are comparable to those in MFC's CString -class, though it is missing locale specific collation. But because Bstrlib -is interoperable with C's char buffers, it will allow programmers to write -their own string searching mechanism (such as Boyer-Moore), or be able to -choose from a variety of available existing string searching libraries (such -as those for regular expressions) without difficulty. - -Microsoft used a very non-ANSI conforming trick in its implementation to -allow printf() to use the "%s" specifier to output a CString correctly. This -can be convenient, but it is inherently not portable. CBString requires an -explicit cast, while bstring requires the data member to be dereferenced. -Microsoft's own documentation recommends casting, instead of relying on this -feature. - -Comparison with C++'s std::string ---------------------------------- - -This is the C++ language's standard STL based string class. - -1. There is no C implementation. -2. The [] operator is not bounds checked. -3. Missing a lot of useful functions like printf-like formatting. -4. Some sub-standard std::string implementations (SGI) are necessarily unsafe - to use with multithreading. -5. Limited by STL's std::iostream which in turn is limited by ifstream which - can only take input from files. (Compare to CBStream's API which can take - abstracted input.) -6. Extremely uneven performance across implementations. - -Comparison with ISO C TR 24731 proposal ---------------------------------------- - -Following the ISO C99 standard, Microsoft has proposed a group of C library -extensions which are supposedly "safer and more secure". This proposal is -expected to be adopted by the ISO C standard which follows C99. - -The proposal reveals itself to be very similar to Microsoft's "StrSafe" -library. The functions are basically the same as other standard C library -string functions except that destination parameters are paired with an -additional length parameter of type rsize_t. rsize_t is the same as size_t, -however, the range is checked to make sure its between 1 and RSIZE_MAX. Like -Bstrlib, the functions perform a "parameter check". Unlike Bstrlib, when a -parameter check fails, rather than simply outputing accumulatable error -statuses, they call a user settable global error function handler, and upon -return of control performs no (additional) detrimental action. The proposal -covers basic string functions as well as a few non-reenterable functions -(asctime, ctime, and strtok). - -1. Still based solely on char * buffers (and therefore strlen() and strcat() - is still O(n), and there are no faster streq() comparison functions.) -2. No growable string semantics. -3. Requires manual buffer length synchronization in the source code. -4. No attempt to enhance functionality of the C library. -5. Introduces a new error scenario (strings exceeding RSIZE_MAX length). - -The hope is that by exposing the buffer length requirements there will be -fewer buffer overrun errors. However, the error modes are really just -transformed, rather than removed. The real problem of buffer overflows is -that they all happen as a result of erroneous programming. So forcing -programmers to manually deal with buffer limits, will make them more aware of -the problem but doesn't remove the possibility of erroneous programming. So -a programmer that erroneously mixes up the rsize_t parameters is no better off -from a programmer that introduces potential buffer overflows through other -more typical lapses. So at best this may reduce the rate of erroneous -programming, rather than making any attempt at removing failure modes. - -The error handler can discriminate between types of failures, but does not -take into account any callsite context. So the problem is that the error is -going to be manifest in a piece of code, but there is no pointer to that -code. It would seem that passing in the call site __FILE__, __LINE__ as -parameters would be very useful, but the API clearly doesn't support such a -thing (it would increase code bloat even more than the extra length -parameter does, and would require macro tricks to implement). - -The Bstrlib C API takes the position that error handling needs to be done at -the callsite, and just tries to make it as painless as possible. Furthermore, -error modes are removed by supporting auto-growing strings and aliasing. For -capturing errors in more central code fragments, Bstrlib's C++ API uses -exception handling extensively, which is superior to the leaf-only error -handler approach. - -Comparison with Managed String Library CERT proposal ----------------------------------------------------- - -The main webpage for the managed string library: -http://www.cert.org/secure-coding/managedstring.html - -Robert Seacord at CERT has proposed a C string library that he calls the -"Managed String Library" for C. Like Bstrlib, it introduces a new type -which is called a managed string. The structure of a managed string -(string_m) is like a struct tagbstring but missing the length field. This -internal structure is considered opaque. The length is, like the C standard -library, always computed on the fly by searching for a terminating NUL on -every operation that requires it. So it suffers from every performance -problem that the C standard library suffers from. Interoperating with C -string APIs (like printf, fopen, or anything else that takes a string -parameter) requires copying to additionally allocating buffers that have to -be manually freed -- this makes this library probably slower and more -cumbersome than any other string library in existence. - -The library gives a fully populated error status as the return value of every -string function. The hope is to be able to diagnose all problems -specifically from the return code alone. Comparing this to Bstrlib, which -aways returns one consistent error message, might make it seem that Bstrlib -would be harder to debug; but this is not true. With Bstrlib, if an error -occurs there is always enough information from just knowing there was an error -and examining the parameters to deduce exactly what kind of error has -happened. The managed string library thus gives up nested function calls -while achieving little benefit, while Bstrlib does not. - -One interesting feature that "managed strings" has is the idea of data -sanitization via character set whitelisting. That is to say, a globally -definable filter that makes any attempt to put invalid characters into strings -lead to an error and not modify the string. The author gives the following -example: - - // create valid char set - if (retValue = strcreate_m(&str1, "abc") ) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - if (retValue = setcharset(str1)) { - fprintf( - stderr, - "Error %d from setcharset().\n", - retValue - ); - } - if (retValue = strcreate_m(&str1, "aabbccabc")) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - // create string with invalid char set - if (retValue = strcreate_m(&str1, "abbccdabc")) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - -Which we can compare with a more Bstrlib way of doing things: - - bstring bCreateWithFilter (const char * cstr, const_bstring filter) { - bstring b = bfromcstr (cstr); - if (BSTR_ERR != bninchr (b, filter) && NULL != b) { - fprintf (stderr, "Filter violation.\n"); - bdestroy (b); - b = NULL; - } - return b; - } - - struct tagbstring charFilter = bsStatic ("abc"); - bstring str1 = bCreateWithFilter ("aabbccabc", &charFilter); - bstring str2 = bCreateWithFilter ("aabbccdabc", &charFilter); - -The first thing we should notice is that with the Bstrlib approach you can -have different filters for different strings if necessary. Furthermore, -selecting a charset filter in the Managed String Library is uni-contextual. -That is to say, there can only be one such filter active for the entire -program, which means its usage is not well defined for intermediate library -usage (a library that uses it will interfere with user code that uses it, and -vice versa.) It is also likely to be poorly defined in multi-threading -environments. - -There is also a question as to whether the data sanitization filter is checked -on every operation, or just on creation operations. Since the charset can be -set arbitrarily at run time, it might be set *after* some managed strings have -been created. This would seem to imply that all functions should run this -additional check every time if there is an attempt to enforce this. This -would make things tremendously slow. On the other hand, if it is assumed that -only creates and other operations that take char *'s as input need be checked -because the charset was only supposed to be called once at and before any -other managed string was created, then one can see that its easy to cover -Bstrlib with equivalent functionality via a few wrapper calls such as the -example given above. - -And finally we have to question the value of sanitation in the first place. -For example, for httpd servers, there is generally a requirement that the -URLs parsed have some form that avoids undesirable translation to local file -system filenames or resources. The problem is that the way URLs can be -encoded, it must be completely parsed and translated to know if it is using -certain invalid character combinations. That is to say, merely filtering -each character one at a time is not necessarily the right way to ensure that -a string has safe contents. - -In the article that describes this proposal, it is claimed that it fairly -closely approximates the existing C API semantics. On this point we should -compare this "closeness" with Bstrlib: - - Bstrlib Managed String Library - ------- ---------------------- - -Pointer arithmetic Segment arithmetic N/A - -Use in C Std lib ->data, or bdata{e} getstr_m(x,*) ... free(x) - -String literals bsStatic, bsStaticBlk strcreate_m() - -Transparency Complete None - -Its pretty clear that the semantic mapping from C strings to Bstrlib is fairly -straightforward, and that in general semantic capabilities are the same or -superior in Bstrlib. On the other hand the Managed String Library is either -missing semantics or changes things fairly significantly. - -Comparison with Annexia's c2lib library ---------------------------------------- - -This library is available at: -http://www.annexia.org/freeware/c2lib - -1. Still based solely on char * buffers (and therefore strlen() and strcat() - is still O(n), and there are no faster streq() comparison functions.) - Their suggestion that alternatives which wrap the string data type (such as - bstring does) imposes a difficulty in interoperating with the C langauge's - ordinary C string library is not founded. -2. Introduction of memory (and vector?) abstractions imposes a learning - curve, and some kind of memory usage policy that is outside of the strings - themselves (and therefore must be maintained by the developer.) -3. The API is massive, and filled with all sorts of trivial (pjoin) and - controvertial (pmatch -- regular expression are not sufficiently - standardized, and there is a very large difference in performance between - compiled and non-compiled, REs) functions. Bstrlib takes a decidely - minimal approach -- none of the functionality in c2lib is difficult or - challenging to implement on top of Bstrlib (except the regex stuff, which - is going to be difficult, and controvertial no matter what.) -4. Understanding why c2lib is the way it is pretty much requires a working - knowledge of Perl. bstrlib requires only knowledge of the C string library - while providing just a very select few worthwhile extras. -5. It is attached to a lot of cruft like a matrix math library (that doesn't - include any functions for getting the determinant, eigenvectors, - eigenvalues, the matrix inverse, test for singularity, test for - orthogonality, a grahm schmit orthogonlization, LU decomposition ... I - mean why bother?) - -Convincing a development house to use c2lib is likely quite difficult. It -introduces too much, while not being part of any kind of standards body. The -code must therefore be trusted, or maintained by those that use it. While -bstring offers nothing more on this front, since its so much smaller, covers -far less in terms of scope, and will typically improve string performance, -the barrier to usage should be much smaller. - -Comparison with stralloc/qmail ------------------------------- - -More information about this library can be found here: -http://www.canonical.org/~kragen/stralloc.html or here: -http://cr.yp.to/lib/stralloc.html - -1. Library is very very minimal. A little too minimal. -2. Untargetted source parameters are not declared const. -3. Slightly different expected emphasis (like _cats function which takes an - ordinary C string char buffer as a parameter.) Its clear that the - remainder of the C string library is still required to perform more - useful string operations. - -The struct declaration for their string header is essentially the same as that -for bstring. But its clear that this was a quickly written hack whose goals -are clearly a subset of what Bstrlib supplies. For anyone who is served by -stralloc, Bstrlib is complete substitute that just adds more functionality. - -stralloc actually uses the interesting policy that a NULL data pointer -indicates an empty string. In this way, non-static empty strings can be -declared without construction. This advantage is minimal, since static empty -bstrings can be declared inline without construction, and if the string needs -to be written to it should be constructed from an empty string (or its first -initializer) in any event. - -wxString class --------------- - -This is the string class used in the wxWindows project. A description of -wxString can be found here: -http://www.wxwindows.org/manuals/2.4.2/wx368.htm#wxstring - -This C++ library is similar to CBString. However, it is littered with -trivial functions (IsAscii, UpperCase, RemoveLast etc.) - -1. There is no C implementation. -2. The memory management strategy is to allocate a bounded fixed amount of - additional space on each resize, meaning that it does not have the - log_2(n) property that Bstrlib has (it will thrash very easily, cause - massive fragmentation in common heap implementations, and can easily be a - common source of performance problems). -3. The library uses a "copy on write" strategy, meaning that it has to deal - with multithreading problems. - -Vstr ----- - -This is a highly orthogonal C string library with an emphasis on -networking/realtime programming. It can be found here: -http://www.and.org/vstr/ - -1. The convoluted internal structure does not contain a '\0' char * compatible - buffer, so interoperability with the C library a non-starter. -2. The API and implementation is very large (owing to its orthogonality) and - can lead to difficulty in understanding its exact functionality. -3. An obvious dependency on gnu tools (confusing make configure step) -4. Uses a reference counting system, meaning that it is not likely to be - thread safe. - -The implementation has an extreme emphasis on performance for nontrivial -actions (adds, inserts and deletes are all constant or roughly O(#operations) -time) following the "zero copy" principle. This trades off performance of -trivial functions (character access, char buffer access/coersion, alias -detection) which becomes significantly slower, as well as incremental -accumulative costs for its searching/parsing functions. Whether or not Vstr -wins any particular performance benchmark will depend a lot on the benchmark, -but it should handily win on some, while losing dreadfully on others. - -The learning curve for Vstr is very steep, and it doesn't come with any -obvious way to build for Windows or other platforms without gnu tools. At -least one mechanism (the iterator) introduces a new undefined scenario -(writing to a Vstr while iterating through it.) Vstr has a very large -footprint, and is very ambitious in its total functionality. Vstr has no C++ -API. - -Vstr usage requires context initialization via vstr_init() which must be run -in a thread-local context. Given the totally reference based architecture -this means that sharing Vstrings across threads is not well defined, or at -least not safe from race conditions. This API is clearly geared to the older -standard of fork() style multitasking in UNIX, and is not safely transportable -to modern shared memory multithreading available in Linux and Windows. There -is no portable external solution making the library thread safe (since it -requires a mutex around each Vstr context -- not each string.) - -In the documentation for this library, a big deal is made of its self hosted -s(n)printf-like function. This is an issue for older compilers that don't -include vsnprintf(), but also an issue because Vstr has a slow conversion to -'\0' terminated char * mechanism. That is to say, using "%s" to format data -that originates from Vstr would be slow without some sort of native function -to do so. Bstrlib sidesteps the issue by relying on what snprintf-like -functionality does exist and having a high performance conversion to a char * -compatible string so that "%s" can be used directly. - -Str Library ------------ - -This is a fairly extensive string library, that includes full unicode support -and targetted at the goal of out performing MFC and STL. The architecture, -similarly to MFC's CStrings, is a copy on write reference counting mechanism. - -http://www.utilitycode.com/str/default.aspx - -1. Commercial. -2. C++ only. - -This library, like Vstr, uses a ref counting system. There is only so deeply -I can analyze it, since I don't have a license for it. However, performance -improvements over MFC's and STL, doesn't seem like a sufficient reason to -move your source base to it. For example, in the future, Microsoft may -improve the performance CString. - -It should be pointed out that performance testing of Bstrlib has indicated -that its relative performance advantage versus MFC's CString and STL's -std::string is at least as high as that for the Str library. - -libmib astrings ---------------- - -A handful of functional extensions to the C library that add dynamic string -functionality. -http://www.mibsoftware.com/libmib/astring/ - -This package basically references strings through char ** pointers and assumes -they are pointing to the top of an allocated heap entry (or NULL, in which -case memory will be newly allocated from the heap.) So its still up to user -to mix and match the older C string functions with these functions whenever -pointer arithmetic is used (i.e., there is no leveraging of the type system -to assert semantic differences between references and base strings as Bstrlib -does since no new types are introduced.) Unlike Bstrlib, exact string length -meta data is not stored, thus requiring a strlen() call on *every* string -writing operation. The library is very small, covering only a handful of C's -functions. - -While this is better than nothing, it is clearly slower than even the -standard C library, less safe and less functional than Bstrlib. - -To explain the advantage of using libmib, their website shows an example of -how dangerous C code: - - char buf[256]; - char *pszExtraPath = ";/usr/local/bin"; - - strcpy(buf,getenv("PATH")); /* oops! could overrun! */ - strcat(buf,pszExtraPath); /* Could overrun as well! */ - - printf("Checking...%s\n",buf); /* Some printfs overrun too! */ - -is avoided using libmib: - - char *pasz = 0; /* Must initialize to 0 */ - char *paszOut = 0; - char *pszExtraPath = ";/usr/local/bin"; - - if (!astrcpy(&pasz,getenv("PATH"))) /* malloc error */ exit(-1); - if (!astrcat(&pasz,pszExtraPath)) /* malloc error */ exit(-1); - - /* Finally, a "limitless" printf! we can use */ - asprintf(&paszOut,"Checking...%s\n",pasz);fputs(paszOut,stdout); - - astrfree(&pasz); /* Can use free(pasz) also. */ - astrfree(&paszOut); - -However, compare this to Bstrlib: - - bstring b, out; - - bcatcstr (b = bfromcstr (getenv ("PATH")), ";/usr/local/bin"); - out = bformat ("Checking...%s\n", bdatae (b, "<Out of memory>")); - /* if (out && b) */ fputs (bdatae (out, "<Out of memory>"), stdout); - bdestroy (b); - bdestroy (out); - -Besides being shorter, we can see that error handling can be deferred right -to the very end. Also, unlike the above two versions, if getenv() returns -with NULL, the Bstrlib version will not exhibit undefined behavior. -Initialization starts with the relevant content rather than an extra -autoinitialization step. - -libclc ------- - -An attempt to add to the standard C library with a number of common useful -functions, including additional string functions. -http://libclc.sourceforge.net/ - -1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass - the responsibility to guard against aliasing to the programmer. -2. Adds no safety or memory management whatsoever. -3. Most of the supplied string functions are completely trivial. - -The goals of libclc and Bstrlib are clearly quite different. - -fireString ----------- - -http://firestuff.org/ - -1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass - the responsibility to guard against aliasing to the programmer. -2. Mixes char * and length wrapped buffers (estr) functions, doubling the API - size, with safety limited to only half of the functions. - -Firestring was originally just a wrapper of char * functionality with extra -length parameters. However, it has been augmented with the inclusion of the -estr type which has similar functionality to stralloc. But firestring does -not nearly cover the functional scope of Bstrlib. - -Safe C String Library ---------------------- - -A library written for the purpose of increasing safety and power to C's string -handling capabilities. -http://www.zork.org/safestr/safestr.html - -1. While the safestr_* functions are safe in of themselves, interoperating - with char * string has dangerous unsafe modes of operation. -2. The architecture of safestr's causes the base pointer to change. Thus, - its not practical/safe to store a safestr in multiple locations if any - single instance can be manipulated. -3. Dependent on an additional error handling library. -4. Uses reference counting, meaning that it is either not thread safe or - slow and not portable. - -I think the idea of reallocating (and hence potentially changing) the base -pointer is a serious design flaw that is fatal to this architecture. True -safety is obtained by having automatic handling of all common scenarios -without creating implicit constraints on the user. - -Because of its automatic temporary clean up system, it cannot use "const" -semantics on input arguments. Interesting anomolies such as: - - safestr_t s, t; - s = safestr_replace (t = SAFESTR_TEMP ("This is a test"), - SAFESTR_TEMP (" "), SAFESTR_TEMP (".")); - /* t is now undefined. */ - -are possible. If one defines a function which takes a safestr_t as a -parameter, then the function would not know whether or not the safestr_t is -defined after it passes it to a safestr library function. The author -recommended method for working around this problem is to examine the -attributes of the safestr_t within the function which is to modify any of -its parameters and play games with its reference count. I think, therefore, -that the whole SAFESTR_TEMP idea is also fatally broken. - -The library implements immutability, optional non-resizability, and a "trust" -flag. This trust flag is interesting, and suggests that applying any -arbitrary sequence of safestr_* function calls on any set of trusted strings -will result in a trusted string. It seems to me, however, that if one wanted -to implement a trusted string semantic, one might do so by actually creating -a different *type* and only implement the subset of string functions that are -deemed safe (i.e., user input would be excluded, for example.) This, in -essence, would allow the compiler to enforce trust propogation at compile -time rather than run time. Non-resizability is also interesting, however, -it seems marginal (i.e., to want a string that cannot be resized, yet can be -modified and yet where a fixed sized buffer is undesirable.) - -=============================================================================== - -Examples --------- - - Dumping a line numbered file: - - FILE * fp; - int i, ret; - struct bstrList * lines; - struct tagbstring prefix = bsStatic ("-> "); - - if (NULL != (fp = fopen ("bstrlib.txt", "rb"))) { - bstring b = bread ((bNread) fread, fp); - fclose (fp); - if (NULL != (lines = bsplit (b, '\n'))) { - for (i=0; i < lines->qty; i++) { - binsert (lines->entry[i], 0, &prefix, '?'); - printf ("%04d: %s\n", i, bdatae (lines->entry[i], "NULL")); - } - bstrListDestroy (lines); - } - bdestroy (b); - } - -For numerous other examples, see bstraux.c, bstraux.h and the example archive. - -=============================================================================== - -License -------- - -The Better String Library is available under either the 3 clause BSD license -(see the accompanying license.txt) or the Gnu Public License version 2 (see -the accompanying gpl.txt) at the option of the user. - -=============================================================================== - -Acknowledgements ----------------- - -The following individuals have made significant contributions to the design -and testing of the Better String Library: - -Bjorn Augestad -Clint Olsen -Darryl Bleau -Fabian Cenedese -Graham Wideman -Ignacio Burgueno -International Business Machines Corporation -Ira Mica -John Kortink -Manuel Woelker -Marcel van Kervinck -Michael Hsieh -Richard A. Smith -Simon Ekstrom -Wayne Scott - -=============================================================================== diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt deleted file mode 100644 index cf78a984cc..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2002-2008 Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of bstrlib nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt deleted file mode 100644 index 11d8d13130..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt +++ /dev/null @@ -1,172 +0,0 @@ -Better String library Porting Guide ------------------------------------ - -by Paul Hsieh - -The bstring library is an attempt to provide improved string processing -functionality to the C and C++ language. At the heart of the bstring library -is the management of "bstring"s which are a significant improvement over '\0' -terminated char buffers. See the accompanying documenation file bstrlib.txt -for more information. - -=============================================================================== - -Identifying the Compiler ------------------------- - -Bstrlib has been tested on the following compilers: - - Microsoft Visual C++ - Watcom C/C++ (32 bit flat) - Intel's C/C++ compiler (on Windows) - The GNU C/C++ compiler (on Windows/Linux on x86 and PPC64) - Borland C++ - Turbo C - -There are slight differences in these compilers which requires slight -differences in the implementation of Bstrlib. These are accomodated in the -same sources using #ifdef/#if defined() on compiler specific macros. To -port Bstrlib to a new compiler not listed above, it is recommended that the -same strategy be followed. If you are unaware of the compiler specific -identifying preprocessor macro for your compiler you might find it here: - -http://predef.sourceforge.net/precomp.html - -Note that Intel C/C++ on Windows sets the Microsoft identifier: _MSC_VER. - -16-bit vs. 32-bit vs. 64-bit Systems ------------------------------------- - -Bstrlib has been architected to deal with strings of length between 0 and -INT_MAX (inclusive). Since the values of int are never higher than size_t -there will be no issue here. Note that on most 64-bit systems int is 32-bit. - -Dependency on The C-Library ---------------------------- - -Bstrlib uses the functions memcpy, memmove, malloc, realloc, free and -vsnprintf. Many free standing C compiler implementations that have a mode in -which the C library is not available will typically not include these -functions which will make porting Bstrlib to it onerous. Bstrlib is not -designed for such bare bones compiler environments. This usually includes -compilers that target ROM environments. - -Porting Issues --------------- - -Bstrlib has been written completely in ANSI/ISO C and ISO C++, however, there -are still a few porting issues. These are described below. - -1. The vsnprintf () function. - -Unfortunately, the earlier ANSI/ISO C standards did not include this function. -If the compiler of interest does not support this function then the -BSTRLIB_NOVSNP should be defined via something like: - - #if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) - # if defined (__TURBOC__) || defined (__COMPILERVENDORSPECIFICMACRO__) - # define BSTRLIB_NOVSNP - # endif - #endif - -which appears at the top of bstrlib.h. Note that the bformat(a) functions -will not be declared or implemented if the BSTRLIB_NOVSNP macro is set. If -the compiler has renamed vsnprintf() to some other named function, then -search for the definition of the exvsnprintf macro in bstrlib.c file and be -sure its defined appropriately: - - #if defined (__COMPILERVENDORSPECIFICMACRO__) - # define exvsnprintf(r,b,n,f,a) {r=__compiler_specific_vsnprintf(b,n,f,a);} - #else - # define exvsnprintf(r,b,n,f,a) {r=vsnprintf(b,n,f,a);} - #endif - -Take notice of the return value being captured in the variable r. It is -assumed that r exceeds n if and only if the underlying vsnprintf function has -determined what the true maximal output length would be for output if the -buffer were large enough to hold it. Non-modern implementations must output a -lesser number (the macro can and should be modified to ensure this). - -2. Weak C++ compiler. - -C++ is a much more complicated language to implement than C. This has lead -to varying quality of compiler implementations. The weaknesses isolated in -the initial ports are inclusion of the Standard Template Library, -std::iostream and exception handling. By default it is assumed that the C++ -compiler supports all of these things correctly. If your compiler does not -support one or more of these define the corresponding macro: - - BSTRLIB_CANNOT_USE_STL - BSTRLIB_CANNOT_USE_IOSTREAM - BSTRLIB_DOESNT_THROW_EXCEPTIONS - -The compiler specific detected macro should be defined at the top of -bstrwrap.h in the Configuration defines section. Note that these disabling -macros can be overrided with the associated enabling macro if a subsequent -version of the compiler gains support. (For example, its possible to rig -up STLport to provide STL support for WATCOM C/C++, so -DBSTRLIB_CAN_USE_STL -can be passed in as a compiler option.) - -3. The bsafe module, and reserved words. - -The bsafe module is in gross violation of the ANSI/ISO C standard in the -sense that it redefines what could be implemented as reserved words on a -given compiler. The typical problem is that a compiler may inline some of the -functions and thus not be properly overridden by the definitions in the bsafe -module. It is also possible that a compiler may prohibit the redefinitions in -the bsafe module. Compiler specific action will be required to deal with -these situations. - -Platform Specific Files ------------------------ - -The makefiles for the examples are basically setup of for particular -environments for each platform. In general these makefiles are not portable -and should be constructed as necessary from scratch for each platform. - -Testing a port --------------- - -To test that a port compiles correctly do the following: - -1. Build a sample project that includes the bstrlib, bstraux, bstrwrap, and - bsafe modules. -2. Compile bstest against the bstrlib module. -3. Run bstest and ensure that 0 errors are reported. -4. Compile test against the bstrlib and bstrwrap modules. -5. Run test and ensure that 0 errors are reported. -6. Compile each of the examples (except for the "re" example, which may be - complicated and is not a real test of bstrlib and except for the mfcbench - example which is Windows specific.) -7. Run each of the examples. - -The builds must have 0 errors, and should have the absolute minimum number of -warnings (in most cases can be reduced to 0.) The result of execution should -be essentially identical on each platform. - -Performance ------------ - -Different CPU and compilers have different capabilities in terms of -performance. It is possible for Bstrlib to assume performance -characteristics that a platform doesn't have (since it was primarily -developed on just one platform). The goal of Bstrlib is to provide very good -performance on all platforms regardless of this but without resorting to -extreme measures (such as using assembly language, or non-portable intrinsics -or library extensions.) - -There are two performance benchmarks that can be found in the example/ -directory. They are: cbench.c and cppbench.cpp. These are variations and -expansions of a benchmark for another string library. They don't cover all -string functionality, but do include the most basic functions which will be -common in most string manipulation kernels. - -............................................................................... - -Feedback --------- - -In all cases, you may email issues found to the primary author of Bstrlib at -the email address: websnarf@users.sourceforge.net - -=============================================================================== diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt deleted file mode 100644 index 9761409f56..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt +++ /dev/null @@ -1,221 +0,0 @@ -Better String library Security Statement ----------------------------------------- - -by Paul Hsieh - -=============================================================================== - -Introduction ------------- - -The Better String library (hereafter referred to as Bstrlib) is an attempt to -provide improved string processing functionality to the C and C++ languages. -At the heart of the Bstrlib is the management of "bstring"s which are a -significant improvement over '\0' terminated char buffers. See the -accompanying documenation file bstrlib.txt for more information. - -DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Like any software, there is always a possibility of failure due to a flawed -implementation. Nevertheless a good faith effort has been made to minimize -such flaws in Bstrlib. Also, use of Bstrlib by itself will not make an -application secure or free from implementation failures. However, it is the -author's conviction that use of Bstrlib can greatly facilitate the creation -of software meeting the highest possible standards of security. - -Part of the reason why this document has been created, is for the purpose of -security auditing, or the creation of further "Statements on Security" for -software that is created that uses Bstrlib. An auditor may check the claims -below against Bstrlib, and use this as a basis for analysis of software which -uses Bstrlib. - -=============================================================================== - -Statement on Security ---------------------- - -This is a document intended to give consumers of the Better String Library -who are interested in security an idea of where the Better String Library -stands on various security issues. Any deviation observed in the actual -library itself from the descriptions below should be considered an -implementation error, not a design flaw. - -This statement is not an analytical proof of correctness or an outline of one -but rather an assertion similar to a scientific claim or hypothesis. By use, -testing and open independent examination (otherwise known as scientific -falsifiability), the credibility of the claims made below can rise to the -level of an established theory. - -Common security issues: -....................... - -1. Buffer Overflows - -The Bstrlib API allows the programmer a way to deal with strings without -having to deal with the buffers containing them. Ordinary usage of the -Bstrlib API itself makes buffer overflows impossible. - -Furthermore, the Bstrlib API has a superset of basic string functionality as -compared to the C library's char * functions, C++'s std::string class and -Microsoft's MFC based CString class. It also has abstracted mechanisms for -dealing with IO. This is important as it gives developers a way of migrating -all their code from a functionality point of view. - -2. Memory size overflow/wrap around attack - -Bstrlib is, by design, impervious to memory size overflow attacks. The -reason is it is resiliant to length overflows is that bstring lengths are -bounded above by INT_MAX, instead of ~(size_t)0. So length addition -overflows cause a wrap around of the integer value making them negative -causing balloc() to fail before an erroneous operation can occurr. Attempted -conversions of char * strings which may have lengths greater than INT_MAX are -detected and the conversion is aborted. - -It is unknown if this property holds on machines that don't represent -integers as 2s complement. It is recommended that Bstrlib be carefully -auditted by anyone using a system which is not 2s complement based. - -3. Constant string protection - -Bstrlib implements runtime enforced constant and read-only string semantics. -I.e., bstrings which are declared as constant via the bsStatic() macro cannot -be modified or deallocated directly through the Bstrlib API, and this cannot -be subverted by casting or other type coercion. This is independent of the -use of the const_bstring data type. - -The Bstrlib C API uses the type const_bstring to specify bstring parameters -whose contents do not change. Although the C language cannot enforce this, -this is nevertheless guaranteed by the implementation of the Bstrlib library -of C functions. The C++ API enforces the const attribute on CBString types -correctly. - -4. Aliased bstring support - -Bstrlib detects and supports aliased parameter management throughout the API. -The kind of aliasing that is allowed is the one where pointers of the same -basic type may be pointing to overlapping objects (this is the assumption the -ANSI C99 specification makes.) Each function behaves as if all read-only -parameters were copied to temporaries which are used in their stead before -the function is enacted (it rarely actually does this). No function in the -Bstrlib uses the "restrict" parameter attribute from the ANSI C99 -specification. - -5. Information leaking - -In bstraux.h, using the semantically equivalent macros bSecureDestroy() and -bSecureWriteProtect() in place of bdestroy() and bwriteprotect() respectively -will ensure that stale data does not linger in the heap's free space after -strings have been released back to memory. Created bstrings or CBStrings -are not linked to anything external to themselves, and thus cannot expose -deterministic data leaking. If a bstring is resized, the preimage may exist -as a copy that is released to the heap. Thus for sensitive data, the bstring -should be sufficiently presized before manipulated so that it is not resized. -bSecureInput() has been supplied in bstraux.c, which can be used to obtain -input securely without any risk of leaving any part of the input image in the -heap except for the allocated bstring that is returned. - -6. Memory leaking - -Bstrlib can be built using memdbg.h enabled via the BSTRLIB_MEMORY_DEBUG -macro. User generated definitions for malloc, realloc and free can then be -supplied which can implement special strategies for memory corruption -detection or memory leaking. Otherwise, bstrlib does not do anything out of -the ordinary to attempt to deal with the standard problem of memory leaking -(i.e., losing references to allocated memory) when programming in the C and -C++ languages. However, it does not compound the problem any more than exists -either, as it doesn't have any intrinsic inescapable leaks in it. Bstrlib -does not preclude the use of automatic garbage collection mechanisms such as -the Boehm garbage collector. - -7. Encryption - -Bstrlib does not present any built-in encryption mechanism. However, it -supports full binary contents in its data buffers, so any standard block -based encryption mechanism can make direct use of bstrings/CBStrings for -buffer management. - -8. Double freeing - -Freeing a pointer that is already free is an extremely rare, but nevertheless -a potentially ruthlessly corrupting operation (its possible to cause Win 98 to -reboot, by calling free mulitiple times on already freed data using the WATCOM -CRT.) Bstrlib invalidates the bstring header data before freeing, so that in -many cases a double free will be detected and an error will be reported -(though this behaviour is not guaranteed and should not be relied on). - -Using bstrFree pervasively (instead of bdestroy) can lead to somewhat -improved invalid free avoidance (it is completely safe whenever bstring -instances are only stored in unique variables). For example: - - struct tagbstring hw = bsStatic ("Hello, world"); - bstring cpHw = bstrcpy (&hw); - - #ifdef NOT_QUITE_AS_SAFE - bdestroy (cpHw); /* Never fail */ - bdestroy (cpHw); /* Error sometimes detected at runtime */ - bdestroy (&hw); /* Error detected at run time */ - #else - bstrFree (cpHw); /* Never fail */ - bstrFree (cpHw); /* Will do nothing */ - bstrFree (&hw); /* Will lead to a compile time error */ - #endif - -9. Resource based denial of service - -bSecureInput() has been supplied in bstraux.c. It has an optional upper limit -for input length. But unlike fgets(), it is also easily determined if the -buffer has been truncated early. In this way, a program can set an upper limit -on input sizes while still allowing for implementing context specific -truncation semantics (i.e., does the program consume but dump the extra -input, or does it consume it in later inputs?) - -10. Mixing char *'s and bstrings - -The bstring and char * representations are not identical. So there is a risk -when converting back and forth that data may lost. Essentially bstrings can -contain '\0' as a valid non-terminating character, while char * strings -cannot and in fact must use the character as a terminator. The risk of data -loss is very low, since: - - A) the simple method of only using bstrings in a char * semantically - compatible way is both easy to achieve and pervasively supported. - B) obtaining '\0' content in a string is either deliberate or indicative - of another, likely more serious problem in the code. - C) the library comes with various functions which deal with this issue - (namely: bfromcstr(), bstr2cstr (), and bSetCstrChar ()) - -Marginal security issues: -......................... - -11. 8-bit versus 9-bit portability - -Bstrlib uses CHAR_BIT and other limits.h constants to the maximum extent -possible to avoid portability problems. However, Bstrlib has not been tested -on any system that does not represent char as 8-bits. So whether or not it -works on 9-bit systems is an open question. It is recommended that Bstrlib be -carefully auditted by anyone using a system in which CHAR_BIT is not 8. - -12. EBCDIC/ASCII/UTF-8 data representation attacks. - -Bstrlib uses ctype.h functions to ensure that it remains portable to non- -ASCII systems. It also checks range to make sure it is well defined even for -data that ANSI does not define for the ctype functions. - -Obscure issues: -............... - -13. Data attributes - -There is no support for a Perl-like "taint" attribute, however, an example of -how to do this using C++'s type system is given as an example. - diff --git a/Code/Tools/HLSLCrossCompiler/src/decode.c b/Code/Tools/HLSLCrossCompiler/src/decode.c deleted file mode 100644 index 0af6423971..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/decode.c +++ /dev/null @@ -1,1845 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/decode.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/reflect.h" -#include "internal_includes/structs.h" -#include "internal_includes/tokens.h" -#include "stdio.h" -#include "stdlib.h" - -enum -{ - FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C') -}; // DirectX byte code -enum -{ - FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R') -}; // Shader model 4 code -enum -{ - FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X') -}; // Shader model 5 code -enum -{ - FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F') -}; // Resource definition (e.g. constant buffers) -enum -{ - FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N') -}; // Input signature -enum -{ - FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E') -}; // Interface (for dynamic linking) -enum -{ - FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N') -}; // Output signature - -enum -{ - FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1') -}; // Input signature with Stream and MinPrecision -enum -{ - FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1') -}; // Output signature with Stream and MinPrecision -enum -{ - FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5') -}; // Output signature with Stream - -typedef struct DXBCContainerHeaderTAG -{ - unsigned fourcc; - uint32_t unk[4]; - uint32_t one; - uint32_t totalSize; - uint32_t chunkCount; -} DXBCContainerHeader; - -typedef struct DXBCChunkHeaderTAG -{ - unsigned fourcc; - unsigned size; -} DXBCChunkHeader; - -#ifdef _DEBUG -static uint64_t operandID = 0; -static uint64_t instructionID = 0; -#endif - -#if defined(_WIN32) -#define osSprintf(dest, size, src) sprintf_s(dest, size, src) -#else -#define osSprintf(dest, size, src) sprintf(dest, src) -#endif - -void DecodeNameToken(const uint32_t* pui32NameToken, Operand* psOperand) -{ - const size_t MAX_BUFFER_SIZE = sizeof(psOperand->pszSpecialName); - psOperand->eSpecialName = DecodeOperandSpecialName(*pui32NameToken); - switch (psOperand->eSpecialName) - { - case NAME_UNDEFINED: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "undefined"); - break; - } - case NAME_POSITION: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "position"); - break; - } - case NAME_CLIP_DISTANCE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "clipDistance"); - break; - } - case NAME_CULL_DISTANCE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "cullDistance"); - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "renderTargetArrayIndex"); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "viewportArrayIndex"); - break; - } - case NAME_VERTEX_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "vertexID"); - break; - } - case NAME_PRIMITIVE_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "primitiveID"); - break; - } - case NAME_INSTANCE_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "instanceID"); - break; - } - case NAME_IS_FRONT_FACE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "isFrontFace"); - break; - } - case NAME_SAMPLE_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "sampleIndex"); - break; - } - // For the quadrilateral domain, there are 6 factors (4 sides, 2 inner). - case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: - case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: - - // For the triangular domain, there are 4 factors (3 sides, 1 inner) - case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_INSIDE_TESSFACTOR: - - // For the isoline domain, there are 2 factors (detail and density). - case NAME_FINAL_LINE_DETAIL_TESSFACTOR: - case NAME_FINAL_LINE_DENSITY_TESSFACTOR: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "tessFactor"); - break; - } - default: - { - ASSERT(0); - break; - } - } - - return; -} - -uint32_t DecodeOperand(const uint32_t* pui32Tokens, Operand* psOperand) -{ - int i; - uint32_t ui32NumTokens = 1; - OPERAND_NUM_COMPONENTS eNumComponents; - -#ifdef _DEBUG - psOperand->id = operandID++; -#endif - - // Some defaults - psOperand->iWriteMaskEnabled = 1; - psOperand->iGSInput = 0; - psOperand->aeDataType[0] = SVT_FLOAT; - psOperand->aeDataType[1] = SVT_FLOAT; - psOperand->aeDataType[2] = SVT_FLOAT; - psOperand->aeDataType[3] = SVT_FLOAT; - - psOperand->iExtended = DecodeIsOperandExtended(*pui32Tokens); - - psOperand->eModifier = OPERAND_MODIFIER_NONE; - psOperand->psSubOperand[0] = 0; - psOperand->psSubOperand[1] = 0; - psOperand->psSubOperand[2] = 0; - - psOperand->eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; - - /* Check if this instruction is extended. If it is, - * we need to print the information first */ - if (psOperand->iExtended) - { - /* OperandToken1 is the second token */ - ui32NumTokens++; - - if (DecodeExtendedOperandType(pui32Tokens[1]) == EXTENDED_OPERAND_MODIFIER) - { - psOperand->eModifier = DecodeExtendedOperandModifier(pui32Tokens[1]); - psOperand->eMinPrecision = DecodeOperandMinPrecision(pui32Tokens[1]); - } - } - - psOperand->iIndexDims = DecodeOperandIndexDimension(*pui32Tokens); - psOperand->eType = DecodeOperandType(*pui32Tokens); - - psOperand->ui32RegisterNumber = 0; - - eNumComponents = DecodeOperandNumComponents(*pui32Tokens); - - switch (eNumComponents) - { - case OPERAND_1_COMPONENT: - { - psOperand->iNumComponents = 1; - break; - } - case OPERAND_4_COMPONENT: - { - psOperand->iNumComponents = 4; - break; - } - default: - { - psOperand->iNumComponents = 0; - break; - } - } - - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) - { - psOperand->eSelMode = DecodeOperand4CompSelMode(*pui32Tokens); - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - psOperand->ui32CompMask = DecodeOperand4CompMask(*pui32Tokens); - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - psOperand->ui32Swizzle = DecodeOperand4CompSwizzle(*pui32Tokens); - - if (psOperand->ui32Swizzle != NO_SWIZZLE) - { - psOperand->aui32Swizzle[0] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 0); - psOperand->aui32Swizzle[1] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 1); - psOperand->aui32Swizzle[2] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 2); - psOperand->aui32Swizzle[3] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 3); - } - else - { - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; - psOperand->aui32Swizzle[1] = OPERAND_4_COMPONENT_Y; - psOperand->aui32Swizzle[2] = OPERAND_4_COMPONENT_Z; - psOperand->aui32Swizzle[3] = OPERAND_4_COMPONENT_W; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psOperand->aui32Swizzle[0] = DecodeOperand4CompSel1(*pui32Tokens); - } - } - - // Set externally to this function based on the instruction opcode. - psOperand->iIntegerImmediate = 0; - - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) - { - for (i = 0; i < psOperand->iNumComponents; ++i) - { - psOperand->afImmediates[i] = *((float*)(&pui32Tokens[ui32NumTokens])); - ui32NumTokens++; - } - } - else if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - for (i = 0; i < psOperand->iNumComponents; ++i) - { - psOperand->adImmediates[i] = *((double*)(&pui32Tokens[ui32NumTokens])); - ui32NumTokens += 2; - } - } - - if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) - { - psOperand->ui32RegisterNumber = -1; - psOperand->ui32CompMask = -1; - } - - for (i = 0; i < psOperand->iIndexDims; ++i) - { - OPERAND_INDEX_REPRESENTATION eRep = DecodeOperandIndexRepresentation(i, *pui32Tokens); - - psOperand->eIndexRep[i] = eRep; - - psOperand->aui32ArraySizes[i] = 0; - psOperand->ui32RegisterNumber = 0; - - switch (eRep) - { - case OPERAND_INDEX_IMMEDIATE32: - { - psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); - psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; - break; - } - case OPERAND_INDEX_RELATIVE: - { - psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); - DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); - - ui32NumTokens++; - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); - psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; - - ui32NumTokens++; - - psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); - DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); - - ui32NumTokens++; - break; - } - default: - { - ASSERT(0); - break; - } - } - - ui32NumTokens++; - } - - psOperand->pszSpecialName[0] = '\0'; - - return ui32NumTokens; -} - -const uint32_t* DecodeDeclaration(Shader* psShader, const uint32_t* pui32Token, Declaration* psDecl) -{ - uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); - const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); - const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); - uint32_t ui32OperandOffset = 1; - - if (eOpcode < NUM_OPCODES && eOpcode >= 0) - { - psShader->aiOpcodeUsed[eOpcode] = 1; - } - - psDecl->eOpcode = eOpcode; - - psDecl->ui32TexReturnType = SVT_FLOAT; - - if (bExtended) - { - ui32OperandOffset = 2; - } - - switch (eOpcode) - { - case OPCODE_DCL_RESOURCE: // DCL* opcodes have - { - ResourceBinding* psBinding = 0; - psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && - GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) - { - psDecl->ui32TexReturnType = psBinding->ui32ReturnType; - } - break; - } - case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. - { - psDecl->value.eCBAccessPattern = DecodeConstantBufferAccessPattern(*pui32Token); - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_SAMPLER: - { - break; - } - case OPCODE_DCL_INDEX_RANGE: - { - psDecl->ui32NumOperands = 1; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - psDecl->value.ui32IndexRange = pui32Token[ui32OperandOffset]; - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) - { - uint32_t i; - const uint32_t indexRange = psDecl->value.ui32IndexRange; - const uint32_t reg = psDecl->asOperands[0].ui32RegisterNumber; - - psShader->aIndexedInput[reg] = indexRange; - psShader->aIndexedInputParents[reg] = reg; - - //-1 means don't declare this input because it falls in - // the range of an already declared array. - for (i = reg + 1; i < reg + indexRange; ++i) - { - psShader->aIndexedInput[i] = -1; - psShader->aIndexedInputParents[i] = reg; - } - } - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) - { - psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.ui32IndexRange; - } - break; - } - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - { - psDecl->value.eOutputPrimitiveTopology = DecodeGSOutputPrimitiveTopology(*pui32Token); - break; - } - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - { - psDecl->value.eInputPrimitive = DecodeGSInputPrimitive(*pui32Token); - break; - } - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - { - psDecl->value.ui32MaxOutputVertexCount = pui32Token[1]; - break; - } - case OPCODE_DCL_TESS_PARTITIONING: - { - psDecl->value.eTessPartitioning = DecodeTessPartitioning(*pui32Token); - break; - } - case OPCODE_DCL_TESS_DOMAIN: - { - psDecl->value.eTessDomain = DecodeTessDomain(*pui32Token); - break; - } - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - { - psDecl->value.eTessOutPrim = DecodeTessOutPrim(*pui32Token); - break; - } - case OPCODE_DCL_THREAD_GROUP: - { - psDecl->value.aui32WorkGroupSize[0] = pui32Token[1]; - psDecl->value.aui32WorkGroupSize[1] = pui32Token[2]; - psDecl->value.aui32WorkGroupSize[2] = pui32Token[3]; - break; - } - case OPCODE_DCL_INPUT: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_SIV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - if (psShader->eShaderType == PIXEL_SHADER) - { - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - } - break; - } - case OPCODE_DCL_INPUT_PS: - { - psDecl->ui32NumOperands = 1; - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_PS_SGV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_PS_SIV: - { - psDecl->ui32NumOperands = 1; - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_OUTPUT: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_OUTPUT_SGV: - { - break; - } - case OPCODE_DCL_OUTPUT_SIV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_TEMPS: - { - psDecl->value.ui32NumTemps = *(pui32Token + ui32OperandOffset); - break; - } - case OPCODE_DCL_INDEXABLE_TEMP: - { - psDecl->sIdxTemp.ui32RegIndex = *(pui32Token + ui32OperandOffset); - psDecl->sIdxTemp.ui32RegCount = *(pui32Token + ui32OperandOffset + 1); - psDecl->sIdxTemp.ui32RegComponentSize = *(pui32Token + ui32OperandOffset + 2); - break; - } - case OPCODE_DCL_GLOBAL_FLAGS: - { - psDecl->value.ui32GlobalFlags = DecodeGlobalFlags(*pui32Token); - break; - } - case OPCODE_DCL_INTERFACE: - { - uint32_t func = 0, numClassesImplementingThisInterface, arrayLen, interfaceID; - interfaceID = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - psDecl->ui32TableLength = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - - numClassesImplementingThisInterface = DecodeInterfaceTableLength(*(pui32Token + ui32OperandOffset)); - arrayLen = DecodeInterfaceArrayLength(*(pui32Token + ui32OperandOffset)); - - ui32OperandOffset++; - - psDecl->value.interface.ui32InterfaceID = interfaceID; - psDecl->value.interface.ui32NumFuncTables = numClassesImplementingThisInterface; - psDecl->value.interface.ui32ArraySize = arrayLen; - - psShader->funcPointer[interfaceID].ui32NumBodiesPerTable = psDecl->ui32TableLength; - - for (; func < numClassesImplementingThisInterface; ++func) - { - uint32_t ui32FuncTable = *(pui32Token + ui32OperandOffset); - psShader->aui32FuncTableToFuncPointer[ui32FuncTable] = interfaceID; - - psShader->funcPointer[interfaceID].aui32FuncTables[func] = ui32FuncTable; - ui32OperandOffset++; - } - - break; - } - case OPCODE_DCL_FUNCTION_BODY: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_FUNCTION_TABLE: - { - uint32_t ui32Func; - const uint32_t ui32FuncTableID = pui32Token[ui32OperandOffset++]; - const uint32_t ui32NumFuncsInTable = pui32Token[ui32OperandOffset++]; - - for (ui32Func = 0; ui32Func < ui32NumFuncsInTable; ++ui32Func) - { - const uint32_t ui32FuncBodyID = pui32Token[ui32OperandOffset++]; - - psShader->aui32FuncBodyToFuncTable[ui32FuncBodyID] = ui32FuncTableID; - - psShader->funcTable[ui32FuncTableID].aui32FuncBodies[ui32Func] = ui32FuncBodyID; - } - - // OpcodeToken0 is followed by a DWORD that represents the function table - // identifier and another DWORD (TableLength) that gives the number of - // functions in the table. - // - // This is followed by TableLength DWORDs which are function body indices. - // - - break; - } - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_HS_DECLS: - { - break; - } - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - { - psDecl->value.ui32MaxOutputVertexCount = DecodeOutputControlPointCount(*pui32Token); - break; - } - case OPCODE_HS_JOIN_PHASE: - case OPCODE_HS_FORK_PHASE: - case OPCODE_HS_CONTROL_POINT_PHASE: - { - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - ASSERT(psShader->ui32ForkPhaseCount != 0); // Check for wrapping when we decrement. - psDecl->value.aui32HullPhaseInstanceInfo[0] = psShader->ui32ForkPhaseCount - 1; - psDecl->value.aui32HullPhaseInstanceInfo[1] = pui32Token[1]; - break; - } - case OPCODE_CUSTOMDATA: - { - ui32TokenLength = pui32Token[1]; - { - const uint32_t ui32NumVec4 = (ui32TokenLength - 2) / 4; - uint32_t uIdx = 0; - - ICBVec4 const* pVec4Array = (void*)(pui32Token + 2); - - // The buffer will contain at least one value, but not more than 4096 scalars/1024 vec4's. - ASSERT(ui32NumVec4 < MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE); - - /* must be a multiple of 4 */ - ASSERT(((ui32TokenLength - 2) % 4) == 0); - - for (uIdx = 0; uIdx < ui32NumVec4; uIdx++) - { - psDecl->asImmediateConstBuffer[uIdx] = pVec4Array[uIdx]; - } - - psDecl->ui32NumOperands = ui32NumVec4; - } - break; - } - case OPCODE_DCL_HS_MAX_TESSFACTOR: - { - psDecl->value.fMaxTessFactor = *((float*)&pui32Token[1]); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - { - psDecl->ui32NumOperands = 2; - psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - psDecl->sUAV.Type = DecodeResourceReturnType(0, pui32Token[ui32OperandOffset]); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - { - - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - // This should be a RTYPE_UAV_RWBYTEADDRESS buffer. It is memory backed by - // a shader storage buffer whose is unknown at compile time. - psDecl->sUAV.ui32BufferSize = 0; - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - { - ResourceBinding* psBinding = NULL; - ConstantBuffer* psBuffer = NULL; - - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding); - - GetConstantBufferFromBindingPoint(RGROUP_UAV, psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); - psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; - switch (psBinding->eType) - { - case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: - case RTYPE_UAV_APPEND_STRUCTURED: - case RTYPE_UAV_CONSUME_STRUCTURED: - psDecl->sUAV.bCounter = 1; - break; - default: - break; - } - break; - } - case OPCODE_DCL_RESOURCE_STRUCTURED: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_RESOURCE_RAW: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - { - - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = 0; - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - psDecl->sTGSM.ui32Stride = pui32Token[ui32OperandOffset++]; - psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - { - - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = 0; - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - psDecl->sTGSM.ui32Stride = 4; - psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++] / 4; - break; - } - case OPCODE_DCL_STREAM: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_GS_INSTANCE_COUNT: - { - psDecl->ui32NumOperands = 0; - psDecl->value.ui32GSInstanceCount = pui32Token[1]; - break; - } - default: - { - // Reached end of declarations - return 0; - } - } - - UpdateDeclarationReferences(psShader, psDecl); - - return pui32Token + ui32TokenLength; -} - -const uint32_t* DecodeInstruction(const uint32_t* pui32Token, Instruction* psInst, Shader* psShader) -{ - uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); - const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); - const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); - uint32_t ui32OperandOffset = 1; - -#ifdef _DEBUG - psInst->id = instructionID++; -#endif - - psInst->eOpcode = eOpcode; - - psInst->bSaturate = DecodeInstructionSaturate(*pui32Token); - - psInst->bAddressOffset = 0; - - psInst->ui32FirstSrc = 1; - - if (bExtended) - { - do - { - const uint32_t ui32ExtOpcodeToken = pui32Token[ui32OperandOffset]; - const EXTENDED_OPCODE_TYPE eExtType = DecodeExtendedOpcodeType(ui32ExtOpcodeToken); - - if (eExtType == EXTENDED_OPCODE_SAMPLE_CONTROLS) - { - psInst->bAddressOffset = 1; - - psInst->iUAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_U, ui32ExtOpcodeToken); - psInst->iVAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_V, ui32ExtOpcodeToken); - psInst->iWAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_W, ui32ExtOpcodeToken); - } - else if (eExtType == EXTENDED_OPCODE_RESOURCE_RETURN_TYPE) - { - psInst->xType = DecodeExtendedResourceReturnType(0, ui32ExtOpcodeToken); - psInst->yType = DecodeExtendedResourceReturnType(1, ui32ExtOpcodeToken); - psInst->zType = DecodeExtendedResourceReturnType(2, ui32ExtOpcodeToken); - psInst->wType = DecodeExtendedResourceReturnType(3, ui32ExtOpcodeToken); - } - else if (eExtType == EXTENDED_OPCODE_RESOURCE_DIM) - { - psInst->eResDim = DecodeExtendedResourceDimension(ui32ExtOpcodeToken); - } - - ui32OperandOffset++; - } while (DecodeIsOpcodeExtended(pui32Token[ui32OperandOffset - 1])); - } - - if (eOpcode < NUM_OPCODES && eOpcode >= 0) - { - psShader->aiOpcodeUsed[eOpcode] = 1; - } - - switch (eOpcode) - { - // no operands - case OPCODE_CUT: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_RET: - case OPCODE_LOOP: - case OPCODE_ENDLOOP: - case OPCODE_BREAK: - case OPCODE_ELSE: - case OPCODE_ENDIF: - case OPCODE_CONTINUE: - case OPCODE_DEFAULT: - case OPCODE_ENDSWITCH: - case OPCODE_NOP: - case OPCODE_HS_CONTROL_POINT_PHASE: - case OPCODE_HS_FORK_PHASE: - case OPCODE_HS_JOIN_PHASE: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - break; - } - case OPCODE_SYNC: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - psInst->ui32SyncFlags = DecodeSyncFlags(*pui32Token); - break; - } - - // 1 operand - case OPCODE_EMIT_STREAM: - case OPCODE_CUT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - case OPCODE_CASE: - case OPCODE_SWITCH: - case OPCODE_LABEL: - { - psInst->ui32NumOperands = 1; - psInst->ui32FirstSrc = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - - // if(eOpcode == OPCODE_CASE) - // { - // psInst->asOperands[0].iIntegerImmediate = 1; - // } - break; - } - - case OPCODE_INTERFACE_CALL: - { - psInst->ui32NumOperands = 1; - psInst->ui32FirstSrc = 0; - psInst->ui32FuncIndexWithinInterface = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - - break; - } - - /* Floating point instruction decodes */ - - // Instructions with two operands go here - case OPCODE_MOV: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - - // Mov with an integer dest. If src is an immediate then it must be encoded as an integer. - if (psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_SINT_16 || psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_UINT_16) - { - psInst->asOperands[1].iIntegerImmediate = 1; - } - break; - } - case OPCODE_LOG: - case OPCODE_RSQ: - case OPCODE_EXP: - case OPCODE_SQRT: - case OPCODE_ROUND_PI: - case OPCODE_ROUND_NI: - case OPCODE_ROUND_Z: - case OPCODE_ROUND_NE: - case OPCODE_FRC: - case OPCODE_FTOU: - case OPCODE_FTOI: - case OPCODE_UTOF: - case OPCODE_ITOF: - case OPCODE_INEG: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - case OPCODE_DMOV: - case OPCODE_DTOF: - case OPCODE_FTOD: - case OPCODE_DRCP: - case OPCODE_COUNTBITS: - case OPCODE_FIRSTBIT_HI: - case OPCODE_FIRSTBIT_LO: - case OPCODE_FIRSTBIT_SHI: - case OPCODE_BFREV: - case OPCODE_F32TOF16: - case OPCODE_F16TOF32: - case OPCODE_RCP: - case OPCODE_DERIV_RTX: - case OPCODE_DERIV_RTY: - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_NOT: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - - // Instructions with three operands go here - case OPCODE_SINCOS: - { - psInst->ui32FirstSrc = 2; - // Intentional fall-through - } - case OPCODE_IMIN: - case OPCODE_UMIN: - case OPCODE_MIN: - case OPCODE_IMAX: - case OPCODE_UMAX: - case OPCODE_MAX: - case OPCODE_MUL: - case OPCODE_DIV: - case OPCODE_ADD: - case OPCODE_DP2: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_NE: - case OPCODE_OR: - case OPCODE_XOR: - case OPCODE_LT: - case OPCODE_IEQ: - case OPCODE_IADD: - case OPCODE_AND: - case OPCODE_GE: - case OPCODE_IGE: - case OPCODE_EQ: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_LD: - case OPCODE_ILT: - case OPCODE_INE: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_IMIN: - case OPCODE_DADD: - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DDIV: - { - psInst->ui32NumOperands = 3; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - case OPCODE_UGE: - case OPCODE_ULT: - case OPCODE_USHR: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_UMIN: - { - psInst->ui32NumOperands = 3; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - // Instructions with four operands go here - case OPCODE_MAD: - case OPCODE_MOVC: - case OPCODE_IMAD: - case OPCODE_UDIV: - case OPCODE_LOD: - case OPCODE_SAMPLE: - case OPCODE_GATHER4: - case OPCODE_LD_MS: - case OPCODE_UBFE: - case OPCODE_IBFE: - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_DMOVC: - case OPCODE_DFMA: - case OPCODE_IMUL: - { - psInst->ui32NumOperands = 4; - - if (eOpcode == OPCODE_IMUL || eOpcode == OPCODE_UDIV) - { - psInst->ui32FirstSrc = 2; - } - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - - break; - } - case OPCODE_UADDC: - case OPCODE_USUBB: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - { - psInst->ui32NumOperands = 4; - - if (eOpcode == OPCODE_IMUL) - { - psInst->ui32FirstSrc = 2; - } - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - - break; - } - case OPCODE_GATHER4_PO: - case OPCODE_SAMPLE_L: - case OPCODE_BFI: - case OPCODE_SWAPC: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - psInst->ui32NumOperands = 5; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - - break; - } - case OPCODE_GATHER4_C: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_B: - { - psInst->ui32NumOperands = 5; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - break; - } - case OPCODE_GATHER4_PO_C: - case OPCODE_SAMPLE_D: - { - psInst->ui32NumOperands = 6; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[5]); - break; - } - case OPCODE_IF: - case OPCODE_BREAKC: - case OPCODE_CONTINUEC: - case OPCODE_RETC: - case OPCODE_DISCARD: - { - psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); - psInst->ui32NumOperands = 1; - psInst->ui32FirstSrc = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - break; - } - case OPCODE_CALLC: - { - psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); - psInst->ui32NumOperands = 2; - psInst->ui32FirstSrc = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - case OPCODE_CUSTOMDATA: - { - psInst->ui32NumOperands = 0; - ui32TokenLength = pui32Token[1]; - break; - } - case OPCODE_EVAL_CENTROID: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_SNAPPED: - case OPCODE_STORE_UAV_TYPED: - case OPCODE_LD_UAV_TYPED: - case OPCODE_LD_RAW: - case OPCODE_STORE_RAW: - { - psInst->ui32NumOperands = 3; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - case OPCODE_STORE_STRUCTURED: - case OPCODE_LD_STRUCTURED: - { - psInst->ui32NumOperands = 4; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - break; - } - case OPCODE_RESINFO: - { - psInst->ui32NumOperands = 3; - - psInst->eResInfoReturnType = DecodeResInfoReturnType(pui32Token[0]); - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - case OPCODE_MSAD: - default: - { - ASSERT(0); - break; - } - } - - UpdateInstructionReferences(psShader, psInst); - - return pui32Token + ui32TokenLength; -} - -void BindTextureToSampler(Shader* psShader, uint32_t ui32TextureRegister, uint32_t ui32SamplerRegister, uint32_t bCompare) -{ - uint32_t ui32Sampler, ui32TextureUnit, bLoad; - ASSERT(ui32TextureRegister < (1 << 10)); - ASSERT(ui32SamplerRegister < (1 << 10)); - - if (psShader->sInfo.ui32NumSamplers >= MAX_RESOURCE_BINDINGS) - { - ASSERT(0); - return; - } - - ui32TextureUnit = ui32TextureRegister; - for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) - { - if (psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureBindPoint == ui32TextureRegister) - { - if (psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10SamplerBindPoint == ui32SamplerRegister) - break; - ui32TextureUnit = MAX_RESOURCE_BINDINGS; // Texture is used by two or more samplers - assign to an available texture unit later - } - } - - // MAX_RESOURCE_BINDINGS means no sampler object (used for texture load) - bLoad = ui32SamplerRegister == MAX_RESOURCE_BINDINGS; - - if (bCompare) - psShader->sInfo.asSamplers[ui32Sampler].sMask.bCompareSample = 1; - else if (!bLoad) - psShader->sInfo.asSamplers[ui32Sampler].sMask.bNormalSample = 1; - else - { - psShader->sInfo.asSamplers[ui32Sampler].sMask.bNormalSample = 0; - psShader->sInfo.asSamplers[ui32Sampler].sMask.bCompareSample = 0; - } - - if (ui32Sampler == psShader->sInfo.ui32NumSamplers) - { - psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureBindPoint = ui32TextureRegister; - psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10SamplerBindPoint = ui32SamplerRegister; - psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit = ui32TextureUnit; - ++psShader->sInfo.ui32NumSamplers; - } -} - -void RegisterUniformBuffer(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) -{ - uint32_t ui32UniformBuffer = psShader->sInfo.ui32NumUniformBuffers; - psShader->sInfo.asUniformBuffers[ui32UniformBuffer].ui32BindPoint = ui32BindPoint; - psShader->sInfo.asUniformBuffers[ui32UniformBuffer].eGroup = eGroup; - ++psShader->sInfo.ui32NumUniformBuffers; -} - -void RegisterStorageBuffer(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) -{ - uint32_t ui32StorageBuffer = psShader->sInfo.ui32NumStorageBuffers; - psShader->sInfo.asStorageBuffers[ui32StorageBuffer].ui32BindPoint = ui32BindPoint; - psShader->sInfo.asStorageBuffers[ui32StorageBuffer].eGroup = eGroup; - ++psShader->sInfo.ui32NumStorageBuffers; -} - -void RegisterImage(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) -{ - uint32_t ui32Image = psShader->sInfo.ui32NumImages; - psShader->sInfo.asImages[ui32Image].ui32BindPoint = ui32BindPoint; - psShader->sInfo.asImages[ui32Image].eGroup = eGroup; - ++psShader->sInfo.ui32NumImages; -} - -void AssignRemainingSamplers(Shader* psShader) -{ - uint32_t ui32Sampler; - uint32_t aui32TextureUnitsUsed[(MAX_RESOURCE_BINDINGS + 31) / 32]; - uint32_t ui32MinAvailUnit; - - memset((void*)aui32TextureUnitsUsed, 0, sizeof(aui32TextureUnitsUsed)); - for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) - { - uint32_t ui32Unit = psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit; - if (ui32Unit < MAX_RESOURCE_BINDINGS) - aui32TextureUnitsUsed[ui32Unit / 32] |= 1 << (ui32Unit % 32); - } - - ui32MinAvailUnit = 0; - for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) - { - uint32_t ui32Unit = psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit; - if (ui32Unit == MAX_RESOURCE_BINDINGS) - { - uint32_t ui32Mask, ui32AvailUnit; - uint32_t ui32WordIndex = ui32MinAvailUnit / 32; - uint32_t ui32BitIndex = ui32MinAvailUnit % 32; - - while (ui32WordIndex < sizeof(aui32TextureUnitsUsed)) - { - if (aui32TextureUnitsUsed[ui32WordIndex] != ~0L) - break; - ++ui32WordIndex; - ui32BitIndex = 0; - } - if (ui32WordIndex == sizeof(aui32TextureUnitsUsed)) - { - ASSERT(0); // Not enough resource bindings - break; - } - - ui32Mask = aui32TextureUnitsUsed[ui32WordIndex]; - while (ui32BitIndex < 32) - { - if ((ui32Mask & (1 << ui32BitIndex)) == 0) - break; - ++ui32BitIndex; - } - if (ui32BitIndex == 32) - { - ASSERT(0); - break; - } - - ui32AvailUnit = 32 * ui32WordIndex + ui32BitIndex; - aui32TextureUnitsUsed[ui32WordIndex] |= (1 << ui32BitIndex); - - psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit = ui32AvailUnit; - ui32MinAvailUnit = ui32AvailUnit + 1; - - ASSERT(psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit < MAX_RESOURCE_BINDINGS); - } - } -} - -void UpdateDeclarationReferences(Shader* psShader, Declaration* psDecl) -{ - switch (psDecl->eOpcode) - { - case OPCODE_DCL_CONSTANT_BUFFER: - RegisterUniformBuffer(psShader, RGROUP_CBUFFER, psDecl->asOperands[0].aui32ArraySizes[0]); - break; - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - RegisterImage(psShader, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber); - break; - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - RegisterStorageBuffer(psShader, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber); - break; - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - RegisterStorageBuffer(psShader, RGROUP_UAV, psDecl->asOperands[0].aui32ArraySizes[0]); - break; - case OPCODE_DCL_RESOURCE_RAW: - RegisterStorageBuffer(psShader, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber); - break; - case OPCODE_DCL_RESOURCE_STRUCTURED: - RegisterStorageBuffer(psShader, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber); - break; - } -} - -void UpdateInstructionReferences(Shader* psShader, Instruction* psInst) -{ - uint32_t ui32Operand; - const uint32_t ui32NumOperands = psInst->ui32NumOperands; - for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) - { - Operand* psOperand = &psInst->asOperands[ui32Operand]; - if (psOperand->eType == OPERAND_TYPE_INPUT || psOperand->eType == OPERAND_TYPE_INPUT_CONTROL_POINT) - { - if (psOperand->iIndexDims == INDEX_2D) - { - if (psOperand->aui32ArraySizes[1] != 0) // gl_in[].gl_Position - { - psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; - } - } - else - { - psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; - } - } - } - - switch (psInst->eOpcode) - { - case OPCODE_SWAPC: - psShader->bUseTempCopy = 1; - break; - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_D: - case OPCODE_SAMPLE_B: - case OPCODE_GATHER4: - BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); - break; - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_C: - case OPCODE_GATHER4_C: - BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); - break; - case OPCODE_GATHER4_PO: - BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0); - break; - case OPCODE_GATHER4_PO_C: - BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 1); - break; - case OPCODE_LD: - case OPCODE_LD_MS: - // MAX_RESOURCE_BINDINGS means no sampler object - BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, MAX_RESOURCE_BINDINGS, 0); - break; - } -} - -const uint32_t* DecodeHullShaderJoinPhase(const uint32_t* pui32Tokens, Shader* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - - Instruction* psInst; - - // Declarations - Declaration* psDecl; - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - psShader->psHSJoinPhaseDecl = psDecl; - psShader->ui32HSJoinDeclCount = 0; - - while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - psShader->ui32HSJoinDeclCount++; - psDecl++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - // Instructions - psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); - psShader->psHSJoinPhaseInstr = psInst; - psShader->ui32HSJoinInstrCount = 0; - - while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) - { - const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); - -#ifdef _DEBUG - if (nextInstr == pui32CurrentToken) - { - ASSERT(0); - break; - } -#endif - - pui32CurrentToken = nextInstr; - psShader->ui32HSJoinInstrCount++; - - psInst++; - } - - return pui32CurrentToken; -} - -const uint32_t* DecodeHullShaderForkPhase(const uint32_t* pui32Tokens, Shader* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - const uint32_t ui32ForkPhaseIndex = psShader->ui32ForkPhaseCount; - - Instruction* psInst; - - // Declarations - Declaration* psDecl; - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - - ASSERT(ui32ForkPhaseIndex < MAX_FORK_PHASES); - - psShader->ui32ForkPhaseCount++; - - psShader->apsHSForkPhaseDecl[ui32ForkPhaseIndex] = psDecl; - psShader->aui32HSForkDeclCount[ui32ForkPhaseIndex] = 0; - - while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - psShader->aui32HSForkDeclCount[ui32ForkPhaseIndex]++; - psDecl++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - // Instructions - psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); - psShader->apsHSForkPhaseInstr[ui32ForkPhaseIndex] = psInst; - psShader->aui32HSForkInstrCount[ui32ForkPhaseIndex] = 0; - - while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) - { - const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); - -#ifdef _DEBUG - if (nextInstr == pui32CurrentToken) - { - ASSERT(0); - break; - } -#endif - - pui32CurrentToken = nextInstr; - - if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) - { - pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - - psShader->aui32HSForkInstrCount[ui32ForkPhaseIndex]++; - psInst++; - } - - return pui32CurrentToken; -} - -const uint32_t* DecodeHullShaderControlPointPhase(const uint32_t* pui32Tokens, Shader* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - - Instruction* psInst; - - // TODO one block of memory for instructions and declarions to reduce memory usage and number of allocs. - // hlscc_malloc max(sizeof(declaration), sizeof(instruction) * shader length; or sizeof(DeclInst) - unifying both structs. - - // Declarations - Declaration* psDecl; - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - psShader->psHSControlPointPhaseDecl = psDecl; - psShader->ui32HSControlPointDeclCount = 0; - - while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - psShader->ui32HSControlPointDeclCount++; - psDecl++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - // Instructions - psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); - psShader->psHSControlPointPhaseInstr = psInst; - psShader->ui32HSControlPointInstrCount = 0; - - while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) - { - const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); - -#ifdef _DEBUG - if (nextInstr == pui32CurrentToken) - { - ASSERT(0); - break; - } -#endif - - pui32CurrentToken = nextInstr; - - if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) - { - pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - if (psInst->eOpcode == OPCODE_HS_JOIN_PHASE) - { - pui32CurrentToken = DecodeHullShaderJoinPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - psInst++; - psShader->ui32HSControlPointInstrCount++; - } - - return pui32CurrentToken; -} - -const uint32_t* DecodeHullShader(const uint32_t* pui32Tokens, Shader* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - Declaration* psDecl; - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - psShader->psHSDecl = psDecl; - psShader->ui32HSDeclCount = 0; - - while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - - if (psDecl->eOpcode == OPCODE_HS_CONTROL_POINT_PHASE) - { - pui32CurrentToken = DecodeHullShaderControlPointPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - if (psDecl->eOpcode == OPCODE_HS_FORK_PHASE) - { - pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - if (psDecl->eOpcode == OPCODE_HS_JOIN_PHASE) - { - pui32CurrentToken = DecodeHullShaderJoinPhase(pui32CurrentToken, psShader); - return pui32CurrentToken; - } - - psDecl++; - psShader->ui32HSDeclCount++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - return pui32CurrentToken; -} - -void Decode(const uint32_t* pui32Tokens, Shader* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = pui32Tokens[1]; - Instruction* psInst; - Declaration* psDecl; - - psShader->ui32MajorVersion = DecodeProgramMajorVersion(*pui32CurrentToken); - psShader->ui32MinorVersion = DecodeProgramMinorVersion(*pui32CurrentToken); - psShader->eShaderType = DecodeShaderType(*pui32CurrentToken); - - pui32CurrentToken++; // Move to shader length - psShader->ui32ShaderLength = ui32ShaderLength; - pui32CurrentToken++; // Move to after shader length (usually a declaration) - - psShader->pui32FirstToken = pui32Tokens; - -#ifdef _DEBUG - operandID = 0; - instructionID = 0; -#endif - - if (psShader->eShaderType == HULL_SHADER) - { - pui32CurrentToken = DecodeHullShader(pui32CurrentToken, psShader); - return; - } - - // Using ui32ShaderLength as the instruction count - // will allocate more than enough memory. Avoids having to - // traverse the entire shader just to get the real instruction count. - psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); - psShader->psInst = psInst; - psShader->ui32InstCount = 0; - - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - psShader->psDecl = psDecl; - psShader->ui32DeclCount = 0; - - while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - psShader->ui32DeclCount++; - psDecl++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) - { - const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); - -#ifdef _DEBUG - if (nextInstr == pui32CurrentToken) - { - ASSERT(0); - break; - } -#endif - - pui32CurrentToken = nextInstr; - psShader->ui32InstCount++; - psInst++; - } - - AssignRemainingSamplers(psShader); -} - -Shader* DecodeDXBC(uint32_t* data) -{ - Shader* psShader; - DXBCContainerHeader* header = (DXBCContainerHeader*)data; - uint32_t i; - uint32_t chunkCount; - uint32_t* chunkOffsets; - ReflectionChunks refChunks; - uint32_t* shaderChunk = 0; - - if (header->fourcc != FOURCC_DXBC) - { - // Could be SM1/2/3. If the shader type token - // looks valid then we continue - uint32_t type = DecodeShaderTypeDX9(data[0]); - - if (type != INVALID_SHADER) - { - return DecodeDX9BC(data); - } - return 0; - } - - refChunks.pui32Inputs = NULL; - refChunks.pui32Interfaces = NULL; - refChunks.pui32Outputs = NULL; - refChunks.pui32Resources = NULL; - refChunks.pui32Inputs11 = NULL; - refChunks.pui32Outputs11 = NULL; - refChunks.pui32OutputsWithStreams = NULL; - - chunkOffsets = (uint32_t*)(header + 1); - - chunkCount = header->chunkCount; - - for (i = 0; i < chunkCount; ++i) - { - uint32_t offset = chunkOffsets[i]; - - DXBCChunkHeader* chunk = (DXBCChunkHeader*)((char*)data + offset); - - switch (chunk->fourcc) - { - case FOURCC_ISGN: - { - refChunks.pui32Inputs = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_ISG1: - { - refChunks.pui32Inputs11 = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_RDEF: - { - refChunks.pui32Resources = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_IFCE: - { - refChunks.pui32Interfaces = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSGN: - { - refChunks.pui32Outputs = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSG1: - { - refChunks.pui32Outputs11 = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSG5: - { - refChunks.pui32OutputsWithStreams = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_SHDR: - case FOURCC_SHEX: - { - shaderChunk = (uint32_t*)(chunk + 1); - break; - } - default: - { - break; - } - } - } - - if (shaderChunk) - { - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - - psShader = hlslcc_calloc(1, sizeof(Shader)); - - ui32MajorVersion = DecodeProgramMajorVersion(*shaderChunk); - ui32MinorVersion = DecodeProgramMinorVersion(*shaderChunk); - - LoadShaderInfo(ui32MajorVersion, ui32MinorVersion, &refChunks, &psShader->sInfo); - - Decode(shaderChunk, psShader); - - return psShader; - } - - return 0; -} diff --git a/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c b/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c deleted file mode 100644 index 68f4dd6225..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c +++ /dev/null @@ -1,1113 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/debug.h" -#include "internal_includes/decode.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/reflect.h" -#include "internal_includes/structs.h" -#include "internal_includes/tokens.h" -#include "stdio.h" -#include "stdlib.h" - -enum -{ - FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B') -}; // Constant table - -#ifdef _DEBUG -static uint64_t dx9operandID = 0; -static uint64_t dx9instructionID = 0; -#endif - -static uint32_t aui32ImmediateConst[256]; -static uint32_t ui32MaxTemp = 0; - -uint32_t DX9_DECODE_OPERAND_IS_SRC = 0x1; -uint32_t DX9_DECODE_OPERAND_IS_DEST = 0x2; -uint32_t DX9_DECODE_OPERAND_IS_DECL = 0x4; - -uint32_t DX9_DECODE_OPERAND_IS_CONST = 0x8; -uint32_t DX9_DECODE_OPERAND_IS_ICONST = 0x10; -uint32_t DX9_DECODE_OPERAND_IS_BCONST = 0x20; - -#define MAX_INPUTS 64 - -static DECLUSAGE_DX9 aeInputUsage[MAX_INPUTS]; -static uint32_t aui32InputUsageIndex[MAX_INPUTS]; - -static void DecodeOperandDX9(const Shader* psShader, const uint32_t ui32Token, const uint32_t ui32Token1, uint32_t ui32Flags, Operand* psOperand) -{ - const uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token); - const uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token); - const uint32_t bRelativeAddr = DecodeOperandIsRelativeAddressModeDX9(ui32Token); - - const uint32_t ui32WriteMask = DecodeDestWriteMaskDX9(ui32Token); - const uint32_t ui32Swizzle = DecodeOperandSwizzleDX9(ui32Token); - - SHADER_VARIABLE_TYPE ConstType; - - psOperand->ui32RegisterNumber = ui32RegNum; - - psOperand->iNumComponents = 4; - -#ifdef _DEBUG - psOperand->id = dx9operandID++; -#endif - - psOperand->iWriteMaskEnabled = 0; - psOperand->iGSInput = 0; - psOperand->iExtended = 0; - psOperand->psSubOperand[0] = 0; - psOperand->psSubOperand[1] = 0; - psOperand->psSubOperand[2] = 0; - - psOperand->iIndexDims = INDEX_0D; - - psOperand->iIntegerImmediate = 0; - - psOperand->pszSpecialName[0] = '\0'; - - psOperand->eModifier = OPERAND_MODIFIER_NONE; - if (ui32Flags & DX9_DECODE_OPERAND_IS_SRC) - { - uint32_t ui32Modifier = DecodeSrcModifierDX9(ui32Token); - - switch (ui32Modifier) - { - case SRCMOD_DX9_NONE: - { - break; - } - case SRCMOD_DX9_NEG: - { - psOperand->eModifier = OPERAND_MODIFIER_NEG; - break; - } - case SRCMOD_DX9_ABS: - { - psOperand->eModifier = OPERAND_MODIFIER_ABS; - break; - } - case SRCMOD_DX9_ABSNEG: - { - psOperand->eModifier = OPERAND_MODIFIER_ABSNEG; - break; - } - default: - { - ASSERT(0); - break; - } - } - } - - if ((ui32Flags & DX9_DECODE_OPERAND_IS_DECL) == 0) - { - if (ui32Flags & DX9_DECODE_OPERAND_IS_DEST) - { - if (ui32WriteMask != DX9_WRITEMASK_ALL) - { - psOperand->iWriteMaskEnabled = 1; - psOperand->eSelMode = OPERAND_4_COMPONENT_MASK_MODE; - - if (ui32WriteMask & DX9_WRITEMASK_0) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_X; - } - if (ui32WriteMask & DX9_WRITEMASK_1) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Y; - } - if (ui32WriteMask & DX9_WRITEMASK_2) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Z; - } - if (ui32WriteMask & DX9_WRITEMASK_3) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_W; - } - } - } - else if (ui32Swizzle != NO_SWIZZLE_DX9) - { - uint32_t component; - - psOperand->iWriteMaskEnabled = 1; - psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE; - - psOperand->ui32Swizzle = 1; - - /* Add the swizzle */ - if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(0)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(1)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Y; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(2)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Z; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(3)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_W; - } - else - { - for (component = 0; component < 4; component++) - { - uint32_t ui32CompSwiz = ui32Swizzle & (3 << (DX9_SWIZZLE_SHIFT + (component * 2))); - ui32CompSwiz >>= (DX9_SWIZZLE_SHIFT + (component * 2)); - - if (ui32CompSwiz == 0) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_X; - } - else if (ui32CompSwiz == 1) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Y; - } - else if (ui32CompSwiz == 2) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Z; - } - else - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_W; - } - } - } - } - - if (bRelativeAddr) - { - psOperand->psSubOperand[0] = hlslcc_malloc(sizeof(Operand)); - DecodeOperandDX9(psShader, ui32Token1, 0, ui32Flags, psOperand->psSubOperand[0]); - - psOperand->iIndexDims = INDEX_1D; - - psOperand->eIndexRep[0] = OPERAND_INDEX_RELATIVE; - - psOperand->aui32ArraySizes[0] = 0; - } - } - - if (ui32RegType == OPERAND_TYPE_DX9_CONSTBOOL) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; - ConstType = SVT_BOOL; - } - else if (ui32RegType == OPERAND_TYPE_DX9_CONSTINT) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; - ConstType = SVT_INT; - } - else if (ui32RegType == OPERAND_TYPE_DX9_CONST) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; - ConstType = SVT_FLOAT; - } - - switch (ui32RegType) - { - case OPERAND_TYPE_DX9_TEMP: - { - psOperand->eType = OPERAND_TYPE_TEMP; - - if (ui32MaxTemp < ui32RegNum + 1) - { - ui32MaxTemp = ui32RegNum + 1; - } - break; - } - case OPERAND_TYPE_DX9_INPUT: - { - psOperand->eType = OPERAND_TYPE_INPUT; - - ASSERT(ui32RegNum < MAX_INPUTS); - - if (psShader->eShaderType == PIXEL_SHADER) - { - if (aeInputUsage[ui32RegNum] == DECLUSAGE_TEXCOORD) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - psOperand->ui32RegisterNumber = aui32InputUsageIndex[ui32RegNum]; - } - else - // 0 = base colour, 1 = offset colour. - if (ui32RegNum == 0) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; - } - else - { - ASSERT(ui32RegNum == 1); - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; - } - } - break; - } - // Same value as OPERAND_TYPE_DX9_TEXCRDOUT - // OPERAND_TYPE_DX9_TEXCRDOUT is the pre-SM3 equivalent - case OPERAND_TYPE_DX9_OUTPUT: - { - psOperand->eType = OPERAND_TYPE_OUTPUT; - - if (psShader->eShaderType == VERTEX_SHADER) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - } - break; - } - case OPERAND_TYPE_DX9_RASTOUT: - { - // RegNum: - // 0=POSIION - // 1=FOG - // 2=POINTSIZE - psOperand->eType = OPERAND_TYPE_OUTPUT; - switch (ui32RegNum) - { - case 0: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_POSITION; - break; - } - case 1: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_FOG; - break; - } - case 2: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_POINTSIZE; - psOperand->iNumComponents = 1; - break; - } - } - break; - } - case OPERAND_TYPE_DX9_ATTROUT: - { - ASSERT(psShader->eShaderType == VERTEX_SHADER); - - psOperand->eType = OPERAND_TYPE_OUTPUT; - - // 0 = base colour, 1 = offset colour. - if (ui32RegNum == 0) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; - } - else - { - ASSERT(ui32RegNum == 1); - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; - } - - break; - } - case OPERAND_TYPE_DX9_COLOROUT: - { - ASSERT(psShader->eShaderType == PIXEL_SHADER); - psOperand->eType = OPERAND_TYPE_OUTPUT; - break; - } - case OPERAND_TYPE_DX9_CONSTBOOL: - case OPERAND_TYPE_DX9_CONSTINT: - case OPERAND_TYPE_DX9_CONST: - { - // c# = constant float - // i# = constant int - // b# = constant bool - - // c0 might be an immediate while i0 is in the constant buffer - if (aui32ImmediateConst[ui32RegNum] & ui32Flags) - { - if (ConstType != SVT_FLOAT) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; - } - else - { - psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONST; - } - } - else - { - psOperand->eType = OPERAND_TYPE_CONSTANT_BUFFER; - psOperand->aui32ArraySizes[1] = psOperand->ui32RegisterNumber; - } - break; - } - case OPERAND_TYPE_DX9_ADDR: - { - // Vertex shader: address register (only have one of these) - // Pixel shader: texture coordinate register (a few of these) - if (psShader->eShaderType == PIXEL_SHADER) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - } - else - { - psOperand->eType = OPERAND_TYPE_SPECIAL_ADDRESS; - } - break; - } - case OPERAND_TYPE_DX9_SAMPLER: - { - psOperand->eType = OPERAND_TYPE_RESOURCE; - break; - } - case OPERAND_TYPE_DX9_LOOP: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_LOOPCOUNTER; - break; - } - default: - { - ASSERT(0); - break; - } - } -} - -static void DeclareNumTemps(Shader* psShader, const uint32_t ui32NumTemps, Declaration* psDecl) -{ - (void)psShader; - - psDecl->eOpcode = OPCODE_DCL_TEMPS; - psDecl->value.ui32NumTemps = ui32NumTemps; -} - -static void SetupRegisterUsage(const Shader* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1) -{ - (void)psShader; - - DECLUSAGE_DX9 eUsage = DecodeUsageDX9(ui32Token0); - uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0); - uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token1); - uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); - - if (ui32RegType == OPERAND_TYPE_DX9_INPUT) - { - ASSERT(ui32RegNum < MAX_INPUTS); - aeInputUsage[ui32RegNum] = eUsage; - aui32InputUsageIndex[ui32RegNum] = ui32UsageIndex; - } -} - -// Declaring one constant from a constant buffer will cause all constants in the buffer decalared. -// In dx9 there is only one constant buffer per shader. -static void DeclareConstantBuffer(const Shader* psShader, Declaration* psDecl) -{ - // Pick any constant register in the table. Might not start at c0 (e.g. when register(cX) is used). - uint32_t ui32RegNum = psShader->sInfo.psConstantBuffers->asVars[0].ui32StartOffset / 16; - OPERAND_TYPE_DX9 ui32RegType = OPERAND_TYPE_DX9_CONST; - - if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_INT) - { - ui32RegType = OPERAND_TYPE_DX9_CONSTINT; - } - else if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_BOOL) - { - ui32RegType = OPERAND_TYPE_DX9_CONSTBOOL; - } - - if (psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_INPUT; - } - else - { - psDecl->eOpcode = OPCODE_DCL_INPUT_PS; - } - psDecl->ui32NumOperands = 1; - - DecodeOperandDX9(psShader, CreateOperandTokenDX9(ui32RegNum, ui32RegType), 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); - - ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER); - - psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index - psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. -} - -static void DecodeDeclarationDX9(const Shader* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1, Declaration* psDecl) -{ - uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); - - if (psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_INPUT; - } - else - { - psDecl->eOpcode = OPCODE_DCL_INPUT_PS; - } - psDecl->ui32NumOperands = 1; - DecodeOperandDX9(psShader, ui32Token1, 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); - - if (ui32RegType == OPERAND_TYPE_DX9_SAMPLER) - { - const RESOURCE_DIMENSION eResDim = DecodeTextureTypeMaskDX9(ui32Token0); - psDecl->value.eResourceDimension = eResDim; - psDecl->eOpcode = OPCODE_DCL_RESOURCE; - } - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) - { - psDecl->eOpcode = OPCODE_DCL_OUTPUT; - - if (psDecl->asOperands[0].ui32RegisterNumber == 0 && psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_OUTPUT_SIV; - // gl_Position - psDecl->asOperands[0].eSpecialName = NAME_POSITION; - } - } - else if (psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index - psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. - } -} - -static void DefineDX9(Shader* psShader, - const uint32_t ui32RegNum, - const uint32_t ui32Flags, - const uint32_t c0, - const uint32_t c1, - const uint32_t c2, - const uint32_t c3, - Declaration* psDecl) -{ - (void)psShader; - - psDecl->eOpcode = OPCODE_SPECIAL_DCL_IMMCONST; - psDecl->ui32NumOperands = 2; - - memset(&psDecl->asOperands[0], 0, sizeof(Operand)); - psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONST; - - psDecl->asOperands[0].ui32RegisterNumber = ui32RegNum; - - if (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) - { - psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; - } - - aui32ImmediateConst[ui32RegNum] |= ui32Flags; - - memset(&psDecl->asOperands[1], 0, sizeof(Operand)); - psDecl->asOperands[1].eType = OPERAND_TYPE_IMMEDIATE32; - psDecl->asOperands[1].iNumComponents = 4; - psDecl->asOperands[1].iIntegerImmediate = (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) ? 1 : 0; - psDecl->asOperands[1].afImmediates[0] = *((float*)&c0); - psDecl->asOperands[1].afImmediates[1] = *((float*)&c1); - psDecl->asOperands[1].afImmediates[2] = *((float*)&c2); - psDecl->asOperands[1].afImmediates[3] = *((float*)&c3); -} - -static void CreateD3D10Instruction(Shader* psShader, - Instruction* psInst, - const OPCODE_TYPE eType, - const uint32_t bHasDest, - const uint32_t ui32SrcCount, - const uint32_t* pui32Tokens) -{ - uint32_t ui32Src; - uint32_t ui32Offset = 1; - - memset(psInst, 0, sizeof(Instruction)); - -#ifdef _DEBUG - psInst->id = dx9instructionID++; -#endif - - psInst->eOpcode = eType; - psInst->ui32NumOperands = ui32SrcCount; - - if (bHasDest) - { - ++psInst->ui32NumOperands; - - DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_DEST, &psInst->asOperands[0]); - - if (DecodeDestModifierDX9(pui32Tokens[ui32Offset]) & DESTMOD_DX9_SATURATE) - { - psInst->bSaturate = 1; - } - - ui32Offset++; - psInst->ui32FirstSrc = 1; - } - - for (ui32Src = 0; ui32Src < ui32SrcCount; ++ui32Src) - { - DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_SRC, &psInst->asOperands[bHasDest + ui32Src]); - - ui32Offset++; - } -} - -Shader* DecodeDX9BC(const uint32_t* pui32Tokens) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - uint32_t ui32NumInstructions = 0; - uint32_t ui32NumDeclarations = 0; - Instruction* psInst; - Declaration* psDecl; - uint32_t decl, inst; - uint32_t bDeclareConstantTable = 0; - Shader* psShader = hlslcc_calloc(1, sizeof(Shader)); - - memset(aui32ImmediateConst, 0, 256); - - psShader->ui32MajorVersion = DecodeProgramMajorVersionDX9(*pui32CurrentToken); - psShader->ui32MinorVersion = DecodeProgramMinorVersionDX9(*pui32CurrentToken); - psShader->eShaderType = DecodeShaderTypeDX9(*pui32CurrentToken); - - pui32CurrentToken++; - - // Work out how many instructions and declarations we need to allocate memory for. - while (1) - { - OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); - uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); - - if (eOpcode == OPCODE_DX9_END) - { - // SM4+ always end with RET. - // Insert a RET instruction on END to - // replicate this behaviour. - ++ui32NumInstructions; - break; - } - else if (eOpcode == OPCODE_DX9_COMMENT) - { - ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); - if (pui32CurrentToken[1] == FOURCC_CTAB) - { - LoadD3D9ConstantTable((char*)(&pui32CurrentToken[2]), &psShader->sInfo); - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - if (psShader->sInfo.psConstantBuffers[0].ui32NumVars) - { - ++ui32NumDeclarations; - bDeclareConstantTable = 1; - } - } - } - else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) - { - ++ui32NumDeclarations; - } - else if (eOpcode == OPCODE_DX9_DCL) - { - const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); - uint32_t ignoreDCL = 0; - - // Inputs and outputs are declared in AddVersionDependentCode - if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) - { - ignoreDCL = 1; - } - if (!ignoreDCL) - { - ++ui32NumDeclarations; - } - } - else - { - switch (eOpcode) - { - case OPCODE_DX9_NRM: - { - // Emulate with dp4 and rsq - ui32NumInstructions += 2; - break; - } - default: - { - ++ui32NumInstructions; - break; - } - } - } - - pui32CurrentToken += ui32InstLen + 1; - } - - psInst = hlslcc_malloc(sizeof(Instruction) * ui32NumInstructions); - psShader->psInst = psInst; - psShader->ui32InstCount = ui32NumInstructions; - - if (psShader->eShaderType == VERTEX_SHADER) - { - // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not - ui32NumDeclarations++; - } - - // For declaring temps. - ui32NumDeclarations++; - - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32NumDeclarations); - psShader->psDecl = psDecl; - psShader->ui32DeclCount = ui32NumDeclarations; - - pui32CurrentToken = pui32Tokens + 1; - - inst = 0; - decl = 0; - while (1) - { - OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); - uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); - - if (eOpcode == OPCODE_DX9_END) - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); - inst++; - break; - } - else if (eOpcode == OPCODE_DX9_COMMENT) - { - ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); - } - else if (eOpcode == OPCODE_DX9_DCL) - { - const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); - uint32_t ignoreDCL = 0; - // Inputs and outputs are declared in AddVersionDependentCode - if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) - { - ignoreDCL = 1; - } - - SetupRegisterUsage(psShader, pui32CurrentToken[1], pui32CurrentToken[2]); - - if (!ignoreDCL) - { - DecodeDeclarationDX9(psShader, pui32CurrentToken[1], pui32CurrentToken[2], &psDecl[decl]); - decl++; - } - } - else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) - { - const uint32_t ui32Const0 = *(pui32CurrentToken + 2); - const uint32_t ui32Const1 = *(pui32CurrentToken + 3); - const uint32_t ui32Const2 = *(pui32CurrentToken + 4); - const uint32_t ui32Const3 = *(pui32CurrentToken + 5); - uint32_t ui32Flags = 0; - - if (eOpcode == OPCODE_DX9_DEF) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; - } - else if (eOpcode == OPCODE_DX9_DEFI) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; - } - else - { - ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; - } - - DefineDX9(psShader, DecodeOperandRegisterNumberDX9(pui32CurrentToken[1]), ui32Flags, ui32Const0, ui32Const1, ui32Const2, ui32Const3, &psDecl[decl]); - decl++; - } - else - { - switch (eOpcode) - { - case OPCODE_DX9_MOV: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOV, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_LIT: - { - /*Dest.x = 1 - Dest.y = (Src0.x > 0) ? Src0.x : 0 - Dest.z = (Src0.x > 0 && Src0.y > 0) ? pow(Src0.y, Src0.w) : 0 - Dest.w = 1 - */ - ASSERT(0); - break; - } - case OPCODE_DX9_ADD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SUB: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); - ASSERT(psInst[inst].asOperands[2].eModifier == OPERAND_MODIFIER_NONE); - psInst[inst].asOperands[2].eModifier = OPERAND_MODIFIER_NEG; - break; - } - case OPCODE_DX9_MAD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAD, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_MUL: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MUL, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_RCP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RCP, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_RSQ: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP3: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP3, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP4: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_MIN: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MIN, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_MAX: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAX, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SLT: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LT, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SGE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_GE, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_EXP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_EXP, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_LOG: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOG, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_NRM: - { - // Convert NRM RESULT, SRCA into: - // dp4 RESULT, SRCA, SRCA - // rsq RESULT, RESULT - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 1, pui32CurrentToken); - memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); - ++inst; - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 0, 0, pui32CurrentToken); - memcpy(&psInst[inst].asOperands[0], &psInst[inst - 1].asOperands[0], sizeof(Operand)); - break; - } - case OPCODE_DX9_SINCOS: - { - // Before SM3, SINCOS has 2 extra constant sources -D3DSINCOSCONST1 and D3DSINCOSCONST2. - // Ignore them. - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SINCOS, 1, 1, pui32CurrentToken); - // Pre-SM4: - // If the write mask is .x: dest.x = cos( V ) - // If the write mask is .y: dest.y = sin( V ) - // If the write mask is .xy: - // dest.x = cos( V ) - // dest.y = sin( V ) - - // SM4+ - // destSin destCos Angle - - psInst[inst].ui32NumOperands = 3; - - // Set the angle - memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); - - // Set the cosine dest - memcpy(&psInst[inst].asOperands[1], &psInst[inst].asOperands[0], sizeof(Operand)); - - // Set write masks - psInst[inst].asOperands[0].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_Y; - if (psInst[inst].asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - // Need cosine - } - else - { - psInst[inst].asOperands[0].eType = OPERAND_TYPE_NULL; - } - psInst[inst].asOperands[1].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_X; - if (psInst[inst].asOperands[1].ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - // Need sine - } - else - { - psInst[inst].asOperands[1].eType = OPERAND_TYPE_NULL; - } - - break; - } - case OPCODE_DX9_FRC: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_FRC, 1, 1, pui32CurrentToken); - break; - } - - case OPCODE_DX9_MOVA: - { - // MOVA preforms RoundToNearest on the src data. - // The only rounding functions available in all GLSL version are ceil and floor. - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ROUND_NI, 1, 1, pui32CurrentToken); - break; - } - - case OPCODE_DX9_TEX: - { - // texld r0, t0, s0 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE, 1, 2, pui32CurrentToken); - psInst[inst].asOperands[2].ui32RegisterNumber = 0; - - break; - } - case OPCODE_DX9_TEXLDL: - { - // texld r0, t0, s0 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_L, 1, 2, pui32CurrentToken); - psInst[inst].asOperands[2].ui32RegisterNumber = 0; - - // Lod comes from fourth coordinate of address. - memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[1], sizeof(Operand)); - - psInst[inst].ui32NumOperands = 5; - - break; - } - - case OPCODE_DX9_IF: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 1, pui32CurrentToken); - psInst[inst].eDX9TestType = D3DSPC_BOOLEAN; - break; - } - - case OPCODE_DX9_IFC: - { - const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 2, pui32CurrentToken); - psInst[inst].eDX9TestType = eCmpOp; - break; - } - case OPCODE_DX9_ELSE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ELSE, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_CMP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOVC, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_REP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_REP, 0, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDREP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDREP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_BREAKC: - { - const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAKC, 0, 2, pui32CurrentToken); - psInst[inst].eDX9TestType = eCmpOp; - break; - } - - case OPCODE_DX9_DSX: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTX, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_DSY: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTY, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_TEXKILL: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DISCARD, 1, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_TEXLDD: - { - // texldd, dst, src0, src1, src2, src3 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler, XGradient, YGradient - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_D, 1, 4, pui32CurrentToken); - psInst[inst].asOperands[2].ui32RegisterNumber = 0; - break; - } - case OPCODE_DX9_LRP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LRP, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP2ADD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP2ADD, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_POW: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_POW, 1, 2, pui32CurrentToken); - break; - } - - case OPCODE_DX9_DST: - case OPCODE_DX9_M4x4: - case OPCODE_DX9_M4x3: - case OPCODE_DX9_M3x4: - case OPCODE_DX9_M3x3: - case OPCODE_DX9_M3x2: - case OPCODE_DX9_CALL: - case OPCODE_DX9_CALLNZ: - case OPCODE_DX9_LABEL: - - case OPCODE_DX9_CRS: - case OPCODE_DX9_SGN: - case OPCODE_DX9_ABS: - - case OPCODE_DX9_TEXCOORD: - case OPCODE_DX9_TEXBEM: - case OPCODE_DX9_TEXBEML: - case OPCODE_DX9_TEXREG2AR: - case OPCODE_DX9_TEXREG2GB: - case OPCODE_DX9_TEXM3x2PAD: - case OPCODE_DX9_TEXM3x2TEX: - case OPCODE_DX9_TEXM3x3PAD: - case OPCODE_DX9_TEXM3x3TEX: - case OPCODE_DX9_TEXM3x3SPEC: - case OPCODE_DX9_TEXM3x3VSPEC: - case OPCODE_DX9_EXPP: - case OPCODE_DX9_LOGP: - case OPCODE_DX9_CND: - case OPCODE_DX9_TEXREG2RGB: - case OPCODE_DX9_TEXDP3TEX: - case OPCODE_DX9_TEXM3x2DEPTH: - case OPCODE_DX9_TEXDP3: - case OPCODE_DX9_TEXM3x3: - case OPCODE_DX9_TEXDEPTH: - case OPCODE_DX9_BEM: - case OPCODE_DX9_SETP: - case OPCODE_DX9_BREAKP: - { - ASSERT(0); - break; - } - case OPCODE_DX9_NOP: - case OPCODE_DX9_PHASE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_NOP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_LOOP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOOP, 0, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_RET: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDLOOP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDLOOP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDIF: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDIF, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_BREAK: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAK, 0, 0, pui32CurrentToken); - break; - } - default: - { - ASSERT(0); - break; - } - } - - UpdateInstructionReferences(psShader, &psInst[inst]); - - inst++; - } - - pui32CurrentToken += ui32InstLen + 1; - } - - DeclareNumTemps(psShader, ui32MaxTemp, &psDecl[decl]); - ++decl; - - if (psShader->eShaderType == VERTEX_SHADER) - { - // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not - if (bDeclareConstantTable) - { - DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl + 1]); - } - else - { - DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl]); - } - } - - if (bDeclareConstantTable) - { - DeclareConstantBuffer(psShader, &psDecl[decl]); - } - - return psShader; -} diff --git a/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c b/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c deleted file mode 100644 index 22abd1a5e2..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c +++ /dev/null @@ -1,167 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -#include "internal_includes/hlslccToolkit.h" -#include "internal_includes/debug.h" -#include "internal_includes/languages.h" - -bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src) -{ - if (src == dest) - return true; - - if ((dest == SVT_FLOAT || dest == SVT_FLOAT10 || dest == SVT_FLOAT16) && - (src == SVT_FLOAT || src == SVT_FLOAT10 || src == SVT_FLOAT16)) - return true; - - if ((dest == SVT_INT || dest == SVT_INT12 || dest == SVT_INT16) && - (src == SVT_INT || src == SVT_INT12 || src == SVT_INT16)) - return true; - - if ((dest == SVT_UINT || dest == SVT_UINT16) && - (src == SVT_UINT || src == SVT_UINT16)) - return true; - - return false; -} - -const char * GetConstructorForTypeGLSL(HLSLCrossCompilerContext* psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision) -{ - const bool usePrecision = useGLSLPrecision && HavePrecisionQualifers(psContext->psShader->eTargetLanguage); - - static const char * const uintTypes[] = { " ", "uint", "uvec2", "uvec3", "uvec4" }; - static const char * const uint16Types[] = { " ", "mediump uint", "mediump uvec2", "mediump uvec3", "mediump uvec4" }; - static const char * const intTypes[] = { " ", "int", "ivec2", "ivec3", "ivec4" }; - static const char * const int16Types[] = { " ", "mediump int", "mediump ivec2", "mediump ivec3", "mediump ivec4" }; - static const char * const int12Types[] = { " ", "lowp int", "lowp ivec2", "lowp ivec3", "lowp ivec4" }; - static const char * const floatTypes[] = { " ", "float", "vec2", "vec3", "vec4" }; - static const char * const float16Types[] = { " ", "mediump float", "mediump vec2", "mediump vec3", "mediump vec4" }; - static const char * const float10Types[] = { " ", "lowp float", "lowp vec2", "lowp vec3", "lowp vec4" }; - static const char * const boolTypes[] = { " ", "bool", "bvec2", "bvec3", "bvec4" }; - - ASSERT(components >= 1 && components <= 4); - - switch (eType) - { - case SVT_UINT: - return uintTypes[components]; - case SVT_UINT16: - return usePrecision ? uint16Types[components] : uintTypes[components]; - case SVT_INT: - return intTypes[components]; - case SVT_INT16: - return usePrecision ? int16Types[components] : intTypes[components]; - case SVT_INT12: - return usePrecision ? int12Types[components] : intTypes[components]; - case SVT_FLOAT: - return floatTypes[components]; - case SVT_FLOAT16: - return usePrecision ? float16Types[components] : floatTypes[components]; - case SVT_FLOAT10: - return usePrecision ? float10Types[components] : floatTypes[components]; - case SVT_BOOL: - return boolTypes[components]; - default: - ASSERT(0); - return ""; - } -} - -SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags) -{ - if (typeflags & TO_FLAG_INTEGER) - return SVT_INT; - if (typeflags & TO_FLAG_UNSIGNED_INTEGER) - return SVT_UINT; - return SVT_FLOAT; -} - -uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType) -{ - if (eType == SVT_FLOAT16 || eType == SVT_FLOAT10 || eType == SVT_FLOAT) - { - return TO_FLAG_FLOAT; - } - if (eType == SVT_UINT || eType == SVT_UINT16) - { - return TO_FLAG_UNSIGNED_INTEGER; - } - else if (eType == SVT_INT || eType == SVT_INT16 || eType == SVT_INT12) - { - return TO_FLAG_INTEGER; - } - else - { - return TO_FLAG_NONE; - } -} - -bool CanDoDirectCast(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) -{ - // uint<->int<->bool conversions possible - if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL || src == SVT_INT12 || src == SVT_INT16 || src == SVT_UINT16) && - (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL || dest == SVT_INT12 || dest == SVT_INT16 || dest == SVT_UINT16)) - return true; - - // float<->double possible - if ((src == SVT_FLOAT || src == SVT_DOUBLE || src == SVT_FLOAT16 || src == SVT_FLOAT10) && - (dest == SVT_FLOAT || dest == SVT_DOUBLE || dest == SVT_FLOAT16 || dest == SVT_FLOAT10)) - return true; - - return false; -} - -const char* GetBitcastOp(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) -{ - static const char* intToFloat = "intBitsToFloat"; - static const char* uintToFloat = "uintBitsToFloat"; - static const char* floatToInt = "floatBitsToInt"; - static const char* floatToUint = "floatBitsToUint"; - - if ((to == SVT_FLOAT || to == SVT_FLOAT16 || to == SVT_FLOAT10) && from == SVT_INT) - return intToFloat; - else if ((to == SVT_FLOAT || to == SVT_FLOAT16 || to == SVT_FLOAT10) && from == SVT_UINT) - return uintToFloat; - else if (to == SVT_INT && (from == SVT_FLOAT || from == SVT_FLOAT16 || from == SVT_FLOAT10)) - return floatToInt; - else if (to == SVT_UINT && (from == SVT_FLOAT || from == SVT_FLOAT16 || from == SVT_FLOAT10)) - return floatToUint; - - ASSERT(0); - return ""; -} - -bool IsGmemReservedSlot(FRAMEBUFFER_FETCH_TYPE typeMask, const uint32_t regNumber) -{ - if (((typeMask & FBF_ARM_COLOR) && regNumber == GMEM_ARM_COLOR_SLOT) || - ((typeMask & FBF_ARM_DEPTH) && regNumber == GMEM_ARM_DEPTH_SLOT) || - ((typeMask & FBF_ARM_STENCIL) && regNumber == GMEM_ARM_STENCIL_SLOT) || - ((typeMask & FBF_EXT_COLOR) && regNumber >= GMEM_FLOAT_START_SLOT)) - { - return true; - } - - return false; -} - -const char * GetAuxArgumentName(const SHADER_VARIABLE_TYPE varType) -{ - switch (varType) - { - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - return "uArg"; - case SVT_INT: - case SVT_INT16: - case SVT_INT12: - return "iArg"; - case SVT_FLOAT: - case SVT_FLOAT16: - case SVT_FLOAT10: - return "fArg"; - case SVT_BOOL: - return "bArg"; - default: - ASSERT(0); - return ""; - } -} \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h deleted file mode 100644 index 5b071709bc..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h +++ /dev/null @@ -1,21 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef DEBUG_H_ -#define DEBUG_H_ - -#ifdef _DEBUG -#include "assert.h" -#define ASSERT(expr) CustomAssert(expr) -static void CustomAssert(int expression) -{ - if(!expression) - { - assert(0); - } -} -#else -#define ASSERT(expr) -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h deleted file mode 100644 index d8102683a8..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h +++ /dev/null @@ -1,21 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef DECODE_H -#define DECODE_H - -#include "internal_includes/structs.h" - -Shader* DecodeDXBC(uint32_t* data); - -//You don't need to call this directly because DecodeDXBC -//will call DecodeDX9BC if the shader looks -//like it is SM1/2/3. -Shader* DecodeDX9BC(const uint32_t* pui32Tokens); - -void UpdateDeclarationReferences(Shader* psShader, Declaration* psDeclaration); -void UpdateInstructionReferences(Shader* psShader, Instruction* psInstruction); - -#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h deleted file mode 100644 index d0875613a4..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h +++ /dev/null @@ -1,35 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -#ifndef HLSLCC_TOOLKIT_DECLARATION_H -#define HLSLCC_TOOLKIT_DECLARATION_H - -#include "hlslcc.h" -#include "bstrlib.h" -#include "internal_includes/structs.h" - -#include <stdbool.h> - -// Check if "src" type can be assigned directly to the "dest" type. -bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src); - -// Returns the constructor needed depending on the type, the number of components and the use of precision qualifier. -const char * GetConstructorForTypeGLSL(HLSLCrossCompilerContext* psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision); - -// Transform from a variable type to a shader variable flag. -uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType); - -// Transform from a shader variable flag to a shader variable type. -SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags); - -// Check if the "src" type can be casted using a constructor to the "dest" type (without bitcasting). -bool CanDoDirectCast(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest); - -// Returns the bitcast operation needed to assign the "src" type to the "dest" type -const char* GetBitcastOp(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest); - -// Check if the register number is part of the ones we used for signaling GMEM input -bool IsGmemReservedSlot(FRAMEBUFFER_FETCH_TYPE type, const uint32_t regNumber); - -// Return the name of an auxiliary variable used to save intermediate values to bypass driver issues -const char * GetAuxArgumentName(const SHADER_VARIABLE_TYPE varType); - -#endif \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c deleted file mode 100644 index 0f1c8d62e6..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c +++ /dev/null @@ -1,16 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifdef _WIN32 -#include <malloc.h> -#else -#include <stdlib.h> -#endif -#include <AzCore/PlatformDef.h> - -AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free/calloc/realloc are not static -void* (*hlslcc_malloc)(size_t size) = malloc; -void* (*hlslcc_calloc)(size_t num,size_t size) = calloc; -void (*hlslcc_free)(void *p) = free; -void* (*hlslcc_realloc)(void *p,size_t size) = realloc; -AZ_POP_DISABLE_WARNING diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h deleted file mode 100644 index 533050e17b..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h +++ /dev/null @@ -1,15 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef __HLSCC_MALLOC_H -#define __HLSCC_MALLOC_H - -extern void* (*hlslcc_malloc)(size_t size); -extern void* (* hlslcc_calloc)(size_t num, size_t size); -extern void (* hlslcc_free)(void* p); -extern void* (* hlslcc_realloc)(void* p, size_t size); - -#define bstr__alloc hlslcc_malloc -#define bstr__free hlslcc_free -#define bstr__realloc hlslcc_realloc -#endif \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h deleted file mode 100644 index dd9562379a..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h +++ /dev/null @@ -1,242 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef LANGUAGES_H -#define LANGUAGES_H - -#include "hlslcc.h" - -static int InOutSupported(const GLLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 0; - } - return 1; -} - -static int WriteToFragData(const GLLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 1; - } - return 0; -} - -static int ShaderBitEncodingSupported(const GLLang eLang) -{ - if( eLang != LANG_ES_300 && - eLang != LANG_ES_310 && - eLang < LANG_330) - { - return 0; - } - return 1; -} - -static int HaveOverloadedTextureFuncs(const GLLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 0; - } - return 1; -} - -//Only enable for ES. -//Not present in 120, ignored in other desktop languages. -static int HavePrecisionQualifers(const GLLang eLang) -{ - if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310) - { - return 1; - } - return 0; -} - -//Only on vertex inputs and pixel outputs. -static int HaveLimitedInOutLocationQualifier(const GLLang eLang) -{ - if(eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveInOutLocationQualifier(const GLLang eLang,const struct GlExtensions *extensions) -{ - if(eLang >= LANG_410 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_attrib_location)) - { - return 1; - } - return 0; -} - -//layout(binding = X) uniform {uniformA; uniformB;} -//layout(location = X) uniform uniform_name; -static int HaveUniformBindingsAndLocations(const GLLang eLang,const struct GlExtensions *extensions) -{ - if(eLang >= LANG_430 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_uniform_location)) - { - return 1; - } - return 0; -} - -static int DualSourceBlendSupported(const GLLang eLang) -{ - if(eLang >= LANG_330) - { - return 1; - } - return 0; -} - -static int SubroutinesSupported(const GLLang eLang) -{ - if(eLang >= LANG_400) - { - return 1; - } - return 0; -} - -//Before 430, flat/smooth/centroid/noperspective must match -//between fragment and its previous stage. -//HLSL bytecode only tells us the interpolation in pixel shader. -static int PixelInterpDependency(const GLLang eLang) -{ - if(eLang < LANG_430) - { - return 1; - } - return 0; -} - -static int HaveUVec(const GLLang eLang) -{ - switch(eLang) - { - case LANG_ES_100: - case LANG_120: - return 0; - default: - break; - } - return 1; -} - -static int HaveGather(const GLLang eLang) -{ - if(eLang >= LANG_400 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveGatherNonConstOffset(const GLLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - - -static int HaveQueryLod(const GLLang eLang) -{ - if(eLang >= LANG_400) - { - return 1; - } - return 0; -} - -static int HaveQueryLevels(const GLLang eLang) -{ - if(eLang >= LANG_430) - { - return 1; - } - return 0; -} - - -static int HaveAtomicCounter(const GLLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveAtomicMem(const GLLang eLang) -{ - if(eLang >= LANG_430) - { - return 1; - } - return 0; -} - -static int HaveCompute(const GLLang eLang) -{ - if(eLang >= LANG_430 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveImageLoadStore(const GLLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int EmulateDepthClamp(const GLLang eLang) -{ - if (eLang >= LANG_ES_300 && eLang < LANG_120) //Requires gl_FragDepth available in fragment shader - { - return 1; - } - return 0; -} - -static int HaveNoperspectiveInterpolation(const GLLang eLang) -{ - if (eLang >= LANG_330) - { - return 1; - } - return 0; -} - -static int EarlyDepthTestSupported(const GLLang eLang) -{ - if ((eLang > LANG_410) || (eLang == LANG_ES_310)) - { - return 1; - } - return 0; -} - -static int StorageBlockBindingSupported(const GLLang eLang) -{ - if (eLang >= LANG_430) - { - return 1; - } - return 0; -} - - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h deleted file mode 100644 index bea00aafc4..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h +++ /dev/null @@ -1,42 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef REFLECT_H -#define REFLECT_H - -#include "hlslcc.h" - -ResourceGroup ResourceTypeToResourceGroup(ResourceType); - -int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding); - -void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf); - -int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); - -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); -int GetOutputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Stream, const uint32_t ui32CompMask, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); - -int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); - -int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, const uint32_t* pui32Swizzle, ConstantBuffer* psCBuf, ShaderVarType** ppsShaderVar, int32_t* pi32Index, int32_t* pi32Rebase); - -typedef struct -{ - uint32_t* pui32Inputs; - uint32_t* pui32Outputs; - uint32_t* pui32Resources; - uint32_t* pui32Interfaces; - uint32_t* pui32Inputs11; - uint32_t* pui32Outputs11; - uint32_t* pui32OutputsWithStreams; -} ReflectionChunks; - -void LoadShaderInfo(const uint32_t ui32MajorVersion, const uint32_t ui32MinorVersion, const ReflectionChunks* psChunks, ShaderInfo* psInfo); - -void LoadD3D9ConstantTable(const char* data, ShaderInfo* psInfo); - -void FreeShaderInfo(ShaderInfo* psShaderInfo); - -#endif - diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h deleted file mode 100644 index 7bddbed4da..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h +++ /dev/null @@ -1,36 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HLSLCC_SHADER_LIMITS_H -#define HLSLCC_SHADER_LIMITS_H - -static enum -{ - MAX_SHADER_VEC4_OUTPUT = 512 -}; -static enum -{ - MAX_SHADER_VEC4_INPUT = 512 -}; -static enum -{ - MAX_TEXTURES = 128 -}; -static enum -{ - MAX_FORK_PHASES = 2 -}; -static enum -{ - MAX_FUNCTION_BODIES = 1024 -}; -static enum -{ - MAX_CLASS_TYPES = 1024 -}; -static enum -{ - MAX_FUNCTION_POINTERS = 128 -}; - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h deleted file mode 100644 index a9e7fd92b7..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h +++ /dev/null @@ -1,374 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef STRUCTS_H -#define STRUCTS_H - -#include "hlslcc.h" -#include "bstrlib.h" - -#include "internal_includes/tokens.h" -#include "internal_includes/reflect.h" - -enum -{ - MAX_SUB_OPERANDS = 3 -}; - -typedef struct Operand_TAG -{ - int iExtended; - OPERAND_TYPE eType; - OPERAND_MODIFIER eModifier; - OPERAND_MIN_PRECISION eMinPrecision; - int iIndexDims; - int indexRepresentation[4]; - int writeMask; - int iGSInput; - int iWriteMaskEnabled; - - int iNumComponents; - - OPERAND_4_COMPONENT_SELECTION_MODE eSelMode; - uint32_t ui32CompMask; - uint32_t ui32Swizzle; - uint32_t aui32Swizzle[4]; - - uint32_t aui32ArraySizes[3]; - uint32_t ui32RegisterNumber; - //If eType is OPERAND_TYPE_IMMEDIATE32 - float afImmediates[4]; - //If eType is OPERAND_TYPE_IMMEDIATE64 - double adImmediates[4]; - - int iIntegerImmediate; - - SPECIAL_NAME eSpecialName; - char pszSpecialName[64]; - - OPERAND_INDEX_REPRESENTATION eIndexRep[3]; - - struct Operand_TAG* psSubOperand[MAX_SUB_OPERANDS]; - - //One type for each component. - SHADER_VARIABLE_TYPE aeDataType[4]; - -#ifdef _DEBUG - uint64_t id; -#endif -} Operand; - -typedef struct Instruction_TAG -{ - OPCODE_TYPE eOpcode; - INSTRUCTION_TEST_BOOLEAN eBooleanTestType; - COMPARISON_DX9 eDX9TestType; - uint32_t ui32SyncFlags; - uint32_t ui32NumOperands; - uint32_t ui32FirstSrc; - Operand asOperands[6]; - uint32_t bSaturate; - uint32_t ui32FuncIndexWithinInterface; - RESINFO_RETURN_TYPE eResInfoReturnType; - - int bAddressOffset; - int iUAddrOffset; - int iVAddrOffset; - int iWAddrOffset; - RESOURCE_RETURN_TYPE xType, yType, zType, wType; - RESOURCE_DIMENSION eResDim; - -#ifdef _DEBUG - uint64_t id; -#endif -} Instruction; - -enum -{ - MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE = 1024 -}; - -typedef struct ICBVec4_TAG -{ - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; -} ICBVec4; - -typedef struct Declaration_TAG -{ - OPCODE_TYPE eOpcode; - - uint32_t ui32NumOperands; - - Operand asOperands[2]; - - ICBVec4 asImmediateConstBuffer[MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE]; - //The declaration can set one of these - //values depending on the opcode. - union - { - uint32_t ui32GlobalFlags; - uint32_t ui32NumTemps; - RESOURCE_DIMENSION eResourceDimension; - CONSTANT_BUFFER_ACCESS_PATTERN eCBAccessPattern; - INTERPOLATION_MODE eInterpolation; - PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology; - PRIMITIVE eInputPrimitive; - uint32_t ui32MaxOutputVertexCount; - TESSELLATOR_DOMAIN eTessDomain; - TESSELLATOR_PARTITIONING eTessPartitioning; - TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; - uint32_t aui32WorkGroupSize[3]; - //Fork phase index followed by the instance count. - uint32_t aui32HullPhaseInstanceInfo[2]; - float fMaxTessFactor; - uint32_t ui32IndexRange; - uint32_t ui32GSInstanceCount; - - struct Interface_TAG - { - uint32_t ui32InterfaceID; - uint32_t ui32NumFuncTables; - uint32_t ui32ArraySize; - } interface; - } value; - - struct UAV_TAG - { - uint32_t ui32GloballyCoherentAccess; - uint32_t ui32BufferSize; - uint8_t bCounter; - RESOURCE_RETURN_TYPE Type; - } sUAV; - - struct TGSM_TAG - { - uint32_t ui32Stride; - uint32_t ui32Count; - } sTGSM; - - struct IndexableTemp_TAG - { - uint32_t ui32RegIndex; - uint32_t ui32RegCount; - uint32_t ui32RegComponentSize; - } sIdxTemp; - - uint32_t ui32TableLength; - - uint32_t ui32TexReturnType; -} Declaration; - -enum -{ - MAX_TEMP_VEC4 = 512 -}; - -enum -{ - MAX_GROUPSHARED = 8 -}; - -enum -{ - MAX_DX9_IMMCONST = 256 -}; - -typedef struct Shader_TAG -{ - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - SHADER_TYPE eShaderType; - - GLLang eTargetLanguage; - const struct GlExtensions *extensions; - - int fp64; - - //DWORDs in program code, including version and length tokens. - uint32_t ui32ShaderLength; - - uint32_t ui32DeclCount; - Declaration* psDecl; - - //Instruction* functions;//non-main subroutines - - uint32_t aui32FuncTableToFuncPointer[MAX_FUNCTION_TABLES];//FIXME dynamic alloc - uint32_t aui32FuncBodyToFuncTable[MAX_FUNCTION_BODIES]; - - struct - { - uint32_t aui32FuncBodies[MAX_FUNCTION_BODIES]; - }funcTable[MAX_FUNCTION_TABLES]; - - struct - { - uint32_t aui32FuncTables[MAX_FUNCTION_TABLES]; - uint32_t ui32NumBodiesPerTable; - }funcPointer[MAX_FUNCTION_POINTERS]; - - uint32_t ui32NextClassFuncName[MAX_CLASS_TYPES]; - - uint32_t ui32InstCount; - Instruction* psInst; - - const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream. - - //Hull shader declarations and instructions. - //psDecl, psInst are null for hull shaders. - uint32_t ui32HSDeclCount; - Declaration* psHSDecl; - - uint32_t ui32HSControlPointDeclCount; - Declaration* psHSControlPointPhaseDecl; - - uint32_t ui32HSControlPointInstrCount; - Instruction* psHSControlPointPhaseInstr; - - uint32_t ui32ForkPhaseCount; - - uint32_t aui32HSForkDeclCount[MAX_FORK_PHASES]; - Declaration* apsHSForkPhaseDecl[MAX_FORK_PHASES]; - - uint32_t aui32HSForkInstrCount[MAX_FORK_PHASES]; - Instruction* apsHSForkPhaseInstr[MAX_FORK_PHASES]; - - uint32_t ui32HSJoinDeclCount; - Declaration* psHSJoinPhaseDecl; - - uint32_t ui32HSJoinInstrCount; - Instruction* psHSJoinPhaseInstr; - - ShaderInfo sInfo; - - int abScalarInput[MAX_SHADER_VEC4_INPUT]; - - int aIndexedOutput[MAX_SHADER_VEC4_OUTPUT]; - - int aIndexedInput[MAX_SHADER_VEC4_INPUT]; - int aIndexedInputParents[MAX_SHADER_VEC4_INPUT]; - - RESOURCE_DIMENSION aeResourceDims[MAX_TEXTURES]; - - int aiInputDeclaredSize[MAX_SHADER_VEC4_INPUT]; - - int aiOutputDeclared[MAX_SHADER_VEC4_OUTPUT]; - - //Does not track built-in inputs. - int abInputReferencedByInstruction[MAX_SHADER_VEC4_INPUT]; - - int aiOpcodeUsed[NUM_OPCODES]; - - uint32_t ui32CurrentVertexOutputStream; - - uint32_t ui32NumDx9ImmConst; - uint32_t aui32Dx9ImmConstArrayRemap[MAX_DX9_IMMCONST]; - - ShaderVarType sGroupSharedVarType[MAX_GROUPSHARED]; - - SHADER_VARIABLE_TYPE aeCommonTempVecType[MAX_TEMP_VEC4]; - uint32_t bUseTempCopy; - FRAMEBUFFER_FETCH_TYPE eGmemType; -} Shader; - -/* CONFETTI NOTE: DAVID SROUR - * The following is super sketchy, but at the moment, - * there is no way to figure out the type of a resource - * since HLSL has only register sets for the following: - * bool, int4, float4, sampler. - * THIS CODE IS DUPLICATED FROM HLSLcc METAL. - * IF ANYTHING CHANGES, BOTH TRANSLATORS SHOULD HAVE THE CHANGE. - * TODO: CONSOLIDATE THE 2 HLSLcc PROJECTS. - */ -enum -{ - GMEM_FLOAT4_START_SLOT = 120 -}; -enum -{ - GMEM_FLOAT3_START_SLOT = 112 -}; -enum -{ - GMEM_FLOAT2_START_SLOT = 104 -}; -enum -{ - GMEM_FLOAT_START_SLOT = 96 -}; - -enum -{ - GMEM_ARM_COLOR_SLOT = 93, - GMEM_ARM_DEPTH_SLOT = 94, - GMEM_ARM_STENCIL_SLOT = 95 -}; - -/* CONFETTI NOTE: DAVID SROUR - * Following is the reserved slot for PLS extension (https://www.khronos.org/registry/gles/extensions/EXT/EXT_shader_pixel_local_storage.txt). - * It will get picked up when a RWStructuredBuffer resource is defined at the following reserved slot. - * Note that only one PLS struct can be present at a time otherwise the behavior is undefined. - * - * Types in the struct and their output conversion (each output variable will always be 4 bytes): - * float2 -> rg16f - * float3 -> r11f_g11f_b10f - * float4 -> rgba8 - * uint -> r32ui - * int2 -> rg16i - * int4 -> rgba8i - */ -enum -{ - GMEM_PLS_RO_SLOT = 60 -}; // READ-ONLY -enum -{ - GMEM_PLS_WO_SLOT = 61 -}; // WRITE-ONLY -enum -{ - GMEM_PLS_RW_SLOT = 62 -}; // READ/WRITE - -static const uint32_t MAIN_PHASE = 0; -static const uint32_t HS_FORK_PHASE = 1; -static const uint32_t HS_CTRL_POINT_PHASE = 2; -static const uint32_t HS_JOIN_PHASE = 3; -enum -{ - NUM_PHASES = 4 -}; - -enum -{ - MAX_COLOR_MRT = 8 -}; - -enum -{ - INPUT_RENDERTARGET = 1 << 0, - OUTPUT_RENDERTARGET = 1 << 1 -}; - -typedef struct HLSLCrossCompilerContext_TAG -{ - bstring glsl; - bstring earlyMain;//Code to be inserted at the start of main() - bstring postShaderCode[NUM_PHASES];//End of main or before emit() - bstring debugHeader; - - bstring* currentGLSLString;//either glsl or earlyMain - - int havePostShaderCode[NUM_PHASES]; - uint32_t currentPhase; - - uint32_t rendertargetUse[MAX_COLOR_MRT]; - - int indent; - unsigned int flags; - Shader* psShader; -} HLSLCrossCompilerContext; - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h deleted file mode 100644 index 337a771e19..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h +++ /dev/null @@ -1,19 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_DECLARATION_H -#define TO_GLSL_DECLARATION_H - -#include "internal_includes/structs.h" - -void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); - -char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); -char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand, int* stream); - -//Hull shaders have multiple phases. -//Each phase has its own temps. -//Convert to global temps for GLSL. -void ConsolidateHullTempVars(Shader* psShader); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h deleted file mode 100644 index bf6795d931..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h +++ /dev/null @@ -1,18 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_INSTRUCTION_H -#define TO_GLSL_INSTRUCTION_H - -#include "internal_includes/structs.h" - -void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst); - -//For each MOV temp, immediate; check to see if the next instruction -//using that temp has an integer opcode. If so then the immediate value -//is flaged as having an integer encoding. -void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext); - -void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h deleted file mode 100644 index 56487ea69b..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h +++ /dev/null @@ -1,46 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_OPERAND_H -#define TO_GLSL_OPERAND_H - -#include "internal_includes/structs.h" - -void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); - -int GetMaxComponentFromComponentMask(const Operand* psOperand); -void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); -void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); -void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle); -void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); - -uint32_t GetNumSwizzleElements(const Operand* psOperand); -void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); -int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -uint32_t IsSwizzleReplacated(const Operand* psOperand); - -void TextureName(bstring output, Shader* psShader, const uint32_t ui32TextureRegister, const uint32_t ui32SamplerRegister, const int bCompare); -void UAVName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber); -void UniformBufferName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber); - -void ConvertToTextureName(bstring output, Shader* psShader, const char* szName, const char* szSamplerName, const int bCompare); -void ConvertToUAVName(bstring output, Shader* psShader, const char* szOriginalUAVName); -void ConvertToUniformBufferName(bstring output, Shader* psShader, const char* szConstantBufferName); - -void ShaderVarName(bstring output, Shader* psShader, const char* OriginalName); -void ShaderVarFullName(bstring output, Shader* psShader, const ShaderVarType* psShaderVar); - -uint32_t ConvertOperandSwizzleToComponentMask(const Operand* psOperand); -//Non-zero means the components overlap -int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB); - -SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand); - - -// NOTE: CODE DUPLICATION FROM HLSLcc METAL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -void TranslateGmemOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements); -uint32_t GetGmemInputResourceSlot(uint32_t const slotIn); -uint32_t GetGmemInputResourceNumElements(uint32_t const slotIn); -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h deleted file mode 100644 index 724723bf49..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h +++ /dev/null @@ -1,16 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_DECLARATION_H -#define TO_METAL_DECLARATION_H - -#include "internal_includes/structs.h" - -void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); - -char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); -char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); - -const char* GetMangleSuffixMETAL(const SHADER_TYPE eShaderType); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h deleted file mode 100644 index eb29e74685..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h +++ /dev/null @@ -1,18 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_INSTRUCTION_H -#define TO_METAL_INSTRUCTION_H - -#include "internal_includes/structs.h" - -void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst); - -//For each MOV temp, immediate; check to see if the next instruction -//using that temp has an integer opcode. If so then the immediate value -//is flaged as having an integer encoding. -void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext); - -void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h deleted file mode 100644 index d4bcbcbc73..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h +++ /dev/null @@ -1,38 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_OPERAND_H -#define TO_METAL_OPERAND_H - -#include "internal_includes/structs.h" - -#define TO_FLAG_NONE 0x0 -#define TO_FLAG_INTEGER 0x1 -#define TO_FLAG_NAME_ONLY 0x2 -#define TO_FLAG_DECLARATION_NAME 0x4 -#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. -#define TO_FLAG_UNSIGNED_INTEGER 0x10 -#define TO_FLAG_DOUBLE 0x20 -#define TO_FLAG_FLOAT 0x40 - -void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); - -int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand); -void TranslateOperandMETALIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); -void TranslateOperandMETALIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); -void TranslateVariableNameMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle); -void TranslateOperandMETALSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand); -void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count); -int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -uint32_t IsSwizzleReplacatedMETAL(const Operand* psOperand); - -void TextureNameMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32RegisterNumber, const int bZCompare); - -uint32_t ConvertOperandSwizzleToComponentMaskMETAL(const Operand* psOperand); -//Non-zero means the components overlap -int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB); - -SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h deleted file mode 100644 index 635edf57be..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h +++ /dev/null @@ -1,812 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TOKENS_H -#define TOKENS_H - -#include "hlslcc.h" - -typedef enum -{ - INVALID_SHADER = -1, - PIXEL_SHADER, - VERTEX_SHADER, - GEOMETRY_SHADER, - HULL_SHADER, - DOMAIN_SHADER, - COMPUTE_SHADER, -} SHADER_TYPE; - -static SHADER_TYPE DecodeShaderType(uint32_t ui32Token) -{ - return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16); -} - -static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token) -{ - return (ui32Token & 0x000000f0) >> 4; -} - -static uint32_t DecodeProgramMinorVersion(uint32_t ui32Token) -{ - return (ui32Token & 0x0000000f); -} - -static uint32_t DecodeInstructionLength(uint32_t ui32Token) -{ - return (ui32Token & 0x7f000000) >> 24; -} - -static uint32_t DecodeIsOpcodeExtended(uint32_t ui32Token) -{ - return (ui32Token & 0x80000000) >> 31; -} - -typedef enum EXTENDED_OPCODE_TYPE -{ - EXTENDED_OPCODE_EMPTY = 0, - EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, - EXTENDED_OPCODE_RESOURCE_DIM = 2, - EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, -} EXTENDED_OPCODE_TYPE; - -static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token) -{ - return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f); -} - -typedef enum RESOURCE_RETURN_TYPE -{ - RETURN_TYPE_UNORM = 1, - RETURN_TYPE_SNORM = 2, - RETURN_TYPE_SINT = 3, - RETURN_TYPE_UINT = 4, - RETURN_TYPE_FLOAT = 5, - RETURN_TYPE_MIXED = 6, - RETURN_TYPE_DOUBLE = 7, - RETURN_TYPE_CONTINUED = 8, - RETURN_TYPE_UNUSED = 9, -} RESOURCE_RETURN_TYPE; - -static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) -{ - return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF); -} - -static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) -{ - return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF); -} - -typedef enum -{ - //For DX9 - OPCODE_POW = -6, - OPCODE_DP2ADD = -5, - OPCODE_LRP = -4, - OPCODE_ENDREP = -3, - OPCODE_REP = -2, - OPCODE_SPECIAL_DCL_IMMCONST = -1, - - OPCODE_ADD, - OPCODE_AND, - OPCODE_BREAK, - OPCODE_BREAKC, - OPCODE_CALL, - OPCODE_CALLC, - OPCODE_CASE, - OPCODE_CONTINUE, - OPCODE_CONTINUEC, - OPCODE_CUT, - OPCODE_DEFAULT, - OPCODE_DERIV_RTX, - OPCODE_DERIV_RTY, - OPCODE_DISCARD, - OPCODE_DIV, - OPCODE_DP2, - OPCODE_DP3, - OPCODE_DP4, - OPCODE_ELSE, - OPCODE_EMIT, - OPCODE_EMITTHENCUT, - OPCODE_ENDIF, - OPCODE_ENDLOOP, - OPCODE_ENDSWITCH, - OPCODE_EQ, - OPCODE_EXP, - OPCODE_FRC, - OPCODE_FTOI, - OPCODE_FTOU, - OPCODE_GE, - OPCODE_IADD, - OPCODE_IF, - OPCODE_IEQ, - OPCODE_IGE, - OPCODE_ILT, - OPCODE_IMAD, - OPCODE_IMAX, - OPCODE_IMIN, - OPCODE_IMUL, - OPCODE_INE, - OPCODE_INEG, - OPCODE_ISHL, - OPCODE_ISHR, - OPCODE_ITOF, - OPCODE_LABEL, - OPCODE_LD, - OPCODE_LD_MS, - OPCODE_LOG, - OPCODE_LOOP, - OPCODE_LT, - OPCODE_MAD, - OPCODE_MIN, - OPCODE_MAX, - OPCODE_CUSTOMDATA, - OPCODE_MOV, - OPCODE_MOVC, - OPCODE_MUL, - OPCODE_NE, - OPCODE_NOP, - OPCODE_NOT, - OPCODE_OR, - OPCODE_RESINFO, - OPCODE_RET, - OPCODE_RETC, - OPCODE_ROUND_NE, - OPCODE_ROUND_NI, - OPCODE_ROUND_PI, - OPCODE_ROUND_Z, - OPCODE_RSQ, - OPCODE_SAMPLE, - OPCODE_SAMPLE_C, - OPCODE_SAMPLE_C_LZ, - OPCODE_SAMPLE_L, - OPCODE_SAMPLE_D, - OPCODE_SAMPLE_B, - OPCODE_SQRT, - OPCODE_SWITCH, - OPCODE_SINCOS, - OPCODE_UDIV, - OPCODE_ULT, - OPCODE_UGE, - OPCODE_UMUL, - OPCODE_UMAD, - OPCODE_UMAX, - OPCODE_UMIN, - OPCODE_USHR, - OPCODE_UTOF, - OPCODE_XOR, - OPCODE_DCL_RESOURCE, // DCL* opcodes have - OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats. - OPCODE_DCL_SAMPLER, - OPCODE_DCL_INDEX_RANGE, - OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, - OPCODE_DCL_GS_INPUT_PRIMITIVE, - OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, - OPCODE_DCL_INPUT, - OPCODE_DCL_INPUT_SGV, - OPCODE_DCL_INPUT_SIV, - OPCODE_DCL_INPUT_PS, - OPCODE_DCL_INPUT_PS_SGV, - OPCODE_DCL_INPUT_PS_SIV, - OPCODE_DCL_OUTPUT, - OPCODE_DCL_OUTPUT_SGV, - OPCODE_DCL_OUTPUT_SIV, - OPCODE_DCL_TEMPS, - OPCODE_DCL_INDEXABLE_TEMP, - OPCODE_DCL_GLOBAL_FLAGS, - - // ----------------------------------------------- - - OPCODE_RESERVED_10, - - // ---------- DX 10.1 op codes--------------------- - - OPCODE_LOD, - OPCODE_GATHER4, - OPCODE_SAMPLE_POS, - OPCODE_SAMPLE_INFO, - - // ----------------------------------------------- - - // This should be 10.1's version of NUM_OPCODES - OPCODE_RESERVED_10_1, - - // ---------- DX 11 op codes--------------------- - OPCODE_HS_DECLS, // token marks beginning of HS sub-shader - OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader - OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader - OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader - - OPCODE_EMIT_STREAM, - OPCODE_CUT_STREAM, - OPCODE_EMITTHENCUT_STREAM, - OPCODE_INTERFACE_CALL, - - OPCODE_BUFINFO, - OPCODE_DERIV_RTX_COARSE, - OPCODE_DERIV_RTX_FINE, - OPCODE_DERIV_RTY_COARSE, - OPCODE_DERIV_RTY_FINE, - OPCODE_GATHER4_C, - OPCODE_GATHER4_PO, - OPCODE_GATHER4_PO_C, - OPCODE_RCP, - OPCODE_F32TOF16, - OPCODE_F16TOF32, - OPCODE_UADDC, - OPCODE_USUBB, - OPCODE_COUNTBITS, - OPCODE_FIRSTBIT_HI, - OPCODE_FIRSTBIT_LO, - OPCODE_FIRSTBIT_SHI, - OPCODE_UBFE, - OPCODE_IBFE, - OPCODE_BFI, - OPCODE_BFREV, - OPCODE_SWAPC, - - OPCODE_DCL_STREAM, - OPCODE_DCL_FUNCTION_BODY, - OPCODE_DCL_FUNCTION_TABLE, - OPCODE_DCL_INTERFACE, - - OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, - OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, - OPCODE_DCL_TESS_DOMAIN, - OPCODE_DCL_TESS_PARTITIONING, - OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, - OPCODE_DCL_HS_MAX_TESSFACTOR, - OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, - OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, - - OPCODE_DCL_THREAD_GROUP, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, - OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, - OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, - OPCODE_DCL_RESOURCE_RAW, - OPCODE_DCL_RESOURCE_STRUCTURED, - OPCODE_LD_UAV_TYPED, - OPCODE_STORE_UAV_TYPED, - OPCODE_LD_RAW, - OPCODE_STORE_RAW, - OPCODE_LD_STRUCTURED, - OPCODE_STORE_STRUCTURED, - OPCODE_ATOMIC_AND, - OPCODE_ATOMIC_OR, - OPCODE_ATOMIC_XOR, - OPCODE_ATOMIC_CMP_STORE, - OPCODE_ATOMIC_IADD, - OPCODE_ATOMIC_IMAX, - OPCODE_ATOMIC_IMIN, - OPCODE_ATOMIC_UMAX, - OPCODE_ATOMIC_UMIN, - OPCODE_IMM_ATOMIC_ALLOC, - OPCODE_IMM_ATOMIC_CONSUME, - OPCODE_IMM_ATOMIC_IADD, - OPCODE_IMM_ATOMIC_AND, - OPCODE_IMM_ATOMIC_OR, - OPCODE_IMM_ATOMIC_XOR, - OPCODE_IMM_ATOMIC_EXCH, - OPCODE_IMM_ATOMIC_CMP_EXCH, - OPCODE_IMM_ATOMIC_IMAX, - OPCODE_IMM_ATOMIC_IMIN, - OPCODE_IMM_ATOMIC_UMAX, - OPCODE_IMM_ATOMIC_UMIN, - OPCODE_SYNC, - - OPCODE_DADD, - OPCODE_DMAX, - OPCODE_DMIN, - OPCODE_DMUL, - OPCODE_DEQ, - OPCODE_DGE, - OPCODE_DLT, - OPCODE_DNE, - OPCODE_DMOV, - OPCODE_DMOVC, - OPCODE_DTOF, - OPCODE_FTOD, - - OPCODE_EVAL_SNAPPED, - OPCODE_EVAL_SAMPLE_INDEX, - OPCODE_EVAL_CENTROID, - - OPCODE_DCL_GS_INSTANCE_COUNT, - - OPCODE_ABORT, - OPCODE_DEBUG_BREAK, - - // ----------------------------------------------- - - // This marks the end of D3D11.0 opcodes - OPCODE_RESERVED_11, - - OPCODE_DDIV, - OPCODE_DFMA, - OPCODE_DRCP, - - OPCODE_MSAD, - - OPCODE_DTOI, - OPCODE_DTOU, - OPCODE_ITOD, - OPCODE_UTOD, - - // ----------------------------------------------- - - // This marks the end of D3D11.1 opcodes - OPCODE_RESERVED_11_1, - - NUM_OPCODES, - OPCODE_INVAILD = NUM_OPCODES, -} OPCODE_TYPE; - -static OPCODE_TYPE DecodeOpcodeType(uint32_t ui32Token) -{ - return (OPCODE_TYPE)(ui32Token & 0x00007ff); -} - -typedef enum -{ - INDEX_0D, - INDEX_1D, - INDEX_2D, - INDEX_3D, -} OPERAND_INDEX_DIMENSION; - -static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token) -{ - return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20); -} - -typedef enum OPERAND_TYPE -{ - OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10, - OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9, - OPERAND_TYPE_SPECIAL_TEXCOORD = -8, - OPERAND_TYPE_SPECIAL_POSITION = -7, - OPERAND_TYPE_SPECIAL_FOG = -6, - OPERAND_TYPE_SPECIAL_POINTSIZE = -5, - OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR = -4, - OPERAND_TYPE_SPECIAL_OUTBASECOLOUR = -3, - OPERAND_TYPE_SPECIAL_ADDRESS = -2, - OPERAND_TYPE_SPECIAL_IMMCONST = -1, - OPERAND_TYPE_TEMP = 0, // Temporary Register File - OPERAND_TYPE_INPUT = 1, // General Input Register File - OPERAND_TYPE_OUTPUT = 2, // General Output Register File - OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable) - OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s) - // If for example, operand token bits - // [01:00]==OPERAND_4_COMPONENT, - // this means that the operand type: - // OPERAND_TYPE_IMMEDIATE32 - // results in 4 additional 32bit - // DWORDS present for the operand. - OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO - OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state - OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture) - OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer - OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer - OPERAND_TYPE_LABEL = 10, // Label - OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID - OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth - OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations - // Below Are operands new in DX 10.1 - OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources - OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar) - // Below Are operands new in DX 11 - OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource - OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition - OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class - OPERAND_TYPE_INTERFACE = 19, // Reference to an interface - OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function - OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function - OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is - OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID - OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID - OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them) - OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them) - OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them) - OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point - OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer - OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u# - OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g# - OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID - OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID - OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group - OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input - OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value. - OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID - OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth - OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth - OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter -} OPERAND_TYPE; - -static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token) -{ - return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12); -} - -static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token) -{ - return (SPECIAL_NAME)(ui32Token & 0x0000ffff); -} - -typedef enum OPERAND_INDEX_REPRESENTATION -{ - OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD - OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs - // (HI32:LO32) - OPERAND_INDEX_RELATIVE = 2, // Extra operand - OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by - // extra operand - OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS - // (HI32:LO32) followed - // by extra operand -} OPERAND_INDEX_REPRESENTATION; - -static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token) -{ - return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3))); -} - -typedef enum OPERAND_NUM_COMPONENTS -{ - OPERAND_0_COMPONENT = 0, - OPERAND_1_COMPONENT = 1, - OPERAND_4_COMPONENT = 2, - OPERAND_N_COMPONENT = 3 // unused for now -} OPERAND_NUM_COMPONENTS; - -static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token) -{ - return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003); -} - -typedef enum OPERAND_4_COMPONENT_SELECTION_MODE -{ - OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components - OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components - OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components -} OPERAND_4_COMPONENT_SELECTION_MODE; - -static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token) -{ - return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2); -} - -#define OPERAND_4_COMPONENT_MASK_X 0x00000001 -#define OPERAND_4_COMPONENT_MASK_Y 0x00000002 -#define OPERAND_4_COMPONENT_MASK_Z 0x00000004 -#define OPERAND_4_COMPONENT_MASK_W 0x00000008 -#define OPERAND_4_COMPONENT_MASK_R OPERAND_4_COMPONENT_MASK_X -#define OPERAND_4_COMPONENT_MASK_G OPERAND_4_COMPONENT_MASK_Y -#define OPERAND_4_COMPONENT_MASK_B OPERAND_4_COMPONENT_MASK_Z -#define OPERAND_4_COMPONENT_MASK_A OPERAND_4_COMPONENT_MASK_W -#define OPERAND_4_COMPONENT_MASK_ALL 0x0000000f - -static uint32_t DecodeOperand4CompMask(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x000000f0) >> 4); -} - -static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x00000ff0) >> 4); -} - -static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x00000030) >> 4); -} - -#define OPERAND_4_COMPONENT_X 0 -#define OPERAND_4_COMPONENT_Y 1 -#define OPERAND_4_COMPONENT_Z 2 -#define OPERAND_4_COMPONENT_W 3 - -static uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/); - -static uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X<<2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6))); -static uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6))); -static uint32_t ZZZZ_SWIZZLE = (((OPERAND_4_COMPONENT_Z) | (OPERAND_4_COMPONENT_Z<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_Z << 6))); -static uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMPONENT_W<<2) | (OPERAND_4_COMPONENT_W << 4) | (OPERAND_4_COMPONENT_W << 6))); - -static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp) -{ - return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3); -} - -typedef enum RESOURCE_DIMENSION -{ - RESOURCE_DIMENSION_UNKNOWN = 0, - RESOURCE_DIMENSION_BUFFER = 1, - RESOURCE_DIMENSION_TEXTURE1D = 2, - RESOURCE_DIMENSION_TEXTURE2D = 3, - RESOURCE_DIMENSION_TEXTURE2DMS = 4, - RESOURCE_DIMENSION_TEXTURE3D = 5, - RESOURCE_DIMENSION_TEXTURECUBE = 6, - RESOURCE_DIMENSION_TEXTURE1DARRAY = 7, - RESOURCE_DIMENSION_TEXTURE2DARRAY = 8, - RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 9, - RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, - RESOURCE_DIMENSION_RAW_BUFFER = 11, - RESOURCE_DIMENSION_STRUCTURED_BUFFER = 12, -} RESOURCE_DIMENSION; - -static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token) -{ - return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11); -} - -static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token) -{ - return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6); -} - -typedef enum CONSTANT_BUFFER_ACCESS_PATTERN -{ - CONSTANT_BUFFER_ACCESS_PATTERN_IMMEDIATEINDEXED = 0, - CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED = 1 -} CONSTANT_BUFFER_ACCESS_PATTERN; - -static CONSTANT_BUFFER_ACCESS_PATTERN DecodeConstantBufferAccessPattern(uint32_t ui32Token) -{ - return (CONSTANT_BUFFER_ACCESS_PATTERN)((ui32Token & 0x00000800) >> 11); -} - -typedef enum INSTRUCTION_TEST_BOOLEAN -{ - INSTRUCTION_TEST_ZERO = 0, - INSTRUCTION_TEST_NONZERO = 1 -} INSTRUCTION_TEST_BOOLEAN; - -static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token) -{ - return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18); -} - -static uint32_t DecodeIsOperandExtended(uint32_t ui32Token) -{ - return (ui32Token & 0x80000000) >> 31; -} - -typedef enum EXTENDED_OPERAND_TYPE -{ - EXTENDED_OPERAND_EMPTY = 0, - EXTENDED_OPERAND_MODIFIER = 1, -} EXTENDED_OPERAND_TYPE; - -static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token) -{ - return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f); -} - -typedef enum OPERAND_MODIFIER -{ - OPERAND_MODIFIER_NONE = 0, - OPERAND_MODIFIER_NEG = 1, - OPERAND_MODIFIER_ABS = 2, - OPERAND_MODIFIER_ABSNEG = 3, -} OPERAND_MODIFIER; - -static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token) -{ - return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6); -} - -static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11); -static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12); -static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13); -static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14); -static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15); -static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16); -static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17); -static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18); - -static uint32_t DecodeGlobalFlags(uint32_t ui32Token) -{ - return (uint32_t)(ui32Token & 0x00fff800); -} - -static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token) -{ - return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11); -} - - -typedef enum PRIMITIVE_TOPOLOGY -{ - PRIMITIVE_TOPOLOGY_UNDEFINED = 0, - PRIMITIVE_TOPOLOGY_POINTLIST = 1, - PRIMITIVE_TOPOLOGY_LINELIST = 2, - PRIMITIVE_TOPOLOGY_LINESTRIP = 3, - PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4, - PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5, - // 6 is reserved for legacy triangle fans - // Adjacency values should be equal to (0x8 & non-adjacency): - PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10, - PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11, - PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12, - PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13, -} PRIMITIVE_TOPOLOGY; - -static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token) -{ - return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11); -} - -typedef enum PRIMITIVE -{ - PRIMITIVE_UNDEFINED = 0, - PRIMITIVE_POINT = 1, - PRIMITIVE_LINE = 2, - PRIMITIVE_TRIANGLE = 3, - // Adjacency values should be equal to (0x4 & non-adjacency): - PRIMITIVE_LINE_ADJ = 6, - PRIMITIVE_TRIANGLE_ADJ = 7, - PRIMITIVE_1_CONTROL_POINT_PATCH = 8, - PRIMITIVE_2_CONTROL_POINT_PATCH = 9, - PRIMITIVE_3_CONTROL_POINT_PATCH = 10, - PRIMITIVE_4_CONTROL_POINT_PATCH = 11, - PRIMITIVE_5_CONTROL_POINT_PATCH = 12, - PRIMITIVE_6_CONTROL_POINT_PATCH = 13, - PRIMITIVE_7_CONTROL_POINT_PATCH = 14, - PRIMITIVE_8_CONTROL_POINT_PATCH = 15, - PRIMITIVE_9_CONTROL_POINT_PATCH = 16, - PRIMITIVE_10_CONTROL_POINT_PATCH = 17, - PRIMITIVE_11_CONTROL_POINT_PATCH = 18, - PRIMITIVE_12_CONTROL_POINT_PATCH = 19, - PRIMITIVE_13_CONTROL_POINT_PATCH = 20, - PRIMITIVE_14_CONTROL_POINT_PATCH = 21, - PRIMITIVE_15_CONTROL_POINT_PATCH = 22, - PRIMITIVE_16_CONTROL_POINT_PATCH = 23, - PRIMITIVE_17_CONTROL_POINT_PATCH = 24, - PRIMITIVE_18_CONTROL_POINT_PATCH = 25, - PRIMITIVE_19_CONTROL_POINT_PATCH = 26, - PRIMITIVE_20_CONTROL_POINT_PATCH = 27, - PRIMITIVE_21_CONTROL_POINT_PATCH = 28, - PRIMITIVE_22_CONTROL_POINT_PATCH = 29, - PRIMITIVE_23_CONTROL_POINT_PATCH = 30, - PRIMITIVE_24_CONTROL_POINT_PATCH = 31, - PRIMITIVE_25_CONTROL_POINT_PATCH = 32, - PRIMITIVE_26_CONTROL_POINT_PATCH = 33, - PRIMITIVE_27_CONTROL_POINT_PATCH = 34, - PRIMITIVE_28_CONTROL_POINT_PATCH = 35, - PRIMITIVE_29_CONTROL_POINT_PATCH = 36, - PRIMITIVE_30_CONTROL_POINT_PATCH = 37, - PRIMITIVE_31_CONTROL_POINT_PATCH = 38, - PRIMITIVE_32_CONTROL_POINT_PATCH = 39, -} PRIMITIVE; - -static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token) -{ - return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11); -} - -static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token) -{ - return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11); -} - -typedef enum TESSELLATOR_DOMAIN -{ - TESSELLATOR_DOMAIN_UNDEFINED = 0, - TESSELLATOR_DOMAIN_ISOLINE = 1, - TESSELLATOR_DOMAIN_TRI = 2, - TESSELLATOR_DOMAIN_QUAD = 3 -} TESSELLATOR_DOMAIN; - -static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token) -{ - return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11); -} - -static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token) -{ - return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11); -} - -static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800; -static const uint32_t SYNC_THREAD_GROUP_SHARED_MEMORY = 0x00001000; -static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP = 0x00002000; -static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000; - -static uint32_t DecodeSyncFlags(uint32_t ui32Token) -{ - return ui32Token & 0x00007800; -} - -// The number of types that implement this interface -static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x0000ffff) >> 0); -} - -// The number of interfaces that are defined in this array. -static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0xffff0000) >> 16); -} - -typedef enum CUSTOMDATA_CLASS -{ - CUSTOMDATA_COMMENT = 0, - CUSTOMDATA_DEBUGINFO, - CUSTOMDATA_OPAQUE, - CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, - CUSTOMDATA_SHADER_MESSAGE, -} CUSTOMDATA_CLASS; - -static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token) -{ - return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11); -} - -static uint32_t DecodeInstructionSaturate(uint32_t ui32Token) -{ - return (ui32Token & 0x00002000) ? 1 : 0; -} - -typedef enum OPERAND_MIN_PRECISION -{ - OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision - // for the shader model - OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float - OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float - OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer - OPERAND_MIN_PRECISION_UINT_16 = 5, // Min 16 bit/comp. unsigned integer -} OPERAND_MIN_PRECISION; - -static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token) -{ - return (ui32Token & 0x0001C000) >> 14; -} - -static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token) -{ - return ((ui32Token & 0x0001f800) >> 11); -} - -typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD -{ - IMMEDIATE_ADDRESS_OFFSET_U = 0, - IMMEDIATE_ADDRESS_OFFSET_V = 1, - IMMEDIATE_ADDRESS_OFFSET_W = 2, -} IMMEDIATE_ADDRESS_OFFSET_COORD; - - -#define IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&3)) -#define IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<<IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord)) - -static uint32_t DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_COORD eCoord, uint32_t ui32Token) -{ - return ((((ui32Token)&IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord))>>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord)))); -} - -// UAV access scope flags -static const uint32_t GLOBALLY_COHERENT_ACCESS = 0x00010000; -static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token) -{ - return ui32Token & 0x00010000; -} - - -typedef enum RESINFO_RETURN_TYPE -{ - RESINFO_INSTRUCTION_RETURN_FLOAT = 0, - RESINFO_INSTRUCTION_RETURN_RCPFLOAT = 1, - RESINFO_INSTRUCTION_RETURN_UINT = 2 -} RESINFO_RETURN_TYPE; - -static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token) -{ - return (RESINFO_RETURN_TYPE)((ui32Token & 0x00001800) >> 11); -} - -#include "tokensDX9.h" - -#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h deleted file mode 100644 index a71afd7b59..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h +++ /dev/null @@ -1,304 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "debug.h" - -static const uint32_t D3D9SHADER_TYPE_VERTEX = 0xFFFE0000; -static const uint32_t D3D9SHADER_TYPE_PIXEL = 0xFFFF0000; - -static SHADER_TYPE DecodeShaderTypeDX9(const uint32_t ui32Token) -{ - uint32_t ui32Type = ui32Token & 0xFFFF0000; - if(ui32Type == D3D9SHADER_TYPE_VERTEX) - return VERTEX_SHADER; - - if(ui32Type == D3D9SHADER_TYPE_PIXEL) - return PIXEL_SHADER; - - return INVALID_SHADER; -} - -static uint32_t DecodeProgramMajorVersionDX9(const uint32_t ui32Token) -{ - return ((ui32Token)>>8)&0xFF; -} - -static uint32_t DecodeProgramMinorVersionDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xFF; -} - -typedef enum -{ - OPCODE_DX9_NOP = 0, - OPCODE_DX9_MOV , - OPCODE_DX9_ADD , - OPCODE_DX9_SUB , - OPCODE_DX9_MAD , - OPCODE_DX9_MUL , - OPCODE_DX9_RCP , - OPCODE_DX9_RSQ , - OPCODE_DX9_DP3 , - OPCODE_DX9_DP4 , - OPCODE_DX9_MIN , - OPCODE_DX9_MAX , - OPCODE_DX9_SLT , - OPCODE_DX9_SGE , - OPCODE_DX9_EXP , - OPCODE_DX9_LOG , - OPCODE_DX9_LIT , - OPCODE_DX9_DST , - OPCODE_DX9_LRP , - OPCODE_DX9_FRC , - OPCODE_DX9_M4x4 , - OPCODE_DX9_M4x3 , - OPCODE_DX9_M3x4 , - OPCODE_DX9_M3x3 , - OPCODE_DX9_M3x2 , - OPCODE_DX9_CALL , - OPCODE_DX9_CALLNZ , - OPCODE_DX9_LOOP , - OPCODE_DX9_RET , - OPCODE_DX9_ENDLOOP , - OPCODE_DX9_LABEL , - OPCODE_DX9_DCL , - OPCODE_DX9_POW , - OPCODE_DX9_CRS , - OPCODE_DX9_SGN , - OPCODE_DX9_ABS , - OPCODE_DX9_NRM , - OPCODE_DX9_SINCOS , - OPCODE_DX9_REP , - OPCODE_DX9_ENDREP , - OPCODE_DX9_IF , - OPCODE_DX9_IFC , - OPCODE_DX9_ELSE , - OPCODE_DX9_ENDIF , - OPCODE_DX9_BREAK , - OPCODE_DX9_BREAKC , - OPCODE_DX9_MOVA , - OPCODE_DX9_DEFB , - OPCODE_DX9_DEFI , - - OPCODE_DX9_TEXCOORD = 64, - OPCODE_DX9_TEXKILL , - OPCODE_DX9_TEX , - OPCODE_DX9_TEXBEM , - OPCODE_DX9_TEXBEML , - OPCODE_DX9_TEXREG2AR , - OPCODE_DX9_TEXREG2GB , - OPCODE_DX9_TEXM3x2PAD , - OPCODE_DX9_TEXM3x2TEX , - OPCODE_DX9_TEXM3x3PAD , - OPCODE_DX9_TEXM3x3TEX , - OPCODE_DX9_RESERVED0 , - OPCODE_DX9_TEXM3x3SPEC , - OPCODE_DX9_TEXM3x3VSPEC , - OPCODE_DX9_EXPP , - OPCODE_DX9_LOGP , - OPCODE_DX9_CND , - OPCODE_DX9_DEF , - OPCODE_DX9_TEXREG2RGB , - OPCODE_DX9_TEXDP3TEX , - OPCODE_DX9_TEXM3x2DEPTH , - OPCODE_DX9_TEXDP3 , - OPCODE_DX9_TEXM3x3 , - OPCODE_DX9_TEXDEPTH , - OPCODE_DX9_CMP , - OPCODE_DX9_BEM , - OPCODE_DX9_DP2ADD , - OPCODE_DX9_DSX , - OPCODE_DX9_DSY , - OPCODE_DX9_TEXLDD , - OPCODE_DX9_SETP , - OPCODE_DX9_TEXLDL , - OPCODE_DX9_BREAKP , - - OPCODE_DX9_PHASE = 0xFFFD, - OPCODE_DX9_COMMENT = 0xFFFE, - OPCODE_DX9_END = 0xFFFF, - - OPCODE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum -} OPCODE_TYPE_DX9; - -static OPCODE_TYPE_DX9 DecodeOpcodeTypeDX9(const uint32_t ui32Token) -{ - return (OPCODE_TYPE_DX9)(ui32Token & 0x0000FFFF); -} - -static uint32_t DecodeInstructionLengthDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x0F000000)>>24; -} - -static uint32_t DecodeCommentLengthDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x7FFF0000)>>16; -} - -static uint32_t DecodeOperandRegisterNumberDX9(const uint32_t ui32Token) -{ - return ui32Token & 0x000007FF; -} - -typedef enum -{ - OPERAND_TYPE_DX9_TEMP = 0, // Temporary Register File - OPERAND_TYPE_DX9_INPUT = 1, // Input Register File - OPERAND_TYPE_DX9_CONST = 2, // Constant Register File - OPERAND_TYPE_DX9_ADDR = 3, // Address Register (VS) - OPERAND_TYPE_DX9_TEXTURE = 3, // Texture Register File (PS) - OPERAND_TYPE_DX9_RASTOUT = 4, // Rasterizer Register File - OPERAND_TYPE_DX9_ATTROUT = 5, // Attribute Output Register File - OPERAND_TYPE_DX9_TEXCRDOUT = 6, // Texture Coordinate Output Register File - OPERAND_TYPE_DX9_OUTPUT = 6, // Output register file for VS3.0+ - OPERAND_TYPE_DX9_CONSTINT = 7, // Constant Integer Vector Register File - OPERAND_TYPE_DX9_COLOROUT = 8, // Color Output Register File - OPERAND_TYPE_DX9_DEPTHOUT = 9, // Depth Output Register File - OPERAND_TYPE_DX9_SAMPLER = 10, // Sampler State Register File - OPERAND_TYPE_DX9_CONST2 = 11, // Constant Register File 2048 - 4095 - OPERAND_TYPE_DX9_CONST3 = 12, // Constant Register File 4096 - 6143 - OPERAND_TYPE_DX9_CONST4 = 13, // Constant Register File 6144 - 8191 - OPERAND_TYPE_DX9_CONSTBOOL = 14, // Constant Boolean register file - OPERAND_TYPE_DX9_LOOP = 15, // Loop counter register file - OPERAND_TYPE_DX9_TEMPFLOAT16 = 16, // 16-bit float temp register file - OPERAND_TYPE_DX9_MISCTYPE = 17, // Miscellaneous (single) registers. - OPERAND_TYPE_DX9_LABEL = 18, // Label - OPERAND_TYPE_DX9_PREDICATE = 19, // Predicate register - OPERAND_TYPE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum -} OPERAND_TYPE_DX9; - -static OPERAND_TYPE_DX9 DecodeOperandTypeDX9(const uint32_t ui32Token) -{ - return (OPERAND_TYPE_DX9)(((ui32Token & 0x70000000) >> 28) | - ((ui32Token & 0x00001800) >> 8)); -} - -static uint32_t CreateOperandTokenDX9(const uint32_t ui32RegNum, const OPERAND_TYPE_DX9 eType) -{ - uint32_t ui32Token = ui32RegNum; - ASSERT(ui32RegNum <2048); - ui32Token |= (eType <<28) & 0x70000000; - ui32Token |= (eType <<8) & 0x00001800; - return ui32Token; -} - -typedef enum { - DECLUSAGE_POSITION = 0, - DECLUSAGE_BLENDWEIGHT = 1, - DECLUSAGE_BLENDINDICES = 2, - DECLUSAGE_NORMAL = 3, - DECLUSAGE_PSIZE = 4, - DECLUSAGE_TEXCOORD = 5, - DECLUSAGE_TANGENT = 6, - DECLUSAGE_BINORMAL = 7, - DECLUSAGE_TESSFACTOR = 8, - DECLUSAGE_POSITIONT = 9, - DECLUSAGE_COLOR = 10, - DECLUSAGE_FOG = 11, - DECLUSAGE_DEPTH = 12, - DECLUSAGE_SAMPLE = 13 -} DECLUSAGE_DX9; - -static DECLUSAGE_DX9 DecodeUsageDX9(const uint32_t ui32Token) -{ - return (DECLUSAGE_DX9) (ui32Token & 0x0000000f); -} - -static uint32_t DecodeUsageIndexDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x000f0000)>>16; -} - -static uint32_t DecodeOperandIsRelativeAddressModeDX9(const uint32_t ui32Token) -{ - return ui32Token & (1<<13); -} - -static const uint32_t DX9_SWIZZLE_SHIFT = 16; -#define NO_SWIZZLE_DX9 ((0<<DX9_SWIZZLE_SHIFT)|(1<<DX9_SWIZZLE_SHIFT)|(2<<DX9_SWIZZLE_SHIFT)|(3<<DX9_SWIZZLE_SHIFT)) - -#define REPLICATE_SWIZZLE_DX9(CHANNEL) ((CHANNEL<<DX9_SWIZZLE_SHIFT)|(CHANNEL<<(DX9_SWIZZLE_SHIFT+2))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+4))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+6))) - -static uint32_t DecodeOperandSwizzleDX9(const uint32_t ui32Token) -{ - return ui32Token & 0x00FF0000; -} - -static const uint32_t DX9_WRITEMASK_0 = 0x00010000; // Component 0 (X;Red) -static const uint32_t DX9_WRITEMASK_1 = 0x00020000; // Component 1 (Y;Green) -static const uint32_t DX9_WRITEMASK_2 = 0x00040000; // Component 2 (Z;Blue) -static const uint32_t DX9_WRITEMASK_3 = 0x00080000; // Component 3 (W;Alpha) -static const uint32_t DX9_WRITEMASK_ALL = 0x000F0000; // All Components - -static uint32_t DecodeDestWriteMaskDX9(const uint32_t ui32Token) -{ - return ui32Token & DX9_WRITEMASK_ALL; -} - -static RESOURCE_DIMENSION DecodeTextureTypeMaskDX9(const uint32_t ui32Token) -{ - - switch(ui32Token & 0x78000000) - { - case 2 << 27: - return RESOURCE_DIMENSION_TEXTURE2D; - case 3 << 27: - return RESOURCE_DIMENSION_TEXTURECUBE; - case 4 << 27: - return RESOURCE_DIMENSION_TEXTURE3D; - default: - return RESOURCE_DIMENSION_UNKNOWN; - } -} - - - -static const uint32_t DESTMOD_DX9_NONE = 0; -static const uint32_t DESTMOD_DX9_SATURATE = (1 << 20); -static const uint32_t DESTMOD_DX9_PARTIALPRECISION = (2 << 20); -static const uint32_t DESTMOD_DX9_MSAMPCENTROID = (4 << 20); -static uint32_t DecodeDestModifierDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xf00000; -} - -typedef enum -{ - SRCMOD_DX9_NONE = 0 << 24, - SRCMOD_DX9_NEG = 1 << 24, - SRCMOD_DX9_BIAS = 2 << 24, - SRCMOD_DX9_BIASNEG = 3 << 24, - SRCMOD_DX9_SIGN = 4 << 24, - SRCMOD_DX9_SIGNNEG = 5 << 24, - SRCMOD_DX9_COMP = 6 << 24, - SRCMOD_DX9_X2 = 7 << 24, - SRCMOD_DX9_X2NEG = 8 << 24, - SRCMOD_DX9_DZ = 9 << 24, - SRCMOD_DX9_DW = 10 << 24, - SRCMOD_DX9_ABS = 11 << 24, - SRCMOD_DX9_ABSNEG = 12 << 24, - SRCMOD_DX9_NOT = 13 << 24, - SRCMOD_DX9_FORCE_DWORD = 0xffffffff -} SRCMOD_DX9; -static uint32_t DecodeSrcModifierDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xf000000; -} - -typedef enum -{ - D3DSPC_RESERVED0 = 0, - D3DSPC_GT = 1, - D3DSPC_EQ = 2, - D3DSPC_GE = 3, - D3DSPC_LT = 4, - D3DSPC_NE = 5, - D3DSPC_LE = 6, - D3DSPC_BOOLEAN = 7, //Make use of the RESERVED1 bit to indicate if-bool opcode. -} COMPARISON_DX9; - -static COMPARISON_DX9 DecodeComparisonDX9(const uint32_t ui32Token) -{ - return (COMPARISON_DX9)((ui32Token & (0x07<<16))>>16); -} diff --git a/Code/Tools/HLSLCrossCompiler/src/reflect.c b/Code/Tools/HLSLCrossCompiler/src/reflect.c deleted file mode 100644 index 66587c0152..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/reflect.c +++ /dev/null @@ -1,1075 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/reflect.h" -#include "internal_includes/debug.h" -#include "internal_includes/decode.h" -#include "internal_includes/hlslcc_malloc.h" -#include "bstrlib.h" -#include <stdlib.h> -#include <stdio.h> - -static void FormatVariableName(char* Name) -{ - int i; - - /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx - The uniform function parameters appear in the - constant table prepended with a dollar sign ($), - unlike the global variables. The dollar sign is - required to avoid name collisions between local - uniform inputs and global variables of the same name.*/ - - /* Leave $ThisPointer, $Element and $Globals as-is. - Otherwise remove $ character ($ is not a valid character for GLSL variable names). */ - if(Name[0] == '$') - { - if(strcmp(Name, "$Element") !=0 && - strcmp(Name, "$Globals") != 0 && - strcmp(Name, "$ThisPointer") != 0) - { - Name[0] = '_'; - } - } - - // remove "__" because it's reserved in OpenGL - for (i = 0; Name[i] != '\0'; ++i) - { - if (Name[i] == '_' && Name[i + 1] == '_') - { - Name[i + 1] = 'x'; - } - } -} - -static void ReadStringFromTokenStream(const uint32_t* tokens, char* str) -{ - char* charTokens = (char*) tokens; - char nextCharacter = *charTokens++; - int length = 0; - - //Add each individual character until - //a terminator is found. - while(nextCharacter != 0) { - - str[length++] = nextCharacter; - - if(length > MAX_REFLECT_STRING_LENGTH) - { - str[length-1] = '\0'; - return; - } - - nextCharacter = *charTokens++; - } - - str[length] = '\0'; -} - -static void ReadInputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int extended) -{ - uint32_t i; - - InOutSignature* psSignatures; - const uint32_t* pui32FirstSignatureToken = pui32Tokens; - const uint32_t ui32ElementCount = *pui32Tokens++; - /* const uint32_t ui32Key = */ *pui32Tokens++; - - psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); - psShaderInfo->psInputSignatures = psSignatures; - psShaderInfo->ui32NumInputSignatures = ui32ElementCount; - - for(i=0; i<ui32ElementCount; ++i) - { - uint32_t ui32ComponentMasks; - InOutSignature* psCurrentSignature = psSignatures + i; - uint32_t ui32SemanticNameOffset; - - psCurrentSignature->ui32Stream = 0; - psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; - - if(extended) - psCurrentSignature->ui32Stream = *pui32Tokens++; - - ui32SemanticNameOffset = *pui32Tokens++; - psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; - psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++; - psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; - psCurrentSignature->ui32Register = *pui32Tokens++; - - ui32ComponentMasks = *pui32Tokens++; - psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; - //Shows which components are read - psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; - - if(extended) - psCurrentSignature->eMinPrec = *pui32Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); - } -} - -static void ReadOutputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int minPrec, const int streams) -{ - uint32_t i; - - InOutSignature* psSignatures; - const uint32_t* pui32FirstSignatureToken = pui32Tokens; - const uint32_t ui32ElementCount = *pui32Tokens++; - /* const uint32_t ui32Key = */ *pui32Tokens++; - - psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); - psShaderInfo->psOutputSignatures = psSignatures; - psShaderInfo->ui32NumOutputSignatures = ui32ElementCount; - - for(i=0; i<ui32ElementCount; ++i) - { - uint32_t ui32ComponentMasks; - InOutSignature* psCurrentSignature = psSignatures + i; - uint32_t ui32SemanticNameOffset; - - psCurrentSignature->ui32Stream = 0; - psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; - - if(streams) - psCurrentSignature->ui32Stream = *pui32Tokens++; - - ui32SemanticNameOffset = *pui32Tokens++; - psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; - psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; - psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; - psCurrentSignature->ui32Register = *pui32Tokens++; - - ui32ComponentMasks = *pui32Tokens++; - psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; - //Shows which components are NEVER written. - psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; - - if(minPrec) - psCurrentSignature->eMinPrec = *pui32Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); - } -} - -static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding) -{ - uint32_t ui32NameOffset = *pui32Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken+ui32NameOffset), psBinding->Name); - FormatVariableName(psBinding->Name); - - psBinding->eType = *pui32Tokens++; - psBinding->ui32ReturnType = *pui32Tokens++; - psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++; - psBinding->ui32NumSamples = *pui32Tokens++; - psBinding->ui32BindPoint = *pui32Tokens++; - psBinding->ui32BindCount = *pui32Tokens++; - psBinding->ui32Flags = *pui32Tokens++; - - return pui32Tokens; -} - -//Read D3D11_SHADER_TYPE_DESC -static void ReadShaderVariableType(const uint32_t ui32MajorVersion, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32tokens, ShaderVarType* varType) -{ - const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens; - uint16_t ui32MemberCount; - uint32_t ui32MemberOffset; - const uint32_t* pui32MemberTokens; - uint32_t i; - - varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0]; - varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1]; - varType->Rows = pui16Tokens[2]; - varType->Columns = pui16Tokens[3]; - varType->Elements = pui16Tokens[4]; - - varType->MemberCount = ui32MemberCount = pui16Tokens[5]; - varType->Members = 0; - - if(ui32MemberCount) - { - varType->Members = (ShaderVarType*)hlslcc_malloc(sizeof(ShaderVarType)*ui32MemberCount); - - ui32MemberOffset = pui32tokens[3]; - - pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberOffset); - - for(i=0; i< ui32MemberCount; ++i) - { - uint32_t ui32NameOffset = *pui32MemberTokens++; - uint32_t ui32MemberTypeOffset = *pui32MemberTokens++; - - varType->Members[i].Parent = varType; - varType->Members[i].ParentCount = varType->ParentCount + 1; - - varType->Members[i].Offset = *pui32MemberTokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), varType->Members[i].Name); - - ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken, - (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberTypeOffset), &varType->Members[i]); - } - } -} - -static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32Tokens, ConstantBuffer* psBuffer) -{ - uint32_t i; - uint32_t ui32NameOffset = *pui32Tokens++; - uint32_t ui32VarCount = *pui32Tokens++; - uint32_t ui32VarOffset = *pui32Tokens++; - const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32VarOffset); - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psBuffer->Name); - FormatVariableName(psBuffer->Name); - - psBuffer->ui32NumVars = ui32VarCount; - - for(i=0; i<ui32VarCount; ++i) - { - //D3D11_SHADER_VARIABLE_DESC - ShaderVar * const psVar = &psBuffer->asVars[i]; - - uint32_t ui32TypeOffset; - uint32_t ui32DefaultValueOffset; - - ui32NameOffset = *pui32VarToken++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psVar->Name); - FormatVariableName(psVar->Name); - - psVar->ui32StartOffset = *pui32VarToken++; - psVar->ui32Size = *pui32VarToken++; - psVar->ui32Flags = *pui32VarToken++; - ui32TypeOffset = *pui32VarToken++; - - strcpy(psVar->sType.Name, psVar->Name); - psVar->sType.Parent = 0; - psVar->sType.ParentCount = 0; - psVar->sType.Offset = 0; - - ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken, - (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32TypeOffset), &psVar->sType); - - ui32DefaultValueOffset = *pui32VarToken++; - - - if (psShaderInfo->ui32MajorVersion >= 5) - { - /* uint32_t StartTexture = */ *pui32VarToken++; - /* uint32_t TextureSize = */ *pui32VarToken++; - /* uint32_t StartSampler = */ *pui32VarToken++; - /* uint32_t SamplerSize = */ *pui32VarToken++; - } - - psVar->haveDefaultValue = 0; - - if(ui32DefaultValueOffset) - { - const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4; - const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32DefaultValueOffset); - - //Always a sequence of 4-bytes at the moment. - //bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes. - ASSERT(psVar->ui32Size%4 == 0); - - psVar->haveDefaultValue = 1; - - psVar->pui32DefaultValues = hlslcc_malloc(psVar->ui32Size); - - for(uint32_t j=0; j<ui32NumDefaultValues;++j) - { - psVar->pui32DefaultValues[j] = pui32DefaultValToken[j]; - } - } - } - - - { - uint32_t ui32Flags; - uint32_t ui32BufferType; - - psBuffer->ui32TotalSizeInBytes = *pui32Tokens++; - psBuffer->blob = 0; - ui32Flags = *pui32Tokens++; - ui32BufferType = *pui32Tokens++; - } - - return pui32Tokens; -} - -static void ReadResources(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) -{ - ResourceBinding* psResBindings; - ConstantBuffer* psConstantBuffers; - const uint32_t* pui32ConstantBuffers; - const uint32_t* pui32ResourceBindings; - const uint32_t* pui32FirstToken = pui32Tokens; - uint32_t i; - - const uint32_t ui32NumConstantBuffers = *pui32Tokens++; - const uint32_t ui32ConstantBufferOffset = *pui32Tokens++; - - uint32_t ui32NumResourceBindings = *pui32Tokens++; - uint32_t ui32ResourceBindingOffset = *pui32Tokens++; - /* uint32_t ui32ShaderModel = */ *pui32Tokens++; - /* uint32_t ui32CompileFlags = */ *pui32Tokens++;//D3DCompile flags? http://msdn.microsoft.com/en-us/library/gg615083(v=vs.85).aspx - - //Resources - pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset); - - psResBindings = hlslcc_malloc(sizeof(ResourceBinding)*ui32NumResourceBindings); - - psShaderInfo->ui32NumResourceBindings = ui32NumResourceBindings; - psShaderInfo->psResourceBindings = psResBindings; - - for(i=0; i < ui32NumResourceBindings; ++i) - { - pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings+i); - ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS); - } - - //Constant buffers - pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset); - - psConstantBuffers = hlslcc_malloc(sizeof(ConstantBuffer) * ui32NumConstantBuffers); - - psShaderInfo->ui32NumConstantBuffers = ui32NumConstantBuffers; - psShaderInfo->psConstantBuffers = psConstantBuffers; - - for(i=0; i < ui32NumConstantBuffers; ++i) - { - pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers+i); - } - - - //Map resource bindings to constant buffers - if(psShaderInfo->ui32NumConstantBuffers) - { - for(i=0; i < ui32NumResourceBindings; ++i) - { - ResourceGroup eRGroup; - uint32_t cbufIndex = 0; - - eRGroup = ResourceTypeToResourceGroup(psResBindings[i].eType); - - //Find the constant buffer whose name matches the resource at the given resource binding point - for(cbufIndex=0; cbufIndex < psShaderInfo->ui32NumConstantBuffers; cbufIndex++) - { - if(strcmp(psConstantBuffers[cbufIndex].Name, psResBindings[i].Name) == 0) - { - psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex; - } - } - } - } -} - -static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType) -{ - const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens; - uint32_t ui32NameOffset = *pui32Tokens; - pui16Tokens+= 2; - - psClassType->ui16ID = *pui16Tokens++; - psClassType->ui16ConstBufStride = *pui16Tokens++; - psClassType->ui16Texture = *pui16Tokens++; - psClassType->ui16Sampler = *pui16Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassType->Name); - - return pui16Tokens; -} - -static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassInstance* psClassInstance) -{ - uint32_t ui32NameOffset = *pui16Tokens++ << 16; - ui32NameOffset |= *pui16Tokens++; - - psClassInstance->ui16ID = *pui16Tokens++; - psClassInstance->ui16ConstBuf = *pui16Tokens++; - psClassInstance->ui16ConstBufOffset = *pui16Tokens++; - psClassInstance->ui16Texture = *pui16Tokens++; - psClassInstance->ui16Sampler = *pui16Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassInstance->Name); - - return pui16Tokens; -} - - -static void ReadInterfaces(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) -{ - uint32_t i; - uint32_t ui32StartSlot; - const uint32_t* pui32FirstInterfaceToken = pui32Tokens; - const uint32_t ui32ClassInstanceCount = *pui32Tokens++; - const uint32_t ui32ClassTypeCount = *pui32Tokens++; - const uint32_t ui32InterfaceSlotRecordCount = *pui32Tokens++; - /* const uint32_t ui32InterfaceSlotCount = */ *pui32Tokens++; - const uint32_t ui32ClassInstanceOffset = *pui32Tokens++; - const uint32_t ui32ClassTypeOffset = *pui32Tokens++; - const uint32_t ui32InterfaceSlotOffset = *pui32Tokens++; - - const uint16_t* pui16ClassTypes = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassTypeOffset); - const uint16_t* pui16ClassInstances = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassInstanceOffset); - const uint32_t* pui32InterfaceSlots = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32InterfaceSlotOffset); - - const uint32_t* pui32InterfaceSlotTokens = pui32InterfaceSlots; - - ClassType* psClassTypes; - ClassInstance* psClassInstances; - - psClassTypes = hlslcc_malloc(sizeof(ClassType) * ui32ClassTypeCount); - for(i=0; i<ui32ClassTypeCount; ++i) - { - pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes+i); - psClassTypes[i].ui16ID = (uint16_t)i; - } - - psClassInstances = hlslcc_malloc(sizeof(ClassInstance) * ui32ClassInstanceCount); - for(i=0; i<ui32ClassInstanceCount; ++i) - { - pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances+i); - } - - //Slots map function table to $ThisPointer cbuffer variable index - ui32StartSlot = 0; - for(i=0; i<ui32InterfaceSlotRecordCount;++i) - { - uint32_t k; - - const uint32_t ui32SlotSpan = *pui32InterfaceSlotTokens++; - const uint32_t ui32Count = *pui32InterfaceSlotTokens++; - const uint32_t ui32TypeIDOffset = *pui32InterfaceSlotTokens++; - const uint32_t ui32TableIDOffset = *pui32InterfaceSlotTokens++; - - const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken+ui32TypeIDOffset); - const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32TableIDOffset); - - for(k=0; k < ui32Count; ++k) - { - psShaderInfo->aui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++; - } - - ui32StartSlot += ui32SlotSpan; - } - - psShaderInfo->ui32NumClassInstances = ui32ClassInstanceCount; - psShaderInfo->psClassInstances = psClassInstances; - - psShaderInfo->ui32NumClassTypes = ui32ClassTypeCount; - psShaderInfo->psClassTypes = psClassTypes; -} - -void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf) -{ - if(psShaderInfo->ui32MajorVersion > 3) - { - *ppsConstBuf = psShaderInfo->psConstantBuffers + psShaderInfo->aui32ResourceMap[eGroup][ui32BindPoint]; - } - else - { - ASSERT(psShaderInfo->ui32NumConstantBuffers == 1); - *ppsConstBuf = psShaderInfo->psConstantBuffers; - } -} - -int GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding) -{ - uint32_t i; - const uint32_t ui32NumBindings = psShaderInfo->ui32NumResourceBindings; - ResourceBinding* psBindings = psShaderInfo->psResourceBindings; - - for(i=0; i<ui32NumBindings; ++i) - { - if(ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup) - { - if(ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount)) - { - *ppsOutBinding = psBindings + i; - return 1; - } - } - } - return 0; -} - -int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar) -{ - uint32_t i; - ConstantBuffer* psThisPointerConstBuffer = psShaderInfo->psThisPointerConstBuffer; - - const uint32_t ui32NumVars = psThisPointerConstBuffer->ui32NumVars; - - for(i=0; i<ui32NumVars; ++i) - { - if(ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset && - ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size)) - { - *ppsShaderVar = &psThisPointerConstBuffer->asVars[i]; - return 1; - } - } - return 0; -} - -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) -{ - uint32_t i; - const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; - - for(i=0; i<ui32NumVars; ++i) - { - InOutSignature* psInputSignatures = psShaderInfo->psInputSignatures; - if(ui32Register == psInputSignatures[i].ui32Register) - { - *ppsOut = psInputSignatures+i; - return 1; - } - } - return 0; -} - -int GetOutputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const uint32_t ui32Stream, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) -{ - uint32_t i; - const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; - - for(i=0; i<ui32NumVars; ++i) - { - InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; - if(ui32Register == psOutputSignatures[i].ui32Register && - (ui32CompMask & psOutputSignatures[i].ui32Mask) && - ui32Stream == psOutputSignatures[i].ui32Stream) - { - *ppsOut = psOutputSignatures+i; - return 1; - } - } - return 0; -} - -int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) -{ - uint32_t i; - const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; - - for(i=0; i<ui32NumVars; ++i) - { - InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; - if(eSystemValueType == psOutputSignatures[i].eSystemValueType && - ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex) - { - *ppsOut = psOutputSignatures+i; - return 1; - } - } - return 0; -} - -static int IsOffsetInType(ShaderVarType* psType, uint32_t parentOffset, uint32_t offsetToFind, const uint32_t* pui32Swizzle, int32_t* pi32Index, int32_t* pi32Rebase) -{ - uint32_t thisOffset = parentOffset + psType->Offset; - uint32_t thisSize = psType->Columns * psType->Rows * 4; - - if(psType->Elements) - { - thisSize += 16 * (psType->Elements - 1); - } - - //Swizzle can point to another variable. In the example below - //cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined - //into vectors. psCBuf->ui32NumVars will be 3. - - // cbuffer cbUIUpdates - // { - // - // float g_fLifeSpan; // Offset: 0 Size: 4 - // float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused] - // float g_fRadiusMin; // Offset: 8 Size: 4 [unused] - // float g_fRadiusMax; // Offset: 12 Size: 4 [unused] - // float g_fGrowTime; // Offset: 16 Size: 4 [unused] - // float g_fStepSize; // Offset: 20 Size: 4 - // float g_fTurnRate; // Offset: 24 Size: 4 - // float g_fTurnSpeed; // Offset: 28 Size: 4 [unused] - // float g_fLeafRate; // Offset: 32 Size: 4 - // float g_fShrinkTime; // Offset: 36 Size: 4 [unused] - // uint g_uMaxFaces; // Offset: 40 Size: 4 - // - // } - - // Name Type Format Dim Slot Elements - // ------------------------------ ---------- ------- ----------- ---- -------- - // cbUIUpdates cbuffer NA NA 1 1 - - if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - offsetToFind += 4; - } - else - if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - offsetToFind += 8; - } - else - if(pui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - offsetToFind += 12; - } - - if((offsetToFind >= thisOffset) && - offsetToFind < (thisOffset + thisSize)) - { - - if(psType->Class == SVC_MATRIX_ROWS || - psType->Class == SVC_MATRIX_COLUMNS) - { - //Matrices are treated as arrays of vectors. - pi32Index[0] = (offsetToFind - thisOffset) / 16; - } - //Check for array of vectors - else if(psType->Class == SVC_VECTOR && psType->Elements > 1) - { - pi32Index[0] = (offsetToFind - thisOffset) / 16; - } - else if(psType->Class == SVC_VECTOR && psType->Columns > 1) - { - //Check for vector starting at a non-vec4 offset. - - // cbuffer $Globals - // { - // - // float angle; // Offset: 0 Size: 4 - // float2 angle2; // Offset: 4 Size: 8 - // - // } - - //cb0[0].x = angle - //cb0[0].yzyy = angle2.xyxx - - //Rebase angle2 so that .y maps to .x, .z maps to .y - - pi32Rebase[0] = thisOffset % 16; - } - - return 1; - } - return 0; -} - -int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, const uint32_t* pui32Swizzle, ConstantBuffer* psCBuf, ShaderVarType** ppsShaderVar, int32_t* pi32Index, int32_t* pi32Rebase) -{ - uint32_t i; - - uint32_t ui32ByteOffset = ui32Vec4Offset * 16; - - const uint32_t ui32NumVars = psCBuf->ui32NumVars; - - for(i=0; i<ui32NumVars; ++i) - { - if(psCBuf->asVars[i].sType.Class == SVC_STRUCT) - { - uint32_t m = 0; - - for(m=0; m < psCBuf->asVars[i].sType.MemberCount; ++m) - { - ShaderVarType* psMember = psCBuf->asVars[i].sType.Members + m; - - ASSERT(psMember->Class != SVC_STRUCT); - - if(IsOffsetInType(psMember, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) - { - ppsShaderVar[0] = psMember; - return 1; - } - } - } - else - { - if(IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) - { - ppsShaderVar[0] = &psCBuf->asVars[i].sType; - return 1; - } - } - } - return 0; -} - -ResourceGroup ResourceTypeToResourceGroup(ResourceType eType) -{ - switch(eType) - { - case RTYPE_CBUFFER: - return RGROUP_CBUFFER; - - case RTYPE_SAMPLER: - return RGROUP_SAMPLER; - - case RTYPE_TEXTURE: - case RTYPE_BYTEADDRESS: - case RTYPE_STRUCTURED: - return RGROUP_TEXTURE; - - case RTYPE_UAV_RWTYPED: - case RTYPE_UAV_RWSTRUCTURED: - case RTYPE_UAV_RWBYTEADDRESS: - case RTYPE_UAV_APPEND_STRUCTURED: - case RTYPE_UAV_CONSUME_STRUCTURED: - case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: - return RGROUP_UAV; - - case RTYPE_TBUFFER: - ASSERT(0); // Need to find out which group this belongs to - return RGROUP_TEXTURE; - } - - ASSERT(0); - return RGROUP_CBUFFER; -} - -void LoadShaderInfo(const uint32_t ui32MajorVersion, const uint32_t ui32MinorVersion, const ReflectionChunks* psChunks, ShaderInfo* psInfo) -{ - uint32_t i; - const uint32_t* pui32Inputs = psChunks->pui32Inputs; - const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11; - const uint32_t* pui32Resources = psChunks->pui32Resources; - const uint32_t* pui32Interfaces = psChunks->pui32Interfaces; - const uint32_t* pui32Outputs = psChunks->pui32Outputs; - const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11; - const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams; - - psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED; - psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED; - for(i=0; i<MAX_SHADER_VEC4_INPUT;++i) - psInfo->aePixelInputInterpolation[i] = INTERPOLATION_LINEAR; - - psInfo->ui32MajorVersion = ui32MajorVersion; - psInfo->ui32MinorVersion = ui32MinorVersion; - - psInfo->ui32NumImports = 0; - psInfo->ui32NumExports = 0; - psInfo->psImports = 0; - psInfo->psExports = 0; - psInfo->ui32InputHash = 0; - psInfo->ui32SymbolsOffset = 0; - psInfo->ui32NumSamplers = 0; - - if(pui32Inputs) - ReadInputSignatures(pui32Inputs, psInfo, 0); - if(pui32Inputs11) - ReadInputSignatures(pui32Inputs11, psInfo, 1); - if(pui32Resources) - ReadResources(pui32Resources, psInfo); - if(pui32Interfaces) - ReadInterfaces(pui32Interfaces, psInfo); - if(pui32Outputs) - ReadOutputSignatures(pui32Outputs, psInfo, 0, 0); - if(pui32Outputs11) - ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1); - if(pui32OutputsWithStreams) - ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1); - - for(i=0; i<psInfo->ui32NumConstantBuffers;++i) - { - bstring cbufName = bfromcstr(&psInfo->psConstantBuffers[i].Name[0]); - bstring cbufThisPointer = bfromcstr("$ThisPointer"); - if(bstrcmp(cbufName, cbufThisPointer) == 0) - { - psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i]; - } - bdestroy(cbufName); - bdestroy(cbufThisPointer); - } - - memset(psInfo->asSamplers, 0, sizeof(psInfo->asSamplers)); -} - -void FreeShaderInfo(ShaderInfo* psShaderInfo) -{ - uint32_t uStep; - //Free any default values for constants. - uint32_t cbuf; - for(cbuf=0; cbuf<psShaderInfo->ui32NumConstantBuffers; ++cbuf) - { - ConstantBuffer* psCBuf = &psShaderInfo->psConstantBuffers[cbuf]; - uint32_t var; - for(var=0; var < psCBuf->ui32NumVars; ++var) - { - ShaderVar* psVar = &psCBuf->asVars[var]; - hlslcc_free(psVar->sType.Members); - if(psVar->haveDefaultValue) - { - hlslcc_free(psVar->pui32DefaultValues); - } - } - } - hlslcc_free(psShaderInfo->psInputSignatures); - hlslcc_free(psShaderInfo->psResourceBindings); - hlslcc_free(psShaderInfo->psConstantBuffers); - hlslcc_free(psShaderInfo->psClassTypes); - hlslcc_free(psShaderInfo->psClassInstances); - hlslcc_free(psShaderInfo->psOutputSignatures); - hlslcc_free(psShaderInfo->psImports); - hlslcc_free(psShaderInfo->psExports); - - for (uStep = 0; uStep < psShaderInfo->ui32NumTraceSteps; ++uStep) - { - hlslcc_free(psShaderInfo->psTraceSteps[uStep].psVariables); - } - hlslcc_free(psShaderInfo->psTraceSteps); - - psShaderInfo->ui32NumInputSignatures = 0; - psShaderInfo->ui32NumResourceBindings = 0; - psShaderInfo->ui32NumConstantBuffers = 0; - psShaderInfo->ui32NumClassTypes = 0; - psShaderInfo->ui32NumClassInstances = 0; - psShaderInfo->ui32NumOutputSignatures = 0; - psShaderInfo->ui32NumTraceSteps = 0; - psShaderInfo->ui32NumImports = 0; - psShaderInfo->ui32NumExports = 0; -} - -typedef struct ConstantTableD3D9_TAG -{ - uint32_t size; - uint32_t creator; - uint32_t version; - uint32_t constants; - uint32_t constantInfos; - uint32_t flags; - uint32_t target; -} ConstantTableD3D9; - -// These enums match those in d3dx9shader.h. -enum RegisterSet -{ - RS_BOOL, - RS_INT4, - RS_FLOAT4, - RS_SAMPLER, -}; - -enum TypeClass -{ - CLASS_SCALAR, - CLASS_VECTOR, - CLASS_MATRIX_ROWS, - CLASS_MATRIX_COLUMNS, - CLASS_OBJECT, - CLASS_STRUCT, -}; - -enum Type -{ - PT_VOID, - PT_BOOL, - PT_INT, - PT_FLOAT, - PT_STRING, - PT_TEXTURE, - PT_TEXTURE1D, - PT_TEXTURE2D, - PT_TEXTURE3D, - PT_TEXTURECUBE, - PT_SAMPLER, - PT_SAMPLER1D, - PT_SAMPLER2D, - PT_SAMPLER3D, - PT_SAMPLERCUBE, - PT_PIXELSHADER, - PT_VERTEXSHADER, - PT_PIXELFRAGMENT, - PT_VERTEXFRAGMENT, - PT_UNSUPPORTED, -}; -typedef struct ConstantInfoD3D9_TAG -{ - uint32_t name; - uint16_t registerSet; - uint16_t registerIndex; - uint16_t registerCount; - uint16_t reserved; - uint32_t typeInfo; - uint32_t defaultValue; -} ConstantInfoD3D9; - -typedef struct TypeInfoD3D9_TAG -{ - uint16_t typeClass; - uint16_t type; - uint16_t rows; - uint16_t columns; - uint16_t elements; - uint16_t structMembers; - uint32_t structMemberInfos; -} TypeInfoD3D9; - -typedef struct StructMemberInfoD3D9_TAG -{ - uint32_t name; - uint32_t typeInfo; -} StructMemberInfoD3D9; - -void LoadD3D9ConstantTable(const char* data, ShaderInfo* psInfo) -{ - ConstantTableD3D9* ctab; - uint32_t constNum; - ConstantInfoD3D9* cinfos; - ConstantBuffer* psConstantBuffer; - uint32_t ui32ConstantBufferSize = 0; - uint32_t numResourceBindingsNeeded = 0; - ShaderVar* var; - - ctab = (ConstantTableD3D9*)data; - - cinfos = (ConstantInfoD3D9*)(data + ctab->constantInfos); - - psInfo->ui32NumConstantBuffers++; - - //Only 1 Constant Table in d3d9 - ASSERT(psInfo->ui32NumConstantBuffers == 1); - - psConstantBuffer = hlslcc_malloc(sizeof(ConstantBuffer)); - - psInfo->psConstantBuffers = psConstantBuffer; - - psConstantBuffer->ui32NumVars = 0; - strcpy(psConstantBuffer->Name, "$Globals"); - - //Determine how many resource bindings to create - for (constNum = 0; constNum < ctab->constants; ++constNum) - { - if (cinfos[constNum].registerSet == RS_SAMPLER) - { - ++numResourceBindingsNeeded; - } - } - - psInfo->psResourceBindings = hlslcc_malloc(numResourceBindingsNeeded * sizeof(ResourceBinding)); - - var = &psConstantBuffer->asVars[0]; - - for (constNum = 0; constNum < ctab->constants; ++constNum) - { - TypeInfoD3D9* typeInfo = (TypeInfoD3D9*)(data + cinfos[constNum].typeInfo); - - if (cinfos[constNum].registerSet != RS_SAMPLER) - { - strcpy(var->Name, data + cinfos[constNum].name); - FormatVariableName(var->Name); - var->ui32Size = cinfos[constNum].registerCount * 16; - var->ui32StartOffset = cinfos[constNum].registerIndex * 16; - var->haveDefaultValue = 0; - - if (ui32ConstantBufferSize < (var->ui32Size + var->ui32StartOffset)) - { - ui32ConstantBufferSize = var->ui32Size + var->ui32StartOffset; - } - - var->sType.Rows = typeInfo->rows; - var->sType.Columns = typeInfo->columns; - var->sType.Elements = typeInfo->elements; - var->sType.MemberCount = typeInfo->structMembers; - var->sType.Members = 0; - var->sType.Offset = 0; - var->sType.Parent = 0; - var->sType.ParentCount = 0; - - switch (typeInfo->typeClass) - { - case CLASS_SCALAR: - { - var->sType.Class = SVC_SCALAR; - break; - } - case CLASS_VECTOR: - { - var->sType.Class = SVC_VECTOR; - break; - } - case CLASS_MATRIX_ROWS: - { - var->sType.Class = SVC_MATRIX_ROWS; - break; - } - case CLASS_MATRIX_COLUMNS: - { - var->sType.Class = SVC_MATRIX_COLUMNS; - break; - } - case CLASS_OBJECT: - { - var->sType.Class = SVC_OBJECT; - break; - } - case CLASS_STRUCT: - { - var->sType.Class = SVC_STRUCT; - break; - } - } - - switch (cinfos[constNum].registerSet) - { - case RS_BOOL: - { - var->sType.Type = SVT_BOOL; - break; - } - case RS_INT4: - { - var->sType.Type = SVT_INT; - break; - } - case RS_FLOAT4: - { - var->sType.Type = SVT_FLOAT; - break; - } - } - - var++; - psConstantBuffer->ui32NumVars++; - } - else - { - //Create a resource if it is sampler in order to replicate the d3d10+ - //method of separating samplers from general constants. - uint32_t ui32ResourceIndex = psInfo->ui32NumResourceBindings++; - ResourceBinding* res = &psInfo->psResourceBindings[ui32ResourceIndex]; - - strcpy(res->Name, data + cinfos[constNum].name); - FormatVariableName(res->Name); - - res->ui32BindPoint = cinfos[constNum].registerIndex; - res->ui32BindCount = cinfos[constNum].registerCount; - res->ui32Flags = 0; - res->ui32NumSamples = 1; - res->ui32ReturnType = 0; - - res->eType = RTYPE_TEXTURE; - - switch (typeInfo->type) - { - case PT_SAMPLER: - case PT_SAMPLER1D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE1D; - break; - case PT_SAMPLER2D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; - break; - case PT_SAMPLER3D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; - break; - case PT_SAMPLERCUBE: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURECUBE; - break; - } - } - } - psConstantBuffer->ui32TotalSizeInBytes = ui32ConstantBufferSize; -} diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSL.c b/Code/Tools/HLSLCrossCompiler/src/toGLSL.c deleted file mode 100644 index ff1546b703..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/toGLSL.c +++ /dev/null @@ -1,1921 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/tokens.h" -#include "internal_includes/structs.h" -#include "internal_includes/decode.h" -#include "stdlib.h" -#include "stdio.h" -#include "bstrlib.h" -#include "internal_includes/toGLSLInstruction.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/toGLSLDeclaration.h" -#include "internal_includes/languages.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/hlslccToolkit.h" -#include "../offline/hash.h" - -#if defined(_WIN32) && !defined(PORTABLE) -#include <AzCore/PlatformDef.h> -AZ_PUSH_DISABLE_WARNING(4115, "-Wunknown-warning-option") // 4115: named type definition in parentheses -#include <d3dcompiler.h> -AZ_POP_DISABLE_WARNING -#pragma comment(lib,"d3dcompiler.lib") -#endif //defined(_WIN32) && !defined(PORTABLE) - -#ifndef GL_VERTEX_SHADER_ARB -#define GL_VERTEX_SHADER_ARB 0x8B31 -#endif -#ifndef GL_FRAGMENT_SHADER_ARB -#define GL_FRAGMENT_SHADER_ARB 0x8B30 -#endif -#ifndef GL_GEOMETRY_SHADER -#define GL_GEOMETRY_SHADER 0x8DD9 -#endif -#ifndef GL_TESS_EVALUATION_SHADER -#define GL_TESS_EVALUATION_SHADER 0x8E87 -#endif -#ifndef GL_TESS_CONTROL_SHADER -#define GL_TESS_CONTROL_SHADER 0x8E88 -#endif -#ifndef GL_COMPUTE_SHADER -#define GL_COMPUTE_SHADER 0x91B9 -#endif - - -HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), void* (*calloc_override)(size_t, size_t), void (* free_override)(void*), void* (*realloc_override)(void*, size_t)) -{ - hlslcc_malloc = malloc_override; - hlslcc_calloc = calloc_override; - hlslcc_free = free_override; - hlslcc_realloc = realloc_override; -} - -void AddIndentation(HLSLCrossCompilerContext* psContext) -{ - int i; - int indent = psContext->indent; - bstring glsl = *psContext->currentGLSLString; - for (i = 0; i < indent; ++i) - { - bcatcstr(glsl, " "); - } -} - -uint32_t AddImport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Default) -{ - bstring glsl = *psContext->currentGLSLString; - uint32_t ui32Symbol = psContext->psShader->sInfo.ui32NumImports; - - psContext->psShader->sInfo.psImports = (Symbol*)hlslcc_realloc(psContext->psShader->sInfo.psImports, (ui32Symbol + 1) * sizeof(Symbol)); - ++psContext->psShader->sInfo.ui32NumImports; - - bformata(glsl, "#ifndef IMPORT_%d\n", ui32Symbol); - bformata(glsl, "#define IMPORT_%d %d\n", ui32Symbol, ui32Default); - bformata(glsl, "#endif\n", ui32Symbol); - - psContext->psShader->sInfo.psImports[ui32Symbol].eType = eType; - psContext->psShader->sInfo.psImports[ui32Symbol].ui32ID = ui32ID; - psContext->psShader->sInfo.psImports[ui32Symbol].ui32Value = ui32Default; - - return ui32Symbol; -} - -uint32_t AddExport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Value) -{ - uint32_t ui32Param = psContext->psShader->sInfo.ui32NumExports; - - psContext->psShader->sInfo.psExports = (Symbol*)hlslcc_realloc(psContext->psShader->sInfo.psExports, (ui32Param + 1) * sizeof(Symbol)); - ++psContext->psShader->sInfo.ui32NumExports; - - psContext->psShader->sInfo.psExports[ui32Param].eType = eType; - psContext->psShader->sInfo.psExports[ui32Param].ui32ID = ui32ID; - psContext->psShader->sInfo.psExports[ui32Param].ui32Value = ui32Value; - - return ui32Param; -} - -void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) -{ - bstring glsl = *psContext->currentGLSLString; - uint32_t ui32DepthClampImp; - - if (!HaveCompute(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->eShaderType == COMPUTE_SHADER) - { - bcatcstr(glsl, "#extension GL_ARB_compute_shader : enable\n"); - bcatcstr(glsl, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); - } - } - - if (!HaveAtomicMem(psContext->psShader->eTargetLanguage) || - !HaveAtomicCounter(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_ALLOC] || - psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_CONSUME] || - psContext->psShader->aiOpcodeUsed[OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED]) - { - bcatcstr(glsl, "#extension GL_ARB_shader_atomic_counters : enable\n"); - - bcatcstr(glsl, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); - } - } - - if (!HaveGather(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_C]) - { - bcatcstr(glsl, "#extension GL_ARB_texture_gather : enable\n"); - } - } - - if (!HaveGatherNonConstOffset(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO]) - { - bcatcstr(glsl, "#extension GL_ARB_gpu_shader5 : enable\n"); - } - } - - if (!HaveQueryLod(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_LOD]) - { - bcatcstr(glsl, "#extension GL_ARB_texture_query_lod : enable\n"); - } - } - - if (!HaveQueryLevels(psContext->psShader->eTargetLanguage)) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_RESINFO]) - { - bcatcstr(glsl, "#extension GL_ARB_texture_query_levels : enable\n"); - } - } - - if (!HaveImageLoadStore(psContext->psShader->eTargetLanguage) && (psContext->flags & HLSLCC_FLAG_AVOID_SHADER_LOAD_STORE_EXTENSION) == 0) - { - if (psContext->psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] || - psContext->psShader->aiOpcodeUsed[OPCODE_STORE_RAW] || - psContext->psShader->aiOpcodeUsed[OPCODE_STORE_STRUCTURED]) - { - bcatcstr(glsl, "#extension GL_ARB_shader_image_load_store : enable\n"); - bcatcstr(glsl, "#extension GL_ARB_shader_bit_encoding : enable\n"); - } - else - if (psContext->psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] || - psContext->psShader->aiOpcodeUsed[OPCODE_LD_RAW] || - psContext->psShader->aiOpcodeUsed[OPCODE_LD_STRUCTURED]) - { - bcatcstr(glsl, "#extension GL_ARB_shader_image_load_store : enable\n"); - } - } - - - // #extension directive must occur before any non-preprocessor token - if (EmulateDepthClamp(psContext->psShader->eTargetLanguage) && (psContext->psShader->eShaderType == VERTEX_SHADER || psContext->psShader->eShaderType == PIXEL_SHADER)) - { - ui32DepthClampImp = AddImport(psContext, SYMBOL_EMULATE_DEPTH_CLAMP, 0, 0); - - bformata(glsl, "#if IMPORT_%d > 0\n", ui32DepthClampImp); - if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#ifdef GL_NV_shader_noperspective_interpolation\n"); - bcatcstr(glsl, "#extension GL_NV_shader_noperspective_interpolation:enable\n"); - bformata(glsl, "#endif\n"); - } - bformata(glsl, "#endif\n"); - } - - if (psContext->psShader->ui32MajorVersion <= 3) - { - bcatcstr(glsl, "int RepCounter;\n"); - bcatcstr(glsl, "int LoopCounter;\n"); - bcatcstr(glsl, "int ZeroBasedCounter;\n"); - if (psContext->psShader->eShaderType == VERTEX_SHADER) - { - uint32_t texCoord; - bcatcstr(glsl, "ivec4 Address;\n"); - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "out vec4 OffsetColour;\n"); - bcatcstr(glsl, "out vec4 BaseColour;\n"); - - bcatcstr(glsl, "out vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "out vec4 TexCoord%d;\n", texCoord); - } - } - else - { - bcatcstr(glsl, "varying vec4 OffsetColour;\n"); - bcatcstr(glsl, "varying vec4 BaseColour;\n"); - - bcatcstr(glsl, "varying vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); - } - } - } - else - { - uint32_t renderTargets, texCoord; - - bcatcstr(glsl, "varying vec4 OffsetColour;\n"); - bcatcstr(glsl, "varying vec4 BaseColour;\n"); - - bcatcstr(glsl, "varying vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); - } - - for (renderTargets = 0; renderTargets < 8; ++renderTargets) - { - bformata(glsl, "#define Output%d gl_FragData[%d]\n", renderTargets, renderTargets); - } - } - } - - - if ((psContext->flags & HLSLCC_FLAG_ORIGIN_UPPER_LEFT) - && (psContext->psShader->eTargetLanguage >= LANG_150) - && (psContext->psShader->eShaderType == PIXEL_SHADER)) - { - bcatcstr(glsl, "layout(origin_upper_left) in vec4 gl_FragCoord;\n"); - } - - if ((psContext->flags & HLSLCC_FLAG_PIXEL_CENTER_INTEGER) - && (psContext->psShader->eTargetLanguage >= LANG_150)) - { - bcatcstr(glsl, "layout(pixel_center_integer) in vec4 gl_FragCoord;\n"); - } - - /* For versions which do not support a vec1 (currently all versions) */ - bcatcstr(glsl, "struct vec1 {\n"); - if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310 || psContext->psShader->eTargetLanguage == LANG_ES_100) - { - bcatcstr(glsl, "\thighp float x;\n"); - } - else - { - bcatcstr(glsl, "\tfloat x;\n"); - } - bcatcstr(glsl, "};\n"); - - if (HaveUVec(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "struct uvec1 {\n"); - bcatcstr(glsl, "\tuint x;\n"); - bcatcstr(glsl, "};\n"); - } - - bcatcstr(glsl, "struct ivec1 {\n"); - bcatcstr(glsl, "\tint x;\n"); - bcatcstr(glsl, "};\n"); - - /* - OpenGL 4.1 API spec: - To use any built-in input or output in the gl_PerVertex block in separable - program objects, shader code must redeclare that block prior to use. - */ - if (psContext->psShader->eShaderType == VERTEX_SHADER && psContext->psShader->eTargetLanguage >= LANG_410) - { - bcatcstr(glsl, "out gl_PerVertex {\n"); - bcatcstr(glsl, "vec4 gl_Position;\n"); - bcatcstr(glsl, "float gl_PointSize;\n"); - bcatcstr(glsl, "float gl_ClipDistance[];"); - bcatcstr(glsl, "};\n"); - } - - //The fragment language has no default precision qualifier for floating point types. - if (psContext->psShader->eShaderType == PIXEL_SHADER && - psContext->psShader->eTargetLanguage == LANG_ES_100 || psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision highp float;\n"); - } - - /* There is no default precision qualifier for the following sampler types in either the vertex or fragment language: */ - if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision lowp sampler3D;\n"); - bcatcstr(glsl, "precision lowp samplerCubeShadow;\n"); - bcatcstr(glsl, "precision lowp sampler2DShadow;\n"); - bcatcstr(glsl, "precision lowp sampler2DArray;\n"); - bcatcstr(glsl, "precision lowp sampler2DArrayShadow;\n"); - bcatcstr(glsl, "precision lowp isampler2D;\n"); - bcatcstr(glsl, "precision lowp isampler3D;\n"); - bcatcstr(glsl, "precision lowp isamplerCube;\n"); - bcatcstr(glsl, "precision lowp isampler2DArray;\n"); - bcatcstr(glsl, "precision lowp usampler2D;\n"); - bcatcstr(glsl, "precision lowp usampler3D;\n"); - bcatcstr(glsl, "precision lowp usamplerCube;\n"); - bcatcstr(glsl, "precision lowp usampler2DArray;\n"); - - if (psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision lowp isampler2DMS;\n"); - bcatcstr(glsl, "precision lowp usampler2D;\n"); - bcatcstr(glsl, "precision lowp usampler3D;\n"); - bcatcstr(glsl, "precision lowp usamplerCube;\n"); - bcatcstr(glsl, "precision lowp usampler2DArray;\n"); - bcatcstr(glsl, "precision lowp usampler2DMS;\n"); - bcatcstr(glsl, "precision lowp image2D;\n"); - bcatcstr(glsl, "precision lowp image3D;\n"); - bcatcstr(glsl, "precision lowp imageCube;\n"); - bcatcstr(glsl, "precision lowp image2DArray;\n"); - bcatcstr(glsl, "precision lowp iimage2D;\n"); - bcatcstr(glsl, "precision lowp iimage3D;\n"); - bcatcstr(glsl, "precision lowp iimageCube;\n"); - bcatcstr(glsl, "precision lowp uimage2DArray;\n"); - //Only highp is valid for atomic_uint - bcatcstr(glsl, "precision highp atomic_uint;\n"); - } - } - - if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "subroutine void SubroutineType();\n"); - } - - if (EmulateDepthClamp(psContext->psShader->eTargetLanguage) && (psContext->psShader->eShaderType == VERTEX_SHADER || psContext->psShader->eShaderType == PIXEL_SHADER)) - { - char* szInOut = psContext->psShader->eShaderType == VERTEX_SHADER ? "out" : "in"; - - bformata(glsl, "#if IMPORT_%d > 0\n", ui32DepthClampImp); - if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#ifdef GL_NV_shader_noperspective_interpolation\n"); - } - bcatcstr(glsl, "#define EMULATE_DEPTH_CLAMP 1\n"); - bformata(glsl, "noperspective %s float unclampedDepth;\n", szInOut); - if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#else\n"); - bcatcstr(glsl, "#define EMULATE_DEPTH_CLAMP 2\n"); - bformata(glsl, "%s float unclampedZ;\n", szInOut); - bformata(glsl, "#endif\n"); - } - bformata(glsl, "#endif\n"); - - if (psContext->psShader->eShaderType == PIXEL_SHADER) - { - bcatcstr(psContext->earlyMain, "#ifdef EMULATE_DEPTH_CLAMP\n"); - bcatcstr(psContext->earlyMain, "#if EMULATE_DEPTH_CLAMP == 2\n"); - bcatcstr(psContext->earlyMain, "\tfloat unclampedDepth = gl_DepthRange.near + unclampedZ * gl_FragCoord.w;\n"); - bcatcstr(psContext->earlyMain, "#endif\n"); - bcatcstr(psContext->earlyMain, "\tgl_FragDepth = clamp(unclampedDepth, 0.0, 1.0);\n"); - bcatcstr(psContext->earlyMain, "#endif\n"); - } - } -} - -FRAMEBUFFER_FETCH_TYPE CollectGmemInfo(HLSLCrossCompilerContext* psContext) -{ - FRAMEBUFFER_FETCH_TYPE fetchType = FBF_NONE; - Shader* psShader = psContext->psShader; - memset(psContext->rendertargetUse, 0x00, sizeof(psContext->rendertargetUse)); - for (uint32_t i = 0; i < psShader->ui32DeclCount; ++i) - { - Declaration* decl = psShader->psDecl + i; - if (decl->eOpcode == OPCODE_DCL_RESOURCE) - { - if (IsGmemReservedSlot(FBF_EXT_COLOR, decl->asOperands[0].ui32RegisterNumber)) - { - int regNum = GetGmemInputResourceSlot(decl->asOperands[0].ui32RegisterNumber); - ASSERT(regNum < MAX_COLOR_MRT); - psContext->rendertargetUse[regNum] |= INPUT_RENDERTARGET; - fetchType |= FBF_EXT_COLOR; - } - else if (IsGmemReservedSlot(FBF_ARM_COLOR, decl->asOperands[0].ui32RegisterNumber)) - { - fetchType |= FBF_ARM_COLOR; - } - else if (IsGmemReservedSlot(FBF_ARM_DEPTH, decl->asOperands[0].ui32RegisterNumber)) - { - fetchType |= FBF_ARM_DEPTH; - } - else if (IsGmemReservedSlot(FBF_ARM_STENCIL, decl->asOperands[0].ui32RegisterNumber)) - { - fetchType |= FBF_ARM_STENCIL; - } - } - else if (decl->eOpcode == OPCODE_DCL_OUTPUT && psShader->eShaderType == PIXEL_SHADER && decl->asOperands[0].eType != OPERAND_TYPE_OUTPUT_DEPTH) - { - ASSERT(decl->asOperands[0].ui32RegisterNumber < MAX_COLOR_MRT); - psContext->rendertargetUse[decl->asOperands[0].ui32RegisterNumber] |= OUTPUT_RENDERTARGET; - } - } - - return fetchType; -} - -uint16_t GetOpcodeWriteMask(OPCODE_TYPE eOpcode) -{ - switch (eOpcode) - { - default: - ASSERT(0); - - // No writes - case OPCODE_ENDREP: - case OPCODE_REP: - case OPCODE_BREAK: - case OPCODE_BREAKC: - case OPCODE_CALL: - case OPCODE_CALLC: - case OPCODE_CASE: - case OPCODE_CONTINUE: - case OPCODE_CONTINUEC: - case OPCODE_CUT: - case OPCODE_DISCARD: - case OPCODE_ELSE: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_ENDIF: - case OPCODE_ENDLOOP: - case OPCODE_ENDSWITCH: - case OPCODE_IF: - case OPCODE_LABEL: - case OPCODE_LOOP: - case OPCODE_NOP: - case OPCODE_RET: - case OPCODE_RETC: - case OPCODE_SWITCH: - case OPCODE_HS_DECLS: - case OPCODE_HS_CONTROL_POINT_PHASE: - case OPCODE_HS_FORK_PHASE: - case OPCODE_HS_JOIN_PHASE: - case OPCODE_EMIT_STREAM: - case OPCODE_CUT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - case OPCODE_INTERFACE_CALL: - case OPCODE_STORE_UAV_TYPED: - case OPCODE_STORE_RAW: - case OPCODE_STORE_STRUCTURED: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_UMIN: - case OPCODE_SYNC: - case OPCODE_ABORT: - case OPCODE_DEBUG_BREAK: - return 0; - - // Write to 0 - case OPCODE_POW: - case OPCODE_DP2ADD: - case OPCODE_LRP: - case OPCODE_ADD: - case OPCODE_AND: - case OPCODE_DERIV_RTX: - case OPCODE_DERIV_RTY: - case OPCODE_DEFAULT: - case OPCODE_DIV: - case OPCODE_DP2: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_EXP: - case OPCODE_FRC: - case OPCODE_ITOF: - case OPCODE_LOG: - case OPCODE_LT: - case OPCODE_MAD: - case OPCODE_MIN: - case OPCODE_MAX: - case OPCODE_MUL: - case OPCODE_ROUND_NE: - case OPCODE_ROUND_NI: - case OPCODE_ROUND_PI: - case OPCODE_ROUND_Z: - case OPCODE_RSQ: - case OPCODE_SQRT: - case OPCODE_UTOF: - case OPCODE_SAMPLE_POS: - case OPCODE_SAMPLE_INFO: - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_RCP: - case OPCODE_F32TOF16: - case OPCODE_F16TOF32: - case OPCODE_DTOF: - case OPCODE_EQ: - case OPCODE_FTOU: - case OPCODE_GE: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_NE: - case OPCODE_NOT: - case OPCODE_OR: - case OPCODE_ULT: - case OPCODE_UGE: - case OPCODE_UMAD: - case OPCODE_XOR: - case OPCODE_UMAX: - case OPCODE_UMIN: - case OPCODE_USHR: - case OPCODE_COUNTBITS: - case OPCODE_FIRSTBIT_HI: - case OPCODE_FIRSTBIT_LO: - case OPCODE_FIRSTBIT_SHI: - case OPCODE_UBFE: - case OPCODE_BFI: - case OPCODE_BFREV: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_MSAD: - case OPCODE_DTOU: - case OPCODE_FTOI: - case OPCODE_IADD: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_BUFINFO: - case OPCODE_IBFE: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_DTOI: - case OPCODE_DADD: - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_FTOD: - case OPCODE_DDIV: - case OPCODE_DFMA: - case OPCODE_DRCP: - case OPCODE_ITOD: - case OPCODE_UTOD: - case OPCODE_LD: - case OPCODE_LD_MS: - case OPCODE_RESINFO: - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_D: - case OPCODE_SAMPLE_B: - case OPCODE_LOD: - case OPCODE_GATHER4: - case OPCODE_GATHER4_C: - case OPCODE_GATHER4_PO: - case OPCODE_GATHER4_PO_C: - case OPCODE_LD_UAV_TYPED: - case OPCODE_LD_RAW: - case OPCODE_LD_STRUCTURED: - case OPCODE_EVAL_SNAPPED: - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_CENTROID: - case OPCODE_MOV: - case OPCODE_MOVC: - return 1u << 0; - - // Write to 0, 1 - case OPCODE_SINCOS: - case OPCODE_UDIV: - case OPCODE_UMUL: - case OPCODE_UADDC: - case OPCODE_USUBB: - case OPCODE_SWAPC: - return (1u << 0) | (1u << 1); - } -} - -void CreateTracingInfo(Shader* psShader) -{ - VariableTraceInfo asInputVarsInfo[MAX_SHADER_VEC4_INPUT * 4]; - uint32_t ui32NumInputVars = 0; - uint32_t uInputVec, uInstruction; - - psShader->sInfo.ui32NumTraceSteps = psShader->ui32InstCount + 1; - psShader->sInfo.psTraceSteps = hlslcc_malloc(sizeof(StepTraceInfo) * psShader->sInfo.ui32NumTraceSteps); - - for (uInputVec = 0; uInputVec < psShader->sInfo.ui32NumInputSignatures; ++uInputVec) - { - uint32_t ui32RWMask = psShader->sInfo.psInputSignatures[uInputVec].ui32ReadWriteMask; - uint8_t ui8Component = 0; - - while (ui32RWMask != 0) - { - if (ui32RWMask & 1) - { - TRACE_VARIABLE_TYPE eType; - switch (psShader->sInfo.psInputSignatures[uInputVec].eComponentType) - { - default: - ASSERT(0); - case INOUT_COMPONENT_UNKNOWN: - case INOUT_COMPONENT_UINT32: - eType = TRACE_VARIABLE_UINT; - break; - case INOUT_COMPONENT_SINT32: - eType = TRACE_VARIABLE_SINT; - break; - case INOUT_COMPONENT_FLOAT32: - eType = TRACE_VARIABLE_FLOAT; - break; - } - - asInputVarsInfo[ui32NumInputVars].eGroup = TRACE_VARIABLE_INPUT; - asInputVarsInfo[ui32NumInputVars].eType = eType; - asInputVarsInfo[ui32NumInputVars].ui8Index = psShader->sInfo.psInputSignatures[uInputVec].ui32Register; - asInputVarsInfo[ui32NumInputVars].ui8Component = ui8Component; - ++ui32NumInputVars; - } - ui32RWMask >>= 1; - ++ui8Component; - } - } - - psShader->sInfo.psTraceSteps[0].ui32NumVariables = ui32NumInputVars; - psShader->sInfo.psTraceSteps[0].psVariables = hlslcc_malloc(sizeof(VariableTraceInfo) * ui32NumInputVars); - memcpy(psShader->sInfo.psTraceSteps[0].psVariables, asInputVarsInfo, sizeof(VariableTraceInfo) * ui32NumInputVars); - - for (uInstruction = 0; uInstruction < psShader->ui32InstCount; ++uInstruction) - { - VariableTraceInfo* psStepVars = NULL; - uint32_t ui32StepVarsCapacity = 0; - uint32_t ui32StepVarsSize = 0; - uint32_t auStepDirtyVecMask[MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT] = {0}; - uint8_t auStepCompTypeMask[4 * (MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT)] = {0}; - uint32_t uOpcodeWriteMask = GetOpcodeWriteMask(psShader->psInst[uInstruction].eOpcode); - uint32_t uOperand, uStepVec; - - for (uOperand = 0; uOperand < psShader->psInst[uInstruction].ui32NumOperands; ++uOperand) - { - if (uOpcodeWriteMask & (1 << uOperand)) - { - uint32_t ui32OperandCompMask = ConvertOperandSwizzleToComponentMask(&psShader->psInst[uInstruction].asOperands[uOperand]); - uint32_t ui32Register = psShader->psInst[uInstruction].asOperands[uOperand].ui32RegisterNumber; - uint32_t ui32VecOffset = 0; - uint8_t ui8Component = 0; - switch (psShader->psInst[uInstruction].asOperands[uOperand].eType) - { - case OPERAND_TYPE_TEMP: - ui32VecOffset = 0; - break; - case OPERAND_TYPE_OUTPUT: - ui32VecOffset = MAX_TEMP_VEC4; - break; - default: - continue; - } - - auStepDirtyVecMask[ui32VecOffset + ui32Register] |= ui32OperandCompMask; - while (ui32OperandCompMask) - { - ASSERT(ui8Component < 4); - if (ui32OperandCompMask & 1) - { - TRACE_VARIABLE_TYPE eOperandCompType = TRACE_VARIABLE_UNKNOWN; - switch (psShader->psInst[uInstruction].asOperands[uOperand].aeDataType[ui8Component]) - { - case SVT_INT: - eOperandCompType = TRACE_VARIABLE_SINT; - break; - case SVT_FLOAT: - eOperandCompType = TRACE_VARIABLE_FLOAT; - break; - case SVT_UINT: - eOperandCompType = TRACE_VARIABLE_UINT; - break; - case SVT_DOUBLE: - eOperandCompType = TRACE_VARIABLE_DOUBLE; - break; - } - if (auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] == 0) - { - auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] = 1u + (uint8_t)eOperandCompType; - } - else if (auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] != eOperandCompType) - { - auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] = 1u + (uint8_t)TRACE_VARIABLE_UNKNOWN; - } - } - ui32OperandCompMask >>= 1; - ++ui8Component; - } - } - } - - for (uStepVec = 0; uStepVec < MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT; ++uStepVec) - { - TRACE_VARIABLE_GROUP eGroup; - uint32_t uBase; - uint8_t ui8Component = 0; - if (uStepVec < MAX_TEMP_VEC4) - { - eGroup = TRACE_VARIABLE_TEMP; - uBase = 0; - } - else - { - eGroup = TRACE_VARIABLE_OUTPUT; - uBase = MAX_TEMP_VEC4; - } - - while (auStepDirtyVecMask[uStepVec] != 0) - { - if (auStepDirtyVecMask[uStepVec] & 1) - { - if (ui32StepVarsCapacity == ui32StepVarsSize) - { - ui32StepVarsCapacity = (1 > ui32StepVarsCapacity ? 1 : ui32StepVarsCapacity) * 16; - if (psStepVars == NULL) - { - psStepVars = hlslcc_malloc(ui32StepVarsCapacity * sizeof(VariableTraceInfo)); - } - else - { - psStepVars = hlslcc_realloc(psStepVars, ui32StepVarsCapacity * sizeof(VariableTraceInfo)); - } - } - ASSERT(ui32StepVarsSize < ui32StepVarsCapacity); - - psStepVars[ui32StepVarsSize].eGroup = eGroup; - psStepVars[ui32StepVarsSize].eType = auStepCompTypeMask[4 * uStepVec + ui8Component] == 0 ? TRACE_VARIABLE_UNKNOWN : (TRACE_VARIABLE_TYPE)(auStepCompTypeMask[4 * uStepVec + ui8Component] - 1); - psStepVars[ui32StepVarsSize].ui8Component = ui8Component; - psStepVars[ui32StepVarsSize].ui8Index = uStepVec - uBase; - ++ui32StepVarsSize; - } - - ++ui8Component; - auStepDirtyVecMask[uStepVec] >>= 1; - } - } - - psShader->sInfo.psTraceSteps[1 + uInstruction].ui32NumVariables = ui32StepVarsSize; - psShader->sInfo.psTraceSteps[1 + uInstruction].psVariables = psStepVars; - } -} - -void WriteTraceDeclarations(HLSLCrossCompilerContext* psContext) -{ - bstring glsl = *psContext->currentGLSLString; - - AddIndentation(psContext); - bcatcstr(glsl, "layout (std430) buffer Trace\n"); - AddIndentation(psContext); - bcatcstr(glsl, "{\n"); - ++psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceSize;\n"); - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceStride;\n"); - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceCapacity;\n"); - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - AddIndentation(psContext); - bcatcstr(glsl, "float fTracePixelCoordX;\n"); - AddIndentation(psContext); - bcatcstr(glsl, "float fTracePixelCoordY;\n"); - break; - case VERTEX_SHADER: - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceVertexID;\n"); - break; - default: - AddIndentation(psContext); - bcatcstr(glsl, "// Trace ID not implelemented for this shader type\n"); - break; - } - AddIndentation(psContext); - bcatcstr(glsl, "uint auTraceValues[];\n"); - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "};\n"); -} - -void WritePreStepsTrace(HLSLCrossCompilerContext* psContext, StepTraceInfo* psStep) -{ - uint32_t uVar; - bstring glsl = *psContext->currentGLSLString; - - AddIndentation(psContext); - bcatcstr(glsl, "bool bRecord = "); - switch (psContext->psShader->eShaderType) - { - case VERTEX_SHADER: - bcatcstr(glsl, "uint(gl_VertexID) == uTraceVertexID"); - break; - case PIXEL_SHADER: - bcatcstr(glsl, "max(abs(gl_FragCoord.x - fTracePixelCoordX), abs(gl_FragCoord.y - fTracePixelCoordY)) <= 0.5"); - break; - default: - bcatcstr(glsl, "/* Trace condition not implelemented for this shader type */"); - bcatcstr(glsl, "false"); - break; - } - bcatcstr(glsl, ";\n"); - - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceIndex = atomicAdd(uTraceSize, uTraceStride * (bRecord ? 1 : 0));\n"); - AddIndentation(psContext); - bcatcstr(glsl, "uint uTraceEnd = uTraceIndex + uTraceStride;\n"); - AddIndentation(psContext); - bcatcstr(glsl, "bRecord = bRecord && uTraceEnd <= uTraceCapacity;\n"); - AddIndentation(psContext); - bcatcstr(glsl, "uTraceEnd *= (bRecord ? 1 : 0);\n"); - - if (psStep->ui32NumVariables > 0) - { - AddIndentation(psContext); - bformata(glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = uint(0);\n"); // Adreno can't handle 0u (it's treated as int) - - for (uVar = 0; uVar < psStep->ui32NumVariables; ++uVar) - { - VariableTraceInfo* psVar = &psStep->psVariables[uVar]; - ASSERT(psVar->eGroup == TRACE_VARIABLE_INPUT); - if (psVar->eGroup == TRACE_VARIABLE_INPUT) - { - AddIndentation(psContext); - bcatcstr(glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = "); - - switch (psVar->eType) - { - case TRACE_VARIABLE_FLOAT: - bcatcstr(glsl, "floatBitsToUint("); - break; - case TRACE_VARIABLE_SINT: - bcatcstr(glsl, "uint("); - break; - case TRACE_VARIABLE_DOUBLE: - ASSERT(0); - // Not implemented yet; - break; - } - - bformata(glsl, "Input%d.%c", psVar->ui8Index, "xyzw"[psVar->ui8Component]); - - switch (psVar->eType) - { - case TRACE_VARIABLE_FLOAT: - case TRACE_VARIABLE_SINT: - bcatcstr(glsl, ")"); - break; - } - - bcatcstr(glsl, ";\n"); - } - } - } -} - -void WritePostStepTrace(HLSLCrossCompilerContext* psContext, uint32_t uStep) -{ - Instruction* psInstruction = psContext->psShader->psInst + uStep; - StepTraceInfo* psStep = psContext->psShader->sInfo.psTraceSteps + (1 + uStep); - - if (psStep->ui32NumVariables > 0) - { - uint32_t uVar; - - AddIndentation(psContext); - bformata(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = %du;\n", uStep + 1); - - for (uVar = 0; uVar < psStep->ui32NumVariables; ++uVar) - { - VariableTraceInfo* psVar = &psStep->psVariables[uVar]; - uint16_t uOpcodeWriteMask = GetOpcodeWriteMask(psInstruction->eOpcode); - uint8_t uOperand = 0; - OPERAND_TYPE eOperandType = OPERAND_TYPE_NULL; - Operand* psOperand = NULL; - uint32_t uiIgnoreSwizzle = 0; - - switch (psVar->eGroup) - { - case TRACE_VARIABLE_TEMP: - eOperandType = OPERAND_TYPE_TEMP; - break; - case TRACE_VARIABLE_OUTPUT: - eOperandType = OPERAND_TYPE_OUTPUT; - break; - } - - if (psVar->eType == TRACE_VARIABLE_DOUBLE) - { - ASSERT(0); - // Not implemented yet - continue; - } - while (uOpcodeWriteMask) - { - if (uOpcodeWriteMask & 1) - { - if (eOperandType == psInstruction->asOperands[uOperand].eType && - psVar->ui8Index == psInstruction->asOperands[uOperand].ui32RegisterNumber) - { - psOperand = &psInstruction->asOperands[uOperand]; - break; - } - } - uOpcodeWriteMask >>= 1; - ++uOperand; - } - - if (psOperand == NULL) - { - ASSERT(0); - continue; - } - - AddIndentation(psContext); - bcatcstr(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = "); - - TranslateVariableName(psContext, psOperand, TO_FLAG_UNSIGNED_INTEGER, &uiIgnoreSwizzle); - ASSERT(uiIgnoreSwizzle == 0); - - bformata(psContext->glsl, ".%c;\n", "xyzw"[psVar->ui8Component]); - } - } -} - -void WriteEndTrace(HLSLCrossCompilerContext* psContext) -{ - AddIndentation(psContext); - bcatcstr(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = 0xFFFFFFFFu;\n"); -} - -int FindEmbeddedResourceName(EmbeddedResourceName* psEmbeddedName, HLSLCrossCompilerContext* psContext, bstring name) -{ - int offset = binstr(psContext->glsl, 0, name); - int size = name->slen; - - if (offset == BSTR_ERR || size > 0x3FF || offset > 0x7FFFF) - { - return 0; - } - - psEmbeddedName->ui20Offset = offset; - psEmbeddedName->ui12Size = size; - return 1; -} - -void IgnoreSampler(ShaderInfo* psInfo, uint32_t index) -{ - if (index + 1 < psInfo->ui32NumSamplers) - { - psInfo->asSamplers[index] = psInfo->asSamplers[psInfo->ui32NumSamplers - 1]; - } - --psInfo->ui32NumSamplers; -} - -void IgnoreResource(Resource* psResources, uint32_t* puSize, uint32_t index) -{ - if (index + 1 < *puSize) - { - psResources[index] = psResources[*puSize - 1]; - } - --*puSize; -} - -void FillInResourceDescriptions(HLSLCrossCompilerContext* psContext) -{ - uint32_t i; - bstring resourceName = bfromcstralloc(MAX_REFLECT_STRING_LENGTH, ""); - Shader* psShader = psContext->psShader; - - for (i = 0; i < psShader->sInfo.ui32NumSamplers; ++i) - { - Sampler* psSampler = psShader->sInfo.asSamplers + i; - SamplerMask* psMask = &psSampler->sMask; - if (psMask->bNormalSample || psMask->bCompareSample) - { - if (psMask->bNormalSample) - { - btrunc(resourceName, 0); - TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 0); - if (!FindEmbeddedResourceName(&psSampler->sNormalName, psContext, resourceName)) - { - psMask->bNormalSample = 0; - } - } - if (psMask->bCompareSample) - { - btrunc(resourceName, 0); - TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 1); - if (!FindEmbeddedResourceName(&psSampler->sCompareName, psContext, resourceName)) - { - psMask->bCompareSample = 0; - } - } - if (!psMask->bNormalSample && !psMask->bCompareSample) - { - IgnoreSampler(&psShader->sInfo, i); // Not used in the shader - ignore - } - } - else - { - btrunc(resourceName, 0); - TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 0); - if (!FindEmbeddedResourceName(&psSampler->sNormalName, psContext, resourceName)) - { - IgnoreSampler(&psShader->sInfo, i); // Not used in the shader - ignore - } - } - } - - for (i = 0; i < psShader->sInfo.ui32NumImages; ++i) - { - Resource* psResources = psShader->sInfo.asImages; - uint32_t* puSize = &psShader->sInfo.ui32NumImages; - - Resource* psResource = psResources + i; - ResourceBinding* psBinding = NULL; - if (!GetResourceFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psBinding)) - { - ASSERT(0); - IgnoreResource(psResources, puSize, i); - } - - btrunc(resourceName, 0); - ConvertToUAVName(resourceName, psShader, psBinding->Name); - if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) - { - IgnoreResource(psResources, puSize, i); - } - } - - for (i = 0; i < psShader->sInfo.ui32NumUniformBuffers; ++i) - { - Resource* psResources = psShader->sInfo.asUniformBuffers; - uint32_t* puSize = &psShader->sInfo.ui32NumUniformBuffers; - - Resource* psResource = psResources + i; - ConstantBuffer* psCB = NULL; - GetConstantBufferFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psCB); - - btrunc(resourceName, 0); - ConvertToUniformBufferName(resourceName, psShader, psCB->Name); - if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) - { - IgnoreResource(psResources, puSize, i); - } - } - - for (i = 0; i < psShader->sInfo.ui32NumStorageBuffers; ++i) - { - Resource* psResources = psShader->sInfo.asStorageBuffers; - uint32_t* puSize = &psShader->sInfo.ui32NumStorageBuffers; - - Resource* psResource = psResources + i; - ConstantBuffer* psCB = NULL; - GetConstantBufferFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psCB); - - btrunc(resourceName, 0); - if (psResource->eGroup == RGROUP_UAV) - { - ConvertToUAVName(resourceName, psShader, psCB->Name); - } - else - { - ConvertToTextureName(resourceName, psShader, psCB->Name, NULL, 0); - } - if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) - { - IgnoreResource(psResources, puSize, i); - } - } - - bdestroy(resourceName); -} - -GLLang ChooseLanguage(Shader* psShader) -{ - // Depends on the HLSL shader model extracted from bytecode. - switch (psShader->ui32MajorVersion) - { - case 5: - { - return LANG_430; - } - case 4: - { - return LANG_330; - } - default: - { - return LANG_120; - } - } -} - -const char* GetVersionString(GLLang language) -{ - switch (language) - { - case LANG_ES_100: - { - return "#version 100\n"; - break; - } - case LANG_ES_300: - { - return "#version 300 es\n"; - break; - } - case LANG_ES_310: - { - return "#version 310 es\n"; - break; - } - case LANG_120: - { - return "#version 120\n"; - break; - } - case LANG_130: - { - return "#version 130\n"; - break; - } - case LANG_140: - { - return "#version 140\n"; - break; - } - case LANG_150: - { - return "#version 150\n"; - break; - } - case LANG_330: - { - return "#version 330\n"; - break; - } - case LANG_400: - { - return "#version 400\n"; - break; - } - case LANG_410: - { - return "#version 410\n"; - break; - } - case LANG_420: - { - return "#version 420\n"; - break; - } - case LANG_430: - { - return "#version 430\n"; - break; - } - case LANG_440: - { - return "#version 440\n"; - break; - } - default: - { - return ""; - break; - } - } -} - -// Force precision of vertex output position to highp. -// Using mediump or lowp for the position of the vertex can cause rendering artifacts in OpenGL ES. -void ForcePositionOutputToHighp(Shader* shader) -{ - // Only sensible in vertex shaders - if (shader->eShaderType != VERTEX_SHADER) - { - return; - } - - // Find the output position declaration - Declaration* posDeclaration = NULL; - for (uint32_t i = 0; i < shader->ui32DeclCount; ++i) - { - Declaration* decl = shader->psDecl + i; - if (decl->eOpcode == OPCODE_DCL_OUTPUT_SIV) - { - if (decl->asOperands[0].eSpecialName == NAME_POSITION) - { - posDeclaration = decl; - break; - } - - if (decl->asOperands[0].eSpecialName != NAME_UNDEFINED) - { - continue; - } - - // This might be SV_Position (because d3dcompiler is weird). Get signature and check - InOutSignature *sig = NULL; - GetOutputSignatureFromRegister(decl->asOperands[0].ui32RegisterNumber, decl->asOperands[0].ui32CompMask, 0, &shader->sInfo, &sig); - ASSERT(sig != NULL); - if ((sig->eSystemValueType == NAME_POSITION || strcmp(sig->SemanticName, "POS") == 0) && sig->ui32SemanticIndex == 0) - { - sig->eMinPrec = MIN_PRECISION_DEFAULT; - posDeclaration = decl; - break; - } - } - else if (decl->eOpcode == OPCODE_DCL_OUTPUT) - { - InOutSignature *sig = NULL; - GetOutputSignatureFromRegister(decl->asOperands[0].ui32RegisterNumber, decl->asOperands[0].ui32CompMask, 0, &shader->sInfo, &sig); - ASSERT(sig != NULL); - if ((sig->eSystemValueType == NAME_POSITION || strcmp(sig->SemanticName, "POS") == 0) && sig->ui32SemanticIndex == 0) - { - sig->eMinPrec = MIN_PRECISION_DEFAULT; - posDeclaration = decl; - break; - } - } - } - - // Do nothing if we don't find suitable output. This may well be INTERNALTESSPOS for tessellation etc. - if (!posDeclaration) - { - return; - } - - posDeclaration->asOperands[0].eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; - posDeclaration->asOperands[0].eSpecialName = NAME_POSITION; - // Go through all the instructions and update the operand. - for (uint32_t i = 0; i < shader->ui32InstCount; ++i) - { - Instruction *inst = shader->psInst + i; - for (uint32_t j = 0; j < inst->ui32FirstSrc; ++j) - { - Operand op = inst->asOperands[j]; - // Since it's an output declaration we know that there's only one - // operand and it's in the first slot. - if (op.eType == OPERAND_TYPE_OUTPUT && op.ui32RegisterNumber == posDeclaration->asOperands[0].ui32RegisterNumber) - { - op.eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; - op.eSpecialName = NAME_POSITION; - } - } - } -} - -void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage, const GlExtensions* extensions) -{ - bstring glsl; - uint32_t i; - Shader* psShader = psContext->psShader; - GLLang language = *planguage; - const uint32_t ui32InstCount = psShader->ui32InstCount; - const uint32_t ui32DeclCount = psShader->ui32DeclCount; - - psContext->indent = 0; - - if (language == LANG_DEFAULT) - { - language = ChooseLanguage(psShader); - *planguage = language; - } - - glsl = bfromcstralloc (1024, ""); - if (!(psContext->flags & HLSLCC_FLAG_NO_VERSION_STRING)) - { - bcatcstr(glsl, GetVersionString(language)); - } - - if (psContext->flags & HLSLCC_FLAG_ADD_DEBUG_HEADER) - { - bstring version = glsl; - glsl = psContext->debugHeader; - bconcat(glsl, version); - bdestroy(version); - } - - psContext->glsl = glsl; - psContext->earlyMain = bfromcstralloc (1024, ""); - for (i = 0; i < NUM_PHASES; ++i) - { - psContext->postShaderCode[i] = bfromcstralloc (1024, ""); - } - - psContext->currentGLSLString = &glsl; - psShader->eTargetLanguage = language; - psShader->extensions = (const struct GlExtensions*)extensions; - psContext->currentPhase = MAIN_PHASE; - - if (extensions) - { - if (extensions->ARB_explicit_attrib_location) - { - bcatcstr(glsl, "#extension GL_ARB_explicit_attrib_location : require\n"); - } - if (extensions->ARB_explicit_uniform_location) - { - bcatcstr(glsl, "#extension GL_ARB_explicit_uniform_location : require\n"); - } - if (extensions->ARB_shading_language_420pack) - { - bcatcstr(glsl, "#extension GL_ARB_shading_language_420pack : require\n"); - } - } - - psContext->psShader->sInfo.ui32SymbolsOffset = blength(glsl); - - FRAMEBUFFER_FETCH_TYPE fetchType = CollectGmemInfo(psContext); - if (fetchType & FBF_EXT_COLOR) - { - bcatcstr(glsl, "#extension GL_EXT_shader_framebuffer_fetch : require\n"); - } - if (fetchType & FBF_ARM_COLOR) - { - bcatcstr(glsl, "#extension GL_ARM_shader_framebuffer_fetch : require\n"); - } - if (fetchType & (FBF_ARM_DEPTH | FBF_ARM_STENCIL)) - { - bcatcstr(glsl, "#extension GL_ARM_shader_framebuffer_fetch_depth_stencil : require\n"); - } - psShader->eGmemType = fetchType; - - AddVersionDependentCode(psContext); - - if (psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) - { - bcatcstr(glsl, "layout(std140) uniform;\n"); - } - - //Special case. Can have multiple phases. - if (psShader->eShaderType == HULL_SHADER) - { - int haveInstancedForkPhase = 0; - uint32_t forkIndex = 0; - - ConsolidateHullTempVars(psShader); - - for (i = 0; i < psShader->ui32HSDeclCount; ++i) - { - TranslateDeclaration(psContext, psShader->psHSDecl + i); - } - - //control - psContext->currentPhase = HS_CTRL_POINT_PHASE; - - if (psShader->ui32HSControlPointDeclCount) - { - bcatcstr(glsl, "//Control point phase declarations\n"); - for (i = 0; i < psShader->ui32HSControlPointDeclCount; ++i) - { - TranslateDeclaration(psContext, psShader->psHSControlPointPhaseDecl + i); - } - } - - if (psShader->ui32HSControlPointInstrCount) - { - SetDataTypes(psContext, psShader->psHSControlPointPhaseInstr, psShader->ui32HSControlPointInstrCount, NULL); - - bcatcstr(glsl, "void control_point_phase()\n{\n"); - psContext->indent++; - - for (i = 0; i < psShader->ui32HSControlPointInstrCount; ++i) - { - TranslateInstruction(psContext, psShader->psHSControlPointPhaseInstr + i); - } - psContext->indent--; - bcatcstr(glsl, "}\n"); - } - - //fork - psContext->currentPhase = HS_FORK_PHASE; - for (forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) - { - bcatcstr(glsl, "//Fork phase declarations\n"); - for (i = 0; i < psShader->aui32HSForkDeclCount[forkIndex]; ++i) - { - TranslateDeclaration(psContext, psShader->apsHSForkPhaseDecl[forkIndex] + i); - if (psShader->apsHSForkPhaseDecl[forkIndex][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) - { - haveInstancedForkPhase = 1; - } - } - - bformata(glsl, "void fork_phase%d()\n{\n", forkIndex); - psContext->indent++; - - SetDataTypes(psContext, psShader->apsHSForkPhaseInstr[forkIndex], psShader->aui32HSForkInstrCount[forkIndex] - 1, NULL); - - if (haveInstancedForkPhase) - { - AddIndentation(psContext); - bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", forkIndex); - psContext->indent++; - } - - //The minus one here is remove the return statement at end of phases. - //This is needed otherwise the for loop will only run once. - ASSERT(psShader->apsHSForkPhaseInstr[forkIndex][psShader->aui32HSForkInstrCount[forkIndex] - 1].eOpcode == OPCODE_RET); - for (i = 0; i < psShader->aui32HSForkInstrCount[forkIndex] - 1; ++i) - { - TranslateInstruction(psContext, psShader->apsHSForkPhaseInstr[forkIndex] + i); - } - - if (haveInstancedForkPhase) - { - psContext->indent--; - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - } - } - - psContext->indent--; - bcatcstr(glsl, "}\n"); - } - - - //join - psContext->currentPhase = HS_JOIN_PHASE; - if (psShader->ui32HSJoinDeclCount) - { - bcatcstr(glsl, "//Join phase declarations\n"); - for (i = 0; i < psShader->ui32HSJoinDeclCount; ++i) - { - TranslateDeclaration(psContext, psShader->psHSJoinPhaseDecl + i); - } - } - - if (psShader->ui32HSJoinInstrCount) - { - SetDataTypes(psContext, psShader->psHSJoinPhaseInstr, psShader->ui32HSJoinInstrCount, NULL); - - bcatcstr(glsl, "void join_phase()\n{\n"); - psContext->indent++; - - for (i = 0; i < psShader->ui32HSJoinInstrCount; ++i) - { - TranslateInstruction(psContext, psShader->psHSJoinPhaseInstr + i); - } - - psContext->indent--; - bcatcstr(glsl, "}\n"); - } - - bcatcstr(glsl, "void main()\n{\n"); - - psContext->indent++; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Start Early Main ---\n"); -#endif - bconcat(glsl, psContext->earlyMain); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End Early Main ---\n"); -#endif - - if (psShader->ui32HSControlPointInstrCount) - { - AddIndentation(psContext); - bcatcstr(glsl, "control_point_phase();\n"); - - if (psShader->ui32ForkPhaseCount || psShader->ui32HSJoinInstrCount) - { - AddIndentation(psContext); - bcatcstr(glsl, "barrier();\n"); - } - } - for (forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) - { - AddIndentation(psContext); - bformata(glsl, "fork_phase%d();\n", forkIndex); - - if (psShader->ui32HSJoinInstrCount || (forkIndex + 1 < psShader->ui32ForkPhaseCount)) - { - AddIndentation(psContext); - bcatcstr(glsl, "barrier();\n"); - } - } - if (psShader->ui32HSJoinInstrCount) - { - AddIndentation(psContext); - bcatcstr(glsl, "join_phase();\n"); - } - - psContext->indent--; - - bcatcstr(glsl, "}\n"); - - return; - } - - if (psShader->eShaderType == DOMAIN_SHADER) - { - uint32_t ui32TessOutPrimImp = AddImport(psContext, SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE, 0, (uint32_t)TESSELLATOR_OUTPUT_TRIANGLE_CCW); - uint32_t ui32TessPartitioningImp = AddImport(psContext, SYMBOL_TESSELLATOR_PARTITIONING, 0, (uint32_t)TESSELLATOR_PARTITIONING_INTEGER); - - bformata(glsl, "#if IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_POINT); - bcatcstr(glsl, "layout(point_mode) in;\n"); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_LINE); - bcatcstr(glsl, "layout(isolines) in;\n"); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_TRIANGLE_CW); - bcatcstr(glsl, "layout(cw) in;\n"); - bcatcstr(glsl, "#endif\n"); - - bformata(glsl, "#if IMPORT_%d == %d\n", ui32TessPartitioningImp, (uint32_t)TESSELLATOR_PARTITIONING_FRACTIONAL_ODD); - bcatcstr(glsl, "layout(fractional_odd_spacing) in;\n"); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessPartitioningImp, (uint32_t)TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN); - bcatcstr(glsl, "layout(fractional_even_spacing) in;\n"); - bcatcstr(glsl, "#endif\n"); - } - - for (i = 0; i < ui32DeclCount; ++i) - { - TranslateDeclaration(psContext, psShader->psDecl + i); - } - - if (psContext->psShader->ui32NumDx9ImmConst) - { - bformata(psContext->glsl, "vec4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); - } - - MarkIntegerImmediates(psContext); - - SetDataTypes(psContext, psShader->psInst, ui32InstCount, psContext->psShader->aeCommonTempVecType); - - if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) - { - for (i = 0; i < MAX_TEMP_VEC4; ++i) - { - switch (psShader->aeCommonTempVecType[i]) - { - case SVT_VOID: - psShader->aeCommonTempVecType[i] = SVT_FLOAT; - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - bformata(psContext->glsl, "%s Temp%d", GetConstructorForTypeGLSL(psContext, psShader->aeCommonTempVecType[i], 4, true), i); - break; - case SVT_FORCE_DWORD: - // temp register not used - continue; - default: - continue; - } - - if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) - { - bformata(psContext->glsl, "[1]"); - } - bformata(psContext->glsl, ";\n"); - } - - if (psContext->psShader->bUseTempCopy) - { - bcatcstr(psContext->glsl, "vec4 TempCopy;\n"); - bcatcstr(psContext->glsl, "uvec4 TempCopy_uint;\n"); - bcatcstr(psContext->glsl, "ivec4 TempCopy_int;\n"); - } - } - - // Declare auxiliary variables used to save intermediate results to bypass driver issues - SHADER_VARIABLE_TYPE auxVarType = SVT_UINT; - bformata(psContext->glsl, "highp %s %s1;\n", GetConstructorForTypeGLSL(psContext, auxVarType, 4, false), GetAuxArgumentName(auxVarType)); - - if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) - { - CreateTracingInfo(psShader); - WriteTraceDeclarations(psContext); - } - - bcatcstr(glsl, "void main()\n{\n"); - - psContext->indent++; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Start Early Main ---\n"); -#endif - bconcat(glsl, psContext->earlyMain); - if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) - { - WritePreStepsTrace(psContext, psShader->sInfo.psTraceSteps); - } -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End Early Main ---\n"); -#endif - - for (i = 0; i < ui32InstCount; ++i) - { - TranslateInstruction(psContext, psShader->psInst + i); - - if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) - { - WritePostStepTrace(psContext, i); - } - } - - psContext->indent--; - - bcatcstr(glsl, "}\n"); - - // Add exports - if (psShader->eShaderType == PIXEL_SHADER) - { - uint32_t ui32Input; - for (ui32Input = 0; ui32Input < MAX_SHADER_VEC4_INPUT; ++ui32Input) - { - INTERPOLATION_MODE eMode = psShader->sInfo.aePixelInputInterpolation[ui32Input]; - if (eMode != INTERPOLATION_LINEAR) - { - AddExport(psContext, SYMBOL_INPUT_INTERPOLATION_MODE, ui32Input, (uint32_t)eMode); - } - } - } - if (psShader->eShaderType == HULL_SHADER) - { - AddExport(psContext, SYMBOL_TESSELLATOR_PARTITIONING, 0, psShader->sInfo.eTessPartitioning); - AddExport(psContext, SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE, 0, psShader->sInfo.eTessOutPrim); - } - - FillInResourceDescriptions(psContext); -} - -static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) -{ - uint32_t ui32Inst; - for (ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) - { - Instruction* psCurrentInst = &psInst[ui32Inst]; - const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; - uint32_t ui32Operand; - - for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) - { - uint32_t ui32SubOperand; - for (ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) - { - if (psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) - { - hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); - psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; - } - } - } - } -} - -void RemoveDoubleUnderscores(char* szName) -{ - char* position; - size_t length; - length = strlen(szName); - position = szName; - position = strstr(position, "__"); - while (position) - { - position[1] = '0'; - position += 2; - position = strstr(position, "__"); - } -} - -void RemoveDoubleUnderscoresFromIdentifiers(Shader* psShader) -{ - uint32_t i, j; - for (i = 0; i < psShader->sInfo.ui32NumConstantBuffers; ++i) - { - for (j = 0; j < psShader->sInfo.psConstantBuffers[i].ui32NumVars; ++j) - { - RemoveDoubleUnderscores(psShader->sInfo.psConstantBuffers[i].asVars[j].sType.Name); - } - } -} - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, size_t size, unsigned int flags, GLLang language, const GlExtensions* extensions, GLSLShader* result) -{ - uint32_t* tokens; - Shader* psShader; - char* glslcstr = NULL; - int GLSLShaderType = GL_FRAGMENT_SHADER_ARB; - int success = 0; - uint32_t i; - - tokens = (uint32_t*)shader; - - psShader = DecodeDXBC(tokens); - - if (flags & (HLSLCC_FLAG_HASH_INPUT | HLSLCC_FLAG_ADD_DEBUG_HEADER)) - { - uint64_t ui64InputHash = hash64((const uint8_t*)tokens, tokens[6], 0); - psShader->sInfo.ui32InputHash = (uint32_t)ui64InputHash ^ (uint32_t)(ui64InputHash >> 32); - } - - RemoveDoubleUnderscoresFromIdentifiers(psShader); - - if (psShader) - { - ForcePositionOutputToHighp(psShader); - HLSLCrossCompilerContext sContext; - - sContext.psShader = psShader; - sContext.flags = flags; - - for (i = 0; i < NUM_PHASES; ++i) - { - sContext.havePostShaderCode[i] = 0; - } - - if (flags & HLSLCC_FLAG_ADD_DEBUG_HEADER) - { -#if defined(_WIN32) && !defined(PORTABLE) - ID3DBlob* pDisassembly = NULL; -#endif //defined(_WIN32) && !defined(PORTABLE) - - sContext.debugHeader = bformat("// HASH = 0x%08X\n", psShader->sInfo.ui32InputHash); - -#if defined(_WIN32) && !defined(PORTABLE) - D3DDisassemble(shader, size, 0, "", &pDisassembly); - bcatcstr(sContext.debugHeader, "/*\n"); - bcatcstr(sContext.debugHeader, (const char*)pDisassembly->lpVtbl->GetBufferPointer(pDisassembly)); - bcatcstr(sContext.debugHeader, "\n*/\n"); - pDisassembly->lpVtbl->Release(pDisassembly); -#endif //defined(_WIN32) && !defined(PORTABLE) - } - - TranslateToGLSL(&sContext, &language, extensions); - - switch (psShader->eShaderType) - { - case VERTEX_SHADER: - { - GLSLShaderType = GL_VERTEX_SHADER_ARB; - break; - } - case GEOMETRY_SHADER: - { - GLSLShaderType = GL_GEOMETRY_SHADER; - break; - } - case DOMAIN_SHADER: - { - GLSLShaderType = GL_TESS_EVALUATION_SHADER; - break; - } - case HULL_SHADER: - { - GLSLShaderType = GL_TESS_CONTROL_SHADER; - break; - } - case COMPUTE_SHADER: - { - GLSLShaderType = GL_COMPUTE_SHADER; - break; - } - default: - { - break; - } - } - - glslcstr = bstr2cstr(sContext.glsl, '\0'); - - bdestroy(sContext.glsl); - bdestroy(sContext.earlyMain); - for (i = 0; i < NUM_PHASES; ++i) - { - bdestroy(sContext.postShaderCode[i]); - } - - hlslcc_free(psShader->psHSControlPointPhaseDecl); - FreeSubOperands(psShader->psHSControlPointPhaseInstr, psShader->ui32HSControlPointInstrCount); - hlslcc_free(psShader->psHSControlPointPhaseInstr); - - for (i = 0; i < psShader->ui32ForkPhaseCount; ++i) - { - hlslcc_free(psShader->apsHSForkPhaseDecl[i]); - FreeSubOperands(psShader->apsHSForkPhaseInstr[i], psShader->aui32HSForkInstrCount[i]); - hlslcc_free(psShader->apsHSForkPhaseInstr[i]); - } - hlslcc_free(psShader->psHSJoinPhaseDecl); - FreeSubOperands(psShader->psHSJoinPhaseInstr, psShader->ui32HSJoinInstrCount); - hlslcc_free(psShader->psHSJoinPhaseInstr); - - hlslcc_free(psShader->psDecl); - FreeSubOperands(psShader->psInst, psShader->ui32InstCount); - hlslcc_free(psShader->psInst); - - memcpy(&result->reflection, &psShader->sInfo, sizeof(psShader->sInfo)); - - - hlslcc_free(psShader); - - success = 1; - } - - shader = 0; - tokens = 0; - - /* Fill in the result struct */ - - result->shaderType = GLSLShaderType; - result->sourceCode = glslcstr; - result->GLSLLanguage = language; - - return success; -} - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename, unsigned int flags, GLLang language, const GlExtensions* extensions, GLSLShader* result) -{ - FILE* shaderFile; - int length; - size_t readLength; - char* shader; - int success = 0; - - shaderFile = fopen(filename, "rb"); - - if (!shaderFile) - { - return 0; - } - - fseek(shaderFile, 0, SEEK_END); - length = ftell(shaderFile); - fseek(shaderFile, 0, SEEK_SET); - - shader = (char*)hlslcc_malloc(length + 1); - - readLength = fread(shader, 1, length, shaderFile); - - fclose(shaderFile); - shaderFile = 0; - - shader[readLength] = '\0'; - - success = TranslateHLSLFromMem(shader, readLength, flags, language, extensions, result); - - hlslcc_free(shader); - - return success; -} - -HLSLCC_API void HLSLCC_APIENTRY FreeGLSLShader(GLSLShader* s) -{ - bcstrfree(s->sourceCode); - s->sourceCode = NULL; - FreeShaderInfo(&s->reflection); -} - diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c deleted file mode 100644 index 3f08f2ab3d..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c +++ /dev/null @@ -1,2908 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "hlslcc.h" -#include "internal_includes/toGLSLDeclaration.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/languages.h" -#include "internal_includes/hlslccToolkit.h" -#include "bstrlib.h" -#include "internal_includes/debug.h" -#include <math.h> -#include <float.h> -#include <stdbool.h> - -#if !defined(isnan) -#ifdef _MSC_VER -#define isnan(x) _isnan(x) -#define isinf(x) (!_finite(x)) -#endif -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) - -typedef enum -{ - GLVARTYPE_FLOAT, - GLVARTYPE_INT, - GLVARTYPE_FLOAT4, -} GLVARTYPE; - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); -extern uint32_t AddImport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Default); -extern uint32_t AddExport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Value); - -const char* GetTypeString(GLVARTYPE eType) -{ - switch (eType) - { - case GLVARTYPE_FLOAT: - { - return "float"; - } - case GLVARTYPE_INT: - { - return "int"; - } - case GLVARTYPE_FLOAT4: - { - return "vec4"; - } - default: - { - return ""; - } - } -} -const uint32_t GetTypeElementCount(GLVARTYPE eType) -{ - switch (eType) - { - case GLVARTYPE_FLOAT: - case GLVARTYPE_INT: - { - return 1; - } - case GLVARTYPE_FLOAT4: - { - return 4; - } - default: - { - return 0; - } - } -} - -void GetSTD140Layout(ShaderVarType* pType, uint32_t* puAlignment, uint32_t* puSize) -{ - *puSize = 0; - *puAlignment = 1; - switch (pType->Type) - { - case SVT_BOOL: - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - *puSize = 4; - *puAlignment = 4; - break; - case SVT_DOUBLE: - *puSize = 8; - *puAlignment = 4; - break; - case SVT_VOID: - break; - default: - ASSERT(0); - break; - } - switch (pType->Class) - { - case SVC_SCALAR: - break; - case SVC_MATRIX_ROWS: - case SVC_MATRIX_COLUMNS: - // Matrices are translated to arrays of vectors - *puSize *= pType->Rows; - case SVC_VECTOR: - switch (pType->Columns) - { - case 2: - *puSize *= 2; - *puAlignment *= 2; - break; - case 3: - case 4: - *puSize *= 4; - *puAlignment *= 4; - break; - } - break; - case SVC_STRUCT: - { - uint32_t uMember; - for (uMember = 0; uMember < pType->MemberCount; ++uMember) - { - uint32_t uMemberAlignment, uMemberSize; - *puSize += pType->Members[uMember].Offset; - GetSTD140Layout(pType->Members + uMember, &uMemberAlignment, &uMemberSize); - *puSize += uMemberAlignment - 1; - *puSize -= *puSize % uMemberAlignment; - *puAlignment = *puAlignment > uMemberAlignment ? *puAlignment : uMemberAlignment; - } - } - break; - default: - ASSERT(0); - break; - } - - if (pType->Elements > 1) - { - *puSize *= pType->Elements; - } - - if (pType->Elements > 1 || pType->Class == SVC_MATRIX_ROWS || pType->Class == SVC_MATRIX_COLUMNS) - { - *puAlignment = (*puAlignment + 0x0000000F) & 0xFFFFFFF0; - } -} - -void AddToDx9ImmConstIndexableArray(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - bstring* savedStringPtr = psContext->currentGLSLString; - - psContext->currentGLSLString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; - bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); - TranslateOperand(psContext, psOperand, TO_FLAG_NONE); - bcatcstr(psContext->earlyMain, ";\n"); - psContext->indent--; - psContext->psShader->ui32NumDx9ImmConst++; - - psContext->currentGLSLString = savedStringPtr; -} - -void DeclareConstBufferShaderVariable(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType, int unsizedArray) -{ - bstring glsl = *psContext->currentGLSLString; - - if (psType->Class == SVC_STRUCT) - { - bcatcstr(glsl, "\t"); - ShaderVarName(glsl, psContext->psShader, Name); - bcatcstr(glsl, "_Type "); - ShaderVarName(glsl, psContext->psShader, Name); - if (psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) - { - switch (psType->Type) - { - case SVT_FLOAT: - { - bformata(glsl, "\tvec%d ", psType->Columns); - ShaderVarName(glsl, psContext->psShader, Name); - bformata(glsl, "[%d", psType->Rows); - break; - } - default: - { - ASSERT(0); - break; - } - } - if (psType->Elements > 1) - { - bformata(glsl, " * %d", psType->Elements); - } - bformata(glsl, "]"); - } - else - if (psType->Class == SVC_VECTOR) - { - switch (psType->Type) - { - default: - ASSERT(0); - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - bformata(glsl, "\t%s ", GetConstructorForTypeGLSL(psContext, psType->Type, psType->Columns, true)); - break; - case SVT_DOUBLE: - bformata(glsl, "\tdvec%d ", psType->Columns); - break; - } - - ShaderVarName(glsl, psContext->psShader, Name); - - if (psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - else - if (psType->Class == SVC_SCALAR) - { - switch (psType->Type) - { - default: - ASSERT(0); - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - bformata(glsl, "\t%s ", GetConstructorForTypeGLSL(psContext, psType->Type, 1, true)); - break; - case SVT_DOUBLE: - bformata(glsl, "\tdouble "); - break; - case SVT_BOOL: - //Use int instead of bool. - //Allows implicit conversions to integer and - //bool consumes 4-bytes in HLSL and GLSL anyway. - bformata(glsl, "\tint "); - break; - } - - ShaderVarName(glsl, psContext->psShader, Name); - - if (psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - if (unsizedArray) - { - bformata(glsl, "[]"); - } - bformata(glsl, ";\n"); -} - -//In GLSL embedded structure definitions are not supported. -void PreDeclareStructType(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType) -{ - uint32_t i; - bstring glsl = *psContext->currentGLSLString; - - for (i = 0; i < psType->MemberCount; ++i) - { - if (psType->Members[i].Class == SVC_STRUCT) - { - PreDeclareStructType(psContext, psType->Members[i].Name, &psType->Members[i]); - } - } - - if (psType->Class == SVC_STRUCT) - { -#if !defined(NDEBUG) - uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; -#endif - //Not supported at the moment - ASSERT(!unnamed_struct); - - bcatcstr(glsl, "struct "); - ShaderVarName(glsl, psContext->psShader, Name); - bcatcstr(glsl, "_Type {\n"); - - for (i = 0; i < psType->MemberCount; ++i) - { - ASSERT(psType->Members != 0); - - DeclareConstBufferShaderVariable(psContext, psType->Members[i].Name, &psType->Members[i], 0); - } - - bformata(glsl, "};\n"); - } -} - -void DeclarePLSStructVars(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType) -{ - (void)Name; - - uint32_t i; - bstring glsl = *psContext->currentGLSLString; - - ASSERT(psType->Members != 0); - - for (i = 0; i < psType->MemberCount; ++i) - { - if (psType->Members[i].Class == SVC_STRUCT) - { - ASSERT(0); // PLS can't have nested structs - } - } - - if (psType->Class == SVC_STRUCT) - { - for (i = 0; i < psType->MemberCount; ++i) - { - ShaderVarType cur_member = psType->Members[i]; - - if (cur_member.Class == SVC_VECTOR) - { - switch (cur_member.Type) - { - case SVT_FLOAT: - { - // float2 -> rg16f - if (2 == cur_member.Columns) - { - bcatcstr(glsl, "\tlayout(rg16f) highp vec2 "); - } - // float3 -> r11f_g11f_b10f - else if (3 == cur_member.Columns) - { - bcatcstr(glsl, "\tlayout(r11f_g11f_b10f) highp vec3 "); - } - // float4 -> rgba8 - else if (4 == cur_member.Columns) - { - bcatcstr(glsl, "\tlayout(rgba8) highp vec4 "); - } - else - { - ASSERT(0); // not supported - } - break; - } - case SVT_INT: - { - // int2 -> rg16i - if (2 == cur_member.Columns) - { - bcatcstr(glsl, "\tlayout(rg16i) highp ivec2 "); - } - // int4 -> rgba8i - else if (4 == cur_member.Columns) - { - bcatcstr(glsl, "\tlayout(rgba8i) highp ivec4 "); - } - else - { - ASSERT(0); // not supported - } - break; - } - case SVT_UINT: - case SVT_DOUBLE: - default: - ASSERT(0); - } - - if (cur_member.Elements > 1) - { - ASSERT(0); // PLS can't have arrays - } - } - else if (cur_member.Class == SVC_SCALAR) - { - switch (cur_member.Type) - { - case SVT_UINT: - bcatcstr(glsl, "\tlayout(r32ui) highp uint "); - break; - case SVT_FLOAT: - case SVT_INT: - case SVT_DOUBLE: - case SVT_BOOL: - default: - ASSERT(0); - } - } - - ShaderVarName(glsl, psContext->psShader, cur_member.Name); - bcatcstr(glsl, ";\n"); - } - } - else - { - ASSERT(0); - } -} - -char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) -{ - bstring inputName; - char* cstr; - InOutSignature* psIn; - - if (eShaderType == GEOMETRY_SHADER) - { - inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else if (eShaderType == HULL_SHADER) - { - inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - else if (eShaderType == DOMAIN_SHADER) - { - inputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); - } - else if (eShaderType == PIXEL_SHADER) - { - if (psContext->flags & HLSLCC_FLAG_TESS_ENABLED) - { - inputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); - } - else - { - inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - } - else - { - ASSERT(eShaderType == VERTEX_SHADER); - inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); - } - if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn)) - { - bformata(inputName, "_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); - } - - cstr = bstr2cstr(inputName, '\0'); - bdestroy(inputName); - return cstr; -} - -char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, - const SHADER_TYPE eShaderType, - const Operand* psOperand, - int* piStream) -{ - bstring outputName; - char* cstr; - InOutSignature* psOut; - - int foundOutput = GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - psContext->psShader->ui32CurrentVertexOutputStream, - &psContext->psShader->sInfo, - &psOut); - - (void)(foundOutput); - ASSERT(foundOutput); - - if (eShaderType == GEOMETRY_SHADER) - { - if (psOut->ui32Stream != 0) - { - outputName = bformat("VtxGeoOutput%d_S%d", psOperand->ui32RegisterNumber, psOut->ui32Stream); - piStream[0] = psOut->ui32Stream; - } - else - { - outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - } - else if (eShaderType == DOMAIN_SHADER) - { - outputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); - } - else if (eShaderType == VERTEX_SHADER) - { - if (psContext->flags & HLSLCC_FLAG_GS_ENABLED) - { - outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else - { - outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - } - else if (eShaderType == PIXEL_SHADER) - { - outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); - } - else - { - ASSERT(eShaderType == HULL_SHADER); - outputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); - } - if (psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) - { - bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); - } - - cstr = bstr2cstr(outputName, '\0'); - bdestroy(outputName); - return cstr; -} -static void DeclareInput( - HLSLCrossCompilerContext* psContext, - const Declaration* psDecl, - const char* Interpolation, const char* StorageQualifier, const char* Precision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) -{ - Shader* psShader = psContext->psShader; - bstring glsl = *psContext->currentGLSLString; - - // This falls within the specified index ranges. The default is 0 if no input range is specified - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - return; - } - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - const char* vecType = "vec"; - const char* scalarType = "float"; - InOutSignature* psSignature = NULL; - - if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature)) - { - switch (psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - vecType = "uvec"; - scalarType = "uint"; - break; - } - case INOUT_COMPONENT_SINT32: - { - vecType = "ivec"; - scalarType = "int"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - } - - if (psShader->eShaderType == PIXEL_SHADER) - { - psShader->sInfo.aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; - } - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) || - (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage))) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - switch (eIndexDim) - { - case INDEX_2D: - { - if (iNumComponents == 1) - { - const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; - - bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, arraySize); - - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; - } - else - { - bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, psDecl->asOperands[0].aui32ArraySizes[0]); - - bformata(glsl, "%s %s%d Input%d[%d];\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].aui32ArraySizes[0]); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; - } - break; - } - default: - { - if (psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) - { - InputName = "TexCoord"; - } - - if (iNumComponents == 1) - { - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; - - bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - else - { - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) - { - bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - bformata(glsl, "%s %s%d Input%d[%d];\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; - } - else - { - bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "%s %s%d Input%d;\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - } - break; - } - } - } - - if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) - { - psContext->currentGLSLString = &psContext->earlyMain; - psContext->indent++; - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array - { - AddIndentation(psContext); - bformata(psContext->earlyMain, "Input%d = %s;\n", psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else - { - int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; - - while (arrayIndex) - { - AddIndentation(psContext); - bformata(psContext->earlyMain, "Input%d[%d] = %s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex - 1, InputName, arrayIndex - 1); - - arrayIndex--; - } - } - psContext->indent--; - psContext->currentGLSLString = &psContext->glsl; - } -} - -void AddBuiltinInput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName, uint32_t uNumComponents) -{ - (void)uNumComponents; - - bstring glsl = *psContext->currentGLSLString; - Shader* psShader = psContext->psShader; - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, &psDecl->asOperands[0]); - bformata(glsl, "%s ", GetConstructorForTypeGLSL(psContext, eType, 4, false)); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, ";\n"); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; - } - else - { - //This register has already been declared. The HLSL bytecode likely looks - //something like this then: - // dcl_input_ps constant v3.x - // dcl_input_ps_sgv v3.y, primitive_id - - //GLSL does not allow assignment to a varying! - } - - psContext->currentGLSLString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - - bformata(psContext->earlyMain, " = %s", builtinName); - - switch (psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); - // Invert w coordinate if necessary to be the same as SV_Position - if (psContext->psShader->eShaderType == PIXEL_SHADER) - { - if (psDecl->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE && - psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) - { - if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - uint32_t ui32IgnoreSwizzle; - bcatcstr(psContext->earlyMain, ";\n#ifdef EMULATE_DEPTH_CLAMP\n"); - AddIndentation(psContext); - TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); - bcatcstr(psContext->earlyMain, ".z = unclampedDepth;\n"); - bcatcstr(psContext->earlyMain, "#endif\n"); - } - if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - uint32_t ui32IgnoreSwizzle; - bcatcstr(psContext->earlyMain, ";\n"); - AddIndentation(psContext); - TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); - bcatcstr(psContext->earlyMain, ".w = 1.0 / "); - TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); - bcatcstr(psContext->earlyMain, ".w;\n"); - } - } - else - { - ASSERT(0); - } - } - - break; - default: - //Scalar built-in. Don't apply swizzle. - break; - } - bcatcstr(psContext->earlyMain, ";\n"); - - psContext->indent--; - psContext->currentGLSLString = &psContext->glsl; -} - -int OutputNeedsDeclaring(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) -{ - Shader* psShader = psContext->psShader; - - // Depth Output operands are a special case and won't have a ui32RegisterNumber, - // so first we have to check if the output operand is depth. - if (psShader->eShaderType == PIXEL_SHADER) - { - if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL) - { - return 1; - } - else if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) - { - return 0; // OpenGL doesn't need to declare depth output variable (gl_FragDepth) - } - } - - const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; - ASSERT(psOperand->ui32RegisterNumber >= 0); - ASSERT(psOperand->ui32RegisterNumber < MAX_SHADER_VEC4_OUTPUT); - if (psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) - { - int offset; - - for (offset = 0; offset < count; offset++) - { - psShader->aiOutputDeclared[psOperand->ui32RegisterNumber + offset] = declared; - } - return 1; - } - - return 0; -} - -void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) -{ - bstring glsl = *psContext->currentGLSLString; - Shader* psShader = psContext->psShader; - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - if (OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) - { - InOutSignature* psSignature = NULL; - - GetOutputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].ui32CompMask, - 0, - &psShader->sInfo, &psSignature); - - bcatcstr(glsl, "#undef "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "\n"); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, " phase%d_", psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "\n"); - - bcatcstr(glsl, "vec4 "); - bformata(glsl, "phase%d_", psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - if (arrayElements) - { - bformata(glsl, "[%d];\n", arrayElements); - } - else - { - bcatcstr(glsl, ";\n"); - } - - psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; - glsl = *psContext->currentGLSLString; - psContext->indent++; - if (arrayElements) - { - int elem; - for (elem = 0; elem < arrayElements; elem++) - { - AddIndentation(psContext); - bformata(glsl, "%s[%d] = %s(phase%d_", builtinName, elem, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, "[%d]", elem); - TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); - bformata(glsl, ");\n"); - } - } - else - { - if (psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) - { - int max = GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); - - int applySiwzzle = GetNumSwizzleElements(&psDecl->asOperands[0]) > 1 ? 1 : 0; - int index; - int i; - int multiplier = 1; - char* swizzle[] = {".x", ".y", ".z", ".w"}; - - ASSERT(psSignature != NULL); - - index = psSignature->ui32SemanticIndex; - - //Clip distance can be spread across 1 or 2 outputs (each no more than a vec4). - //Some examples: - //float4 clip[2] : SV_ClipDistance; //8 clip distances - //float3 clip[2] : SV_ClipDistance; //6 clip distances - //float4 clip : SV_ClipDistance; //4 clip distances - //float clip : SV_ClipDistance; //1 clip distance. - - //In GLSL the clip distance built-in is an array of up to 8 floats. - //So vector to array conversion needs to be done here. - if (index == 1) - { - InOutSignature* psFirstClipSignature; - if (GetOutputSignatureFromSystemValue(NAME_CLIP_DISTANCE, 1, &psShader->sInfo, &psFirstClipSignature)) - { - if (psFirstClipSignature->ui32Mask & (1 << 3)) - { - multiplier = 4; - } - else - if (psFirstClipSignature->ui32Mask & (1 << 2)) - { - multiplier = 3; - } - else - if (psFirstClipSignature->ui32Mask & (1 << 1)) - { - multiplier = 2; - } - } - } - - for (i = 0; i < max; ++i) - { - AddIndentation(psContext); - bformata(glsl, "%s[%d] = (phase%d_", builtinName, i + multiplier * index, psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - if (applySiwzzle) - { - bformata(glsl, ")%s;\n", swizzle[i]); - } - else - { - bformata(glsl, ");\n"); - } - } - } - else - { - uint32_t elements = GetNumSwizzleElements(&psDecl->asOperands[0]); - - if (elements != GetTypeElementCount(type)) - { - //This is to handle float3 position seen in control point phases - //struct HS_OUTPUT - //{ - // float3 vPosition : POSITION; - //}; -> dcl_output o0.xyz - //gl_Position is vec4. - AddIndentation(psContext); - bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, ", 1);\n"); - } - else - { - AddIndentation(psContext); - bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, ");\n"); - } - } - - if (psShader->eShaderType == VERTEX_SHADER && psDecl->asOperands[0].eSpecialName == NAME_POSITION) - { - if (psContext->flags & HLSLCC_FLAG_INVERT_CLIP_SPACE_Y) - { - AddIndentation(psContext); - bformata(glsl, "gl_Position.y = -gl_Position.y;\n"); - } - - if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#ifdef EMULATE_DEPTH_CLAMP\n"); - bcatcstr(glsl, "#if EMULATE_DEPTH_CLAMP == 1\n"); - AddIndentation(psContext); - bcatcstr(glsl, "unclampedDepth = gl_DepthRange.near + gl_DepthRange.diff * gl_Position.z / gl_Position.w;\n"); - bcatcstr(glsl, "#elif EMULATE_DEPTH_CLAMP == 2\n"); - AddIndentation(psContext); - bcatcstr(glsl, "unclampedZ = gl_DepthRange.diff * gl_Position.z;\n"); - bcatcstr(glsl, "#endif\n"); - AddIndentation(psContext); - bcatcstr(glsl, "gl_Position.z = 0.0;\n"); - } - - if (psContext->flags & HLSLCC_FLAG_CONVERT_CLIP_SPACE_Z) - { - if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#else\n"); - } - - AddIndentation(psContext); - bcatcstr(glsl, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); - } - - if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "#endif\n"); - } - } - } - psContext->indent--; - psContext->currentGLSLString = &psContext->glsl; - } -} - -void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) -{ - bstring glsl = *psContext->currentGLSLString; - Shader* psShader = psContext->psShader; - - if (OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - const char* Precision = ""; - const char* type = "vec"; - - InOutSignature* psSignature = NULL; - - GetOutputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].ui32CompMask, - psShader->ui32CurrentVertexOutputStream, - &psShader->sInfo, - &psSignature); - - switch (psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uvec"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "ivec"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - - if (HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch (psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - //type = "ivec"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - //type = "uvec"; - break; - } - } - } - - switch (psShader->eShaderType) - { - case PIXEL_SHADER: - { - switch (psDecl->asOperands[0].eType) - { - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - case OPERAND_TYPE_OUTPUT_DEPTH: - { - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - { - bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); - bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); - bcatcstr(glsl, "layout (depth_greater) out float gl_FragDepth;\n"); - bcatcstr(glsl, "#endif\n"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); - bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); - bcatcstr(glsl, "layout (depth_less) out float gl_FragDepth;\n"); - bcatcstr(glsl, "#endif\n"); - break; - } - default: - { - if (WriteToFragData(psContext->psShader->eTargetLanguage)) - { - bformata(glsl, "#define Output%d gl_FragData[%d]\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); - } - else - { - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, PIXEL_SHADER, psOperand, &stream); - - uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; - - // Check if we already defined this as a "inout" - if ((psContext->rendertargetUse[renderTarget] & INPUT_RENDERTARGET) == 0) - { - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) || HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage)) - { - uint32_t index = 0; - - if ((psContext->flags & HLSLCC_FLAG_DUAL_SOURCE_BLENDING) && DualSourceBlendSupported(psContext->psShader->eTargetLanguage)) - { - if (renderTarget > 0) - { - renderTarget = 0; - index = 1; - } - bformata(glsl, "layout(location = %d, index = %d) ", renderTarget, index); - } - else - { - bformata(glsl, "layout(location = %d) ", renderTarget); - } - } - - bformata(glsl, "out %s %s4 %s;\n", Precision, type, OutputName); - } - - if (stream) - { - bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); - } - else - { - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - } - bcstrfree(OutputName); - } - break; - } - } - break; - } - case VERTEX_SHADER: - { - int iNumComponents = 4; //GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); - - if (psShader->eShaderType == VERTEX_SHADER) - { - uint32_t ui32InterpImp = AddImport(psContext, SYMBOL_INPUT_INTERPOLATION_MODE, psDecl->asOperands[0].ui32RegisterNumber, (uint32_t)INTERPOLATION_LINEAR); - bformata(glsl, "#if IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_CONSTANT); - bformata(glsl, "#define Output%dInterpolation flat\n", psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_CENTROID); - bformata(glsl, "#define Output%dInterpolation centroid\n", psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE); - bformata(glsl, "#define Output%dInterpolation noperspective\n", psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID); - bformata(glsl, "#define Output%dInterpolation noperspective centroid\n", psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_SAMPLE); - bformata(glsl, "#define Output%dInterpolation sample\n", psDecl->asOperands[0].ui32RegisterNumber); - bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE); - bformata(glsl, "#define Output%dInterpolation noperspective sample\n", psDecl->asOperands[0].ui32RegisterNumber); - bcatcstr(glsl, "#else\n"); - bformata(glsl, "#define Output%dInterpolation \n", psDecl->asOperands[0].ui32RegisterNumber); - bcatcstr(glsl, "#endif\n"); - } - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - if (psShader->eShaderType == VERTEX_SHADER) - { - bformata(glsl, "Output%dInterpolation ", psDecl->asOperands[0].ui32RegisterNumber); - } - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - bformata(glsl, "out %s %s%d %s;\n", Precision, type, iNumComponents, OutputName); - } - else - { - bformata(glsl, "varying %s %s%d %s;\n", Precision, type, iNumComponents, OutputName); - } - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - bcstrfree(OutputName); - - break; - } - case GEOMETRY_SHADER: - { - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, GEOMETRY_SHADER, psOperand, &stream); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - bformata(glsl, "out %s4 %s;\n", type, OutputName); - if (stream) - { - bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); - } - else - { - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - } - bcstrfree(OutputName); - break; - } - case HULL_SHADER: - { - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, HULL_SHADER, psOperand, &stream); - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber != 0); //Reg 0 should be gl_out[gl_InvocationID].gl_Position. - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - bformata(glsl, "out %s4 %s[];\n", type, OutputName); - bformata(glsl, "#define Output%d %s[gl_InvocationID]\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - bcstrfree(OutputName); - break; - } - case DOMAIN_SHADER: - { - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, DOMAIN_SHADER, psOperand, &stream); - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - bformata(glsl, "out %s4 %s;\n", type, OutputName); - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - bcstrfree(OutputName); - break; - } - } - } - else - { - /* - Multiple outputs can be packed into one register. e.g. - // Name Index Mask Register SysValue Format Used - // -------------------- ----- ------ -------- -------- ------- ------ - // FACTOR 0 x 3 NONE int x - // MAX 0 y 3 NONE int y - - We want unique outputs to make it easier to use transform feedback. - - out ivec4 FACTOR0; - #define Output3 FACTOR0 - out ivec4 MAX0; - - MAIN SHADER CODE. Writes factor and max to Output3 which aliases FACTOR0. - - MAX0.x = FACTOR0.y; - - This unpacking of outputs is only done when using HLSLCC_FLAG_INOUT_SEMANTIC_NAMES. - When not set the application will be using HLSL reflection information to discover - what the input and outputs mean if need be. - */ - - // - - if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - InOutSignature* psSignature = NULL; - const char* type = "vec"; - int stream = 0; - char* OutputName = GetDeclaredOutputName(psContext, psShader->eShaderType, psOperand, &stream); - - GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - 0, - &psShader->sInfo, - &psSignature); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - switch (psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uvec"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "ivec"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - bformata(glsl, "out %s4 %s;\n", type, OutputName); - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; - glsl = *psContext->currentGLSLString; - - bcatcstr(glsl, OutputName); - bcstrfree(OutputName); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); - bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); - TranslateOperandSwizzle(psContext, psOperand); - bcatcstr(glsl, ";\n"); - - psContext->currentGLSLString = &psContext->glsl; - glsl = *psContext->currentGLSLString; - } - } -} - -void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf) -{ - bstring glsl = *psContext->currentGLSLString; - - uint32_t i, implicitOffset; - const char* Name = psCBuf->Name; - uint32_t auiSortedVars[MAX_SHADER_VARS]; - if (psCBuf->Name[0] == '$') //For $Globals - { - Name++; - } - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - PreDeclareStructType(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType); - } - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) - { - bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); - } - - bformata(glsl, "uniform "); - ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); - bformata(glsl, " {\n "); - - if (psCBuf->ui32NumVars > 0) - { - uint32_t bSorted = 1; - auiSortedVars[0] = 0; - for (i = 1; i < psCBuf->ui32NumVars; ++i) - { - auiSortedVars[i] = i; - bSorted = bSorted && psCBuf->asVars[i - 1].ui32StartOffset <= psCBuf->asVars[i].ui32StartOffset; - } - while (!bSorted) - { - bSorted = 1; - for (i = 1; i < psCBuf->ui32NumVars; ++i) - { - if (psCBuf->asVars[auiSortedVars[i - 1]].ui32StartOffset > psCBuf->asVars[auiSortedVars[i]].ui32StartOffset) - { - uint32_t uiTemp = auiSortedVars[i]; - auiSortedVars[i] = auiSortedVars[i - 1]; - auiSortedVars[i - 1] = uiTemp; - bSorted = 0; - } - } - } - } - - implicitOffset = 0; - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - uint32_t uVarAlignment, uVarSize; - ShaderVar* psVar = psCBuf->asVars + auiSortedVars[i]; - GetSTD140Layout(&psVar->sType, &uVarAlignment, &uVarSize); - - if ((implicitOffset + 16 - 1) / 16 < psVar->ui32StartOffset / 16) - { - uint32_t uNumPaddingUvecs = psVar->ui32StartOffset / 16 - (implicitOffset + 16 - 1) / 16; - bcatcstr(glsl, "\tuvec4 padding_"); - ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); - bformata(glsl, "_%d[%d];\n", implicitOffset, uNumPaddingUvecs); - implicitOffset = psVar->ui32StartOffset - psVar->ui32StartOffset % 16; - } - - if ((implicitOffset + 4 - 1) / 4 < psVar->ui32StartOffset / 4) - { - uint32_t uNumPaddingUints = psVar->ui32StartOffset / 4 - (implicitOffset + 4 - 1) / 4; - uint32_t uPaddingUint; - for (uPaddingUint = 0; uPaddingUint < uNumPaddingUints; ++uPaddingUint) - { - bcatcstr(glsl, "\tuint padding_"); - ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); - bformata(glsl, "_%d_%d;\n", psVar->ui32StartOffset, uPaddingUint); - } - implicitOffset = psVar->ui32StartOffset - psVar->ui32StartOffset % 4; - } - - implicitOffset += uVarAlignment - 1; - implicitOffset -= implicitOffset % uVarAlignment; - - ASSERT(implicitOffset == psVar->ui32StartOffset); - - DeclareConstBufferShaderVariable(psContext, psVar->sType.Name, &psVar->sType, 0); - implicitOffset += uVarSize; - } - - bcatcstr(glsl, "};\n"); -} - -void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, const Operand* psOperand, const uint32_t ui32GloballyCoherentAccess, const ResourceType eResourceType) -{ - const char* Name = psCBuf->Name; - bstring StructName; -#if !defined(NDEBUG) - uint32_t unnamed_struct = strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; -#endif - bstring glsl = *psContext->currentGLSLString; - - ASSERT(psCBuf->ui32NumVars == 1); - ASSERT(unnamed_struct); - - StructName = bfromcstr(""); - - //TranslateOperand(psContext, psOperand, TO_FLAG_NAME_ONLY); - if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) - { - bformata(StructName, "StructuredRes%d", psOperand->ui32RegisterNumber); - } - else if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) - { - bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); - } - else - { - bformata(StructName, "UAV%d", psOperand->ui32RegisterNumber); - } - - PreDeclareStructType(psContext, bstr2cstr(StructName, '\0'), &psCBuf->asVars[0].sType); - - // Add 'std430' layout for storage buffers. - // We don't use a global setting for all buffers because Mali drivers don't like that. - bcatcstr(glsl, "layout(std430"); - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - // If storage blocking binding is not supported, then we must set the binding location in the shader. If we don't do it, - // all the storage buffers of the program get assigned the same value (0). - // Unfortunately this could cause binding collisions between different render stages for a storage buffer. - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && - (!StorageBlockBindingSupported(psContext->psShader->eTargetLanguage) || (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0)) - { - bformata(glsl, ", binding = %d", ui32BindingPoint); - } - - // Close 'layout' - bcatcstr(glsl, ")"); - - if (ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) - { - bcatcstr(glsl, "coherent "); - } - - if (eResourceType == RTYPE_STRUCTURED) - { - bcatcstr(glsl, "readonly "); - } - - bcatcstr(glsl, "buffer "); - if (eResourceType == RTYPE_STRUCTURED) - { - ConvertToTextureName(glsl, psContext->psShader, Name, NULL, 0); - } - else - { - ConvertToUAVName(glsl, psContext->psShader, Name); - } - bcatcstr(glsl, " {\n "); - - DeclareConstBufferShaderVariable(psContext, bstr2cstr(StructName, '\0'), &psCBuf->asVars[0].sType, 1); - - bcatcstr(glsl, "};\n"); - - bdestroy(StructName); -} - -void DeclarePLSVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* plsVar, const Operand* psOperand, const uint32_t ui32GloballyCoherentAccess, const ResourceType eResourceType) -{ - (void)psOperand; - (void)ui32GloballyCoherentAccess; - (void)eResourceType; - - const char* Name = plsVar->Name; -#if !defined(NDEBUG) - uint32_t unnamed_struct = strcmp(plsVar->asVars[0].Name, "$Element") == 0 ? 1 : 0; -#endif - bstring glsl = *psContext->currentGLSLString; - - ASSERT(plsVar->ui32NumVars == 1); - ASSERT(unnamed_struct); - - // Define extension - // TODO: if we need more than one PLS var... we can't redefine the extension every time - // Extensions need to be declared before any non-preprocessor symbols. So we put it all the way at the beginning. - bstring ext = bfromcstralloc(1024, "#extension GL_EXT_shader_pixel_local_storage : require\n"); - bconcat(ext, glsl); - bassign(glsl, ext); - bdestroy(ext); - - switch (ui32BindingPoint) - { - case GMEM_PLS_RO_SLOT: - bcatcstr(glsl, "__pixel_local_inEXT PLS_STRUCT_READ_ONLY"); - break; - case GMEM_PLS_WO_SLOT: - bcatcstr(glsl, "__pixel_local_outEXT PLS_STRUCT_WRITE_ONLY"); - break; - case GMEM_PLS_RW_SLOT: - bcatcstr(glsl, "__pixel_localEXT PLS_STRUCT_READ_WRITE"); - break; - default: - ASSERT(0); - } - - bcatcstr(glsl, "\n{\n"); - - ASSERT(plsVar->ui32NumVars == 1); - ASSERT(plsVar->asVars[0].sType.Members != 0); - DeclarePLSStructVars(psContext, plsVar->asVars[0].sType.Name, &plsVar->asVars[0].sType); - - bcatcstr(glsl, "\n} "); - ConvertToUAVName(glsl, psContext->psShader, Name); - bcatcstr(glsl, ";\n\n"); -} - -void DeclareStructConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, const Operand* psOperand) -{ - bstring glsl = *psContext->currentGLSLString; - - uint32_t i; - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - PreDeclareStructType(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType); - } - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) - { - bformata(glsl, "layout(location = %d) ", ui32BindingPoint); - } - bcatcstr(glsl, "uniform struct "); - TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); - - bcatcstr(glsl, "_Type {\n"); - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - DeclareConstBufferShaderVariable(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType, 0); - } - - bcatcstr(glsl, "} "); - - TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); - - bcatcstr(glsl, ";\n"); -} - -void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) -{ - bstring glsl = *psContext->currentGLSLString; - Shader* psShader = psContext->psShader; - - switch (psDecl->eOpcode) - { - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_PS_SGV: - case OPCODE_DCL_INPUT_PS_SIV: - { - const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; - switch (eSpecialName) - { - case NAME_POSITION: - { - if (psShader->eShaderType == PIXEL_SHADER) - { - AddBuiltinInput(psContext, psDecl, "gl_FragCoord", 4); - } - else - { - AddBuiltinInput(psContext, psDecl, "gl_Position", 4); - } - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_Layer", 1); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinInput(psContext, psDecl, "gl_ClipDistance", 4); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_ViewportIndex", 1); - break; - } - case NAME_INSTANCE_ID: - { - AddBuiltinInput(psContext, psDecl, "uint(gl_InstanceID)", 1); - break; - } - case NAME_IS_FRONT_FACE: - { - /* - Cast to uint used because - if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. - Suggests no implicit conversion for bool<->uint. - */ - - AddBuiltinInput(psContext, psDecl, "uint(gl_FrontFacing)", 1); - break; - } - case NAME_SAMPLE_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_SampleID", 1); - break; - } - case NAME_VERTEX_ID: - { - AddBuiltinInput(psContext, psDecl, "uint(gl_VertexID)", 1); - break; - } - case NAME_PRIMITIVE_ID: - { - AddBuiltinInput(psContext, psDecl, "gl_PrimitiveID", 1); - break; - } - default: - { - bformata(glsl, "in vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); - break; - } - } - break; - } - - case OPCODE_DCL_OUTPUT_SIV: - { - switch (psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_Position"); - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_Layer"); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_ClipDistance"); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_ViewportIndex"); - break; - } - case NAME_VERTEX_ID: - { - ASSERT(0); //VertexID is not an output - break; - } - case NAME_PRIMITIVE_ID: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_PrimitiveID"); - break; - } - case NAME_INSTANCE_ID: - { - ASSERT(0); //InstanceID is not an output - break; - } - case NAME_IS_FRONT_FACE: - { - ASSERT(0); //FrontFacing is not an output - break; - } - case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: - { - if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 4, "gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); - break; - } - case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[3]"); - break; - } - case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: - { - if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 3, "gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); - break; - } - case NAME_FINAL_LINE_DENSITY_TESSFACTOR: - { - if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_LINE_DETAIL_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_TRI_INSIDE_TESSFACTOR: - case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: - { - if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelInner"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[0]"); - } - break; - } - case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[1]"); - break; - } - default: - { - bformata(glsl, "out vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); - break; - } - } - break; - } - case OPCODE_DCL_INPUT: - { - const Operand* psOperand = &psDecl->asOperands[0]; - //Force the number of components to be 4. - /*dcl_output o3.xy - dcl_output o3.z - - Would generate a vec2 and a vec3. We discard the second one making .z invalid! - - */ - int iNumComponents = 4; //GetMaxComponentFromComponentMask(psOperand); - const char* StorageQualifier = "attribute"; - char* InputName; - const char* Precision = ""; - - if ((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT) || - (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID) || - (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK) || - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID) || - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID) || - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP) || - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED)) - { - break; - } - - //Already declared as part of an array. - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - break; - } - - InputName = GetDeclaredInputName(psContext, psShader->eShaderType, psOperand); - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - StorageQualifier = "in"; - } - - if (HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch (psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - break; - } - } - } - - DeclareInput(psContext, psDecl, - "", StorageQualifier, Precision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); - bcstrfree(InputName); - - break; - } - case OPCODE_DCL_INPUT_SIV: - { - if (psShader->eShaderType == PIXEL_SHADER) - { - psShader->sInfo.aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; - } - break; - } - case OPCODE_DCL_INPUT_PS: - { - const Operand* psOperand = &psDecl->asOperands[0]; - int iNumComponents = 4; //GetMaxComponentFromComponentMask(psOperand); - const char* StorageQualifier = "varying"; - const char* Precision = ""; - char* InputName = GetDeclaredInputName(psContext, PIXEL_SHADER, psOperand); - const char* Interpolation = ""; - - //Already declared as part of an array. - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - break; - } - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - StorageQualifier = "in"; - } - - switch (psDecl->value.eInterpolation) - { - case INTERPOLATION_CONSTANT: - { - Interpolation = "flat"; - break; - } - case INTERPOLATION_LINEAR: - { - break; - } - case INTERPOLATION_LINEAR_CENTROID: - { - Interpolation = "centroid"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE: - { - Interpolation = "noperspective"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: - { - Interpolation = "noperspective centroid"; - break; - } - case INTERPOLATION_LINEAR_SAMPLE: - { - Interpolation = "sample"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: - { - Interpolation = "noperspective sample"; - break; - } - } - - if (HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch (psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - break; - } - } - } - - DeclareInput(psContext, psDecl, - Interpolation, StorageQualifier, Precision, iNumComponents, INDEX_1D, InputName); - bcstrfree(InputName); - - break; - } - case OPCODE_DCL_TEMPS: - { - const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; - - if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) - { - break; - } - - if (ui32NumTemps > 0) - { - bformata(glsl, "vec4 Temp[%d];\n", ui32NumTemps); - if (psContext->psShader->bUseTempCopy) - { - bcatcstr(glsl, "vec4 TempCopy;\n"); - } - - bformata(glsl, "ivec4 Temp_int[%d];\n", ui32NumTemps); - if (psContext->psShader->bUseTempCopy) - { - bcatcstr(glsl, "vec4 TempCopy_int;\n"); - } - if (HaveUVec(psShader->eTargetLanguage)) - { - bformata(glsl, "uvec4 Temp_uint[%d];\n", ui32NumTemps); - if (psContext->psShader->bUseTempCopy) - { - bcatcstr(glsl, "uvec4 TempCopy_uint;\n"); - } - } - if (psShader->fp64) - { - bformata(glsl, "dvec4 Temp_double[%d];\n", ui32NumTemps); - if (psContext->psShader->bUseTempCopy) - { - bcatcstr(glsl, "dvec4 TempCopy_double;\n"); - } - } - } - - break; - } - case OPCODE_SPECIAL_DCL_IMMCONST: - { - const Operand* psDest = &psDecl->asOperands[0]; - const Operand* psSrc = &psDecl->asOperands[1]; - - ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); - if (psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) - { - bformata(glsl, "const ivec4 IntImmConst%d = ", psDest->ui32RegisterNumber); - } - else - { - bformata(glsl, "const vec4 ImmConst%d = ", psDest->ui32RegisterNumber); - AddToDx9ImmConstIndexableArray(psContext, psDest); - } - TranslateOperand(psContext, psSrc, TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); - - break; - } - case OPCODE_DCL_CONSTANT_BUFFER: - { - const Operand* psOperand = &psDecl->asOperands[0]; - const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; - - ConstantBuffer* psCBuf = NULL; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - if (psCBuf) - { - // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. - // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads - // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. - psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; - } - - // We don't have a original resource name, maybe generate one??? - if (!psCBuf) - { - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) - { - bformata(glsl, "layout(location = %d) ", ui32BindingPoint); - } - - bformata(glsl, "layout(std140) uniform ConstantBuffer%d {\n\tvec4 data[%d];\n} cb%d;\n", ui32BindingPoint, psOperand->aui32ArraySizes[1], ui32BindingPoint); - break; - } - else if (psCBuf->blob) - { - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) - { - bformata(glsl, "layout(location = %d) ", ui32BindingPoint); - } - - bcatcstr(glsl, "layout(std140) uniform "); - ConvertToUniformBufferName(glsl, psShader, psCBuf->Name); - bcatcstr(glsl, " {\n\tvec4 "); - ConvertToUniformBufferName(glsl, psShader, psCBuf->Name); - bformata(glsl, "_data[%d];\n};\n", psOperand->aui32ArraySizes[1]); - break; - } - - if (psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) - { - if (psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO && psCBuf->Name[0] == '$') - { - DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand); - } - else - { - DeclareUBOConstants(psContext, ui32BindingPoint, psCBuf); - } - } - else - { - DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand); - } - break; - } - case OPCODE_DCL_RESOURCE: - { - bool isGmemResource = false; - const int initialMemSize = 64; - bstring earlyMain = bfromcstralloc(initialMemSize, ""); - if (IsGmemReservedSlot(FBF_EXT_COLOR, psDecl->asOperands[0].ui32RegisterNumber)) - { - // A GMEM reserve slot was used. - // This is not a resource but an inout RT of the pixel shader - int regNum = GetGmemInputResourceSlot(psDecl->asOperands[0].ui32RegisterNumber); - // FXC thinks this is a texture so we can't trust the number of elements. We get that from the "register number". - int numElements = GetGmemInputResourceNumElements(psDecl->asOperands[0].ui32RegisterNumber); - ASSERT(numElements); - - const char* Precision = "highp"; - const char* outputName = "PixOutput"; - - bformata(glsl, "layout(location = %d) ", regNum); - bformata(glsl, "inout %s vec%d %s%d;\n", Precision, numElements, outputName, regNum); - - const char* mask[] = { "x", "y", "z", "w" }; - // Since we are using Textures as GMEM inputs FXC will threat them as vec4 values. The rendertarget may not be a vec4 (numElements != 4) - // so we create a new variable (GMEM_InputXX) at the beginning of the shader that wraps the rendertarget value. - bformata(earlyMain, "%s vec4 GMEM_Input%d = %s vec4(%s%d.", Precision, regNum, Precision, outputName, regNum); - for (int i = 0; i < 4; ++i) - { - bformata(earlyMain, "%s", i < numElements ? mask[i] : mask[numElements - 1]); - } - bcatcstr(earlyMain, ");\n"); - isGmemResource = true; - } - else if (IsGmemReservedSlot(FBF_ARM_COLOR, psDecl->asOperands[0].ui32RegisterNumber)) - { - bcatcstr(earlyMain, "vec4 GMEM_Input0 = vec4(gl_LastFragColorARM);\n"); - isGmemResource = true; - } - else if (IsGmemReservedSlot(FBF_ARM_DEPTH, psDecl->asOperands[0].ui32RegisterNumber)) - { - bcatcstr(earlyMain, "vec4 GMEM_Depth = vec4(gl_LastFragDepthARM);\n"); - isGmemResource = true; - } - else if (IsGmemReservedSlot(FBF_ARM_STENCIL, psDecl->asOperands[0].ui32RegisterNumber)) - { - bcatcstr(earlyMain, "ivec4 GMEM_Stencil = ivec4(gl_LastFragStencilARM);\n"); - isGmemResource = true; - } - - if (isGmemResource) - { - if (earlyMain->slen) - { - bstring* savedStringPtr = psContext->currentGLSLString; - psContext->currentGLSLString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - bconcat(*psContext->currentGLSLString, earlyMain); - psContext->indent--; - psContext->currentGLSLString = savedStringPtr; - } - break; - } - - char* szResourceTypeName = ""; - uint32_t bCanBeCompare; - uint32_t i; - SamplerMask sMask; - - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) - { - //Constant buffer locations start at 0. Resource locations start at ui32NumConstantBuffers. - bformata(glsl, "layout(location = %d) ", psContext->psShader->sInfo.ui32NumConstantBuffers + psDecl->asOperands[0].ui32RegisterNumber); - } - - switch (psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_BUFFER: - szResourceTypeName = "Buffer"; - bCanBeCompare = 0; - break; - case RESOURCE_DIMENSION_TEXTURE1D: - szResourceTypeName = "1D"; - bCanBeCompare = 1; - break; - case RESOURCE_DIMENSION_TEXTURE2D: - szResourceTypeName = "2D"; - bCanBeCompare = 1; - break; - case RESOURCE_DIMENSION_TEXTURE2DMS: - szResourceTypeName = "2DMS"; - bCanBeCompare = 0; - break; - case RESOURCE_DIMENSION_TEXTURE3D: - szResourceTypeName = "3D"; - bCanBeCompare = 0; - break; - case RESOURCE_DIMENSION_TEXTURECUBE: - szResourceTypeName = "Cube"; - bCanBeCompare = 1; - break; - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - szResourceTypeName = "1DArray"; - bCanBeCompare = 1; - break; - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - szResourceTypeName = "2DArray"; - bCanBeCompare = 1; - break; - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - szResourceTypeName = "2DMSArray"; - bCanBeCompare = 0; - break; - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - szResourceTypeName = "CubeArray"; - bCanBeCompare = 1; - break; - } - - for (i = 0; i < psShader->sInfo.ui32NumSamplers; ++i) - { - if (psShader->sInfo.asSamplers[i].sMask.ui10TextureBindPoint == psDecl->asOperands[0].ui32RegisterNumber) - { - sMask = psShader->sInfo.asSamplers[i].sMask; - - if (bCanBeCompare && sMask.bCompareSample) // Sampled with depth comparison - { - bformata(glsl, "uniform sampler%sShadow ", szResourceTypeName); - TextureName(*psContext->currentGLSLString, psContext->psShader, psDecl->asOperands[0].ui32RegisterNumber, sMask.ui10SamplerBindPoint, 1); - bcatcstr(glsl, ";\n"); - } - if (sMask.bNormalSample || !sMask.bCompareSample) // Either sampled normally or with texelFetch - { - if (psDecl->ui32TexReturnType == RETURN_TYPE_SINT) - { - bformata(glsl, "uniform isampler%s ", szResourceTypeName); - } - else if (psDecl->ui32TexReturnType == RETURN_TYPE_UINT) - { - bformata(glsl, "uniform usampler%s ", szResourceTypeName); - } - else - { - bformata(glsl, "uniform sampler%s ", szResourceTypeName); - } - TextureName(*psContext->currentGLSLString, psContext->psShader, psDecl->asOperands[0].ui32RegisterNumber, sMask.ui10SamplerBindPoint, 0); - bcatcstr(glsl, ";\n"); - } - } - } - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); - psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; - break; - } - case OPCODE_DCL_OUTPUT: - { - if (psShader->eShaderType == HULL_SHADER && psDecl->asOperands[0].ui32RegisterNumber == 0) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_out[gl_InvocationID].gl_Position"); - } - else - { - AddUserOutput(psContext, psDecl); - } - break; - } - case OPCODE_DCL_GLOBAL_FLAGS: - { - uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; - - // OpenGL versions lower than 4.1 don't support the - // layout(early_fragment_tests) directive and will fail to compile - // the shader - if (ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL && EarlyDepthTestSupported(psShader->eTargetLanguage) && - !(psShader->eGmemType & (FBF_ARM_DEPTH | FBF_ARM_STENCIL))) // Early fragment test is not allowed when fetching from the depth/stencil buffer. - { - bcatcstr(glsl, "layout(early_fragment_tests) in;\n"); - } - if (!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) - { - //TODO add precise - //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx - } - if (ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) - { - bcatcstr(glsl, "#extension GL_ARB_gpu_shader_fp64 : enable\n"); - psShader->fp64 = 1; - } - break; - } - - case OPCODE_DCL_THREAD_GROUP: - { - bformata(glsl, "layout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\n", - psDecl->value.aui32WorkGroupSize[0], - psDecl->value.aui32WorkGroupSize[1], - psDecl->value.aui32WorkGroupSize[2]); - break; - } - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - { - if (psContext->psShader->eShaderType == HULL_SHADER) - { - psContext->psShader->sInfo.eTessOutPrim = psDecl->value.eTessOutPrim; - } - break; - } - case OPCODE_DCL_TESS_DOMAIN: - { - if (psContext->psShader->eShaderType == DOMAIN_SHADER) - { - switch (psDecl->value.eTessDomain) - { - case TESSELLATOR_DOMAIN_ISOLINE: - { - bcatcstr(glsl, "layout(isolines) in;\n"); - break; - } - case TESSELLATOR_DOMAIN_TRI: - { - bcatcstr(glsl, "layout(triangles) in;\n"); - break; - } - case TESSELLATOR_DOMAIN_QUAD: - { - bcatcstr(glsl, "layout(quads) in;\n"); - break; - } - default: - { - break; - } - } - } - break; - } - case OPCODE_DCL_TESS_PARTITIONING: - { - if (psContext->psShader->eShaderType == HULL_SHADER) - { - psContext->psShader->sInfo.eTessPartitioning = psDecl->value.eTessPartitioning; - } - break; - } - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - { - switch (psDecl->value.eOutputPrimitiveTopology) - { - case PRIMITIVE_TOPOLOGY_POINTLIST: - { - bcatcstr(glsl, "layout(points) out;\n"); - break; - } - case PRIMITIVE_TOPOLOGY_LINELIST_ADJ: - case PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: - case PRIMITIVE_TOPOLOGY_LINELIST: - case PRIMITIVE_TOPOLOGY_LINESTRIP: - { - bcatcstr(glsl, "layout(line_strip) out;\n"); - break; - } - - case PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: - case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: - case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: - case PRIMITIVE_TOPOLOGY_TRIANGLELIST: - { - bcatcstr(glsl, "layout(triangle_strip) out;\n"); - break; - } - default: - { - break; - } - } - break; - } - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - { - bformata(glsl, "layout(max_vertices = %d) out;\n", psDecl->value.ui32MaxOutputVertexCount); - break; - } - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - { - switch (psDecl->value.eInputPrimitive) - { - case PRIMITIVE_POINT: - { - bcatcstr(glsl, "layout(points) in;\n"); - break; - } - case PRIMITIVE_LINE: - { - bcatcstr(glsl, "layout(lines) in;\n"); - break; - } - case PRIMITIVE_LINE_ADJ: - { - bcatcstr(glsl, "layout(lines_adjacency) in;\n"); - break; - } - case PRIMITIVE_TRIANGLE: - { - bcatcstr(glsl, "layout(triangles) in;\n"); - break; - } - case PRIMITIVE_TRIANGLE_ADJ: - { - bcatcstr(glsl, "layout(triangles_adjacency) in;\n"); - break; - } - default: - { - break; - } - } - break; - } - case OPCODE_DCL_INTERFACE: - { - const uint32_t interfaceID = psDecl->value.interface.ui32InterfaceID; - const uint32_t numUniforms = psDecl->value.interface.ui32ArraySize; - const uint32_t ui32NumBodiesPerTable = psContext->psShader->funcPointer[interfaceID].ui32NumBodiesPerTable; - ShaderVar* psVar; - uint32_t varFound; - - const char* uniformName; - - varFound = GetInterfaceVarFromOffset(interfaceID, &psContext->psShader->sInfo, &psVar); - ASSERT(varFound); - uniformName = &psVar->sType.Name[0]; - - bformata(glsl, "subroutine uniform SubroutineType %s[%d*%d];\n", uniformName, numUniforms, ui32NumBodiesPerTable); - break; - } - case OPCODE_DCL_FUNCTION_BODY: - { - //bformata(glsl, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); - break; - } - case OPCODE_DCL_FUNCTION_TABLE: - { - break; - } - case OPCODE_CUSTOMDATA: - { - const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; - const uint32_t ui32NumVec4Minus1 = (ui32NumVec4 - 1); - uint32_t ui32ConstIndex = 0; - int integerCoords[4]; - bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; - - if (qualcommWorkaround) - { - bformata(glsl, "const "); - } - - bformata(glsl, "ivec4 immediateConstBufferInt[%d] = ivec4[%d] (\n", ui32NumVec4, ui32NumVec4); - for (ui32ConstIndex = 0; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) - { - integerCoords[0] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - integerCoords[1] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - integerCoords[2] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - integerCoords[3] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - - bformata(glsl, "\tivec4(%d, %d, %d, %d), \n", integerCoords[0], integerCoords[1], integerCoords[2], integerCoords[3]); - } - //No trailing comma on this one - integerCoords[0] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - integerCoords[1] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - integerCoords[2] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - integerCoords[3] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - - bformata(glsl, "\tivec4(%d, %d, %d, %d)\n", integerCoords[0], integerCoords[1], integerCoords[2], integerCoords[3]); - bcatcstr(glsl, ");\n"); - - //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. - //else 2 buffers - one integer and one float. - More data - - if (ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) - { - float floatCoords[4]; - bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(glsl, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); - - bformata(glsl, "vec4 immediateConstBuffer[%d] = vec4[%d] (\n", ui32NumVec4, ui32NumVec4); - for (ui32ConstIndex = 0; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) - { - floatCoords[0] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - floatCoords[1] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - floatCoords[2] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - floatCoords[3] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - - //A single vec4 can mix integer and float types. - //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. - if (fpcheck(floatCoords[0])) - { - floatCoords[0] = 0; - } - if (fpcheck(floatCoords[1])) - { - floatCoords[1] = 0; - } - if (fpcheck(floatCoords[2])) - { - floatCoords[2] = 0; - } - if (fpcheck(floatCoords[3])) - { - floatCoords[3] = 0; - } - - bformata(glsl, "\tvec4(%e, %e, %e, %e), \n", floatCoords[0], floatCoords[1], floatCoords[2], floatCoords[3]); - } - //No trailing comma on this one - floatCoords[0] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - floatCoords[1] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - floatCoords[2] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - floatCoords[3] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - if (fpcheck(floatCoords[0])) - { - floatCoords[0] = 0; - } - if (fpcheck(floatCoords[1])) - { - floatCoords[1] = 0; - } - if (fpcheck(floatCoords[2])) - { - floatCoords[2] = 0; - } - if (fpcheck(floatCoords[3])) - { - floatCoords[3] = 0; - } - bformata(glsl, "\tvec4(%e, %e, %e, %e)\n", floatCoords[0], floatCoords[1], floatCoords[2], floatCoords[3]); - bcatcstr(glsl, ");\n"); - } - else - { - if (qualcommWorkaround) - { - bcatcstr(glsl, "ivec4 immediateConstBufferI(int idx) { return immediateConstBufferInt[idx]; }\n"); - bcatcstr(glsl, "vec4 immediateConstBufferF(int idx) { return intBitsToFloat(immediateConstBufferInt[idx]); }\n"); - } - else - { - bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(glsl, "#define immediateConstBufferF(idx) intBitsToFloat(immediateConstBufferInt[idx])\n"); - } - } - - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - const uint32_t forkPhaseNum = psDecl->value.aui32HullPhaseInstanceInfo[0]; - const uint32_t instanceCount = psDecl->value.aui32HullPhaseInstanceInfo[1]; - bformata(glsl, "const int HullPhase%dInstanceCount = %d;\n", forkPhaseNum, instanceCount); - break; - } - case OPCODE_DCL_INDEXABLE_TEMP: - { - const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; - const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; - const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; - bformata(glsl, "vec%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - bformata(glsl, "ivec%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - if (HaveUVec(psShader->eTargetLanguage)) - { - bformata(glsl, "uvec%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - } - if (psShader->fp64) - { - bformata(glsl, "dvec%d TempArray%d_double[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - } - break; - } - case OPCODE_DCL_INDEX_RANGE: - { - break; - } - case OPCODE_HS_DECLS: - { - break; - } - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - { - if (psContext->psShader->eShaderType == HULL_SHADER) - { - bformata(glsl, "layout(vertices=%d) out;\n", psDecl->value.ui32MaxOutputVertexCount); - } - break; - } - case OPCODE_HS_FORK_PHASE: - { - break; - } - case OPCODE_HS_JOIN_PHASE: - { - break; - } - case OPCODE_DCL_SAMPLER: - { - break; - } - case OPCODE_DCL_HS_MAX_TESSFACTOR: - { - //For GLSL the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - { - if (psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) - { - bcatcstr(glsl, "coherent "); - } - - if (psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] == 0) - { - bcatcstr(glsl, "writeonly "); - } - else - { - if (psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) - { - bcatcstr(glsl, "readonly "); - } - - switch (psDecl->sUAV.Type) - { - case RETURN_TYPE_FLOAT: - bcatcstr(glsl, "layout(rgba32f) "); - break; - case RETURN_TYPE_UNORM: - bcatcstr(glsl, "layout(rgba8) "); - break; - case RETURN_TYPE_SNORM: - bcatcstr(glsl, "layout(rgba8_snorm) "); - break; - case RETURN_TYPE_UINT: - bcatcstr(glsl, "layout(rgba32ui) "); - break; - case RETURN_TYPE_SINT: - bcatcstr(glsl, "layout(rgba32i) "); - break; - default: - ASSERT(0); - } - } - - { - char* prefix = ""; - switch (psDecl->sUAV.Type) - { - case RETURN_TYPE_UINT: - prefix = "u"; - break; - case RETURN_TYPE_SINT: - prefix = "i"; - break; - default: - break; - } - - switch (psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_BUFFER: - bformata(glsl, "uniform %simageBuffer ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE1D: - bformata(glsl, "uniform %simage1D ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE2D: - bformata(glsl, "uniform %simage2D ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE2DMS: - bformata(glsl, "uniform %simage2DMS ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE3D: - bformata(glsl, "uniform %simage3D ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURECUBE: - bformata(glsl, "uniform %simageCube ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - bformata(glsl, "uniform %simage1DArray ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - bformata(glsl, "uniform %simage2DArray ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - bformata(glsl, "uniform %simage3DArray ", prefix); - break; - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - bformata(glsl, "uniform %simageCubeArray ", prefix); - break; - } - } - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - { - const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; - ConstantBuffer* psCBuf = NULL; - - if (psDecl->sUAV.bCounter) - { - bformata(glsl, "layout (binding = 1) uniform atomic_uint UAV%d_counter;\n", psDecl->asOperands[0].ui32RegisterNumber); - } - - GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - if (ui32BindingPoint >= GMEM_PLS_RO_SLOT && ui32BindingPoint <= GMEM_PLS_RW_SLOT) - { - DeclarePLSVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED); - } - else - { - DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED); - } - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - { - bstring varName; - if (psDecl->sUAV.bCounter) - { - bformata(glsl, "layout (binding = 1) uniform atomic_uint UAV%d_counter;\n", psDecl->asOperands[0].ui32RegisterNumber); - } - - varName = bfromcstralloc(16, ""); - bformata(varName, "UAV%d", psDecl->asOperands[0].ui32RegisterNumber); - - bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); - ShaderVarName(glsl, psShader, bstr2cstr(varName, '\0')); - bcatcstr(glsl, "[];\n};\n"); - - bdestroy(varName); - break; - } - case OPCODE_DCL_RESOURCE_STRUCTURED: - { - ConstantBuffer* psCBuf = NULL; - - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], 0, RTYPE_STRUCTURED); - break; - } - case OPCODE_DCL_RESOURCE_RAW: - { - bstring varName = bfromcstralloc(16, ""); - bformata(varName, "RawRes%d", psDecl->asOperands[0].ui32RegisterNumber); - - bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); - ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); - bcatcstr(glsl, "[];\n};\n"); - - bdestroy(varName); - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - { - ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); - ASSERT(psDecl->sTGSM.ui32Count == 1); - - bcatcstr(glsl, "shared uint "); - - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, "[%d];\n", psDecl->sTGSM.ui32Count); - - memset(psVarType, 0, sizeof(ShaderVarType)); - strcpy(psVarType->Name, "$Element"); - - psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; - psVarType->Elements = psDecl->sTGSM.ui32Count; - psVarType->Type = SVT_UINT; - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - { - ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); - - bcatcstr(glsl, "shared struct {\n"); - bformata(glsl, "uint value[%d];\n", psDecl->sTGSM.ui32Stride / 4); - bcatcstr(glsl, "} "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, "[%d];\n", - psDecl->sTGSM.ui32Count); - - memset(psVarType, 0, sizeof(ShaderVarType)); - strcpy(psVarType->Name, "$Element"); - - psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; - psVarType->Elements = psDecl->sTGSM.ui32Count; - psVarType->Type = SVT_UINT; - break; - } - case OPCODE_DCL_STREAM: - { - ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_STREAM); - - psShader->ui32CurrentVertexOutputStream = psDecl->asOperands[0].ui32RegisterNumber; - - bformata(glsl, "layout(stream = %d) out;\n", psShader->ui32CurrentVertexOutputStream); - - break; - } - case OPCODE_DCL_GS_INSTANCE_COUNT: - { - bformata(glsl, "layout(invocations = %d) in;\n", psDecl->value.ui32GSInstanceCount); - break; - } - default: - { - ASSERT(0); - break; - } - } -} - -//Convert from per-phase temps to global temps for GLSL. -void ConsolidateHullTempVars(Shader* psShader) -{ - uint32_t i, k; - const uint32_t ui32NumDeclLists = 3 + psShader->ui32ForkPhaseCount; - Declaration* pasDeclArray[3 + MAX_FORK_PHASES]; - uint32_t aui32DeclCounts[3 + MAX_FORK_PHASES]; - uint32_t ui32NumTemps = 0; - - i = 0; - - pasDeclArray[i] = psShader->psHSDecl; - aui32DeclCounts[i++] = psShader->ui32HSDeclCount; - - pasDeclArray[i] = psShader->psHSControlPointPhaseDecl; - aui32DeclCounts[i++] = psShader->ui32HSControlPointDeclCount; - for (k = 0; k < psShader->ui32ForkPhaseCount; ++k) - { - pasDeclArray[i] = psShader->apsHSForkPhaseDecl[k]; - aui32DeclCounts[i++] = psShader->aui32HSForkDeclCount[k]; - } - pasDeclArray[i] = psShader->psHSJoinPhaseDecl; - aui32DeclCounts[i++] = psShader->ui32HSJoinDeclCount; - - for (k = 0; k < ui32NumDeclLists; ++k) - { - for (i = 0; i < aui32DeclCounts[k]; ++i) - { - Declaration* psDecl = pasDeclArray[k] + i; - - if (psDecl->eOpcode == OPCODE_DCL_TEMPS) - { - if (ui32NumTemps < psDecl->value.ui32NumTemps) - { - //Find the total max number of temps needed by the entire - //shader. - ui32NumTemps = psDecl->value.ui32NumTemps; - } - //Only want one global temp declaration. - psDecl->value.ui32NumTemps = 0; - } - } - } - - //Find the first temp declaration and make it - //declare the max needed amount of temps. - for (k = 0; k < ui32NumDeclLists; ++k) - { - for (i = 0; i < aui32DeclCounts[k]; ++i) - { - Declaration* psDecl = pasDeclArray[k] + i; - - if (psDecl->eOpcode == OPCODE_DCL_TEMPS) - { - psDecl->value.ui32NumTemps = ui32NumTemps; - return; - } - } - } -} - -const char* GetMangleSuffix(const SHADER_TYPE eShaderType) -{ - switch (eShaderType) - { - case VERTEX_SHADER: - return "VS"; - case PIXEL_SHADER: - return "PS"; - case GEOMETRY_SHADER: - return "GS"; - case HULL_SHADER: - return "HS"; - case DOMAIN_SHADER: - return "DS"; - case COMPUTE_SHADER: - return "CS"; - } - ASSERT(0); - return ""; -} - diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c deleted file mode 100644 index e5124b4122..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c +++ /dev/null @@ -1,5598 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toGLSLInstruction.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/languages.h" -#include "internal_includes/hlslccToolkit.h" -#include "bstrlib.h" -#include "stdio.h" -#include "internal_includes/debug.h" - -#include <stdbool.h> - -#ifndef min -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); -extern void WriteEndTrace(HLSLCrossCompilerContext* psContext); - -typedef enum -{ - CMP_EQ, - CMP_LT, - CMP_GE, - CMP_NE, -} ComparisonType; - -void BeginAssignmentEx(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate, const char* szDestSwizzle) -{ - if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) - { - const char* szCastFunction = ""; - SHADER_VARIABLE_TYPE eSrcType; - SHADER_VARIABLE_TYPE eDestType = GetOperandDataType(psContext, psDestOperand); - uint32_t uDestElemCount = GetNumSwizzleElements(psDestOperand); - - eSrcType = TypeFlagsToSVTType(uSrcToFlag); - if (bSaturate) - { - eSrcType = SVT_FLOAT; - } - - if (!DoAssignmentDataTypesMatch(eDestType, eSrcType)) - { - switch (eDestType) - { - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - { - switch (eSrcType) - { - case SVT_UINT: - case SVT_UINT16: - szCastFunction = GetConstructorForTypeGLSL(psContext, eDestType, uDestElemCount, false); - break; - case SVT_FLOAT: - szCastFunction = "floatBitsToInt"; - break; - default: - // Bitcasts from lower precisions floats are ambiguous - ASSERT(0); - break; - } - } - break; - case SVT_UINT: - case SVT_UINT16: - { - switch (eSrcType) - { - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - szCastFunction = GetConstructorForTypeGLSL(psContext, eDestType, uDestElemCount, false); - break; - case SVT_FLOAT: - szCastFunction = "floatBitsToUint"; - break; - default: - // Bitcasts from lower precisions floats are ambiguous - ASSERT(0); - break; - } - } - break; - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - { - switch (eSrcType) - { - case SVT_UINT: - szCastFunction = "uintBitsToFloat"; - break; - case SVT_INT: - szCastFunction = "intBitsToFloat"; - break; - default: - // Bitcasts from lower precisions int/uint are ambiguous - ASSERT(0); - break; - } - } - break; - default: - ASSERT(0); - break; - } - } - - TranslateOperand(psContext, psDestOperand, TO_FLAG_DESTINATION); - if (szDestSwizzle) - { - bformata(*psContext->currentGLSLString, ".%s = %s(", szDestSwizzle, szCastFunction); - } - else - { - bformata(*psContext->currentGLSLString, " = %s(", szCastFunction); - } - } - else - { - TranslateOperand(psContext, psDestOperand, TO_FLAG_DESTINATION | uSrcToFlag); - if (szDestSwizzle) - { - bformata(*psContext->currentGLSLString, ".%s = ", szDestSwizzle); - } - else - { - bcatcstr(*psContext->currentGLSLString, " = "); - } - } - if (bSaturate) - { - bcatcstr(*psContext->currentGLSLString, "clamp("); - } -} - -void BeginAssignment(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate) -{ - BeginAssignmentEx(psContext, psDestOperand, uSrcToFlag, bSaturate, NULL); -} - -void EndAssignment(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate) -{ - (void)psDestOperand; - (void)uSrcToFlag; - - if (bSaturate) - { - bcatcstr(*psContext->currentGLSLString, ", 0.0, 1.0)"); - } - - if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) - { - bcatcstr(*psContext->currentGLSLString, ")"); - } -} - -static void AddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, ComparisonType eType, - uint32_t typeFlag) -{ - bstring glsl = *psContext->currentGLSLString; - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - const uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); - - uint32_t minElemCount = destElemCount < s0ElemCount ? destElemCount : s0ElemCount; - - minElemCount = s1ElemCount < minElemCount ? s1ElemCount : minElemCount; - - if (typeFlag == TO_FLAG_NONE) - { - const SHADER_VARIABLE_TYPE e0Type = GetOperandDataType(psContext, &psInst->asOperands[1]); - const SHADER_VARIABLE_TYPE e1Type = GetOperandDataType(psContext, &psInst->asOperands[2]); - if (e0Type != e1Type) - { - typeFlag = TO_FLAG_INTEGER; - } - else - { - switch (e0Type) - { - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - typeFlag = TO_FLAG_INTEGER; - break; - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - typeFlag = TO_FLAG_UNSIGNED_INTEGER; - break; - default: - typeFlag = TO_FLAG_FLOAT; - } - } - } - - if (destElemCount > 1) - { - const char* glslOpcode [] = { - "equal", - "lessThan", - "greaterThanEqual", - "notEqual", - }; - char* constructor = "vec"; - - if (typeFlag & TO_FLAG_INTEGER) - { - constructor = "ivec"; - } - else if (typeFlag & TO_FLAG_UNSIGNED_INTEGER) - { - constructor = "uvec"; - } - - bstring varName = bfromcstr(GetAuxArgumentName(SVT_UINT)); - bcatcstr(varName, "1"); - - //Component-wise compare - AddIndentation(psContext); - if (psContext->psShader->ui32MajorVersion < 4) - { - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - } - else - { - // Qualcomm driver workaround. Save the operation result into - // a temporary variable before assigning it to the register. - bconcat(glsl, varName); - AddSwizzleUsingElementCount(psContext, minElemCount); - bcatcstr(glsl, " = "); - } - - bformata(glsl, "uvec%d(%s(%s4(", minElemCount, glslOpcode[eType], constructor); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - //AddSwizzleUsingElementCount(psContext, minElemCount); - bformata(glsl, ", %s4(", constructor); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - //AddSwizzleUsingElementCount(psContext, minElemCount); - if (psContext->psShader->ui32MajorVersion < 4) - { - //Result is 1.0f or 0.0f - bcatcstr(glsl, "))"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - } - else - { - bcatcstr(glsl, ")) * 0xFFFFFFFFu;\n"); - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bconcat(glsl, varName); - AddSwizzleUsingElementCount(psContext, minElemCount); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - } - bcatcstr(glsl, ";\n"); - } - else - { - const char* glslOpcode [] = { - "==", - "<", - ">=", - "!=", - }; - - bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; - const char* tempVariableName = "cond"; - //Scalar compare - AddIndentation(psContext); - // There's a bug with Qualcomm OpenGLES 3.0 drivers that - // makes something like this: "temp1.x = temp2.x == 0 ? 1.0f : 0.0f" always return 0.0f - // The workaround is saving the result in a temp variable: bool cond = temp2.x == 0; temp1.x = !!cond ? 1.0f : 0.0f - if (qualcommWorkaround) - { - bcatcstr(glsl, "{\n"); - ++psContext->indent; - AddIndentation(psContext); - bformata(glsl, "bool %s = ", tempVariableName); - bcatcstr(glsl, "("); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bcatcstr(glsl, ")"); - if (s0ElemCount > minElemCount) - { - AddSwizzleUsingElementCount(psContext, minElemCount); - } - bformata(glsl, " %s (", glslOpcode[eType]); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, ")"); - if (s1ElemCount > minElemCount) - { - AddSwizzleUsingElementCount(psContext, minElemCount); - } - bcatcstr(glsl, ";\n"); - AddIndentation(psContext); - } - - if (psContext->psShader->ui32MajorVersion < 4) - { - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - } - else - { - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - } - - if (qualcommWorkaround) - { - // Using the temporary variable where we stored the result of the comparison for the ternary operator. - bformata(glsl, "!!%s ", tempVariableName); - } - else - { - bcatcstr(glsl, "(("); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bcatcstr(glsl, ")"); - if (s0ElemCount > minElemCount) - { - AddSwizzleUsingElementCount(psContext, minElemCount); - } - bformata(glsl, " %s (", glslOpcode[eType]); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, ")"); - if (s1ElemCount > minElemCount) - { - AddSwizzleUsingElementCount(psContext, minElemCount); - } - bcatcstr(glsl, ") "); - } - - if (psContext->psShader->ui32MajorVersion < 4) - { - bcatcstr(glsl, "? 1.0f : 0.0f"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - } - else - { - bcatcstr(glsl, "? 0xFFFFFFFFu : uint(0)"); // Adreno can't handle 0u (it's treated as int) - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - } - bcatcstr(glsl, ";\n"); - if (qualcommWorkaround) - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - } - } -} - -static void AddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDst, const Operand* pSrc, uint32_t bSrcCopy, uint32_t bSaturate) -{ - bstring glsl = *psContext->currentGLSLString; - - const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataType(psContext, pSrc); - uint32_t srcCount = GetNumSwizzleElements(pSrc); - uint32_t dstCount = GetNumSwizzleElements(pDst); - uint32_t bMismatched = 0; - - uint32_t ui32SrcFlags = TO_FLAG_FLOAT; - if (!bSaturate) - { - switch (eSrcType) - { - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - ui32SrcFlags = TO_FLAG_INTEGER; - break; - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - ui32SrcFlags = TO_FLAG_UNSIGNED_INTEGER; - break; - } - } - if (bSrcCopy) - { - ui32SrcFlags |= TO_FLAG_COPY; - } - - AddIndentation(psContext); - BeginAssignment(psContext, pDst, ui32SrcFlags, bSaturate); - - //Mismatched element count or destination has any swizzle - if (srcCount != dstCount || (GetFirstOperandSwizzle(psContext, pDst) != -1)) - { - bMismatched = 1; - - // Special case for immediate operands that can be folded into *vec4 - if (srcCount == 1) - { - switch (ui32SrcFlags) - { - case TO_FLAG_INTEGER: - bcatcstr(glsl, "ivec4"); - break; - case TO_FLAG_UNSIGNED_INTEGER: - bcatcstr(glsl, "uvec4"); - break; - default: - bcatcstr(glsl, "vec4"); - } - } - - bcatcstr(glsl, "("); - } - - TranslateOperand(psContext, pSrc, ui32SrcFlags); - - if (bMismatched) - { - bcatcstr(glsl, ")"); - - if (GetFirstOperandSwizzle(psContext, pDst) != -1) - { - TranslateOperandSwizzle(psContext, pDst); - } - else - { - AddSwizzleUsingElementCount(psContext, dstCount); - } - } - - EndAssignment(psContext, pDst, ui32SrcFlags, bSaturate); - bcatcstr(glsl, ";\n"); -} - -static void AddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, uint32_t bDestCopy, const Operand* src0, const Operand* src1, const Operand* src2) -{ - bstring glsl = *psContext->currentGLSLString; - - uint32_t destElemCount = GetNumSwizzleElements(pDest); - uint32_t s0ElemCount = GetNumSwizzleElements(src0); - uint32_t s1ElemCount = GetNumSwizzleElements(src1); - uint32_t s2ElemCount = GetNumSwizzleElements(src2); - uint32_t destElem; - int qualcommWorkaround = psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND; - - const char* swizzles = "xyzw"; - uint32_t eDstDataType; - const char* szVecType; - - uint32_t uDestFlags = TO_FLAG_DESTINATION; - if (bDestCopy) - { - uDestFlags |= TO_FLAG_COPY; - } - - AddIndentation(psContext); - // Qualcomm OpenGLES 3.0 bug that makes something likes this: - // temp4.xyz = vec3(floatsToInt(temp1).x != 0 ? temp2.x : temp2.x, floatsToInt(temp1).y != 0 ? temp2.y : temp2.y, floatsToInt(temp1).z != 0 ? temp2.z : temp2.z) - // to fail in the ternary operator. The workaround is to save the floatToInt(temp1) into a temp variable: - // { ivec4 cond = floatsToInt(temp1); temp4.xyz = vec3(cond.x != 0 ? temp2.x : temp2.x, cond.y != 0 ? temp2.y : temp2.y, cond.z != 0 ? temp2.z : temp2.z); } - if (qualcommWorkaround) - { - bformata(glsl, "{\n"); - ++psContext->indent; - AddIndentation(psContext); - if (s0ElemCount > 1) - bformata(glsl, "ivec%d cond = ", s0ElemCount); - else - bformata(glsl, "int cond = "); - TranslateOperand(psContext, src0, TO_FLAG_INTEGER); - bformata(glsl, ";\n"); - AddIndentation(psContext); - } - - TranslateOperand(psContext, pDest, uDestFlags); - - switch (GetOperandDataType(psContext, pDest)) - { - case SVT_UINT: - case SVT_UINT8: - case SVT_UINT16: - szVecType = "uvec"; - eDstDataType = TO_FLAG_UNSIGNED_INTEGER; - break; - case SVT_INT: - case SVT_INT12: - case SVT_INT16: - szVecType = "ivec"; - eDstDataType = TO_FLAG_INTEGER; - break; - default: - szVecType = "vec"; - eDstDataType = TO_FLAG_FLOAT; - break; - } - - if (destElemCount > 1) - { - bformata(glsl, " = %s%d(", szVecType, destElemCount); - } - else - { - bcatcstr(glsl, " = "); - } - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - if (destElem > 0) - { - bcatcstr(glsl, ", "); - } - - if (qualcommWorkaround) - { - bcatcstr(glsl, "cond"); - } - else - { - TranslateOperand(psContext, src0, TO_FLAG_INTEGER); - } - - if (s0ElemCount > 1) - { - TranslateOperandSwizzle(psContext, pDest); - bformata(glsl, ".%c", swizzles[destElem]); - } - - bcatcstr(glsl, " != 0 ? "); - - TranslateOperand(psContext, src1, eDstDataType); - if (s1ElemCount > 1) - { - TranslateOperandSwizzle(psContext, pDest); - bformata(glsl, ".%c", swizzles[destElem]); - } - - bcatcstr(glsl, " : "); - - TranslateOperand(psContext, src2, eDstDataType); - if (s2ElemCount > 1) - { - TranslateOperandSwizzle(psContext, pDest); - bformata(glsl, ".%c", swizzles[destElem]); - } - } - if (destElemCount > 1) - { - bcatcstr(glsl, ");\n"); - } - else - { - bcatcstr(glsl, ";\n"); - } - - if (qualcommWorkaround) - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - } -} - -void CallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, uint32_t dataType) -{ - bstring glsl = *psContext->currentGLSLString; - uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); - uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - - AddIndentation(psContext); - // Qualcomm OpenGLES 3.0 drivers don't support bitwise operators for vectors. - // Because of this we need to do the operation per component. - bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; - bool isBitwiseOperator = psInst->eOpcode == OPCODE_AND || psInst->eOpcode == OPCODE_OR || psInst->eOpcode == OPCODE_XOR; - const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; - if (src1SwizCount == src0SwizCount == dstSwizCount) - { - BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - if (qualcommWorkaround && isBitwiseOperator && src0SwizCount > 1) - { - for (uint32_t i = 0; i < src0SwizCount; ++i) - { - if (i > 0) - { - bcatcstr(glsl, ", "); - } - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, "%s", swizzleString[i]); - bformata(glsl, " %s ", name); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - bformata(glsl, "%s", swizzleString[i]); - } - } - else - { - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", name); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - } - EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - else - { - //Upconvert the inputs to vec4 then apply the dest swizzle. - BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - if (dataType == TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(glsl, "uvec4("); - } - else if (dataType == TO_FLAG_INTEGER) - { - bcatcstr(glsl, "ivec4("); - } - else - { - bcatcstr(glsl, "vec4("); - } - - if (qualcommWorkaround && isBitwiseOperator && src0SwizCount > 1) - { - for (uint32_t i = 0; i < src0SwizCount; ++i) - { - if (i > 0) - { - bcatcstr(glsl, ", "); - } - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, "%s", swizzleString[i]); - bformata(glsl, " %s ", name); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - bformata(glsl, "%s", swizzleString[i]); - } - } - else - { - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", name); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - } - bcatcstr(glsl, ")"); - //Limit src swizzles based on dest swizzle - //e.g. given hlsl asm: add r0.xy, v0.xyxx, l(0.100000, 0.000000, 0.000000, 0.000000) - //the two sources must become vec2 - //Temp0.xy = Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000); - //becomes - //Temp0.xy = vec4(Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000)).xy; - - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } -} - -void CallTernaryOp(HLSLCrossCompilerContext* psContext, const char* op1, const char* op2, Instruction* psInst, - int dest, int src0, int src1, int src2, uint32_t dataType) -{ - bstring glsl = *psContext->currentGLSLString; - uint32_t src2SwizCount = GetNumSwizzleElements(&psInst->asOperands[src2]); - uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); - uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - - AddIndentation(psContext); - - if (src1SwizCount == src0SwizCount == src2SwizCount == dstSwizCount) - { - BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", op1); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", op2); - TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_NONE | dataType); - EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - else - { - BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - if (dataType == TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(glsl, "uvec4("); - } - else if (dataType == TO_FLAG_INTEGER) - { - bcatcstr(glsl, "ivec4("); - } - else - { - bcatcstr(glsl, "vec4("); - } - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", op1); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); - bformata(glsl, " %s ", op2); - TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_NONE | dataType); - bcatcstr(glsl, ")"); - //Limit src swizzles based on dest swizzle - //e.g. given hlsl asm: add r0.xy, v0.xyxx, l(0.100000, 0.000000, 0.000000, 0.000000) - //the two sources must become vec2 - //Temp0.xy = Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000); - //becomes - //Temp0.xy = vec4(Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000)).xy; - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } -} - -void CallHelper3(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, int src2) -{ - bstring glsl = *psContext->currentGLSLString; - AddIndentation(psContext); - - BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - - bcatcstr(glsl, "vec4("); - - bcatcstr(glsl, name); - bcatcstr(glsl, "("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_FLOAT); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_FLOAT); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} - -void CallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1) -{ - bstring glsl = *psContext->currentGLSLString; - AddIndentation(psContext); - - BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - - bcatcstr(glsl, "vec4("); - - bcatcstr(glsl, name); - bcatcstr(glsl, "("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_FLOAT); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} - -void CallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1) -{ - bstring glsl = *psContext->currentGLSLString; - AddIndentation(psContext); - - BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_INTEGER, psInst->bSaturate); - - bcatcstr(glsl, "ivec4("); - - bcatcstr(glsl, name); - bcatcstr(glsl, "(int("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_INTEGER); - bcatcstr(glsl, "), int("); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} -void CallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1) -{ - bstring glsl = *psContext->currentGLSLString; - AddIndentation(psContext); - - BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - - bcatcstr(glsl, "uvec4("); - - bcatcstr(glsl, name); - bcatcstr(glsl, "(uint("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, "), uint("); - TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ")))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} - -void CallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0) -{ - bstring glsl = *psContext->currentGLSLString; - - AddIndentation(psContext); - - BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - - // Qualcomm driver workaround - // Example: Instead of Temp1.xyz = (vec4(log2(Temp0[0].xyzx)).xyz); we write - // Temp1.xyz = (log2(vec4(Temp0[0].xyzx).xyz)); - if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) - { - bcatcstr(glsl, name); - bcatcstr(glsl, "("); - bcatcstr(glsl, "vec4("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - bcatcstr(glsl, ")"); - } - else - { - bcatcstr(glsl, "vec4("); - bcatcstr(glsl, name); - bcatcstr(glsl, "("); - TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); - } - EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} - -//Makes sure the texture coordinate swizzle is appropriate for the texture type. -//i.e. vecX for X-dimension texture. -//Currently supports floating point coord only, so not used for texelFetch. -static void TranslateTexCoord(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eResDim, - Operand* psTexCoordOperand) -{ - unsigned int uNumCoords = psTexCoordOperand->iNumComponents; - int constructor = 0; - bstring glsl = *psContext->currentGLSLString; - - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - //Vec1 texcoord. Mask out the other components. - psTexCoordOperand->aui32Swizzle[1] = 0xFFFFFFFF; - psTexCoordOperand->aui32Swizzle[2] = 0xFFFFFFFF; - psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; - if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || - psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - psTexCoordOperand->iNumComponents = 1; - } - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - //Vec2 texcoord. Mask out the other components. - psTexCoordOperand->aui32Swizzle[2] = 0xFFFFFFFF; - psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; - if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || - psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - psTexCoordOperand->iNumComponents = 2; - } - if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - constructor = 1; - bcatcstr(glsl, "vec2("); - } - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - //Vec3 texcoord. Mask out the other component. - psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; - if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || - psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - psTexCoordOperand->iNumComponents = 3; - } - if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - constructor = 1; - bcatcstr(glsl, "vec3("); - } - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - uNumCoords = 4; - if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - constructor = 1; - bcatcstr(glsl, "vec4("); - } - break; - } - default: - { - ASSERT(0); - break; - } - } - - //Mask out the other components. - switch (psTexCoordOperand->eSelMode) - { - case OPERAND_4_COMPONENT_SELECT_1_MODE: - ASSERT(uNumCoords == 1); - break; - case OPERAND_4_COMPONENT_SWIZZLE_MODE: - while (uNumCoords < 4) - { - psTexCoordOperand->aui32Swizzle[uNumCoords] = 0xFFFFFFFF; - ++uNumCoords; - } - break; - case OPERAND_4_COMPONENT_MASK_MODE: - if (psTexCoordOperand->ui32CompMask < 4) - { - psTexCoordOperand->ui32CompMask = - (uNumCoords > 0) * OPERAND_4_COMPONENT_MASK_X | - (uNumCoords > 1) * OPERAND_4_COMPONENT_MASK_Y | - (uNumCoords > 2) * OPERAND_4_COMPONENT_MASK_Z; - } - break; - } - TranslateOperand(psContext, psTexCoordOperand, TO_FLAG_FLOAT); - - if (constructor) - { - bcatcstr(glsl, ")"); - } -} - -static int GetNumTextureDimensions(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eResDim) -{ - (void)(psContext); - - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - return 1; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBE: - { - return 2; - } - - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - return 3; - } - default: - { - ASSERT(0); - break; - } - } - return 0; -} - -void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index) -{ - bstring glsl = *psContext->currentGLSLString; - const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - //[width, height, depth or array size, total-mip-count] - if (index < 3) - { - int dim = GetNumTextureDimensions(psContext, eResDim); - - if (dim < (index + 1)) - { - bcatcstr(glsl, "0"); - } - else - { - if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - { - bformata(glsl, "ivec%d(textureSize(", dim); - } - else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) - { - bformata(glsl, "vec%d(1.0f) / vec%d(textureSize(", dim, dim); - } - else - { - bformata(glsl, "vec%d(textureSize(", dim); - } - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - - switch (index) - { - case 0: - bcatcstr(glsl, ".x"); - break; - case 1: - bcatcstr(glsl, ".y"); - break; - case 2: - bcatcstr(glsl, ".z"); - break; - } - } - } - else - { - bcatcstr(glsl, "textureQueryLevels("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ")"); - } -} - -uint32_t GetReturnTypeToFlags(RESOURCE_RETURN_TYPE eReturnType) -{ - switch (eReturnType) - { - case RETURN_TYPE_FLOAT: - return TO_FLAG_FLOAT; - case RETURN_TYPE_UINT: - return TO_FLAG_UNSIGNED_INTEGER; - case RETURN_TYPE_SINT: - return TO_FLAG_INTEGER; - case RETURN_TYPE_DOUBLE: - return TO_FLAG_DOUBLE; - } - ASSERT(0); - return TO_FLAG_NONE; -} - -uint32_t GetResourceReturnTypeToFlags(ResourceGroup eGroup, uint32_t ui32BindPoint, HLSLCrossCompilerContext* psContext) -{ - ResourceBinding* psBinding; - if (GetResourceFromBindingPoint(eGroup, ui32BindPoint, &psContext->psShader->sInfo, &psBinding)) - { - return GetReturnTypeToFlags(psBinding->ui32ReturnType); - } - ASSERT(0); - return TO_FLAG_NONE; -} - -#define TEXSMP_FLAG_NONE 0x0 -#define TEXSMP_FLAG_LOD 0x1 //LOD comes from operand -#define TEXSMP_FLAG_COMPARE 0x2 -#define TEXSMP_FLAG_FIRSTLOD 0x4 //LOD is 0 -#define TEXSMP_FLAG_BIAS 0x8 -#define TEXSMP_FLAGS_GRAD 0x10 -static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, uint32_t ui32Flags) -{ - bstring glsl = *psContext->currentGLSLString; - - const char* funcName = "texture"; - const char* offset = ""; - const char* depthCmpCoordType = ""; - const char* gradSwizzle = ""; - uint32_t sampleTypeToFlags = TO_FLAG_FLOAT; - - uint32_t ui32NumOffsets = 0; - - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); - - ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); - - if (psInst->bAddressOffset) - { - offset = "Offset"; - } - - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - depthCmpCoordType = "vec2"; - gradSwizzle = ".x"; - ui32NumOffsets = 1; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture1D"; - if (ui32Flags & TEXSMP_FLAG_COMPARE) - { - funcName = "shadow1D"; - } - } - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture2D"; - if (ui32Flags & TEXSMP_FLAG_COMPARE) - { - funcName = "shadow2D"; - } - } - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (!iHaveOverloadedTexFuncs) - { - funcName = "textureCube"; - } - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - depthCmpCoordType = "vec4"; - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture3D"; - } - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".x"; - ui32NumOffsets = 1; - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - depthCmpCoordType = "vec4"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (ui32Flags & TEXSMP_FLAG_COMPARE) - { - //Special. Reference is a separate argument. - AddIndentation(psContext); - sampleTypeToFlags = TO_FLAG_FLOAT; - BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bcatcstr(glsl, "(vec4(textureLod("); - } - else - { - bcatcstr(glsl, "(vec4(texture("); - } - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); - bcatcstr(glsl, ","); - TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ","); - //.z = reference. - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); - - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - - bcatcstr(glsl, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - return; - } - - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (ui32Flags & TEXSMP_FLAG_COMPARE) - { - //For non-cubeMap Arrays the reference value comes from the - //texture coord vector in GLSL. For cubmap arrays there is a - //separate parameter. - //It is always separate paramter in HLSL. - AddIndentation(psContext); - sampleTypeToFlags = TO_FLAG_FLOAT; - BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); - - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bformata(glsl, "(vec4(%sLod%s(", funcName, offset); - } - else - { - bformata(glsl, "(vec4(%s%s(", funcName, offset); - } - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); - bformata(glsl, ", %s(", depthCmpCoordType); - TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ","); - //.z = reference. - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); - bcatcstr(glsl, ")"); - - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - - bcatcstr(glsl, "))"); - } - else - { - AddIndentation(psContext); - sampleTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); - BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bformata(glsl, "(%sLod%s(", funcName, offset); - } - else - if (ui32Flags & TEXSMP_FLAGS_GRAD) - { - bformata(glsl, "(%sGrad%s(", funcName, offset); - } - else - { - bformata(glsl, "(%s%s(", funcName, offset); - } - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); - bcatcstr(glsl, ", "); - TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - if (ui32Flags & (TEXSMP_FLAG_LOD)) - { - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); - if (psContext->psShader->ui32MajorVersion < 4) - { - bcatcstr(glsl, ".w"); - } - } - else - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - else - if (ui32Flags & TEXSMP_FLAGS_GRAD) - { - bcatcstr(glsl, ", vec4("); - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT);//dx - bcatcstr(glsl, ")"); - bcatcstr(glsl, gradSwizzle); - bcatcstr(glsl, ", vec4("); - TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_FLOAT);//dy - bcatcstr(glsl, ")"); - bcatcstr(glsl, gradSwizzle); - } - - if (psInst->bAddressOffset) - { - if (ui32NumOffsets == 1) - { - bformata(glsl, ", %d", - psInst->iUAddrOffset); - } - else - if (ui32NumOffsets == 2) - { - bformata(glsl, ", ivec2(%d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset); - } - else - if (ui32NumOffsets == 3) - { - bformata(glsl, ", ivec3(%d, %d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset, - psInst->iWAddrOffset); - } - } - - if (ui32Flags & (TEXSMP_FLAG_BIAS)) - { - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); - } - - bcatcstr(glsl, ")"); - } - - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); -} - -static ShaderVarType* LookupStructuredVarExtended(HLSLCrossCompilerContext* psContext, - Operand* psResource, - Operand* psByteOffset, - uint32_t ui32Component, - uint32_t* swizzle) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; - int byteOffset = psByteOffset ? ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component : 0; - int vec4Offset = byteOffset >> 4; - int32_t index = -1; - int32_t rebase = -1; - int found; - //TODO: multi-component stores and vector writes need testing. - - //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; - - switch (byteOffset % 16) - { - case 0: - aui32Swizzle[0] = 0; - break; - case 4: - aui32Swizzle[0] = 1; - break; - case 8: - aui32Swizzle[0] = 2; - break; - case 12: - aui32Swizzle[0] = 3; - break; - } - - switch (psResource->eType) - { - case OPERAND_TYPE_RESOURCE: - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - //dcl_tgsm_structured defines the amount of memory and a stride. - ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); - ASSERT(swizzle == NULL); - return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; - } - default: - ASSERT(0); - break; - } - - found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - ASSERT(found); - - if (swizzle) - { - // Assuming the components are 4 bytes in length - const int bytesPerComponent = 4; - // Calculate the variable swizzling based on the byteOffset and the position of the variable in the structure - ASSERT((byteOffset - psVarType->Offset) % 4 == 0); - *swizzle = (byteOffset - psVarType->Offset) / bytesPerComponent; - ASSERT(*swizzle < 4); - } - - return psVarType; -} - -static ShaderVarType* LookupStructuredVar(HLSLCrossCompilerContext* psContext, - Operand* psResource, - Operand* psByteOffset, - uint32_t ui32Component) -{ - return LookupStructuredVarExtended(psContext, psResource, psByteOffset, ui32Component, NULL); -} - -static void TranslateShaderStorageVarName(bstring output, Shader* psShader, const Operand* operand, int structured) -{ - bstring varName = bfromcstr(""); - if (operand->eType == OPERAND_TYPE_RESOURCE) - { - if (structured) - { - bformata(varName, "StructuredRes%d", operand->ui32RegisterNumber); - } - else - { - bformata(varName, "RawRes%d", operand->ui32RegisterNumber); - } - } - else if(operand->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) - { - bformata(varName, "UAV%d", operand->ui32RegisterNumber); - } - else - { - ASSERT(0); - } - ShaderVarName(output, psShader, bstr2cstr(varName, '\0')); - bdestroy(varName); -} - -static void TranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - ShaderVarType* psVarType = NULL; - int component; - int srcComponent = 0; - - Operand* psDest = 0; - Operand* psDestAddr = 0; - Operand* psDestByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_STORE_STRUCTURED: - psDest = &psInst->asOperands[0]; - psDestAddr = &psInst->asOperands[1]; - psDestByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - break; - case OPCODE_STORE_RAW: - psDest = &psInst->asOperands[0]; - psDestByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - for (component = 0; component < 4; component++) - { - const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; - ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psInst->asOperands[0].ui32CompMask & (1 << component)) - { - uint32_t swizzle = 0; - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - psVarType = LookupStructuredVarExtended(psContext, psDest, psDestByteOff, component, &swizzle); - } - - AddIndentation(psContext); - TranslateShaderStorageVarName(glsl, psContext->psShader, psDest, structured); - bformata(glsl, "["); - if (structured) //Dest address and dest byte offset - { - if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, "].value["); - TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, " >> 2u ");//bytes to floats - } - else - { - TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - } - else - { - TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - - //RAW: change component using index offset - if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(glsl, " + %d", component); - } - - bformata(glsl, "]"); - - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - if (strcmp(psVarType->Name, "$Element") != 0) - { - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - } - - if (psVarType->Columns > 1) - { - bformata(glsl, swizzleString[swizzle]); - } - } - - - if (structured) - { - uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; - if (psVarType) - { - if (psVarType->Type == SVT_INT) - { - flags = TO_FLAG_INTEGER; - } - else if (psVarType->Type == SVT_FLOAT) - { - flags = TO_FLAG_NONE; - } - } - //TGSM always uint - bformata(glsl, " = ("); - TranslateOperand(psContext, psSrc, flags); - } - else - { - //Dest type is currently always a uint array. - bformata(glsl, " = ("); - TranslateOperand(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER); - } - - if (GetNumSwizzleElements(psSrc) > 1) - { - bformata(glsl, swizzleString[srcComponent++]); - } - - //Double takes an extra slot. - if (psVarType && psVarType->Type == SVT_DOUBLE) - { - if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - bcatcstr(glsl, ")"); - } - component++; - } - - bformata(glsl, ");\n"); - } - } -} - -static void TranslateShaderPLSStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - ShaderVarType* psVarType = NULL; - int component; - int srcComponent = 0; - - Operand* psDest = 0; - Operand* psDestAddr = 0; - Operand* psDestByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_STORE_STRUCTURED: - psDest = &psInst->asOperands[0]; - psDestAddr = &psInst->asOperands[1]; - psDestByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - break; - case OPCODE_STORE_RAW: - default: - ASSERT(0); - } - - ASSERT(structured); - - for (component = 0; component < 4; component++) - { - const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; - ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psInst->asOperands[0].ui32CompMask & (1 << component)) - { - - ASSERT(psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY); - - psVarType = LookupStructuredVar(psContext, psDest, psDestByteOff, component); - - AddIndentation(psContext); - - if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) - { - bstring varName = bfromcstralloc(16, ""); - bformata(varName, "StructuredRes%d", psDest->ui32RegisterNumber); - ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); - bdestroy(varName); - } - else - { - TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - } - - ASSERT(strcmp(psVarType->Name, "$Element") != 0); - - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - - if (psVarType->Class == SVC_VECTOR) - { - int byteOffset = ((int*)psDestByteOff->afImmediates)[0] + 4 * (psDest->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psDest->aui32Swizzle[component] : component); - int byteOffsetOfVar = psVarType->Offset; - unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; - unsigned int s = startComponent; - - bformata(glsl, "%s", swizzleString[s]); - } - - uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; - if (psVarType) - { - if (psVarType->Type == SVT_INT) - { - flags = TO_FLAG_INTEGER; - } - else if (psVarType->Type == SVT_FLOAT) - { - flags = TO_FLAG_NONE; - } - else - { - ASSERT(0); - } - } - //TGSM always uint - bformata(glsl, " = ("); - TranslateOperand(psContext, psSrc, flags); - - - - if (GetNumSwizzleElements(psSrc) > 1) - { - bformata(glsl, swizzleString[srcComponent++]); - } - - //Double takes an extra slot. - if (psVarType && psVarType->Type == SVT_DOUBLE) - { - if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - bcatcstr(glsl, ")"); - } - component++; - } - - bformata(glsl, ");\n"); - } - } -} - -static void TranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; - uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; - int component; - int destComponent = 0; - - Operand* psDest = 0; - Operand* psSrcAddr = 0; - Operand* psSrcByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_LD_STRUCTURED: - psDest = &psInst->asOperands[0]; - psSrcAddr = &psInst->asOperands[1]; - psSrcByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - break; - case OPCODE_LD_RAW: - psDest = &psInst->asOperands[0]; - psSrcByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - if (psInst->eOpcode == OPCODE_LD_RAW) - { - unsigned int ui32CompNum = GetNumSwizzleElements(psDest); - - for (component = 0; component < 4; component++) - { - const char* swizzleString [] = { "x", "y", "z", "w" }; - ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psDest->ui32CompMask & (1 << component)) - { - int addedBitcast = 0; - - if (structured) - { - psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); - } - - AddIndentation(psContext); - - aui32Swizzle[0] = psSrc->aui32Swizzle[component]; - - if (ui32CompNum > 1) - { - BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); - } - else - { - BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - } - - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - // unknown how to make this without TO_FLAG_NAME_ONLY - bcatcstr(glsl, "uintBitsToFloat("); - addedBitcast = 1; - - TranslateOperand(psContext, psSrc, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); - - if (((int*)psSrcByteOff->afImmediates)[0] == 0) - { - bformata(glsl, "[0"); - } - else - { - bformata(glsl, "[(("); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(glsl, ") >> 2u)"); - } - } - else - { - bstring varName = bfromcstralloc(16, ""); - bformata(varName, "RawRes%d", psSrc->ui32RegisterNumber); - - ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); - bcatcstr(glsl, "[(("); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(glsl, ") >> 2u)"); - - bdestroy(varName); - } - - if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) - { - bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); - } - bcatcstr(glsl, "]"); - - if (addedBitcast) - { - bcatcstr(glsl, ")"); - } - - EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - bformata(glsl, ";\n"); - } - } - } - else - { - unsigned int ui32CompNum = GetNumSwizzleElements(psDest); - - //(int)GetNumSwizzleElements(&psInst->asOperands[0]) - for (component = 0; component < 4; component++) - { - const char* swizzleString [] = { "x", "y", "z", "w" }; - ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psDest->ui32CompMask & (1 << component)) - { - int addedBitcast = 0; - - psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); - - AddIndentation(psContext); - - aui32Swizzle[0] = psSrc->aui32Swizzle[component]; - - if (ui32CompNum > 1) - { - BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); - } - else - { - BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - } - - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - // unknown how to make this without TO_FLAG_NAME_ONLY - if (psVarType->Type == SVT_UINT) - { - bcatcstr(glsl, "uintBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_INT) - { - bcatcstr(glsl, "intBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_DOUBLE) - { - bcatcstr(glsl, "unpackDouble2x32("); - addedBitcast = 1; - } - - // input already in uints - TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "["); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "].value[("); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, " >> 2u)]"); - } - else - { - ConstantBuffer* psCBuf = NULL; - uint32_t swizzle = 0; - psVarType = LookupStructuredVarExtended(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component, &swizzle); - GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - if (psVarType->Type == SVT_UINT) - { - bcatcstr(glsl, "uintBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_INT) - { - bcatcstr(glsl, "intBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_DOUBLE) - { - bcatcstr(glsl, "unpackDouble2x32("); - addedBitcast = 1; - } - - if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) - { - TranslateShaderStorageVarName(glsl, psContext->psShader, psSrc, 1); - bformata(glsl, "["); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - if (strcmp(psVarType->Name, "$Element") != 0) - { - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - } - - if (psVarType->Columns > 1) - { - bformata(glsl, ".%s", swizzleString[swizzle]); - } - } - else if (psSrc->eType == OPERAND_TYPE_RESOURCE) - { - TranslateShaderStorageVarName(glsl, psContext->psShader, psSrc, 1); - bcatcstr(glsl, "["); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - - if (strcmp(psVarType->Name, "$Element") != 0) - { - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - } - - if (psVarType->Class == SVC_SCALAR) - { - } - else if (psVarType->Class == SVC_VECTOR) - { - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - int byteOffsetOfVar = psVarType->Offset; - unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; - unsigned int s = startComponent; - - bcatcstr(glsl, "."); -#if 0 - for (s = startComponent; s < min(min(psVarType->Columns, 4U - component), ui32CompNum); ++s) -#endif - bformata(glsl, "%s", swizzleString[s]); - } - else if (psVarType->Class == SVC_MATRIX_ROWS) - { - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - int byteOffsetOfVar = psVarType->Offset; - unsigned int startRow = ((byteOffset - byteOffsetOfVar) >> 2) / psVarType->Columns; - unsigned int startComponent = ((byteOffset - byteOffsetOfVar) >> 2) % psVarType->Columns; - unsigned int s = startComponent; - - bformata(glsl, "[%d]", startRow); - bcatcstr(glsl, "."); -#if 0 - for (s = startComponent; s < min(min(psVarType->Rows, 4U - component), ui32CompNum); ++s) -#endif - bformata(glsl, "%s", swizzleString[s]); - } - else if (psVarType->Class == SVC_MATRIX_COLUMNS) - { - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - int byteOffsetOfVar = psVarType->Offset; - unsigned int startCol = ((byteOffset - byteOffsetOfVar) >> 2) / psVarType->Rows; - unsigned int startComponent = ((byteOffset - byteOffsetOfVar) >> 2) % psVarType->Rows; - unsigned int s = startComponent; - - bformata(glsl, "[%d]", startCol); - bcatcstr(glsl, "."); -#if 0 - for (s = startComponent; s < min(min(psVarType->Columns, 4U - component), ui32CompNum); ++s) -#endif - bformata(glsl, "%s", swizzleString[s]); - } - else - { - //assert(0); - } - } - else - { - TranslateOperand(psContext, psSrc, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); - bformata(glsl, "["); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "]."); - - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - } - - if (psVarType->Type == SVT_DOUBLE) - { - component++; // doubles take up 2 slots - } -#if 0 - if (psVarType->Class == SVC_VECTOR) - { - component += min(psVarType->Columns, ui32CompNum) - 1; // vector take up various slots - } - if (psVarType->Class == SVC_MATRIX_ROWS) - { - component += min(psVarType->Columns * psVarType->Rows, ui32CompNum) - 1; // matrix take up various slots - } - if (psVarType->Class == SVC_MATRIX_COLUMNS) - { - component += min(psVarType->Columns * psVarType->Rows, ui32CompNum) - 1; // matrix take up various slots - } -#endif - } - - if (addedBitcast) - { - bcatcstr(glsl, ")"); - } - - EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - bformata(glsl, ";\n"); - } - } - } -} - -static void TranslateShaderPLSLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; - int component; - int destComponent = 0; - - Operand* psDest = 0; - Operand* psSrcAddr = 0; - Operand* psSrcByteOff = 0; - Operand* psSrc = 0; - - switch (psInst->eOpcode) - { - case OPCODE_LD_STRUCTURED: - psDest = &psInst->asOperands[0]; - psSrcAddr = &psInst->asOperands[1]; - psSrcByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - break; - case OPCODE_LD_RAW: - default: - ASSERT(0); - } - - unsigned int ui32CompNum = GetNumSwizzleElements(psDest); - - for (component = 0; component < 4; component++) - { - const char* swizzleString[] = { "x", "y", "z", "w" }; - ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psDest->ui32CompMask & (1 << component)) - { - int addedBitcast = 0; - - psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); - - AddIndentation(psContext); - - aui32Swizzle[0] = psSrc->aui32Swizzle[component]; - - if (ui32CompNum > 1) - { - BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); - } - else - { - BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - } - - ASSERT(psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY); - - ConstantBuffer* psCBuf = NULL; - psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - if (psVarType->Type == SVT_UINT) - { - bcatcstr(glsl, "uintBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_INT) - { - bcatcstr(glsl, "intBitsToFloat("); - addedBitcast = 1; - } - else if (psVarType->Type == SVT_DOUBLE) - { - ASSERT(0); - } - - ASSERT(psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW); - - TranslateOperand(psContext, psSrc, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - ASSERT(strcmp(psVarType->Name, "$Element") != 0); - - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - - ASSERT(psVarType->Type != SVT_DOUBLE); - ASSERT(psVarType->Class != SVC_MATRIX_ROWS); - ASSERT(psVarType->Class != SVC_MATRIX_COLUMNS); - - if (psVarType->Class == SVC_VECTOR) - { - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - int byteOffsetOfVar = psVarType->Offset; - unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; - unsigned int s = startComponent; - - bcatcstr(glsl, "."); - bformata(glsl, "%s", swizzleString[s]); - } - - if (addedBitcast) - { - bcatcstr(glsl, ")"); - } - - EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); - bformata(glsl, ";\n"); - } - } -} - -void TranslateAtomicMemOp(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - ShaderVarType* psVarType = NULL; - uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; - const char* func = ""; - Operand* dest = 0; - Operand* previousValue = 0; - Operand* destAddr = 0; - Operand* src = 0; - Operand* compare = 0; - - switch (psInst->eOpcode) - { - case OPCODE_IMM_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IADD\n"); -#endif - func = "atomicAdd"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IADD\n"); -#endif - func = "atomicAdd"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_AND\n"); -#endif - func = "atomicAnd"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_AND\n"); -#endif - func = "atomicAnd"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_OR\n"); -#endif - func = "atomicOr"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_OR\n"); -#endif - func = "atomicOr"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_XOR\n"); -#endif - func = "atomicXor"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_XOR\n"); -#endif - func = "atomicXor"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - - case OPCODE_IMM_ATOMIC_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_EXCH\n"); -#endif - func = "atomicExchange"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_CMP_EXC\n"); -#endif - func = "atomicCompSwap"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - compare = &psInst->asOperands[3]; - src = &psInst->asOperands[4]; - break; - } - case OPCODE_ATOMIC_CMP_STORE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_CMP_STORE\n"); -#endif - func = "atomicCompSwap"; - previousValue = 0; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - compare = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_UMIN\n"); -#endif - func = "atomicMin"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_UMIN\n"); -#endif - func = "atomicMin"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IMIN\n"); -#endif - func = "atomicMin"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IMIN\n"); -#endif - func = "atomicMin"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_UMAX\n"); -#endif - func = "atomicMax"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_UMAX\n"); -#endif - func = "atomicMax"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IMAX\n"); -#endif - func = "atomicMax"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IMAX\n"); -#endif - func = "atomicMax"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - } - - AddIndentation(psContext); - - psVarType = LookupStructuredVar(psContext, dest, NULL, 0); - - if (psVarType->Type == SVT_UINT) - { - ui32DataTypeFlag = TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER; - } - else if (psVarType->Type == SVT_INT) - { - ui32DataTypeFlag = TO_FLAG_INTEGER; - } - - if (previousValue) - { - BeginAssignment(psContext, previousValue, ui32DataTypeFlag, psInst->bSaturate); - } - - if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - bcatcstr(glsl, func); - bcatcstr(glsl, "("); - TranslateOperand(psContext, dest, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); - bformata(glsl, "[%d]", 0); - } - else - { - bcatcstr(glsl, func); - bcatcstr(glsl, "("); - TranslateShaderStorageVarName(glsl, psContext->psShader, dest, 1); - bformata(glsl, "["); - TranslateOperand(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - // For some reason the destAddr with the swizzle doesn't translate to an index - // I'm not sure if ".x" is the correct behavior. - bformata(glsl, ".x]"); - } - - if (strcmp(psVarType->Name, "$Element") != 0) - { - bcatcstr(glsl, "."); - ShaderVarName(glsl, psContext->psShader, psVarType->Name); - } - bcatcstr(glsl, ", "); - - if (compare) - { - TranslateOperand(psContext, compare, ui32DataTypeFlag); - bcatcstr(glsl, ", "); - } - - TranslateOperand(psContext, src, ui32DataTypeFlag); - bcatcstr(glsl, ")"); - - if (previousValue) - { - EndAssignment(psContext, previousValue, ui32DataTypeFlag, psInst->bSaturate); - } - - bcatcstr(glsl, ";\n"); -} - -static void TranslateConditional(HLSLCrossCompilerContext* psContext, - Instruction* psInst, - bstring glsl) -{ - const char* statement = ""; - uint32_t bWriteTraceEnd = 0; - if (psInst->eOpcode == OPCODE_BREAKC) - { - statement = "break"; - } - else if (psInst->eOpcode == OPCODE_CONTINUEC) - { - statement = "continue"; - } - else if (psInst->eOpcode == OPCODE_RETC) - { - statement = "return"; - bWriteTraceEnd = (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) != 0; - } - - if (psContext->psShader->ui32MajorVersion < 4) - { - bcatcstr(glsl, "if("); - - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - switch (psInst->eDX9TestType) - { - case D3DSPC_GT: - { - bcatcstr(glsl, " > "); - break; - } - case D3DSPC_EQ: - { - bcatcstr(glsl, " == "); - break; - } - case D3DSPC_GE: - { - bcatcstr(glsl, " >= "); - break; - } - case D3DSPC_LT: - { - bcatcstr(glsl, " < "); - break; - } - case D3DSPC_NE: - { - bcatcstr(glsl, " != "); - break; - } - case D3DSPC_LE: - { - bcatcstr(glsl, " <= "); - break; - } - case D3DSPC_BOOLEAN: - { - bcatcstr(glsl, " != 0"); - break; - } - default: - { - break; - } - } - - if (psInst->eDX9TestType != D3DSPC_BOOLEAN) - { - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - } - - if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) - { - bformata(glsl, "){ %s; }\n", statement); - } - else - { - bcatcstr(glsl, "){\n"); - } - } - else - { - if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) - { - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - bformata(glsl, ")==uint(0){%s;}\n", statement); // Adreno can't handle 0u (it's treated as int) - } - else - { - bformata(glsl, ")==0){%s;}\n", statement); - } - } - else - { - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - bcatcstr(glsl, ")==uint(0){\n"); // Adreno can't handle 0u (it's treated as int) - } - else - { - bcatcstr(glsl, ")==0){\n"); - } - } - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) - { - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - bformata(glsl, ")!=uint(0)){%s;}\n", statement); // Adreno can't handle 0u (it's treated as int) - } - else - { - bformata(glsl, ")!=0){%s;}\n", statement); - } - } - else - { - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - bcatcstr(glsl, ")!=uint(0)){\n"); // Adreno can't handle 0u (it's treated as int) - } - else - { - bcatcstr(glsl, ")!=0){\n"); - } - } - } - } - - if (bWriteTraceEnd) - { - ASSERT(*psContext->currentGLSLString == glsl); - ++psContext->indent; - WriteEndTrace(psContext); - AddIndentation(psContext); - bformata(glsl, "%s;\n", statement); - AddIndentation(psContext); - --psContext->indent; - bcatcstr(glsl, "}\n"); - } -} - -void UpdateCommonTempVecType(SHADER_VARIABLE_TYPE* peCommonTempVecType, SHADER_VARIABLE_TYPE eNewType) -{ - if (*peCommonTempVecType == SVT_FORCE_DWORD) - { - *peCommonTempVecType = eNewType; - } - else if (*peCommonTempVecType != eNewType) - { - *peCommonTempVecType = SVT_VOID; - } -} - -bool IsFloatType(SHADER_VARIABLE_TYPE type) -{ - switch (type) - { - case SVT_FLOAT: - case SVT_FLOAT10: - case SVT_FLOAT16: - return true; - default: - return false; - } -} - -void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType) -{ - int32_t i; - - SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; - - for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) - { - aeTempVecType[i] = SVT_FLOAT; - } - if (aeCommonTempVecType != NULL) - { - for (i = 0; i < MAX_TEMP_VEC4; ++i) - { - aeCommonTempVecType[i] = SVT_FORCE_DWORD; - } - } - - for (i = 0; i < i32InstCount; ++i, psInst++) - { - int k = 0; - - if (psInst->ui32NumOperands == 0) - { - continue; - } - - //Preserve the current type on dest array index - if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) - { - Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; - if (psSubOperand != 0) - { - const uint32_t ui32RegIndex = psSubOperand->ui32RegisterNumber * 4; - ASSERT(psSubOperand->eType == OPERAND_TYPE_TEMP); - - if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; - } - else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psSubOperand->ui32Swizzle == (NO_SWIZZLE)) - { - psSubOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; - } - else - { - psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; - } - } - else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psSubOperand->ui32CompMask; - if (!psSubOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - psSubOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; - } - } - } - } - } - - //Preserve the current type on sources. - for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) - { - int32_t subOperand; - Operand* psOperand = &psInst->asOperands[k]; - - if (psOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; - psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; - psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; - psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; - } - else - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; - } - } - } - } - - for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) - { - if (psOperand->psSubOperand[subOperand] != 0) - { - Operand* psSubOperand = psOperand->psSubOperand[subOperand]; - if (psSubOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psSubOperand->ui32RegisterNumber * 4; - - if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; - } - else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psSubOperand->ui32Swizzle == (NO_SWIZZLE)) - { - psSubOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; - psSubOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; - } - else - { - psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; - } - } - else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psSubOperand->ui32CompMask; - if (!psSubOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - psSubOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; - } - } - } - } - } - } - } - - SHADER_VARIABLE_TYPE eNewType = SVT_FORCE_DWORD; - - switch (psInst->eOpcode) - { - case OPCODE_RESINFO: - { - if (psInst->eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - { - eNewType = SVT_INT; - } - else - { - eNewType = SVT_FLOAT; - } - break; - } - case OPCODE_AND: - case OPCODE_OR: - case OPCODE_XOR: - case OPCODE_NOT: - { - eNewType = SVT_UINT; - break; - } - case OPCODE_IADD: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - { - eNewType = SVT_UINT; - - //If the rhs evaluates to signed then that is the dest type picked. - for (uint32_t kk = psInst->ui32FirstSrc; kk < psInst->ui32NumOperands; ++kk) - { - if (GetOperandDataType(psContext, &psInst->asOperands[kk]) == SVT_INT || - psInst->asOperands[kk].eModifier == OPERAND_MODIFIER_NEG || - psInst->asOperands[kk].eModifier == OPERAND_MODIFIER_ABSNEG) - { - eNewType = SVT_INT; - break; - } - } - - break; - } - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - Operand* dest = &psInst->asOperands[1]; - ShaderVarType* type = LookupStructuredVar(psContext, dest, NULL, 0); - eNewType = type->Type; - break; - } - - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_INE: - case OPCODE_EQ: - case OPCODE_GE: - case OPCODE_LT: - case OPCODE_NE: - case OPCODE_UDIV: - case OPCODE_ULT: - case OPCODE_UGE: - case OPCODE_UMUL: - case OPCODE_UMAD: - case OPCODE_UMAX: - case OPCODE_UMIN: - case OPCODE_USHR: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - { - if (psContext->psShader->ui32MajorVersion < 4) - { - //SLT and SGE are translated to LT and GE respectively. - //But SLT and SGE have a floating point 1.0f or 0.0f result - //instead of setting all bits on or all bits off. - eNewType = SVT_FLOAT; - } - else - { - eNewType = SVT_UINT; - } - break; - } - - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_D: - case OPCODE_SAMPLE_B: - case OPCODE_LD: - case OPCODE_LD_MS: - case OPCODE_LD_UAV_TYPED: - { - ResourceBinding* psRes = NULL; - if (psInst->eOpcode == OPCODE_LD_UAV_TYPED) - { - GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); - } - else - { - GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); - } - switch (psRes->ui32ReturnType) - { - case RETURN_TYPE_SINT: - eNewType = SVT_INT; - break; - case RETURN_TYPE_UINT: - eNewType = SVT_UINT; - break; - case RETURN_TYPE_FLOAT: - eNewType = SVT_FLOAT; - break; - default: - ASSERT(0); - break; - } - break; - } - - case OPCODE_MOV: - { - //Inherit the type of the source operand - const Operand* psOperand = &psInst->asOperands[0]; - if (psOperand->eType == OPERAND_TYPE_TEMP) - { - eNewType = GetOperandDataType(psContext, &psInst->asOperands[1]); - } - else - { - continue; - } - break; - } - case OPCODE_MOVC: - { - //Inherit the type of the source operand - const Operand* psOperand = &psInst->asOperands[0]; - if (psOperand->eType == OPERAND_TYPE_TEMP) - { - eNewType = GetOperandDataType(psContext, &psInst->asOperands[2]); - //Check assumption that both the values which MOVC might pick have the same basic data type. - if (!psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) - { - ASSERT(GetOperandDataType(psContext, &psInst->asOperands[2]) == GetOperandDataType(psContext, &psInst->asOperands[3])); - } - } - else - { - continue; - } - break; - } - case OPCODE_FTOI: - { - ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1])) || - GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_VOID); - eNewType = SVT_INT; - break; - } - case OPCODE_FTOU: - { - ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1])) || - GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_VOID); - eNewType = SVT_UINT; - break; - } - - case OPCODE_UTOF: - case OPCODE_ITOF: - { - eNewType = SVT_FLOAT; - break; - } - case OPCODE_IF: - case OPCODE_SWITCH: - case OPCODE_BREAKC: - { - const Operand* psOperand = &psInst->asOperands[0]; - if (psOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - eNewType = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - eNewType = aeTempVecType[ui32RegIndex]; - } - else - { - eNewType = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - for (; k < 4; ++k) - { - if (ui32CompMask & (1 << k)) - { - eNewType = aeTempVecType[ui32RegIndex + k]; - } - } - } - } - else - { - continue; - } - break; - } - case OPCODE_DADD: - { - eNewType = SVT_DOUBLE; - break; - } - case OPCODE_STORE_RAW: - { - eNewType = SVT_FLOAT; - break; - } - default: - { - eNewType = SVT_FLOAT; - break; - } - } - - if (eNewType == SVT_UINT && HaveUVec(psContext->psShader->eTargetLanguage) == 0) - { - //Fallback to signed int if unsigned int is not supported. - eNewType = SVT_INT; - } - - //Process the destination last in order to handle instructions - //where the destination register is also used as a source. - for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) - { - Operand* psOperand = &psInst->asOperands[k]; - if (psOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - if (HavePrecisionQualifers(psContext->psShader->eTargetLanguage)) - { - switch (psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - break; - case OPERAND_MIN_PRECISION_SINT_16: - eNewType = SVT_INT16; - break; - case OPERAND_MIN_PRECISION_UINT_16: - eNewType = SVT_UINT16; - break; - case OPERAND_MIN_PRECISION_FLOAT_2_8: - eNewType = SVT_FLOAT10; - break; - case OPERAND_MIN_PRECISION_FLOAT_16: - eNewType = SVT_FLOAT16; - break; - default: - break; - } - } - - if (aeCommonTempVecType != NULL) - { - UpdateCommonTempVecType(aeCommonTempVecType + psOperand->ui32RegisterNumber, eNewType); - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]] = eNewType; - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = eNewType; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - aeTempVecType[ui32RegIndex] = eNewType; - psOperand->aeDataType[0] = eNewType; - psOperand->aeDataType[1] = eNewType; - psOperand->aeDataType[2] = eNewType; - psOperand->aeDataType[3] = eNewType; - } - else - { - aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]] = eNewType; - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = eNewType; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - aeTempVecType[ui32RegIndex + c] = eNewType; - psOperand->aeDataType[c] = eNewType; - } - } - } - } - } - ASSERT(eNewType != SVT_FORCE_DWORD); - } -} - -void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentGLSLString; - -#ifdef _DEBUG - AddIndentation(psContext); - bformata(glsl, "//Instruction %d\n", psInst->id); -#if 0 - if (psInst->id == 73) - { - ASSERT(1); //Set breakpoint here to debug an instruction from its ID. - } -#endif -#endif - - switch (psInst->eOpcode) - { - case OPCODE_FTOI: //Fall-through to MOV - case OPCODE_FTOU: //Fall-through to MOV - case OPCODE_MOV: - { - uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t ui32DstFlags = TO_FLAG_NONE; - - if (psInst->eOpcode == OPCODE_FTOU) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FTOU\n"); -#endif - ui32DstFlags |= TO_FLAG_UNSIGNED_INTEGER; - - ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1]))); - } - else if (psInst->eOpcode == OPCODE_FTOI) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FTOI\n"); -#endif - ui32DstFlags |= TO_FLAG_INTEGER; - - ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1]))); - } - else - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MOV\n"); -#endif - } - - if (psInst->eOpcode == OPCODE_FTOU) - { - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - - if (srcCount == 1) - { - bcatcstr(glsl, "uint("); - } - if (srcCount == 2) - { - bcatcstr(glsl, "uvec2("); - } - if (srcCount == 3) - { - bcatcstr(glsl, "uvec3("); - } - if (srcCount == 4) - { - bcatcstr(glsl, "uvec4("); - } - - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - if (srcCount != dstCount) - { - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - else - { - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - } - else - if (psInst->eOpcode == OPCODE_FTOI) - { - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - - if (srcCount == 1) - { - bcatcstr(glsl, "int("); - } - if (srcCount == 2) - { - bcatcstr(glsl, "ivec2("); - } - if (srcCount == 3) - { - bcatcstr(glsl, "ivec3("); - } - if (srcCount == 4) - { - bcatcstr(glsl, "ivec4("); - } - - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - - if (srcCount != dstCount) - { - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - else - { - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - } - else - { - AddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], 0, psInst->bSaturate); - } - break; - } - case OPCODE_ITOF: //signed to float - case OPCODE_UTOF: //unsigned to float - { -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_ITOF) - { - bcatcstr(glsl, "//ITOF\n"); - } - else - { - bcatcstr(glsl, "//UTOF\n"); - } -#endif - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "vec4("); - TranslateOperand(psContext, &psInst->asOperands[1], (psInst->eOpcode == OPCODE_ITOF) ? TO_FLAG_INTEGER : TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_MAD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MAD\n"); -#endif - CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_FLOAT); - break; - } - case OPCODE_IMAD: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMAD\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); - break; - } - case OPCODE_DADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DADD\n"); -#endif - CallBinaryOp(psContext, "+", psInst, 0, 1, 2, TO_FLAG_DOUBLE); - break; - } - case OPCODE_IADD: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IADD\n"); -#endif - //Is this a signed or unsigned add? - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - CallBinaryOp(psContext, "+", psInst, 0, 1, 2, ui32Flags); - break; - } - case OPCODE_ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ADD\n"); -#endif - CallBinaryOp(psContext, "+", psInst, 0, 1, 2, TO_FLAG_FLOAT); - break; - } - case OPCODE_OR: - { - /*Todo: vector version */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//OR\n"); -#endif - CallBinaryOp(psContext, "|", psInst, 0, 1, 2, TO_FLAG_INTEGER); - break; - } - case OPCODE_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//AND\n"); -#endif - CallBinaryOp(psContext, "&", psInst, 0, 1, 2, TO_FLAG_INTEGER); - break; - } - case OPCODE_GE: - { - /* - dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); - Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. - */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GE\n"); -#endif - AddComparision(psContext, psInst, CMP_GE, TO_FLAG_FLOAT); - break; - } - case OPCODE_MUL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MUL\n"); -#endif - CallBinaryOp(psContext, "*", psInst, 0, 1, 2, TO_FLAG_FLOAT); - break; - } - case OPCODE_IMUL: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMUL\n"); -#endif - if (GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); - - CallBinaryOp(psContext, "*", psInst, 1, 2, 3, ui32Flags); - break; - } - case OPCODE_UDIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UDIV\n"); -#endif - //destQuotient, destRemainder, src0, src1 - CallBinaryOp(psContext, "/", psInst, 0, 2, 3, TO_FLAG_UNSIGNED_INTEGER); - CallBinaryOp(psContext, "%", psInst, 1, 2, 3, TO_FLAG_UNSIGNED_INTEGER); - break; - } - case OPCODE_DIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DIV\n"); -#endif - CallBinaryOp(psContext, "/", psInst, 0, 1, 2, TO_FLAG_FLOAT); - break; - } - case OPCODE_SINCOS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SINCOS\n"); -#endif - if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) - { - CallHelper1(psContext, "sin", psInst, 0, 2); - } - - if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) - { - CallHelper1(psContext, "cos", psInst, 1, 2); - } - break; - } - - case OPCODE_DP2: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP2\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "vec4(dot(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - bcatcstr(glsl, ").xy, ("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bcatcstr(glsl, ").xy))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DP3: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP3\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "vec4(dot(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - bcatcstr(glsl, ").xyz, ("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bcatcstr(glsl, ").xyz))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DP4: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP4\n"); -#endif - CallHelper2(psContext, "dot", psInst, 0, 1, 2); - break; - } - case OPCODE_INE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INE\n"); -#endif - AddComparision(psContext, psInst, CMP_NE, TO_FLAG_INTEGER); - break; - } - case OPCODE_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//NE\n"); -#endif - AddComparision(psContext, psInst, CMP_NE, TO_FLAG_FLOAT); - break; - } - case OPCODE_IGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IGE\n"); -#endif - AddComparision(psContext, psInst, CMP_GE, TO_FLAG_INTEGER); - break; - } - case OPCODE_ILT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ILT\n"); -#endif - AddComparision(psContext, psInst, CMP_LT, TO_FLAG_INTEGER); - break; - } - case OPCODE_LT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LT\n"); -#endif - AddComparision(psContext, psInst, CMP_LT, TO_FLAG_FLOAT); - break; - } - case OPCODE_IEQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IEQ\n"); -#endif - AddComparision(psContext, psInst, CMP_EQ, TO_FLAG_INTEGER); - break; - } - case OPCODE_ULT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ULT\n"); -#endif - AddComparision(psContext, psInst, CMP_LT, TO_FLAG_UNSIGNED_INTEGER); - break; - } - case OPCODE_UGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UGE\n"); -#endif - AddComparision(psContext, psInst, CMP_GE, TO_FLAG_UNSIGNED_INTEGER); - break; - } - case OPCODE_MOVC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MOVC\n"); -#endif - AddMOVCBinaryOp(psContext, &psInst->asOperands[0], 0, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); - break; - } - case OPCODE_SWAPC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SWAPC\n"); -#endif - AddMOVCBinaryOp(psContext, &psInst->asOperands[0], 1, &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); - AddMOVCBinaryOp(psContext, &psInst->asOperands[1], 0, &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); - AddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[0], 1, 0); - break; - } - - case OPCODE_LOG: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOG\n"); -#endif - CallHelper1(psContext, "log2", psInst, 0, 1); - break; - } - case OPCODE_RSQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RSQ\n"); -#endif - CallHelper1(psContext, "inversesqrt", psInst, 0, 1); - break; - } - case OPCODE_EXP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EXP\n"); -#endif - CallHelper1(psContext, "exp2", psInst, 0, 1); - break; - } - case OPCODE_SQRT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SQRT\n"); -#endif - CallHelper1(psContext, "sqrt", psInst, 0, 1); - break; - } - case OPCODE_ROUND_PI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_PI\n"); -#endif - CallHelper1(psContext, "ceil", psInst, 0, 1); - break; - } - case OPCODE_ROUND_NI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_NI\n"); -#endif - CallHelper1(psContext, "floor", psInst, 0, 1); - break; - } - case OPCODE_ROUND_Z: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_Z\n"); -#endif - CallHelper1(psContext, "trunc", psInst, 0, 1); - break; - } - case OPCODE_ROUND_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_NE\n"); -#endif - CallHelper1(psContext, "roundEven", psInst, 0, 1); - break; - } - case OPCODE_FRC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FRC\n"); -#endif - CallHelper1(psContext, "fract", psInst, 0, 1); - break; - } - case OPCODE_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMAX\n"); -#endif - CallHelper2Int(psContext, "max", psInst, 0, 1, 2); - break; - } - case OPCODE_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UMAX\n"); -#endif - CallHelper2UInt(psContext, "max", psInst, 0, 1, 2); - break; - } - case OPCODE_MAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MAX\n"); -#endif - CallHelper2(psContext, "max", psInst, 0, 1, 2); - break; - } - case OPCODE_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMIN\n"); -#endif - CallHelper2Int(psContext, "min", psInst, 0, 1, 2); - break; - } - case OPCODE_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UMIN\n"); -#endif - CallHelper2UInt(psContext, "min", psInst, 0, 1, 2); - break; - } - case OPCODE_MIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MIN\n"); -#endif - CallHelper2(psContext, "min", psInst, 0, 1, 2); - break; - } - case OPCODE_GATHER4: - { - //dest, coords, tex, sampler - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - const uint32_t ui32SampleToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4\n"); -#endif - //gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); - bcatcstr(glsl, "(textureGather("); - - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); - bcatcstr(glsl, ", "); - TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ")"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_GATHER4_PO_C: - { - //dest, coords, offset, tex, sampler, srcReferenceValue - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_PO_C\n"); -#endif - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "(textureGatherOffset("); - - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 1); - - bcatcstr(glsl, ", "); - - TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_NONE); - - bcatcstr(glsl, ", ivec2("); - //ivec2 offset - psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_GATHER4_PO: - { - //dest, coords, offset, tex, sampler - const uint32_t ui32SampleToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, psContext); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_PO\n"); -#endif - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); - bcatcstr(glsl, "(textureGatherOffset("); - - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0); - - bcatcstr(glsl, ", "); - //Texture coord cannot be vec4 - //Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - - bcatcstr(glsl, ", ivec2("); - //ivec2 offset - psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_GATHER4_C: - { - //dest, coords, tex, sampler srcReferenceValue -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_C\n"); -#endif - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "(textureGather("); - - TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); - - bcatcstr(glsl, ", "); - //Texture coord cannot be vec4 - //Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_NONE); - bcatcstr(glsl, ")"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - bcatcstr(glsl, ")"); - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_SAMPLE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE\n"); -#endif - TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); - break; - } - case OPCODE_SAMPLE_L: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_L\n"); -#endif - TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); - break; - } - case OPCODE_SAMPLE_C: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_C\n"); -#endif - - TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_COMPARE); - break; - } - case OPCODE_SAMPLE_C_LZ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_C_LZ\n"); -#endif - - TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_COMPARE | TEXSMP_FLAG_FIRSTLOD); - break; - } - case OPCODE_SAMPLE_D: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_D\n"); -#endif - - TranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); - break; - } - case OPCODE_SAMPLE_B: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_B\n"); -#endif - - TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); - break; - } - case OPCODE_RET: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RET\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - } - if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) - { - WriteEndTrace(psContext); - } - AddIndentation(psContext); - bcatcstr(glsl, "return;\n"); - break; - } - case OPCODE_INTERFACE_CALL: - { - const char* name; - ShaderVar* psVar; - uint32_t varFound; - - uint32_t funcPointer; - uint32_t funcTableIndex; - uint32_t funcTable; - uint32_t funcBodyIndex; - uint32_t funcBody; - uint32_t ui32NumBodiesPerTable; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INTERFACE_CALL\n"); -#endif - - ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); - - funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; - funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; - funcBodyIndex = psInst->ui32FuncIndexWithinInterface; - - ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; - - funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; - - funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; - - varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); - - ASSERT(varFound); - - name = &psVar->sType.Name[0]; - - AddIndentation(psContext); - bcatcstr(glsl, name); - TranslateOperandIndexMAD(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); - //bformata(glsl, "[%d]", funcBodyIndex); - bcatcstr(glsl, "();\n"); - break; - } - case OPCODE_LABEL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LABEL\n"); -#endif - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); //Closing brace ends the previous function. - AddIndentation(psContext); - - bcatcstr(glsl, "subroutine(SubroutineType)\n"); - bcatcstr(glsl, "void "); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, "(){\n"); - ++psContext->indent; - break; - } - case OPCODE_COUNTBITS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//COUNTBITS\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "bitCount("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_FIRSTBIT_HI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_HI\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "findMSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_FIRSTBIT_LO: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_LO\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "findLSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_FIRSTBIT_SHI: //signed high - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_SHI\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "findMSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_BFREV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BFREV\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "bitfieldReverse("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_BFI: - { - uint32_t numelements_width = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t numelements_offset = GetNumSwizzleElements(&psInst->asOperands[2]); - uint32_t numelements_dest = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t numoverall_elements = min(min(numelements_width, numelements_offset), numelements_dest); - uint32_t i, j; - static const char* bfi_elementidx[] = { "x", "y", "z", "w" }; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BFI\n"); -#endif - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bformata(glsl, "ivec%d(", numoverall_elements); - for (i = 0; i < numoverall_elements; ++i) - { - bcatcstr(glsl, "bitfieldInsert("); - - for (j = 4; j >= 1; --j) - { - uint32_t opSwizzleCount = GetNumSwizzleElements(&psInst->asOperands[j]); - - if (opSwizzleCount != 1) - { - bcatcstr(glsl, " ("); - } - TranslateOperand(psContext, &psInst->asOperands[j], TO_FLAG_INTEGER); - if (opSwizzleCount != 1) - { - bformata(glsl, " ).%s", bfi_elementidx[i]); - } - if (j != 1) - { - bcatcstr(glsl, ","); - } - } - - bcatcstr(glsl, ") "); - if (i + 1 != numoverall_elements) - { - bcatcstr(glsl, ", "); - } - } - - bcatcstr(glsl, ")."); - for (i = 0; i < numoverall_elements; ++i) - { - bformata(glsl, "%s", bfi_elementidx[i]); - } - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_CUT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EndPrimitive();\n"); - break; - } - case OPCODE_EMIT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMIT\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - AddIndentation(psContext); - } - - AddIndentation(psContext); - bcatcstr(glsl, "EmitVertex();\n"); - break; - } - case OPCODE_EMITTHENCUT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMITTHENCUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EmitVertex();\nEndPrimitive();\n"); - break; - } - - case OPCODE_CUT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EndStreamPrimitive("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - - break; - } - case OPCODE_EMIT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMIT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EmitStreamVertex("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_EMITTHENCUT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMITTHENCUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EmitStreamVertex("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - bcatcstr(glsl, "EndStreamPrimitive("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_REP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//REP\n"); -#endif - //Need to handle nesting. - //Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx - - AddIndentation(psContext); - bcatcstr(glsl, "RepCounter = ivec4("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ").x;\n"); - - AddIndentation(psContext); - bcatcstr(glsl, "while(RepCounter!=0){\n"); - ++psContext->indent; - break; - } - case OPCODE_ENDREP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ENDREP\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "RepCounter--;\n"); - - --psContext->indent; - - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_LOOP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOOP\n"); -#endif - AddIndentation(psContext); - - if (psInst->ui32NumOperands == 2) - { - //DX9 version - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); - bcatcstr(glsl, "for("); - bcatcstr(glsl, "LoopCounter = "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".y, ZeroBasedCounter = 0;"); - bcatcstr(glsl, "ZeroBasedCounter < "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".x;"); - - bcatcstr(glsl, "LoopCounter += "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".z, ZeroBasedCounter++){\n"); - ++psContext->indent; - } - else - { - bcatcstr(glsl, "while(true){\n"); - ++psContext->indent; - } - break; - } - case OPCODE_ENDLOOP: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ENDLOOP\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_BREAK: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BREAK\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "break;\n"); - break; - } - case OPCODE_BREAKC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BREAKC\n"); -#endif - AddIndentation(psContext); - - TranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_CONTINUEC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CONTINUEC\n"); -#endif - AddIndentation(psContext); - - TranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_IF: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IF\n"); -#endif - AddIndentation(psContext); - - TranslateConditional(psContext, psInst, glsl); - ++psContext->indent; - break; - } - case OPCODE_RETC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RETC\n"); -#endif - AddIndentation(psContext); - - TranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_ELSE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ELSE\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "} else {\n"); - psContext->indent++; - break; - } - case OPCODE_ENDSWITCH: - case OPCODE_ENDIF: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "//ENDIF\n"); - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_CONTINUE: - { - AddIndentation(psContext); - bcatcstr(glsl, "continue;\n"); - break; - } - case OPCODE_DEFAULT: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "default:\n"); - ++psContext->indent; - break; - } - case OPCODE_NOP: - { - break; - } - case OPCODE_SYNC: - { - const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SYNC\n"); -#endif - - if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) - { - AddIndentation(psContext); - bcatcstr(glsl, "barrier();\n"); - AddIndentation(psContext); - bcatcstr(glsl, "groupMemoryBarrier();\n"); - } - if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) - { - AddIndentation(psContext); - bcatcstr(glsl, "memoryBarrierShared();\n"); - } - if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) - { - AddIndentation(psContext); - bcatcstr(glsl, "memoryBarrier();\n"); - } - break; - } - case OPCODE_SWITCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SWITCH\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "switch(int("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ")){\n"); - - psContext->indent += 2; - break; - } - case OPCODE_CASE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//case\n"); -#endif - AddIndentation(psContext); - - bcatcstr(glsl, "case "); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ":\n"); - - ++psContext->indent; - break; - } - case OPCODE_EQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EQ\n"); -#endif - AddComparision(psContext, psInst, CMP_EQ, TO_FLAG_FLOAT); - break; - } - case OPCODE_USHR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//USHR\n"); -#endif - CallBinaryOp(psContext, ">>", psInst, 0, 1, 2, TO_FLAG_UNSIGNED_INTEGER); - break; - } - case OPCODE_ISHL: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ISHL\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - CallBinaryOp(psContext, "<<", psInst, 0, 1, 2, ui32Flags); - break; - } - case OPCODE_ISHR: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ISHR\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - CallBinaryOp(psContext, ">>", psInst, 0, 1, 2, ui32Flags); - break; - } - case OPCODE_LD: - case OPCODE_LD_MS: - { - ResourceBinding* psBinding = 0; - uint32_t ui32FetchTypeToFlags; -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_LD) - { - bcatcstr(glsl, "//LD\n"); - } - else - { - bcatcstr(glsl, "//LD_MS\n"); - } -#endif - - GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - ui32FetchTypeToFlags = GetReturnTypeToFlags(psBinding->ui32ReturnType); - - const char* fetchFunctionString = psInst->bAddressOffset ? "texelFetchOffset" : "texelFetch"; - switch (psBinding->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - { - //texelFetch(samplerBuffer, int coord, level) - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, fetchFunctionString); - bcatcstr(glsl, "("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").x, int(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").w)"); - if (psInst->bAddressOffset) - { - bformata(glsl, ", %d", psInst->iUAddrOffset); - } - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - { - //texelFetch(samplerBuffer, ivec3 coord, level) - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, fetchFunctionString); - bcatcstr(glsl, "("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").xyz, int(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").w)"); - if (psInst->bAddressOffset) - { - if (psBinding->eDimension == REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY) - { - bformata(glsl, ", ivec2(%d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset); - } - else - { - bformata(glsl, ", ivec3(%d, %d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset, - psInst->iWAddrOffset); - } - } - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - - if (IsGmemReservedSlot(FBF_ANY, psInst->asOperands[2].ui32RegisterNumber)) // FRAMEBUFFER FETCH - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - } - else - { - bcatcstr(glsl, fetchFunctionString); - bcatcstr(glsl, "("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").xy, int(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").w)"); - if (psInst->bAddressOffset) - { - if (psBinding->eDimension == REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY) - { - bformata(glsl, ", int(%d)", psInst->iUAddrOffset); - } - else - { - bformata(glsl, ", ivec2(%d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset); - } - } - bcatcstr(glsl, ")"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - } - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_BUFFER: - { - //texelFetch(samplerBuffer, scalar integer coord) - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, "texelFetch("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").x)"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - { - //texelFetch(samplerBuffer, ivec2 coord, sample) - - ASSERT(psInst->eOpcode == OPCODE_LD_MS); - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, "texelFetch("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").xy, int("); - TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - //texelFetch(samplerBuffer, ivec3 coord, sample) - - ASSERT(psInst->eOpcode == OPCODE_LD_MS); - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, "texelFetch("); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", ivec3(("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").xyz), int("); - TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - case REFLECT_RESOURCE_DIMENSION_BUFFEREX: - default: - { - break; - } - } - break; - } - case OPCODE_DISCARD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DISCARD\n"); -#endif - AddIndentation(psContext); - if (psContext->psShader->ui32MajorVersion <= 3) - { - bcatcstr(glsl, "if(any(lessThan(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); - - if (psContext->psShader->ui32MajorVersion == 1) - { - /* SM1.X only kills based on the rgb channels */ - bcatcstr(glsl, ").xyz, vec3(0.0)))){discard;}\n"); - } - else - { - bcatcstr(glsl, "), vec4(0.0)))){discard;}\n"); - } - } - else if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); - bcatcstr(glsl, ")==0.0){discard;}\n"); - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); - bcatcstr(glsl, ")!=0.0){discard;}\n"); - } - break; - } - case OPCODE_LOD: - { - uint32_t ui32SampleTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOD\n"); -#endif - //LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) - - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleTypeToFlags, psInst->bSaturate); - - //If the core language does not have query-lod feature, - //then the extension is used. The name of the function - //changed between extension and core. - if (HaveQueryLod(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "textureQueryLod("); - } - else - { - bcatcstr(glsl, "textureQueryLOD("); - } - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ","); - TranslateTexCoord(psContext, - psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], - &psInst->asOperands[1]); - bcatcstr(glsl, ")"); - - //The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. - - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - EndAssignment(psContext, &psInst->asOperands[0], ui32SampleTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_EVAL_CENTROID: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_CENTROID\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "interpolateAtCentroid("); - //interpolateAtCentroid accepts in-qualified variables. - //As long as bytecode only writes vX registers in declarations - //we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_EVAL_SAMPLE_INDEX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_SAMPLE_INDEX\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "interpolateAtSample("); - //interpolateAtSample accepts in-qualified variables. - //As long as bytecode only writes vX registers in declarations - //we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_EVAL_SNAPPED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_SNAPPED\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "interpolateAtOffset("); - //interpolateAtOffset accepts in-qualified variables. - //As long as bytecode only writes vX registers in declarations - //we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - bcatcstr(glsl, ".xy)"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_LD_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_STRUCTURED "); -#endif - uint32_t reg_num = psInst->asOperands[3].ui32RegisterNumber; - if (reg_num >= GMEM_PLS_RO_SLOT && reg_num <= GMEM_PLS_RW_SLOT) - { -#ifdef _DEBUG - bcatcstr(glsl, "-> LOAD FROM PLS\n"); -#endif - // Ensure it's not a write only PLS - ASSERT(reg_num != GMEM_PLS_WO_SLOT); - - TranslateShaderPLSLoad(psContext, psInst); - } - else - { - bcatcstr(glsl, "\n"); - TranslateShaderStorageLoad(psContext, psInst); - } - break; - } - case OPCODE_LD_UAV_TYPED: - { - uint32_t ui32UAVReturnTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_UAV, psInst->asOperands[2].ui32RegisterNumber, psContext); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_UAV_TYPED\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], ui32UAVReturnTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, "imageLoad("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); - - switch (psInst->eResDim) - { - case RESOURCE_DIMENSION_BUFFER: - case RESOURCE_DIMENSION_TEXTURE1D: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").x)"); - break; - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - case RESOURCE_DIMENSION_TEXTURE2DMS: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").xy)"); - break; - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case RESOURCE_DIMENSION_TEXTURECUBE: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").xyz)"); - break; - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").xyzw)"); - break; - } - - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - EndAssignment(psContext, &psInst->asOperands[0], ui32UAVReturnTypeToFlags, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_STORE_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_RAW\n"); -#endif - TranslateShaderStorageStore(psContext, psInst); - break; - } - case OPCODE_STORE_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_STRUCTURE "); -#endif - uint32_t reg_num = psInst->asOperands[0].ui32RegisterNumber; - if (reg_num >= GMEM_PLS_RO_SLOT && reg_num <= GMEM_PLS_RW_SLOT) - { -#ifdef _DEBUG - bcatcstr(glsl, "-> STORE TO PLS\n"); -#endif - // Ensure it's not a read only PLS - ASSERT(reg_num != GMEM_PLS_RO_SLOT); - - TranslateShaderPLSStore(psContext, psInst); - } - else - { - bcatcstr(glsl, "\n"); - TranslateShaderStorageStore(psContext, psInst); - } - break; - } - - case OPCODE_STORE_UAV_TYPED: - { - ResourceBinding* psRes; - int foundResource; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_UAV_TYPED\n"); -#endif - AddIndentation(psContext); - - foundResource = GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); - - ASSERT(foundResource); - - bcatcstr(glsl, "imageStore("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); - - switch (psRes->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_BUFFER: - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ").x"); - - // HACK!! - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, ");\n"); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ".xy)"); - - // HACK!! - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bformata(glsl, ");\n"); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ".xyz)"); - - // HACK!! - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bformata(glsl, ");\n"); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ".xyzw)"); - - // HACK!! - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bformata(glsl, ");\n"); - break; - } - - break; - } - case OPCODE_LD_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_RAW\n"); -#endif - - TranslateShaderStorageLoad(psContext, psInst); - break; - } - - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMIN: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - TranslateAtomicMemOp(psContext, psInst); - break; - } - case OPCODE_UBFE: - case OPCODE_IBFE: - { - const char* swizzles = "xyzw"; - uint32_t eDataType, destElem; - uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); - uint32_t s2ElemCount = GetNumSwizzleElements(&psInst->asOperands[3]); - const char* szVecType; - const char* szDataType; -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_UBFE) - { - bcatcstr(glsl, "//OPCODE_UBFE\n"); - } - else - { - bcatcstr(glsl, "//OPCODE_IBFE\n"); - } -#endif - if (psInst->eOpcode == OPCODE_UBFE) - { - eDataType = TO_FLAG_UNSIGNED_INTEGER; - szVecType = "uvec"; - szDataType = "uint"; - } - else - { - eDataType = TO_FLAG_INTEGER; - szVecType = "ivec"; - szDataType = "int"; - } - - if (psContext->psShader->eTargetLanguage != LANG_ES_300) - { - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], eDataType, psInst->bSaturate); - - if (destElemCount > 1) - { - bformata(glsl, "%s%d(", szVecType, destElemCount); - } - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - if (destElem > 0) - { - bcatcstr(glsl, ", "); - } - - bformata(glsl, "bitfieldExtract("); - - TranslateOperand(psContext, &psInst->asOperands[3], eDataType); - if (s2ElemCount > 1) - { - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - bformata(glsl, ".%c", swizzles[destElem]); - } - - bcatcstr(glsl, ", "); - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - if (s1ElemCount > 1) - { - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - bformata(glsl, ".%c", swizzles[destElem]); - } - - bcatcstr(glsl, ", "); - - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - if (s0ElemCount > 1) - { - TranslateOperandSwizzle(psContext, &psInst->asOperands[1]); - bformata(glsl, ".%c", swizzles[destElem]); - } - - bformata(glsl, ")"); - } - if (destElemCount > 1) - { - bcatcstr(glsl, ")"); - } - EndAssignment(psContext, &psInst->asOperands[0], eDataType, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - else - { - // Following is the explicit impl' for ES3.0 - // Here's the description of what bitfieldExtract actually does - // https://www.opengl.org/registry/specs/ARB/gpu_shader5.txt - - - AddIndentation(psContext); - bcatcstr(glsl, "{\n"); - - // << (32-bits-offset) - AddIndentation(psContext); - AddIndentation(psContext); - bcatcstr(glsl, "int offsetLeft = (32 - "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, " - "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - - // >> (32-bits) - AddIndentation(psContext); - AddIndentation(psContext); - bcatcstr(glsl, "int offsetRight = (32 - "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - - AddIndentation(psContext); - AddIndentation(psContext); - bformata(glsl, "%s tmp;\n", szDataType); - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - AddIndentation(psContext); - AddIndentation(psContext); - bcatcstr(glsl, "tmp = "); - - if (psInst->eOpcode == OPCODE_IBFE) - { - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, " ? "); - } - - TranslateOperand(psContext, &psInst->asOperands[3], eDataType); - if (s2ElemCount > 1) - { - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - bformata(glsl, ".%c", swizzles[destElem]); - } - if (psInst->eOpcode == OPCODE_IBFE) - { - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, " : 0 "); - } - bcatcstr(glsl, ";\n"); - - AddIndentation(psContext); - AddIndentation(psContext); - bcatcstr(glsl, "tmp = ((tmp << offsetLeft) >> offsetRight);\n"); - - AddIndentation(psContext); - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], 0, psInst->bSaturate); - if (eDataType == TO_FLAG_INTEGER) - { - bcatcstr(glsl, "intBitsToFloat(tmp));\n"); - } - else - { - bcatcstr(glsl, "uintBitsToFloat(tmp));\n"); - } - } - - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - } - - break; - } - case OPCODE_RCP: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RCP\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "(vec4(1.0) / vec4("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - bcatcstr(glsl, "))"); - AddSwizzleUsingElementCount(psContext, destElemCount); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_F16TOF32: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//F16TOF32\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = {".x", ".y", ".z", ".w"}; - - //unpackHalf2x16 converts two f16s packed into uint to two f32s. - - //dest.swiz.x = unpackHalf2x16(src.swiz.x).x - //dest.swiz.y = unpackHalf2x16(src.swiz.y).x - //dest.swiz.z = unpackHalf2x16(src.swiz.z).x - //dest.swiz.w = unpackHalf2x16(src.swiz.w).x - - AddIndentation(psContext); - if (destElemCount > 1) - { - BeginAssignmentEx(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate, swizzle[destElem]); - } - else - { - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - } - - bcatcstr(glsl, "unpackHalf2x16("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - if (s0ElemCount > 1) - { - bcatcstr(glsl, swizzle[destElem]); - } - bcatcstr(glsl, ").x"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - break; - } - case OPCODE_F32TOF16: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//F32TOF16\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = {".x", ".y", ".z", ".w"}; - - //packHalf2x16 converts two f32s to two f16s packed into a uint. - - //dest.swiz.x = packHalf2x16(vec2(src.swiz.x)) & 0xFFFF - //dest.swiz.y = packHalf2x16(vec2(src.swiz.y)) & 0xFFFF - //dest.swiz.z = packHalf2x16(vec2(src.swiz.z)) & 0xFFFF - //dest.swiz.w = packHalf2x16(vec2(src.swiz.w)) & 0xFFFF - - AddIndentation(psContext); - if (destElemCount > 1) - { - BeginAssignmentEx(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate, swizzle[destElem]); - } - else - { - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - } - - bcatcstr(glsl, "packHalf2x16(vec2("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - if (s0ElemCount > 1) - { - bcatcstr(glsl, swizzle[destElem]); - } - bcatcstr(glsl, ")) & 0xFFFFu"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - } - break; - } - case OPCODE_INEG: - { - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INEG\n"); -#endif - //dest = 0 - src0 - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - //bcatcstr(glsl, " = 0 - "); - bcatcstr(glsl, "-("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); - if (srcCount > dstCount) - { - AddSwizzleUsingElementCount(psContext, dstCount); - } - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DERIV_RTX\n"); -#endif - CallHelper1(psContext, "dFdx", psInst, 0, 1); - break; - } - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_DERIV_RTY: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DERIV_RTY\n"); -#endif - CallHelper1(psContext, "dFdy", psInst, 0, 1); - break; - } - case OPCODE_LRP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LRP\n"); -#endif - CallHelper3(psContext, "mix", psInst, 0, 2, 3, 1); - break; - } - case OPCODE_DP2ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP2ADD\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "dot(vec2("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - bcatcstr(glsl, "), vec2("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bcatcstr(glsl, ")) + "); - TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_FLOAT); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_POW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//POW\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, "pow(abs("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); - bcatcstr(glsl, "), "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); - bcatcstr(glsl, ")"); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - - case OPCODE_IMM_ATOMIC_ALLOC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_ALLOC\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "atomicCounterIncrement("); - bformata(glsl, "UAV%d_counter)", psInst->asOperands[1].ui32RegisterNumber); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_IMM_ATOMIC_CONSUME: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_CONSUME\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, "atomicCounterDecrement("); - bformata(glsl, "UAV%d_counter)", psInst->asOperands[1].ui32RegisterNumber); - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - - case OPCODE_NOT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INOT\n"); -#endif - AddIndentation(psContext); - BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - - uint32_t uDestElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t uSrcElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - - if (uDestElemCount == uSrcElemCount) - { - bcatcstr(glsl, "~("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - } - else - { - ASSERT(uSrcElemCount > uDestElemCount); - bformata(glsl, "ivec%d(~(", uSrcElemCount); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - } - - EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//XOR\n"); -#endif - - CallBinaryOp(psContext, "^", psInst, 0, 1, 2, TO_FLAG_INTEGER); - break; - } - case OPCODE_RESINFO: - { - const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; - uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RESINFO\n"); -#endif - - //ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - //ASSERT(psInst->asOperands[0].ui32CompMask == OPERAND_4_COMPONENT_MASK_ALL); - - - - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = {"x", "y", "z", "w"}; - uint32_t ui32ResInfoReturnTypeToFlags = (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) ? TO_FLAG_INTEGER /* currently it's treated as int */ : TO_FLAG_FLOAT; - - AddIndentation(psContext); - if (destElemCount > 1) - { - BeginAssignmentEx(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate, swizzle[destElem]); - } - else - { - BeginAssignment(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate); - } - - GetResInfoData(psContext, psInst, destElem); - - EndAssignment(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate); - - bcatcstr(glsl, ";\n"); - } - - break; - } - - - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_DTOF: - case OPCODE_FTOD: - case OPCODE_DDIV: - case OPCODE_DFMA: - case OPCODE_DRCP: - case OPCODE_MSAD: - case OPCODE_DTOI: - case OPCODE_DTOU: - case OPCODE_ITOD: - case OPCODE_UTOD: - default: - { - ASSERT(0); - break; - } - } -} - -static int IsIntegerOpcode(OPCODE_TYPE eOpcode) -{ - switch (eOpcode) - { - case OPCODE_IADD: - case OPCODE_IF: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_ITOF: - case OPCODE_AND: - case OPCODE_OR: - { - return 1; - } - default: - { - return 0; - } - } -} - -int InstructionUsesRegister(const Instruction* psInst, const Operand* psOperand) -{ - uint32_t operand; - for (operand = 0; operand < psInst->ui32NumOperands; ++operand) - { - if (psInst->asOperands[operand].eType == psOperand->eType) - { - if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) - { - if (CompareOperandSwizzles(&psInst->asOperands[operand], psOperand)) - { - return 1; - } - } - } - } - return 0; -} - -void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext) -{ - const uint32_t count = psContext->psShader->ui32InstCount; - Instruction* psInst = psContext->psShader->psInst; - uint32_t i; - - for (i = 0; i < count; ) - { - if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && - psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) - { - uint32_t k; - - for (k = i + 1; k < count; ++k) - { - if (psInst[k].eOpcode == OPCODE_ILT) - { - k = k; - } - if (InstructionUsesRegister(&psInst[k], &psInst[i].asOperands[0])) - { - if (IsIntegerOpcode(psInst[k].eOpcode)) - { - psInst[i].asOperands[1].iIntegerImmediate = 1; - } - - goto next_iteration; - } - } - } -next_iteration: - ++i; - } -} diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c deleted file mode 100644 index b77576ed51..0000000000 --- a/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c +++ /dev/null @@ -1,2121 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/toGLSLDeclaration.h" -#include "internal_includes/hlslccToolkit.h" -#include "internal_includes/languages.h" -#include "bstrlib.h" -#include "hlslcc.h" -#include "internal_includes/debug.h" - -#include <float.h> -#include <math.h> -#include <stdbool.h> - -#if !defined(isnan) -#ifdef _MSC_VER -#define isnan(x) _isnan(x) -#define isinf(x) (!_finite(x)) -#endif -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -// Returns true if types are just different precisions of the same underlying type -static bool AreTypesCompatible(SHADER_VARIABLE_TYPE a, uint32_t ui32TOFlag) -{ - SHADER_VARIABLE_TYPE b = TypeFlagsToSVTType(ui32TOFlag); - - if (a == b) - return true; - - // Special case for array indices: both uint and int are fine - if ((ui32TOFlag & TO_FLAG_INTEGER) && (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) && - (a == SVT_INT || a == SVT_INT16 || a == SVT_UINT || a == SVT_UINT16)) - return true; - - if ((a == SVT_FLOAT || a == SVT_FLOAT16 || a == SVT_FLOAT10) && - (b == SVT_FLOAT || b == SVT_FLOAT16 || b == SVT_FLOAT10)) - return true; - - if ((a == SVT_INT || a == SVT_INT16 || a == SVT_INT12) && - (b == SVT_INT || b == SVT_INT16 || a == SVT_INT12)) - return true; - - if ((a == SVT_UINT || a == SVT_UINT16) && - (b == SVT_UINT || b == SVT_UINT16)) - return true; - - return false; -} - -int GetMaxComponentFromComponentMask(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Comonent Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 4; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 3; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 1; - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - return 4; - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return 1; - } - } - - return 4; -} - -//Single component repeated -//e..g .wwww -uint32_t IsSwizzleReplacated(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == WWWW_SWIZZLE || - psOperand->ui32Swizzle == ZZZZ_SWIZZLE || - psOperand->ui32Swizzle == YYYY_SWIZZLE || - psOperand->ui32Swizzle == XXXX_SWIZZLE) - { - return 1; - } - } - } - return 0; -} - -//e.g. -//.z = 1 -//.x = 1 -//.yw = 2 -uint32_t GetNumSwizzleElements(const Operand* psOperand) -{ - uint32_t count = 0; - - switch (psOperand->eType) - { - case OPERAND_TYPE_IMMEDIATE32: - case OPERAND_TYPE_IMMEDIATE64: - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH: - { - return psOperand->iNumComponents; - } - default: - { - break; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Comonent Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - count++; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - count++; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - count++; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - count++; - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - count++; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - count++; - } - } - - //Component Select 1 - } - - if (!count) - { - return psOperand->iNumComponents; - } - - return count; -} - -void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count) -{ - bstring glsl = *psContext->currentGLSLString; - if (count) - { - bcatcstr(glsl, "."); - bcatcstr(glsl, "x"); - count--; - } - if (count) - { - bcatcstr(glsl, "y"); - count--; - } - if (count) - { - bcatcstr(glsl, "z"); - count--; - } - if (count) - { - bcatcstr(glsl, "w"); - count--; - } -} - -uint32_t ConvertOperandSwizzleToComponentMask(const Operand* psOperand) -{ - uint32_t mask = 0; - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Comonent Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - mask = psOperand->ui32CompMask; - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - - //Component Select 1 - } - - return mask; -} - -//Non-zero means the components overlap -int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB) -{ - uint32_t maskA = ConvertOperandSwizzleToComponentMask(psOperandA); - uint32_t maskB = ConvertOperandSwizzleToComponentMask(psOperandB); - - return maskA & maskB; -} - - -void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - bstring glsl = *psContext->currentGLSLString; - - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return; - } - } - - if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - /*ConstantBuffer* psCBuf = NULL; - ShaderVar* psVar = NULL; - int32_t index = -1; - GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) - //then apply the sizzle. - - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); - - bformata(glsl, ".%s", psVar->Name); - if(index != -1) - { - bformata(glsl, "[%d]", index); - }*/ - - //return; - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Comonent Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - bcatcstr(glsl, "."); - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - bcatcstr(glsl, "x"); - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - bcatcstr(glsl, "y"); - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - bcatcstr(glsl, "z"); - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - bcatcstr(glsl, "w"); - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - bcatcstr(glsl, "."); - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - bcatcstr(glsl, "x"); - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(glsl, "y"); - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(glsl, "z"); - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - bcatcstr(glsl, "w"); - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - bcatcstr(glsl, "."); - - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - bcatcstr(glsl, "x"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(glsl, "y"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(glsl, "z"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - bcatcstr(glsl, "w"); - } - } - - //Component Select 1 - } -} - -int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return -1; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Comonent Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 0; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 1; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 3; - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - - //Component Select 1 - } - - return -1; -} - -void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) -{ - int i = index; - int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; - - bstring glsl = *psContext->currentGLSLString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0 || isGeoShader) - { - bformata(glsl, "[%d]", psOperand->aui32ArraySizes[i]); - } - else - { - bformata(glsl, "%d", psOperand->aui32ArraySizes[i]); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(glsl, "[int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bcatcstr(glsl, ")]"); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(glsl, "[int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bformata(glsl, ") + %d]", psOperand->aui32ArraySizes[i]); - break; - } - default: - { - break; - } - } -} - -void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) -{ - int i = index; - int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; - - bstring glsl = *psContext->currentGLSLString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0 || isGeoShader) - { - bformata(glsl, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - } - else - { - bformata(glsl, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(glsl, "[int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bformata(glsl, ")*%d+%d]", multiply, add); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(glsl, "[(int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bformata(glsl, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - break; - } - default: - { - break; - } - } -} - -void TranslateVariableNameByOperandType(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) -{ - bstring glsl = *psContext->currentGLSLString; - - switch (psOperand->eType) - { - case OPERAND_TYPE_IMMEDIATE32: - { - if (psOperand->iNumComponents == 1) - { - if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bformata(glsl, "%uu", - *((unsigned int*)(&psOperand->afImmediates[0]))); - } - else - if ((ui32TOFlag & TO_FLAG_INTEGER) || ((ui32TOFlag & TO_FLAG_FLOAT) == 0 && psOperand->iIntegerImmediate) || fpcheck(psOperand->afImmediates[0])) - { - if (ui32TOFlag & TO_FLAG_FLOAT) - { - bcatcstr(glsl, "float"); - } - else if (ui32TOFlag & TO_FLAG_INTEGER) - { - bcatcstr(glsl, "int"); - } - bcatcstr(glsl, "("); - - // yet another Qualcomm's special case - // GLSL compiler thinks that -2147483648 is an integer overflow which is not - if (*((int*)(&psOperand->afImmediates[0])) == 2147483648) - { - bformata(glsl, "-2147483647-1"); - } - else - { - // this is expected to fix paranoid compiler checks such as Qualcomm's - if (*((unsigned int*)(&psOperand->afImmediates[0])) >= 2147483648) - { - bformata(glsl, "%d", - *((int*)(&psOperand->afImmediates[0]))); - } - else - { - bformata(glsl, "%d", - *((int*)(&psOperand->afImmediates[0]))); - } - } - bcatcstr(glsl, ")"); - } - else - { - bformata(glsl, "%e", - psOperand->afImmediates[0]); - } - } - else - { - if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bformata(glsl, "uvec4(%uu, %uu, %uu, %uu)", - *(unsigned int*)&psOperand->afImmediates[0], - *(unsigned int*)&psOperand->afImmediates[1], - *(unsigned int*)&psOperand->afImmediates[2], - *(unsigned int*)&psOperand->afImmediates[3]); - } - else - if ((ui32TOFlag & TO_FLAG_INTEGER) || - ((ui32TOFlag & TO_FLAG_FLOAT) == 0 && psOperand->iIntegerImmediate) || - fpcheck(psOperand->afImmediates[0]) || - fpcheck(psOperand->afImmediates[1]) || - fpcheck(psOperand->afImmediates[2]) || - fpcheck(psOperand->afImmediates[3])) - { - // this is expected to fix paranoid compiler checks such as Qualcomm's - if (ui32TOFlag & TO_FLAG_FLOAT) - { - bcatcstr(glsl, "vec4"); - } - else if (ui32TOFlag & TO_FLAG_INTEGER) - { - bcatcstr(glsl, "ivec4"); - } - else if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(glsl, "uvec4"); - } - bcatcstr(glsl, "("); - - if ((*(unsigned int*)&psOperand->afImmediates[0]) == 2147483648u) - { - bformata(glsl, "int(-2147483647-1), "); - } - else - { - bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[0]); - } - if ((*(unsigned int*)&psOperand->afImmediates[1]) == 2147483648u) - { - bformata(glsl, "int(-2147483647-1), "); - } - else - { - bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[1]); - } - if ((*(unsigned int*)&psOperand->afImmediates[2]) == 2147483648u) - { - bformata(glsl, "int(-2147483647-1), "); - } - else - { - bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[2]); - } - if ((*(unsigned int*)&psOperand->afImmediates[3]) == 2147483648u) - { - bformata(glsl, "int(-2147483647-1)) "); - } - else - { - bformata(glsl, "%d)", *(int*)&psOperand->afImmediates[3]); - } - } - else - { - bformata(glsl, "vec4(%e, %e, %e, %e)", - psOperand->afImmediates[0], - psOperand->afImmediates[1], - psOperand->afImmediates[2], - psOperand->afImmediates[3]); - } - if (psOperand->iNumComponents != 4) - { - AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); - } - } - break; - } - case OPERAND_TYPE_IMMEDIATE64: - { - if (psOperand->iNumComponents == 1) - { - bformata(glsl, "%e", - psOperand->adImmediates[0]); - } - else - { - bformata(glsl, "dvec4(%e, %e, %e, %e)", - psOperand->adImmediates[0], - psOperand->adImmediates[1], - psOperand->adImmediates[2], - psOperand->adImmediates[3]); - if (psOperand->iNumComponents != 4) - { - AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - switch (psOperand->iIndexDims) - { - case INDEX_2D: - { - if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. - { - bcatcstr(glsl, "gl_in"); - TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE); //Vertex index - bcatcstr(glsl, ".gl_Position"); - } - else - { - const char* name = "Input"; - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); - } - - bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - bcstrfree((char*)name); - } - TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE); //Vertex index - } - break; - } - default: - { - if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) - { - bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber); - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")]"); - } - else - { - if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) - { - const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; - bformata(glsl, "Input%d[%d]", parentIndex, - psOperand->ui32RegisterNumber - parentIndex); - } - else - { - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); - bcatcstr(glsl, name); - bcstrfree(name); - } - else - { - bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); - } - } - } - break; - } - } - break; - } - case OPERAND_TYPE_OUTPUT: - { - bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); - if (psOperand->psSubOperand[0]) - { - bcatcstr(glsl, "[int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")]"); - } - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH: - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bcatcstr(glsl, "gl_FragDepth"); - break; - } - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); - bcatcstr(glsl, "Temp"); - - if ((psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) == 0 || psContext->psShader->eShaderType == HULL_SHADER) - { - if (eType == SVT_INT) - { - bcatcstr(glsl, "_int"); - } - else if (eType == SVT_UINT) - { - bcatcstr(glsl, "_uint"); - } - else if (eType == SVT_DOUBLE) - { - bcatcstr(glsl, "_double"); - } - else if (eType == SVT_VOID || - (ui32TOFlag & TO_FLAG_DESTINATION)) - { - if (ui32TOFlag & TO_FLAG_INTEGER) - { - bcatcstr(glsl, "_int"); - } - else - if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(glsl, "_uint"); - } - } - - bformata(glsl, "[%d]", psOperand->ui32RegisterNumber); - } - else - { - if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) - bformata(glsl, "%d[0]", psOperand->ui32RegisterNumber); - else - bformata(glsl, "%d", psOperand->ui32RegisterNumber); - } - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONSTINT: - { - bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONST: - { - if (psOperand->psSubOperand[0] != NULL) - { - bformata(glsl, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); - bcatcstr(glsl, "]"); - } - else - { - bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber); - } - break; - } - case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: - { - bcatcstr(glsl, "BaseColour"); - break; - } - case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: - { - bcatcstr(glsl, "OffsetColour"); - break; - } - case OPERAND_TYPE_SPECIAL_POSITION: - { - bcatcstr(glsl, "gl_Position"); - break; - } - case OPERAND_TYPE_SPECIAL_FOG: - { - bcatcstr(glsl, "Fog"); - break; - } - case OPERAND_TYPE_SPECIAL_POINTSIZE: - { - bcatcstr(glsl, "gl_PointSize"); - break; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - { - bcatcstr(glsl, "Address"); - break; - } - case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: - { - bcatcstr(glsl, "LoopCounter"); - pui32IgnoreSwizzle[0] = 1; - break; - } - case OPERAND_TYPE_SPECIAL_TEXCOORD: - { - bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - bool addParentheses = false; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - pui32IgnoreSwizzle[0] = 1; - } - - if ((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) - { - if (psCBuf) - { - //$Globals. - if (psCBuf->Name[0] == '$') - { - ConvertToUniformBufferName(glsl, psContext->psShader, "$Globals"); - } - else - { - ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); - } - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(glsl, "."); - } - } - else - { - //bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]); - } - } - - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - //Work out the variable name. Don't apply swizzle to that variable yet. - int32_t rebase = 0; - - if (psCBuf && !psCBuf->blob) - { - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) - { - if (psVarType->Class == SVC_VECTOR || psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) - { - switch (psVarType->Type) - { - case SVT_FLOAT: - case SVT_FLOAT16: - case SVT_FLOAT10: - { - bformata(glsl, "vec%d(", psVarType->Columns); - break; - } - case SVT_UINT: - case SVT_UINT16: - { - bformata(glsl, "uvec%d(", psVarType->Columns); - break; - } - case SVT_INT: - case SVT_INT16: - case SVT_INT12: - { - bformata(glsl, "ivec%d(", psVarType->Columns); - break; - } - default: - { - ASSERT(0); - break; - } - } - addParentheses = true; - } - else if (psVarType->Class == SVC_SCALAR) - { - switch (psVarType->Type) - { - case SVT_FLOAT: - case SVT_FLOAT16: - case SVT_FLOAT10: - { - bformata(glsl, "float("); - break; - } - case SVT_UINT: - case SVT_UINT16: - { - bformata(glsl, "uint("); - break; - } - case SVT_INT: - case SVT_INT16: - case SVT_INT12: - { - bformata(glsl, "int("); - break; - } - default: - { - ASSERT(0); - break; - } - } - addParentheses = true; - } - } - ShaderVarFullName(glsl, psContext->psShader, psVarType); - } - else if (psCBuf) - { - ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); - bcatcstr(glsl, "_data"); - index = psOperand->aui32ArraySizes[1]; - } - else - // We don't have a semantic for this variable, so try the raw dump appoach. - { - bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]); // - index = psOperand->aui32ArraySizes[1]; - } - - //Dx9 only? - if (psOperand->psSubOperand[0] != NULL) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[0]); - if (eType != SVT_INT && eType != SVT_UINT) - { - bcatcstr(glsl, "[int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")]"); - } - else - { - bcatcstr(glsl, "["); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - } - } - else - if (index != -1 && psOperand->psSubOperand[1] != NULL) - { - //Array of matrices is treated as array of vec4s - if (index != -1) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); - if (eType != SVT_INT && eType != SVT_UINT) - { - bcatcstr(glsl, "[int("); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bformata(glsl, ") + %d]", index); - } - else - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bformata(glsl, " + %d]", index); - } - } - } - else if (index != -1) - { - bformata(glsl, "[%d]", index); - } - else if (psOperand->psSubOperand[1] != NULL) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); - if (eType != SVT_INT && eType != SVT_UINT) - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - } - else - { - bcatcstr(glsl, "[int("); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ")]"); - } - } - - if (addParentheses) - bcatcstr(glsl, ")"); - - if (psVarType && psVarType->Class == SVC_VECTOR) - { - switch (rebase) - { - case 4: - { - if (psVarType->Columns == 2) - { - //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) - bcatcstr(glsl, ".xxyx"); - } - else if (psVarType->Columns == 3) - { - //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL) - bcatcstr(glsl, ".xxyz"); - } - break; - } - case 8: - { - if (psVarType->Columns == 2) - { - //.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL) - bcatcstr(glsl, ".xxxy"); - } - break; - } - case 0: - default: - { - //No rebase, but extend to vec4. - if (psVarType->Columns == 2) - { - bcatcstr(glsl, ".xyxx"); - } - else if (psVarType->Columns == 3) - { - bcatcstr(glsl, ".xyzx"); - } - break; - } - } - } - - if (psVarType && psVarType->Class == SVC_SCALAR) - { - *pui32IgnoreSwizzle = 1; - } - } - break; - } - case OPERAND_TYPE_RESOURCE: - { - TextureName(*psContext->currentGLSLString, psContext->psShader, psOperand->ui32RegisterNumber, MAX_RESOURCE_BINDINGS, 0); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_SAMPLER: - { - bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_FUNCTION_BODY: - { - const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; - const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; - //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; - const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; - const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; - const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; - - bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); - break; - } - case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: - { - bcatcstr(glsl, "forkInstanceID"); - *pui32IgnoreSwizzle = 1; - return; - } - case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: - { - bcatcstr(glsl, "immediateConstBufferF"); - - if (psOperand->psSubOperand[0]) - { - bcatcstr(glsl, "(int("); //Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - } - break; - } - case OPERAND_TYPE_INPUT_DOMAIN_POINT: - { - bcatcstr(glsl, "gl_TessCoord"); - break; - } - case OPERAND_TYPE_INPUT_CONTROL_POINT: - { - if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. - { - bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); - } - else - { - bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); - } - break; - } - case OPERAND_TYPE_NULL: - { - // Null register, used to discard results of operations - bcatcstr(glsl, "//null"); - break; - } - case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: - { - bcatcstr(glsl, "gl_InvocationID"); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - bcatcstr(glsl, "gl_SampleMask[0]"); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_COVERAGE_MASK: - { - bcatcstr(glsl, "gl_SampleMaskIn[0]"); - //Skip swizzle on scalar types. - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID://SV_DispatchThreadID - { - bcatcstr(glsl, "gl_GlobalInvocationID.xyzz"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID://SV_GroupThreadID - { - bcatcstr(glsl, "gl_WorkGroupID.xyzz"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP://SV_GroupID - { - bcatcstr(glsl, "gl_LocalInvocationID.xyzz"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED://SV_GroupIndex - { - bcatcstr(glsl, "gl_LocalInvocationIndex.xyzz"); - break; - } - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - { - UAVName(*psContext->currentGLSLString, psContext->psShader, psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_PRIMITIVEID: - { - bcatcstr(glsl, "gl_PrimitiveID"); - break; - } - case OPERAND_TYPE_INDEXABLE_TEMP: - { - bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]); - bformata(glsl, "[%d", psOperand->aui32ArraySizes[1]); - - if (psOperand->psSubOperand[1]) - { - bcatcstr(glsl, "+"); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_UNSIGNED_INTEGER); - } - bcatcstr(glsl, "]"); - break; - } - case OPERAND_TYPE_STREAM: - { - bformata(glsl, "%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: - { - bcatcstr(glsl, "gl_InvocationID"); - break; - } - case OPERAND_TYPE_THIS_POINTER: - { - /* - The "this" register is a register that provides up to 4 pieces of information: - X: Which CB holds the instance data - Y: Base element offset of the instance data within the instance CB - Z: Base sampler index - W: Base Texture index - - Can be different for each function call - */ - break; - } - default: - { - ASSERT(0); - break; - } - } -} - -void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) -{ - bool hasConstructor = false; - bstring glsl = *psContext->currentGLSLString; - - *pui32IgnoreSwizzle = 0; - - if (psOperand->eType != OPERAND_TYPE_IMMEDIATE32 && - psOperand->eType != OPERAND_TYPE_IMMEDIATE64) - { - if (ui32TOFlag != TO_FLAG_NONE && !(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) - { - SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTType(ui32TOFlag); - const uint32_t swizCount = psOperand->iNumComponents; - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); - - if (!AreTypesCompatible(eType, ui32TOFlag)) - { - if (CanDoDirectCast(eType, requestedType)) - { - bformata(glsl, "%s(", GetConstructorForTypeGLSL(psContext, requestedType, swizCount, false)); - } - else - { - // Direct cast not possible, need to do bitcast. - bformata(glsl, "%s(", GetBitcastOp(eType, requestedType)); - } - - hasConstructor = true; - } - } - } - - if (ui32TOFlag & TO_FLAG_COPY) - { - bcatcstr(glsl, "TempCopy"); - if ((psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) == 0) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); - switch (eType) - { - case SVT_FLOAT: - break; - case SVT_INT: - bcatcstr(glsl, "_int"); - break; - case SVT_UINT: - bcatcstr(glsl, "_uint"); - break; - case SVT_DOUBLE: - bcatcstr(glsl, "_double"); - break; - default: - ASSERT(0); - break; - } - } - } - else - { - TranslateVariableNameByOperandType(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle); - } - - if (hasConstructor) - { - bcatcstr(glsl, ")"); - } -} -SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - if (HavePrecisionQualifers(psContext->psShader->eTargetLanguage)) - { - // The min precision qualifier overrides all of the stuff below - switch (psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_FLOAT_16: - return SVT_FLOAT16; - case OPERAND_MIN_PRECISION_FLOAT_2_8: - return SVT_FLOAT10; - case OPERAND_MIN_PRECISION_SINT_16: - return SVT_INT16; - case OPERAND_MIN_PRECISION_UINT_16: - return SVT_UINT16; - default: - break; - } - } - - switch (psOperand->eType) - { - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; - int i = 0; - - if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) - { - return psContext->psShader->aeCommonTempVecType[psOperand->ui32RegisterNumber]; - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - return psOperand->aeDataType[0]; - } - - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - for (; i < 4; ++i) - { - if (ui32CompMask & (1 << i)) - { - eCurrentType = psOperand->aeDataType[i]; - break; - } - } - -#ifdef _DEBUG - //Check if all elements have the same basic type. - for (; i < 4; ++i) - { - if (psOperand->ui32CompMask & (1 << i)) - { - if (eCurrentType != psOperand->aeDataType[i]) - { - ASSERT(0); - } - } - } -#endif - return eCurrentType; - } - - ASSERT(0); - - break; - } - case OPERAND_TYPE_OUTPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psOut; - - if (GetOutputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, 0, &psContext->psShader->sInfo, &psOut)) - { - if (psOut->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psIn; - - //UINT in DX, INT in GL. - if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) - { - return SVT_INT; - } - - if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) - { - if (psIn->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - int32_t rebase = -1; - int foundVar; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - if (psCBuf && !psCBuf->blob) - { - foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) - { - return psVarType->Type; - } - } - else - { - // Todo: this isn't correct yet. - return SVT_FLOAT; - } - break; - } - case OPERAND_TYPE_IMMEDIATE32: - { - return psOperand->iIntegerImmediate ? SVT_INT : SVT_FLOAT; - } - - case OPERAND_TYPE_INPUT_THREAD_ID: - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: - { - return SVT_UINT; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - { - return SVT_INT; - } - default: - { - return SVT_FLOAT; - } - } - - return SVT_FLOAT; -} - -void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) -{ - bstring glsl = *psContext->currentGLSLString; - uint32_t ui32IgnoreSwizzle = 0; - - if (ui32TOFlag & TO_FLAG_NAME_ONLY) - { - TranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); - return; - } - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - bcatcstr(glsl, "-"); - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(glsl, "abs("); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(glsl, "-abs("); - break; - } - } - - TranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); - - if (!ui32IgnoreSwizzle || IsGmemReservedSlot(FBF_ANY, psOperand->ui32RegisterNumber)) - { - TranslateOperandSwizzle(psContext, psOperand); - } - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(glsl, ")"); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(glsl, ")"); - break; - } - } -} - -char ShaderTypePrefix(Shader* psShader) -{ - switch (psShader->eShaderType) - { - default: - ASSERT(0); - case PIXEL_SHADER: - return 'p'; - case VERTEX_SHADER: - return 'v'; - case GEOMETRY_SHADER: - return 'g'; - case HULL_SHADER: - return 'h'; - case DOMAIN_SHADER: - return 'd'; - case COMPUTE_SHADER: - return 'c'; - } -} - -char ResourceGroupPrefix(ResourceGroup eResGroup) -{ - switch (eResGroup) - { - default: - ASSERT(0); - case RGROUP_CBUFFER: - return 'c'; - case RGROUP_TEXTURE: - return 't'; - case RGROUP_SAMPLER: - return 's'; - case RGROUP_UAV: - return 'u'; - } -} - -void ResourceName(bstring output, Shader* psShader, const char* szName, ResourceGroup eGroup, const char* szSecondaryName, ResourceGroup eSecondaryGroup, uint32_t ui32ArrayOffset, const char* szModifier) -{ - - const char* pBracket; - - bconchar(output, ShaderTypePrefix(psShader)); - bcatcstr(output, szModifier); - - bconchar(output, ResourceGroupPrefix(eGroup)); - while ((pBracket = strpbrk(szName, "[]")) != NULL) - { - //array syntax [X] becomes _0_ - //Otherwise declarations could end up as: - //uniform sampler2D SomeTextures[0]; - //uniform sampler2D SomeTextures[1]; - bcatblk(output, (const void*)szName, (int)(pBracket - szName)); - bconchar(output, '_'); - szName = pBracket + 1; - } - bcatcstr(output, szName); - - if (ui32ArrayOffset) - { - bformata(output, "%d", ui32ArrayOffset); - } - - if (szSecondaryName != NULL) - { - bconchar(output, ResourceGroupPrefix(eSecondaryGroup)); - bcatcstr(output, szSecondaryName); - } -} - -void TextureName(bstring output, Shader* psShader, const uint32_t ui32TextureRegister, const uint32_t ui32SamplerRegister, const int bCompare) -{ - ResourceBinding* psTextureBinding = 0; - ResourceBinding* psSamplerBinding = 0; - int found; - const char* szModifier = bCompare ? "c" : ""; - - found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegister, &psShader->sInfo, &psTextureBinding); - if (ui32SamplerRegister < MAX_RESOURCE_BINDINGS) - { - found &= GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegister, &psShader->sInfo, &psSamplerBinding); - } - - if (found) - { - if (IsGmemReservedSlot(FBF_EXT_COLOR, ui32TextureRegister) || IsGmemReservedSlot(FBF_ARM_COLOR, ui32TextureRegister)) // FRAMEBUFFER FETCH - { - int regNum = GetGmemInputResourceSlot(ui32TextureRegister); - bformata(output, "GMEM_Input%d", regNum); - } - else if (IsGmemReservedSlot(FBF_ARM_DEPTH, ui32TextureRegister)) - { - bcatcstr(output, "GMEM_Depth"); - } - else if (IsGmemReservedSlot(FBF_ARM_STENCIL, ui32TextureRegister)) - { - bcatcstr(output, "GMEM_Stencil"); - } - else - { - ResourceName(output, psShader, psTextureBinding->Name, RGROUP_TEXTURE, psSamplerBinding ? psSamplerBinding->Name : NULL, RGROUP_SAMPLER, ui32TextureRegister - psTextureBinding->ui32BindPoint, szModifier); - } - } - else if (ui32SamplerRegister < MAX_RESOURCE_BINDINGS) - { - bformata(output, "UnknownTexture%s_%d_%d", szModifier, ui32TextureRegister, ui32SamplerRegister); - } - else - { - bformata(output, "UnknownTexture%s_%d", szModifier, ui32TextureRegister); - } -} - -void UAVName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber) -{ - ResourceBinding* psBinding = 0; - int found; - - found = GetResourceFromBindingPoint(RGROUP_UAV, ui32RegisterNumber, &psShader->sInfo, &psBinding); - - if (found) - { - ResourceName(output, psShader, psBinding->Name, RGROUP_UAV, NULL, RGROUP_COUNT, ui32RegisterNumber - psBinding->ui32BindPoint, ""); - } - else - { - bformata(output, "UnknownUAV%d", ui32RegisterNumber); - } -} - -void UniformBufferName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber) -{ - ResourceBinding* psBinding = 0; - int found; - - found = GetResourceFromBindingPoint(RGROUP_CBUFFER, ui32RegisterNumber, &psShader->sInfo, &psBinding); - - if (found) - { - ResourceName(output, psShader, psBinding->Name, RGROUP_CBUFFER, NULL, RGROUP_COUNT, ui32RegisterNumber - psBinding->ui32BindPoint, ""); - } - else - { - bformata(output, "UnknownUniformBuffer%d", ui32RegisterNumber); - } -} - -void ShaderVarName(bstring output, Shader* psShader, const char* OriginalName) -{ - bconchar(output, ShaderTypePrefix(psShader)); - bcatcstr(output, OriginalName); -} - -void ShaderVarFullName(bstring output, Shader* psShader, const ShaderVarType* psShaderVar) -{ - if (psShaderVar->Parent != NULL) - { - ShaderVarFullName(output, psShader, psShaderVar->Parent); - bconchar(output, '.'); - } - ShaderVarName(output, psShader, psShaderVar->Name); -} - -void ConvertToTextureName(bstring output, Shader* psShader, const char* szName, const char* szSamplerName, const int bCompare) -{ - (void)bCompare; - - ResourceName(output, psShader, szName, RGROUP_TEXTURE, szSamplerName, RGROUP_SAMPLER, 0, ""); -} - -void ConvertToUAVName(bstring output, Shader* psShader, const char* szOriginalUAVName) -{ - ResourceName(output, psShader, szOriginalUAVName, RGROUP_UAV, NULL, RGROUP_COUNT, 0, ""); -} - -void ConvertToUniformBufferName(bstring output, Shader* psShader, const char* szConstantBufferName) -{ - ResourceName(output, psShader, szConstantBufferName, RGROUP_CBUFFER, NULL, RGROUP_COUNT, 0, ""); -} - -uint32_t GetGmemInputResourceSlot(uint32_t const slotIn) -{ - if (slotIn == GMEM_ARM_COLOR_SLOT) - { - // ARM framebuffer fetch only works with COLOR0 - return 0; - } - if (slotIn >= GMEM_FLOAT4_START_SLOT) - { - return slotIn - GMEM_FLOAT4_START_SLOT; - } - if (slotIn >= GMEM_FLOAT3_START_SLOT) - { - return slotIn - GMEM_FLOAT3_START_SLOT; - } - if (slotIn >= GMEM_FLOAT2_START_SLOT) - { - return slotIn - GMEM_FLOAT2_START_SLOT; - } - if (slotIn >= GMEM_FLOAT_START_SLOT) - { - return slotIn - GMEM_FLOAT_START_SLOT; - } - return slotIn; -} - -uint32_t GetGmemInputResourceNumElements(uint32_t const slotIn) -{ - if (slotIn >= GMEM_FLOAT4_START_SLOT) - { - return 4; - } - if (slotIn >= GMEM_FLOAT3_START_SLOT) - { - return 3; - } - if (slotIn >= GMEM_FLOAT2_START_SLOT) - { - return 2; - } - if (slotIn >= GMEM_FLOAT_START_SLOT) - { - return 1; - } - return 0; -} - -void TranslateGmemOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements) -{ - // Similar as TranslateOperandSwizzleWithMaskMETAL but need to considerate max # of elements - - bstring metal = *psContext->currentGLSLString; - - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents != 1) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t mask; - if (psOperand->ui32CompMask != 0) - { - mask = psOperand->ui32CompMask & ui32ComponentMask; - } - else - { - mask = ui32ComponentMask; - } - - if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) - { - bcatcstr(metal, "."); - if (mask & OPERAND_4_COMPONENT_MASK_X) - { - bcatcstr(metal, "x"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - if (mask & OPERAND_4_COMPONENT_MASK_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - if (mask & OPERAND_4_COMPONENT_MASK_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || - !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && - psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && - psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && - psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W - ) - ) - { - uint32_t i; - - bcatcstr(metal, "."); - - for (i = 0; i < 4; ++i) - { - if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) - { - continue; - } - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case - { - bcatcstr(metal, "."); - - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - - //Component Select 1 - } -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt b/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt deleted file mode 100644 index 33fcc54e34..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -if (PAL_TRAIT_BUILD_HOST_TOOLS) - - ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) - - include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) - if (NOT PAL_TRAIT_BUILD_HLSLCC_METAL) - return() - endif() - - ly_add_target( - NAME HLSLcc_Metal EXECUTABLE - NAMESPACE AZ - OUTPUT_NAME HLSLcc - OUTPUT_SUBDIRECTORY Compiler/PCGMETAL/HLSLcc - FILES_CMAKE - hlslcc_metal_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - include - src - src/cbstring - offline/cjson - BUILD_DEPENDENCIES - PRIVATE - AZ::AzCore - ) - ly_add_source_properties( - SOURCES - offline/compilerStandalone.cpp - offline/cjson/cJSON.c - src/toGLSL.c - src/toGLSLDeclaration.c - src/cbstring/bstrlib.c - src/cbstring/bstraux.c - src/reflect.c - src/decode.c - src/toMETAL.c - src/toMETALDeclaration.c - PROPERTY COMPILE_DEFINITIONS - VALUES _CRT_SECURE_NO_WARNINGS - ) - -endif() diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake deleted file mode 100644 index 6dc23ee057..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_HLSLCC_METAL FALSE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake deleted file mode 100644 index 6dc23ee057..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_HLSLCC_METAL FALSE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake deleted file mode 100644 index ee003b245b..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(PAL_TRAIT_BUILD_HLSLCC_METAL TRUE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/README b/Code/Tools/HLSLCrossCompilerMETAL/README deleted file mode 100644 index 2f36e0966e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/README +++ /dev/null @@ -1,52 +0,0 @@ -What does this software do? - Cross compiles HLSL bytecode to GLSL or GLSL ES. It also provides functions to - decode the reflection information embedded in HLSL bytecode. Both offline and online compiliation - is supported. - -Supported bytecode formats: - cs_4_0 cs_4_1 cs_5_0 - ds_5_0 - hs_5_0 - gs_4_0 gs_4_1 gs_5_0 - ps_4_0 ps_4_0_level_9_1 ps_4_0_level_9_3 ps_4_0_level_9_0 ps_4_1 ps_5_0 - vs_4_0_level_9_3 vs_4_0_level_9_0 vs_4_1 vs_5_0 - -Work is underway to support the DX9 bytecode formats: - ps_2_0 ps_2_a ps_2_b ps_3_0 - vs_1_1 vs_2_0 vs_2_a vs_3_0 - -Supported target languages: - GLSL ES 100 - GLSL ES 300 - GLSL ES 310 - GLSL 120 - GLSL 130 - GLSL 140 - GLSL 150 - GLSL 330 - GLSL 400 - GLSL 410 - GLSL 420 - GLSL 430 - GLSL 440 - METAL - -I have plans to add support for more target languages including: - ARB assembly (ARB_vertex_program et al.) - NVIDIA assembly (NV_vertex_program et al.) - -If the source shader contains instructions not support by the target language then compilation is allowed -to fail at the GLSL compile stage, i.e. the cross compiler may not generate errors/warnings but an OpenGL -driver will reject the shader. - -The tests directory contains HLSL, bytecode and asm versions of some shaders used to verify this decoder. -There are also a few sample applications used to make sure that generated GLSL is correct. - -A cmake makefile can be found in the mk directory. - -Generating hlsl_opcode_funcs_glsl.h - Use fwrap.py -f hlsl_opcode_funcs.glsl - fwrap.py can be found in my Helpful-scripts github repository. - -For further information please see the Wiki page for this project at -https://github.com/James-Jones/HLSLCrossCompiler/wiki. diff --git a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe deleted file mode 100644 index f1206847af..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35285dbf53617bf58f22035bb502d0b3328678344245635de578c2e73d484d04 -size 216064 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe deleted file mode 100644 index 64dab82ae4..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:99f686d3fc04c80f3460e6d35507acb09f5975f7c4d5e5cae95834e48a46898a -size 462848 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake b/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake deleted file mode 100644 index ffeb9d9755..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake +++ /dev/null @@ -1,65 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -set(FILES - include/hlslcc.h - include/hlslcc.hpp - include/pstdint.h - include/hlslcc_bin.hpp - offline/hash.h - offline/serializeReflection.h - offline/timer.h - offline/compilerStandalone.cpp - offline/serializeReflection.cpp - offline/timer.cpp - offline/cjson/cJSON.h - offline/cjson/cJSON.c - src/decode.c - src/decodeDX9.c - src/reflect.c - src/toGLSL.c - src/toMETAL.c - src/toMETALDeclaration.c - src/toMETALInstruction.c - src/toMETALOperand.c - src/toGLSLDeclaration.c - src/toGLSLInstruction.c - src/toGLSLOperand.c - src/internal_includes/debug.h - src/internal_includes/decode.h - src/internal_includes/hlslcc_malloc.h - src/internal_includes/hlslcc_malloc.c - src/internal_includes/languages.h - src/internal_includes/reflect.h - src/internal_includes/shaderLimits.h - src/internal_includes/structs.h - src/internal_includes/toMETALDeclaration.h - src/internal_includes/toMETALInstruction.h - src/internal_includes/toMETALOperand.h - src/internal_includes/toGLSLDeclaration.h - src/internal_includes/toGLSLInstruction.h - src/internal_includes/toGLSLOperand.h - src/internal_includes/tokens.h - src/internal_includes/tokensDX9.h - src/internal_includes/structsMetal.h - src/internal_includes/structsMetal.c - src/cbstring/bsafe.h - src/cbstring/bstraux.h - src/cbstring/bstrlib.h - src/cbstring/bsafe.c - src/cbstring/bstraux.c - src/cbstring/bstrlib.c -) - -set(SKIP_UNITY_BUILD_INCLUSION_FILES - # 'bsafe.c' tries to forward declar 'strncpy', 'strncat', etc, but they are already declared in other modules. Remove from unity builds conideration - src/cbstring/bsafe.c -) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h deleted file mode 100644 index b7444121bc..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h +++ /dev/null @@ -1,537 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HLSLCC_H_ -#define HLSLCC_H_ - -#if defined (_WIN32) && defined(HLSLCC_DYNLIB) - #define HLSLCC_APIENTRY __stdcall - #if defined(libHLSLcc_EXPORTS) - #define HLSLCC_API __declspec(dllexport) - #else - #define HLSLCC_API __declspec(dllimport) - #endif -#else - #define HLSLCC_APIENTRY - #define HLSLCC_API -#endif - -#include <stdint.h> -#include <stddef.h> - -#ifndef __cplusplus - #ifndef max - #define max(a,b) (((a) > (b)) ? (a) : (b)) - #endif - - #ifndef min - #define min(a,b) (((a) < (b)) ? (a) : (b)) - #endif -#endif //__cplusplus - -typedef enum -{ - LANG_DEFAULT,// Depends on the HLSL shader model. - LANG_ES_100, - LANG_ES_300, - LANG_ES_310, - LANG_120, - LANG_130, - LANG_140, - LANG_150, - LANG_330, - LANG_400, - LANG_410, - LANG_420, - LANG_430, - LANG_440, - // CONFETTI - LANG_METAL, -} ShaderLang; - -typedef struct -{ - uint32_t ARB_explicit_attrib_location : 1; - uint32_t ARB_explicit_uniform_location : 1; - uint32_t ARB_shading_language_420pack : 1; -}GlExtensions; - -enum -{ - MAX_SHADER_VEC4_OUTPUT = 512 -}; -enum -{ - MAX_SHADER_VEC4_INPUT = 512 -}; -enum -{ - MAX_TEXTURES = 128 -}; -enum -{ - MAX_FORK_PHASES = 2 -}; -enum -{ - MAX_FUNCTION_BODIES = 1024 -}; -enum -{ - MAX_CLASS_TYPES = 1024 -}; -enum -{ - MAX_FUNCTION_POINTERS = 128 -}; - -//Reflection -#define MAX_REFLECT_STRING_LENGTH 512 -#define MAX_CBUFFERS 256 -#define MAX_UAV 256 -#define MAX_FUNCTION_TABLES 256 -#define MAX_RESOURCE_BINDINGS 256 - -typedef enum SPECIAL_NAME -{ - NAME_UNDEFINED = 0, - NAME_POSITION = 1, - NAME_CLIP_DISTANCE = 2, - NAME_CULL_DISTANCE = 3, - NAME_RENDER_TARGET_ARRAY_INDEX = 4, - NAME_VIEWPORT_ARRAY_INDEX = 5, - NAME_VERTEX_ID = 6, - NAME_PRIMITIVE_ID = 7, - NAME_INSTANCE_ID = 8, - NAME_IS_FRONT_FACE = 9, - NAME_SAMPLE_INDEX = 10, - // The following are added for D3D11 - NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11, - NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12, - NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13, - NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14, - NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15, - NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16, - NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17, - NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18, - NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19, - NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20, - NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21, - NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22, -} SPECIAL_NAME; - - -typedef enum -{ - INOUT_COMPONENT_UNKNOWN = 0, - INOUT_COMPONENT_UINT32 = 1, - INOUT_COMPONENT_SINT32 = 2, - INOUT_COMPONENT_FLOAT32 = 3 -} INOUT_COMPONENT_TYPE; - -typedef enum MIN_PRECISION -{ - MIN_PRECISION_DEFAULT = 0, - MIN_PRECISION_FLOAT_16 = 1, - MIN_PRECISION_FLOAT_2_8 = 2, - MIN_PRECISION_RESERVED = 3, - MIN_PRECISION_SINT_16 = 4, - MIN_PRECISION_UINT_16 = 5, - MIN_PRECISION_ANY_16 = 0xf0, - MIN_PRECISION_ANY_10 = 0xf1 -} MIN_PRECISION; - -typedef struct InOutSignature_TAG -{ - char SemanticName[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32SemanticIndex; - SPECIAL_NAME eSystemValueType; - INOUT_COMPONENT_TYPE eComponentType; - uint32_t ui32Register; - uint32_t ui32Mask; - uint32_t ui32ReadWriteMask; - - uint32_t ui32Stream; - MIN_PRECISION eMinPrec; -} InOutSignature; - -typedef enum ResourceType_TAG -{ - RTYPE_CBUFFER,//0 - RTYPE_TBUFFER,//1 - RTYPE_TEXTURE,//2 - RTYPE_SAMPLER,//3 - RTYPE_UAV_RWTYPED,//4 - RTYPE_STRUCTURED,//5 - RTYPE_UAV_RWSTRUCTURED,//6 - RTYPE_BYTEADDRESS,//7 - RTYPE_UAV_RWBYTEADDRESS,//8 - RTYPE_UAV_APPEND_STRUCTURED,//9 - RTYPE_UAV_CONSUME_STRUCTURED,//10 - RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11 - RTYPE_COUNT, -} ResourceType; - -typedef enum ResourceGroup_TAG -{ - RGROUP_CBUFFER, - RGROUP_TEXTURE, - RGROUP_SAMPLER, - RGROUP_UAV, - RGROUP_COUNT, -} ResourceGroup; - -typedef enum UAVBindingArea_TAG -{ - UAVAREA_INVALID, - UAVAREA_CBUFFER, - UAVAREA_TEXTURE, - UAVAREA_COUNT, -} UAVBindingArea; - -typedef enum REFLECT_RESOURCE_DIMENSION -{ - REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0, - REFLECT_RESOURCE_DIMENSION_BUFFER = 1, - REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2, - REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3, - REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6, - REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7, - REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8, - REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9, - REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, - REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, -} REFLECT_RESOURCE_DIMENSION; - -typedef struct ResourceBinding_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - ResourceType eType; - uint32_t ui32BindPoint; - uint32_t ui32BindCount; - uint32_t ui32Flags; - REFLECT_RESOURCE_DIMENSION eDimension; - uint32_t ui32ReturnType; - uint32_t ui32NumSamples; - UAVBindingArea eBindArea; -} ResourceBinding; - -typedef enum _SHADER_VARIABLE_TYPE -{ - SVT_VOID = 0, - SVT_BOOL = 1, - SVT_INT = 2, - SVT_FLOAT = 3, - SVT_STRING = 4, - SVT_TEXTURE = 5, - SVT_TEXTURE1D = 6, - SVT_TEXTURE2D = 7, - SVT_TEXTURE3D = 8, - SVT_TEXTURECUBE = 9, - SVT_SAMPLER = 10, - SVT_PIXELSHADER = 15, - SVT_VERTEXSHADER = 16, - SVT_UINT = 19, - SVT_UINT8 = 20, - SVT_GEOMETRYSHADER = 21, - SVT_RASTERIZER = 22, - SVT_DEPTHSTENCIL = 23, - SVT_BLEND = 24, - SVT_BUFFER = 25, - SVT_CBUFFER = 26, - SVT_TBUFFER = 27, - SVT_TEXTURE1DARRAY = 28, - SVT_TEXTURE2DARRAY = 29, - SVT_RENDERTARGETVIEW = 30, - SVT_DEPTHSTENCILVIEW = 31, - SVT_TEXTURE2DMS = 32, - SVT_TEXTURE2DMSARRAY = 33, - SVT_TEXTURECUBEARRAY = 34, - SVT_HULLSHADER = 35, - SVT_DOMAINSHADER = 36, - SVT_INTERFACE_POINTER = 37, - SVT_COMPUTESHADER = 38, - SVT_DOUBLE = 39, - SVT_RWTEXTURE1D = 40, - SVT_RWTEXTURE1DARRAY = 41, - SVT_RWTEXTURE2D = 42, - SVT_RWTEXTURE2DARRAY = 43, - SVT_RWTEXTURE3D = 44, - SVT_RWBUFFER = 45, - SVT_BYTEADDRESS_BUFFER = 46, - SVT_RWBYTEADDRESS_BUFFER = 47, - SVT_STRUCTURED_BUFFER = 48, - SVT_RWSTRUCTURED_BUFFER = 49, - SVT_APPEND_STRUCTURED_BUFFER = 50, - SVT_CONSUME_STRUCTURED_BUFFER = 51, - - // Partial precision types - SVT_FLOAT10 = 53, - SVT_FLOAT16 = 54, - - - SVT_FORCE_DWORD = 0x7fffffff -} SHADER_VARIABLE_TYPE; - -typedef enum _SHADER_VARIABLE_CLASS -{ - SVC_SCALAR = 0, - SVC_VECTOR = (SVC_SCALAR + 1), - SVC_MATRIX_ROWS = (SVC_VECTOR + 1), - SVC_MATRIX_COLUMNS = (SVC_MATRIX_ROWS + 1), - SVC_OBJECT = (SVC_MATRIX_COLUMNS + 1), - SVC_STRUCT = (SVC_OBJECT + 1), - SVC_INTERFACE_CLASS = (SVC_STRUCT + 1), - SVC_INTERFACE_POINTER = (SVC_INTERFACE_CLASS + 1), - SVC_FORCE_DWORD = 0x7fffffff -} SHADER_VARIABLE_CLASS; - -typedef struct ShaderVarType_TAG -{ - SHADER_VARIABLE_CLASS Class; - SHADER_VARIABLE_TYPE Type; - uint32_t Rows; - uint32_t Columns; - uint32_t Elements; - uint32_t MemberCount; - uint32_t Offset; - char Name[MAX_REFLECT_STRING_LENGTH]; - - uint32_t ParentCount; - struct ShaderVarType_TAG* Parent; - //Includes all parent names. - char FullName[MAX_REFLECT_STRING_LENGTH]; - - struct ShaderVarType_TAG* Members; -} ShaderVarType; - -typedef struct ShaderVar_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - int haveDefaultValue; - uint32_t* pui32DefaultValues; - //Offset/Size in bytes. - uint32_t ui32StartOffset; - uint32_t ui32Size; - - ShaderVarType sType; -} ShaderVar; - -typedef struct ConstantBuffer_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - - uint32_t ui32NumVars; - ShaderVar* asVars; - - uint32_t ui32TotalSizeInBytes; - int blob; // Used with dynamic indexed const. buffers -} ConstantBuffer; - -typedef struct ClassType_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - uint16_t ui16ID; - uint16_t ui16ConstBufStride; - uint16_t ui16Texture; - uint16_t ui16Sampler; -} ClassType; - -typedef struct ClassInstance_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; - uint16_t ui16ID; - uint16_t ui16ConstBuf; - uint16_t ui16ConstBufOffset; - uint16_t ui16Texture; - uint16_t ui16Sampler; -} ClassInstance; - -typedef enum TESSELLATOR_PARTITIONING -{ - TESSELLATOR_PARTITIONING_UNDEFINED = 0, - TESSELLATOR_PARTITIONING_INTEGER = 1, - TESSELLATOR_PARTITIONING_POW2 = 2, - TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3, - TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4 -} TESSELLATOR_PARTITIONING; - -typedef enum TESSELLATOR_OUTPUT_PRIMITIVE -{ - TESSELLATOR_OUTPUT_UNDEFINED = 0, - TESSELLATOR_OUTPUT_POINT = 1, - TESSELLATOR_OUTPUT_LINE = 2, - TESSELLATOR_OUTPUT_TRIANGLE_CW = 3, - TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4 -} TESSELLATOR_OUTPUT_PRIMITIVE; - -typedef struct TextureSamplerPair_TAG -{ - char Name[MAX_REFLECT_STRING_LENGTH]; -} TextureSamplerPair; - -typedef struct TextureSamplerInfo_TAG -{ - uint32_t ui32NumTextureSamplerPairs; - TextureSamplerPair aTextureSamplerPair[MAX_RESOURCE_BINDINGS]; -} TextureSamplerInfo; - -typedef struct ShaderInfo_TAG -{ - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - - uint32_t ui32NumInputSignatures; - InOutSignature* psInputSignatures; - - uint32_t ui32NumOutputSignatures; - InOutSignature* psOutputSignatures; - - uint32_t ui32NumPatchConstantSignatures; - InOutSignature* psPatchConstantSignatures; - - uint32_t ui32NumResourceBindings; - ResourceBinding* psResourceBindings; - - uint32_t ui32NumConstantBuffers; - ConstantBuffer* psConstantBuffers; - ConstantBuffer* psThisPointerConstBuffer; - - uint32_t ui32NumClassTypes; - ClassType* psClassTypes; - - uint32_t ui32NumClassInstances; - ClassInstance* psClassInstances; - - //Func table ID to class name ID. - uint32_t aui32TableIDToTypeID[MAX_FUNCTION_TABLES]; - - uint32_t aui32ResourceMap[RGROUP_COUNT][MAX_RESOURCE_BINDINGS]; - - // Texture index to sampler slot - uint32_t aui32SamplerMap[MAX_RESOURCE_BINDINGS]; - - TESSELLATOR_PARTITIONING eTessPartitioning; - TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; - - //compute shader thread number - uint32_t ui32Thread_x; - uint32_t ui32Thread_y; - uint32_t ui32Thread_z; -} ShaderInfo; - -typedef enum INTERPOLATION_MODE -{ - INTERPOLATION_UNDEFINED = 0, - INTERPOLATION_CONSTANT = 1, - INTERPOLATION_LINEAR = 2, - INTERPOLATION_LINEAR_CENTROID = 3, - INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, - INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, - INTERPOLATION_LINEAR_SAMPLE = 6, - INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, -} INTERPOLATION_MODE; - -typedef struct -{ - int shaderType; //One of the GL enums. - char* sourceCode; - ShaderInfo reflection; - ShaderLang GLSLLanguage; - TextureSamplerInfo textureSamplerInfo; // HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS fills this out -} Shader; - -// NOTE: HLSLCC flags are specified by command line when executing this cross compiler. -// If these flags change, the command line switch '-flags=XXX' must change as well. -// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' - -/*HLSL constant buffers are treated as default-block unform arrays by default. This is done - to support versions of GLSL which lack ARB_uniform_buffer_object functionality. - Setting this flag causes each one to have its own uniform block. - Note: Currently the nth const buffer will be named UnformBufferN. This is likey to change to the original HLSL name in the future.*/ -static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT = 0x1; - -static const unsigned int HLSLCC_FLAG_ORIGIN_UPPER_LEFT = 0x2; - -static const unsigned int HLSLCC_FLAG_PIXEL_CENTER_INTEGER = 0x4; - -static const unsigned int HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO = 0x8; - -//GS enabled? -//Affects vertex shader (i.e. need to compile vertex shader again to use with/without GS). -//This flag is needed in order for the interfaces between stages to match when GS is in use. -//PS inputs VtxGeoOutput -//GS outputs VtxGeoOutput -//Vs outputs VtxOutput if GS enabled. VtxGeoOutput otherwise. -static const unsigned int HLSLCC_FLAG_GS_ENABLED = 0x10; - -static const unsigned int HLSLCC_FLAG_TESS_ENABLED = 0x20; - -//Either use this flag or glBindFragDataLocationIndexed. -//When set the first pixel shader output is the first input to blend -//equation, the others go to the second input. -static const unsigned int HLSLCC_FLAG_DUAL_SOURCE_BLENDING = 0x40; - -//If set, shader inputs and outputs are declared with their semantic name. -static const unsigned int HLSLCC_FLAG_INOUT_SEMANTIC_NAMES = 0x80; -//If set, shader inputs and outputs are declared with their semantic name appended. -static const unsigned int HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES = 0x100; - -//If set, combines texture/sampler pairs used together into samplers named "texturename_X_samplername". -static const unsigned int HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS = 0x200; - -//If set, attribute and uniform explicit location qualifiers are disabled (even if the language version supports that) -static const unsigned int HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS = 0x400; - -//If set, global uniforms are not stored in a struct. -static const unsigned int HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT = 0x800; - -// If set, HLSL DX9 lower precision qualifiers (e.g half) will be transformed to DX11 style (e.g min16float) -// before compiling. Necessary to preserve precision information. If not, FXC just silently transform -// everything to full precision (e.g float32). -static const unsigned int HLSLCC_FLAG_HALF_FLOAT_TRANSFORM = 0x40000; - -#ifdef __cplusplus -extern "C" { -#endif - -HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), - void* (*calloc_override)(size_t, size_t), - void (* free_override)(void*), - void* (*realloc_override)(void*, size_t)); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToGLSL(const char* filename, - unsigned int flags, - ShaderLang language, - const GlExtensions* extensions, - Shader* result - ); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToGLSL(const char* shader, - unsigned int flags, - ShaderLang language, - const GlExtensions* extensions, - Shader* result); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToMETAL(const char* filename, - unsigned int flags, - ShaderLang language, - Shader* result - ); - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToMETAL(const char* shader, - unsigned int flags, - ShaderLang language, - Shader* result); - - -HLSLCC_API void HLSLCC_APIENTRY FreeShader(Shader*); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp deleted file mode 100644 index 193415f277..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp +++ /dev/null @@ -1,7 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -extern "C" { -#include "hlslcc.h" -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp deleted file mode 100644 index cc41572aa2..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp +++ /dev/null @@ -1,448 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) - -enum -{ - DXBC_BASE_ALIGNMENT = 4, - FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C'), - FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F'), - FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N'), - FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N'), - FOURCC_PCSG = FOURCC('P', 'C', 'S', 'G'), - FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R'), - FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X'), - FOURCC_GLSL = FOURCC('G', 'L', 'S', 'L'), - FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1'), // When lower precision float/int/uint is used - FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1'), // When lower precision float/int/uint is used -}; - -#undef FOURCC - -template <typename T> -inline T DXBCSwapBytes(const T& kValue) -{ - return kValue; -} - -#if defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN - -inline uint16_t DXBCSwapBytes(const uint16_t& uValue) -{ - return - (((uValue) >> 8) & 0xFF) | - (((uValue) << 8) & 0xFF); -} - -inline uint32_t DXBCSwapBytes(const uint32_t& uValue) -{ - return - (((uValue) >> 24) & 0x000000FF) | - (((uValue) >> 8) & 0x0000FF00) | - (((uValue) << 8) & 0x00FF0000) | - (((uValue) << 24) & 0xFF000000); -} - -#endif //defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN - -template <typename Element> -struct SDXBCBufferBase -{ - Element* m_pBegin; - Element* m_pEnd; - Element* m_pIter; - - SDXBCBufferBase(Element* pBegin, Element* pEnd) - : m_pBegin(pBegin) - , m_pEnd(pEnd) - , m_pIter(pBegin) - { - } - - bool SeekRel(int32_t iOffset) - { - Element* pIterAfter(m_pIter + iOffset); - if (pIterAfter > m_pEnd) - { - return false; - } - - m_pIter = pIterAfter; - return true; - } - - bool SeekAbs(uint32_t uPosition) - { - Element* pIterAfter(m_pBegin + uPosition); - if (pIterAfter > m_pEnd) - { - return false; - } - - m_pIter = pIterAfter; - return true; - } -}; - -struct SDXBCInputBuffer - : SDXBCBufferBase<const uint8_t> -{ - SDXBCInputBuffer(const uint8_t* pBegin, const uint8_t* pEnd) - : SDXBCBufferBase(pBegin, pEnd) - { - } - - bool Read(void* pElements, size_t uSize) - { - const uint8_t* pIterAfter(m_pIter + uSize); - if (pIterAfter > m_pEnd) - { - return false; - } - - memcpy(pElements, m_pIter, uSize); - - m_pIter = pIterAfter; - return true; - } -}; - -struct SDXBCOutputBuffer - : SDXBCBufferBase<uint8_t> -{ - SDXBCOutputBuffer(uint8_t* pBegin, uint8_t* pEnd) - : SDXBCBufferBase(pBegin, pEnd) - { - } - - bool Write(const void* pElements, size_t uSize) - { - uint8_t* pIterAfter(m_pIter + uSize); - if (pIterAfter > m_pEnd) - { - return false; - } - - memcpy(m_pIter, pElements, uSize); - - m_pIter = pIterAfter; - return true; - } -}; - -template <typename S, typename External, typename Internal> -inline bool DXBCReadAs(S& kStream, External& kValue) -{ - Internal kInternal; - bool bResult(kStream.Read(&kInternal, sizeof(Internal))); - kValue = static_cast<External>(DXBCSwapBytes(kInternal)); - return bResult; -} - -template <typename S, typename Internal> -inline bool DXBCWriteAs(S& kStream, Internal kValue) -{ - Internal kInternal(DXBCSwapBytes(kValue)); - return kStream.Write(&kInternal, sizeof(Internal)); -} - -template <typename S, typename T> -bool DXBCReadUint8 (S& kStream, T& kValue) { return DXBCReadAs<S, T, uint8_t >(kStream, kValue); } -template <typename S, typename T> -bool DXBCReadUint16(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint16_t>(kStream, kValue); } -template <typename S, typename T> -bool DXBCReadUint32(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint32_t>(kStream, kValue); } - -template <typename S> -bool DXBCWriteUint8 (S& kStream, uint8_t kValue) { return DXBCWriteAs<S, uint8_t >(kStream, kValue); } -template <typename S> -bool DXBCWriteUint16(S& kStream, uint16_t kValue) { return DXBCWriteAs<S, uint16_t>(kStream, kValue); } -template <typename S> -bool DXBCWriteUint32(S& kStream, uint32_t kValue) { return DXBCWriteAs<S, uint32_t>(kStream, kValue); } - -template <typename O, typename I> -bool DXBCCopy(O& kOutput, I& kInput, size_t uSize) -{ - char acBuffer[1024]; - while (uSize > 0) - { - size_t uToCopy(std::min<size_t>(uSize, sizeof(acBuffer))); - if (!kInput.Read(acBuffer, uToCopy) || - !kOutput.Write(acBuffer, uToCopy)) - { - return false; - } - uSize -= uToCopy; - } - return true; -} - -enum -{ - DXBC_SIZE_POSITION = 6 * 4, - DXBC_HEADER_SIZE = 7 * 4, - DXBC_CHUNK_HEADER_SIZE = 2 * 4, - DXBC_MAX_NUM_CHUNKS_IN = 128, - DXBC_MAX_NUM_CHUNKS_OUT = 8, - DXBC_OUT_CHUNKS_INDEX_SIZE = (1 + 1 + DXBC_MAX_NUM_CHUNKS_OUT) * 4, - DXBC_OUT_FIXED_SIZE = DXBC_HEADER_SIZE + DXBC_OUT_CHUNKS_INDEX_SIZE, -}; - -inline void DXBCSizeGLSLChunk(uint32_t& uGLSLChunkSize, uint32_t& uNumSamplers, uint32_t& uGLSLSourceSize, const Shader* pShader) -{ - enum - { - GLSL_HEADER_SIZE = 4 * 8, // {uint32 uNumSamplers; uint32 uNumImports; uint32 uNumExports; uint32 uInputHash;uint32 uResources; uint32 ui32Thread_x; uint32 ui32Thread_y; uint32 ui32Thread_z} - GLSL_SAMPLER_SIZE = 4 * 2, // {uint32 uTexture; uint32 uSampler;} - GLSL_SYMBOL_SIZE = 4 * 3, // {uint32 uType; uint32 uID; uint32 uValue} - //extend for metal compute UAV type - GLSL_UAV_RESOURCES_AREA = 4 * 2, //{uint32 uResource; uint32 eBindArea} - }; - - // Only texture registers that are used are written - uNumSamplers = 0; - for (uint32_t uTexture = 0; uTexture < MAX_RESOURCE_BINDINGS; ++uTexture) - { - if (pShader->reflection.aui32SamplerMap[uTexture] != MAX_RESOURCE_BINDINGS) - { - ++uNumSamplers; - } - } - - //uint32_t uNumSymbols( - // pShader->reflection.ui32NumImports + - // pShader->reflection.ui32NumExports); - uint32_t uNumSymbols(0); // always 0 - uint32_t uNumResources(pShader->reflection.ui32NumResourceBindings); - - uint32_t uGLSLInfoSize( - DXBC_CHUNK_HEADER_SIZE + - GLSL_HEADER_SIZE + - uNumSamplers * GLSL_SAMPLER_SIZE + - uNumSymbols * GLSL_SYMBOL_SIZE + - uNumResources * GLSL_UAV_RESOURCES_AREA - ); - uGLSLSourceSize = (uint32_t)strlen(pShader->sourceCode) + 1; - uGLSLChunkSize = uGLSLInfoSize + uGLSLSourceSize; - uGLSLChunkSize += DXBC_BASE_ALIGNMENT - 1 - (uGLSLChunkSize - 1) % DXBC_BASE_ALIGNMENT; -} - -inline uint32_t DXBCSizeOutputChunk(uint32_t uCode, uint32_t uSizeIn) -{ - uint32_t uSizeOut; - switch (uCode) - { - case FOURCC_RDEF: - case FOURCC_ISGN: - case FOURCC_OSGN: - case FOURCC_PCSG: - case FOURCC_OSG1: - case FOURCC_ISG1: - // Preserve entire chunk - uSizeOut = uSizeIn; - break; - case FOURCC_SHDR: - case FOURCC_SHEX: - // Only keep the shader version - uSizeOut = uSizeIn < 4u ? uSizeIn : 4u; - break; - default: - // Discard the chunk - uSizeOut = 0; - break; - } - - return uSizeOut + DXBC_BASE_ALIGNMENT - 1 - (uSizeOut - 1) % DXBC_BASE_ALIGNMENT; -} - -template <typename I> -size_t DXBCGetCombinedSize(I& kDXBCInput, const Shader* pShader) -{ - uint32_t uNumChunksIn; - if (!kDXBCInput.SeekAbs(DXBC_HEADER_SIZE) || - !DXBCReadUint32(kDXBCInput, uNumChunksIn)) - { - return 0; - } - - uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - if (!DXBCReadUint32(kDXBCInput, auChunkOffsetsIn[uChunk])) - { - return 0; - } - } - - uint32_t uNumChunksOut(0); - uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); - for (uint32_t uChunk = 0; uChunk < uNumChunksIn && uNumChunksOut < DXBC_MAX_NUM_CHUNKS_OUT; ++uChunk) - { - uint32_t uChunkCode, uChunkSizeIn; - if (!kDXBCInput.SeekAbs(auChunkOffsetsIn[uChunk]) || - !DXBCReadUint32(kDXBCInput, uChunkCode) || - !DXBCReadUint32(kDXBCInput, uChunkSizeIn)) - { - return 0; - } - - uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); - if (uChunkSizeOut > 0) - { - uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; - } - } - - uint32_t uNumSamplers, uGLSLSourceSize, uGLSLChunkSize; - DXBCSizeGLSLChunk(uGLSLChunkSize, uNumSamplers, uGLSLSourceSize, pShader); - uOutSize += uGLSLChunkSize; - - return uOutSize; -} - -template <typename I, typename O> -bool DXBCCombineWithGLSL(I& kInput, O& kOutput, const Shader* pShader) -{ - uint32_t uNumChunksIn; - if (!DXBCCopy(kOutput, kInput, DXBC_HEADER_SIZE) || - !DXBCReadUint32(kInput, uNumChunksIn) || - uNumChunksIn > DXBC_MAX_NUM_CHUNKS_IN) - { - return false; - } - - uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - if (!DXBCReadUint32(kInput, auChunkOffsetsIn[uChunk])) - { - return false; - } - } - - uint32_t auZeroChunkIndex[DXBC_OUT_CHUNKS_INDEX_SIZE] = {0}; - if (!kOutput.Write(auZeroChunkIndex, DXBC_OUT_CHUNKS_INDEX_SIZE)) - { - return false; - } - - // Copy required input chunks just after the chunk index - uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); - uint32_t uNumChunksOut(0); - uint32_t auChunkOffsetsOut[DXBC_MAX_NUM_CHUNKS_OUT]; - for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) - { - uint32_t uChunkCode, uChunkSizeIn; - if (!kInput.SeekAbs(auChunkOffsetsIn[uChunk]) || - !DXBCReadUint32(kInput, uChunkCode) || - !DXBCReadUint32(kInput, uChunkSizeIn)) - { - return false; - } - - // Filter only input chunks of the specified types - uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); - if (uChunkSizeOut > 0) - { - if (uNumChunksOut >= DXBC_MAX_NUM_CHUNKS_OUT) - { - return false; - } - - if (!DXBCWriteUint32(kOutput, uChunkCode) || - !DXBCWriteUint32(kOutput, uChunkSizeOut) || - !DXBCCopy(kOutput, kInput, uChunkSizeOut)) - { - return false; - } - - auChunkOffsetsOut[uNumChunksOut] = uOutSize; - ++uNumChunksOut; - uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; - } - } - // Write GLSL chunk - uint32_t uGLSLChunkOffset(uOutSize); - uint32_t uGLSLChunkSize, uNumSamplers, uGLSLSourceSize; - DXBCSizeGLSLChunk(uGLSLChunkSize, uNumSamplers, uGLSLSourceSize, pShader); - if (!DXBCWriteUint32(kOutput, (uint32_t)FOURCC_GLSL) || - !DXBCWriteUint32(kOutput, uGLSLChunkSize) || - !DXBCWriteUint32(kOutput, uNumSamplers) || - !DXBCWriteUint32(kOutput, 0) || - !DXBCWriteUint32(kOutput, 0) || - !DXBCWriteUint32(kOutput, 0) || - /*!DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImports) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumExports) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32InputHash)*/ - !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumResourceBindings) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_x) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_y) || - !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_z)) - { - return false; - } - for (uint32_t uTexture = 0; uTexture < MAX_RESOURCE_BINDINGS; ++uTexture) - { - uint32_t uSampler(pShader->reflection.aui32SamplerMap[uTexture]); - if (uSampler != MAX_RESOURCE_BINDINGS) - { - if (!DXBCWriteUint32(kOutput, uTexture) || - !DXBCWriteUint32(kOutput, uSampler)) - { - return false; - } - } - } - //for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumImports; ++uSymbol) - //{ - // if (!DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].eType) || - // !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32ID) || - // !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32Value)) - // return false; - //} - //for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumExports; ++uSymbol) - //{ - // if (!DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].eType) || - // !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32ID) || - // !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32Value)) - // return false; - //} - for (uint32_t uResource = 0; uResource < pShader->reflection.ui32NumResourceBindings; ++uResource) - { - ResourceBinding* rb = pShader->reflection.psResourceBindings + uResource; - if (uResource != MAX_RESOURCE_BINDINGS) - { - if (!DXBCWriteUint32(kOutput, uResource) || - !DXBCWriteUint32(kOutput, rb->eBindArea)) - { - return false; - } - } - } - - if (!kOutput.Write(pShader->sourceCode, uGLSLSourceSize)) - { - return false; - } - uOutSize += uGLSLChunkSize; - - // Write total size and chunk index - if (!kOutput.SeekAbs(DXBC_SIZE_POSITION) || - !DXBCWriteUint32(kOutput, uOutSize) || - !kOutput.SeekAbs(DXBC_HEADER_SIZE) || - !DXBCWriteUint32(kOutput, uNumChunksOut + 1)) - { - return false; - } - for (uint32_t uChunk = 0; uChunk < uNumChunksOut; ++uChunk) - { - if (!DXBCWriteUint32(kOutput, auChunkOffsetsOut[uChunk])) - { - return false; - } - } - DXBCWriteUint32(kOutput, uGLSLChunkOffset); - - return true; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h b/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h deleted file mode 100644 index 6998242aa1..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h +++ /dev/null @@ -1,801 +0,0 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2011 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - **************************************************************************** - * - * Version 0.1.12 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * John Dill - * - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#include <stddef.h> -#include <limits.h> -#include <signal.h> - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED) -#include <stdint.h> -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include <wchar.h> -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what did Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - -#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) - -/* - * Please compile with the maximum warning settings to make sure macros are not - * defined more than once. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#define glue3_aux(x,y,z) x ## y ## z -#define glue3(x,y,z) glue3_aux(x,y,z) - -#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); -#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); - -#define DECL(us,bits) glue3(DECL,us,) (bits) - -#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) - -int main () { - DECL(I,8) - DECL(U,8) - DECL(I,16) - DECL(U,16) - DECL(I,32) - DECL(U,32) -#ifdef INT64_MAX - DECL(I,64) - DECL(U,64) -#endif - intmax_t imax = INTMAX_C(0); - uintmax_t umax = UINTMAX_C(0); - char str0[256], str1[256]; - - sprintf (str0, "%d %x\n", 0, ~0); - - sprintf (str1, "%d %x\n", i8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); - sprintf (str1, "%u %x\n", u8, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); - sprintf (str1, "%d %x\n", i16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); - sprintf (str1, "%u %x\n", u16, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); - sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); -#ifdef INT64_MAX - sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); -#endif - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); - sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); - if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); - - TESTUMAX(8); - TESTUMAX(16); - TESTUMAX(32); -#ifdef INT64_MAX - TESTUMAX(64); -#endif - - return EXIT_SUCCESS; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk b/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk deleted file mode 100644 index 66e2bb4ecf..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# -# Android Makefile conversion -# -# Leander Beernaert -# -# How to build: $ANDROID_NDK/ndk-build -# -VERSION=1.17 - -LOCAL_PATH := $(call my-dir)/../ - -include $(CLEAR_VARS) - -LOCAL_ARM_MODE := arm -LOCAL_ARM_NEON := true - -LOCAL_MODULE := HLSLcc - -LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/include \ - $(LOCAL_PATH)/src \ - $(LOCAL_PATH)/src/cbstring -LOCAL_CFLAGS += -Wall -W -# For dynamic library -#LOCAL_CFLAGS += -DHLSLCC_DYNLIB -LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/src/*.c) \ - $(wildcard $(LOCAL_PATH)/src/cbstring/*.c) \ - $(wildcard $(LOCAL_PATH)/src/internal_includes/*.c) -#LOCAL_LDLIBS += -lGLESv3 - -include $(BUILD_STATIC_LIBRARY) - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk b/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk deleted file mode 100644 index a8ae0839b1..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk +++ /dev/null @@ -1,3 +0,0 @@ -APP_PLATFORM := android-18 -APP_ABI := armeabi-v7a -APP_OPTIM := release diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a deleted file mode 100644 index 79305b66b7..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3469d419dc589eb7a68be97885d7a55b8b0bbbffd74c5c1586959be4698fb273 -size 1046940 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a deleted file mode 100644 index 7ecdd304eb..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:98fbcc0779c4a400530ad643e1125727c50fdbf01912f059ca296153f209eec5 -size 466488 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a deleted file mode 100644 index c76e85704a..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:270583c8762539856bf9f7c7cccf743c37db7fd4128cabd8fdfcfe3586177e27 -size 360488 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a deleted file mode 100644 index ee23387576..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:85f1fcddb62db461ff1012f91c38d323591a220ef3f6c1e41277161a43959333 -size 1139822 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a deleted file mode 100644 index 85bf31eed4..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af9216c54d23dd3754f7ae18d56b97ae256eb29a0046d8e0d2a0716054d8c230 -size 218888 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a deleted file mode 100644 index 00095a3615..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6a07bec349614cdd3e40c3577bddace1203148016f9276c7ef807bdbc37dcabf -size 671232 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a deleted file mode 100644 index c7b92fcc1e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:88acec4cedad5699900ec2d1a3ce83ab5e9365ebea4b4af0ababba562382f399 -size 296852 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a deleted file mode 100644 index 29dd7fbf7a..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4c0625b7f534df5817646dd1335f9d7916389f27a83b7d118fadab504064d910 -size 1144250 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib deleted file mode 100644 index 311dec443e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f4d128256b757a7e800514482f1278348b489db53be2548b7770d701eece7ea9 -size 1022450 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib deleted file mode 100644 index d7fda333b7..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d037d414fea62daf076b41ad1a0ffbb451fcaf4443f8b2f721166a4a33fe5865 -size 632236 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib deleted file mode 100644 index d531d2635f..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4e8d6023a2afd3db8f8bc6033db3d937d5a9ec635a9005bbc0dca121a196b2bb -size 428768 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib deleted file mode 100644 index d167e54c31..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d7d890fdabc3b8cb4f61e10140090455bae656ec6d3fc8fa6460d96435120186 -size 809218 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib deleted file mode 100644 index 5135e7e081..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:caa74b7cebff2b35d0db9bb8b2eb70065ca7f5816a93004e8fa195aabefefe18 -size 600034 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/license.txt b/Code/Tools/HLSLCrossCompilerMETAL/license.txt deleted file mode 100644 index e20caeefef..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/license.txt +++ /dev/null @@ -1,52 +0,0 @@ -Copyright (c) 2012 James Jones -All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -This software makes use of the bstring library which is provided under the following license: - -Copyright (c) 2002-2008 Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of bstrlib nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README deleted file mode 100644 index 7531c049a6..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README +++ /dev/null @@ -1,247 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -Welcome to cJSON. - -cJSON aims to be the dumbest possible parser that you can get your job done with. -It's a single file of C, and a single header file. - -JSON is described best here: http://www.json.org/ -It's like XML, but fat-free. You use it to move data around, store things, or just -generally represent your program's state. - - -First up, how do I build? -Add cJSON.c to your project, and put cJSON.h somewhere in the header search path. -For example, to build the test app: - -gcc cJSON.c test.c -o test -lm -./test - - -As a library, cJSON exists to take away as much legwork as it can, but not get in your way. -As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it -in one of two modes: Auto and Manual. Let's have a quick run-through. - - -I lifted some JSON from this page: http://www.json.org/fatfree.html -That page inspired me to write cJSON, which is a parser that tries to share the same -philosophy as JSON itself. Simple, dumb, out of the way. - -Some JSON: -{ - "name": "Jack (\"Bee\") Nimble", - "format": { - "type": "rect", - "width": 1920, - "height": 1080, - "interlace": false, - "frame rate": 24 - } -} - -Assume that you got this from a file, a webserver, or magic JSON elves, whatever, -you have a char * to it. Everything is a cJSON struct. -Get it parsed: - cJSON *root = cJSON_Parse(my_json_string); - -This is an object. We're in C. We don't have objects. But we do have structs. -What's the framerate? - - cJSON *format = cJSON_GetObjectItem(root,"format"); - int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; - - -Want to change the framerate? - cJSON_GetObjectItem(format,"frame rate")->valueint=25; - -Back to disk? - char *rendered=cJSON_Print(root); - -Finished? Delete the root (this takes care of everything else). - cJSON_Delete(root); - -That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers -before you dereference them. If you want to see how you'd build this struct in code? - cJSON *root,*fmt; - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); - cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); - cJSON_AddStringToObject(fmt,"type", "rect"); - cJSON_AddNumberToObject(fmt,"width", 1920); - cJSON_AddNumberToObject(fmt,"height", 1080); - cJSON_AddFalseToObject (fmt,"interlace"); - cJSON_AddNumberToObject(fmt,"frame rate", 24); - -Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup. -Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and -a few from elsewhere. - -What about manual mode? First up you need some detail. -Let's cover how the cJSON objects represent the JSON data. -cJSON doesn't distinguish arrays from objects in handling; just type. -Each cJSON has, potentially, a child, siblings, value, a name. - -The root object has: Object Type and a Child -The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: -Sibling has type Object, name "format", and a child. -That child has type String, name "type", value "rect", and a sibling: -Sibling has type Number, name "width", value 1920, and a sibling: -Sibling has type Number, name "height", value 1080, and a sibling: -Sibling hs type False, name "interlace", and a sibling: -Sibling has type Number, name "frame rate", value 24 - -Here's the structure: -typedef struct cJSON { - struct cJSON *next,*prev; - struct cJSON *child; - - int type; - - char *valuestring; - int valueint; - double valuedouble; - - char *string; -} cJSON; - -By default all values are 0 unless set by virtue of being meaningful. - -next/prev is a doubly linked list of siblings. next takes you to your sibling, -prev takes you back from your sibling to you. -Only objects and arrays have a "child", and it's the head of the doubly linked list. -A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0. -The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in -cJSON.h - -A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read -valuedouble. - -Any entry which is in the linked list which is the child of an object will have a "string" -which is the "name" of the entry. When I said "name" in the above example, that's "string". -"string" is the JSON name for the 'variable name' if you will. - -Now you can trivially walk the lists, recursively, and parse as you please. -You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take -the root object, and traverse the structure (which is, formally, an N-tree), -and tokenise as you please. If you wanted to build a callback style parser, this is how -you'd do it (just an example, since these things are very specific): - -void parse_and_callback(cJSON *item,const char *prefix) -{ - while (item) - { - char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); - sprintf(newprefix,"%s/%s",prefix,item->name); - int dorecurse=callback(newprefix, item->type, item); - if (item->child && dorecurse) parse_and_callback(item->child,newprefix); - item=item->next; - free(newprefix); - } -} - -The prefix process will build you a separated list, to simplify your callback handling. -The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or -let you invoke it per-item. For the item above, your callback might look like this: - -int callback(const char *name,int type,cJSON *item) -{ - if (!strcmp(name,"name")) { /* populate name */ } - else if (!strcmp(name,"format/type") { /* handle "rect" */ } - else if (!strcmp(name,"format/width") { /* 800 */ } - else if (!strcmp(name,"format/height") { /* 600 */ } - else if (!strcmp(name,"format/interlace") { /* false */ } - else if (!strcmp(name,"format/frame rate") { /* 24 */ } - return 1; -} - -Alternatively, you might like to parse iteratively. -You'd use: - -void parse_object(cJSON *item) -{ - int i; for (i=0;i<cJSON_GetArraySize(item);i++) - { - cJSON *subitem=cJSON_GetArrayItem(item,i); - // handle subitem. - } -} - -Or, for PROPER manual mode: - -void parse_object(cJSON *item) -{ - cJSON *subitem=item->child; - while (subitem) - { - // handle subitem - if (subitem->child) parse_object(subitem->child); - - subitem=subitem->next; - } -} - -Of course, this should look familiar, since this is just a stripped-down version -of the callback-parser. - -This should cover most uses you'll find for parsing. The rest should be possible -to infer.. and if in doubt, read the source! There's not a lot of it! ;) - - -In terms of constructing JSON data, the example code above is the right way to do it. -You can, of course, hand your sub-objects to other functions to populate. -Also, if you find a use for it, you can manually build the objects. -For instance, suppose you wanted to build an array of objects? - -cJSON *objects[24]; - -cJSON *Create_array_of_anything(cJSON **items,int num) -{ - int i;cJSON *prev, *root=cJSON_CreateArray(); - for (i=0;i<24;i++) - { - if (!i) root->child=objects[i]; - else prev->next=objects[i], objects[i]->prev=prev; - prev=objects[i]; - } - return root; -} - -and simply: Create_array_of_anything(objects,24); - -cJSON doesn't make any assumptions about what order you create things in. -You can attach the objects, as above, and later add children to each -of those objects. - -As soon as you call cJSON_Print, it renders the structure to text. - - - -The test.c code shows how to handle a bunch of typical cases. If you uncomment -the code, it'll load, parse and print a bunch of test files, also from json.org, -which are more complex than I'd care to try and stash into a const char array[]. - - -Enjoy cJSON! - - -- Dave Gamble, Aug 2009 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c deleted file mode 100644 index 56fb753ee8..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -// Modifications copyright Amazon.com, Inc. or its affiliates. - -/* cJSON */ -/* JSON parser in C. */ - -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <stdlib.h> -#include <float.h> -#include <limits.h> -#include <ctype.h> -#include "cJSON.h" -#include <AzCore/PlatformDef.h> - -static const char *ep; - -const char *cJSON_GetErrorPtr(void) {return ep;} - -static int cJSON_strcasecmp(const char *s1,const char *s2) -{ - if (!s1) return (s1==s2)?0:1;if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free are not static -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void (*cJSON_free)(void *ptr) = free; -AZ_POP_DISABLE_WARNING - -static char* cJSON_strdup(const char* str) -{ - size_t len = strlen(str) + 1; - char* copy = (char*)cJSON_malloc(len); - - if (!copy) return 0; - memcpy(copy,str,len); - return copy; -} - -void cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(void) -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; -} - -/* Delete a cJSON structure. */ -void cJSON_Delete(cJSON *c) -{ - cJSON *next; - while (c) - { - next=c->next; - if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); - if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); - if (c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) -{ - double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; - - /* Could use sscanf for this? */ - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ - if (*num=='e' || *num=='E') /* Exponent? */ - { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ - while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ - } - - n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ - - item->valuedouble=n; - item->valueint=(int)n; - item->type=cJSON_Number; - return num; -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item) -{ - char *str; - double d=item->valuedouble; - if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ - if (str) sprintf(str,"%d",item->valueint); - } - else - { - str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ - if (str) - { - if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); - else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); - else sprintf(str,"%f",d); - } - } - return str; -} - -/* Parse the input text into an unescaped cstring, and populate item. */ -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static const char *parse_string(cJSON *item,const char *str) -{ - const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; - if (*str!='\"') {ep=str;return 0;} /* not a string! */ - - while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ - - out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ - if (!out) return 0; - - ptr=str+1;ptr2=out; - while (*ptr!='\"' && *ptr) - { - if (*ptr!='\\') *ptr2++=*ptr++; - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++='\b'; break; - case 'f': *ptr2++='\f'; break; - case 'n': *ptr2++='\n'; break; - case 'r': *ptr2++='\r'; break; - case 't': *ptr2++='\t'; break; - case 'u': /* transcode utf16 to utf8. */ - sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */ - - if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ - - if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ - { - if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ - sscanf(ptr+3,"%4x",&uc2);ptr+=6; - if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ - uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); - } - - len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; - - switch (len) { - case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 1: *--ptr2 =(uc | firstByteMark[len]); - } - ptr2+=len; - break; - default: *ptr2++=*ptr; break; - } - ptr++; - } - } - *ptr2=0; - if (*ptr=='\"') ptr++; - item->valuestring=out; - item->type=cJSON_String; - return ptr; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str) -{ - const char *ptr;char *ptr2,*out;int len=0;unsigned char token; - - if (!str) return cJSON_strdup(""); - ptr=str; - token = *ptr; - while (token && ++len) - { - if (strchr("\"\\\b\f\n\r\t",token)) len++; - else if (token<32) len+=5; - ptr++; - token = *ptr; - } - - out=(char*)cJSON_malloc(len+3); - if (!out) return 0; - - ptr2=out;ptr=str; - *ptr2++='\"'; - while (*ptr) - { - if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (token=*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ - } - } - } - *ptr2++='\"';*ptr2++=0; - return out; -} -/* Invote print_string_ptr (which is useful) on an item. */ -static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} - -/* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item,const char *value); -static char *print_value(cJSON *item,int depth,int fmt); -static const char *parse_array(cJSON *item,const char *value); -static char *print_array(cJSON *item,int depth,int fmt); -static const char *parse_object(cJSON *item,const char *value); -static char *print_object(cJSON *item,int depth,int fmt); - -/* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} - -/* Parse an object - create a new root, and populate. */ -cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) -{ - const char *end=0; - cJSON *c=cJSON_New_Item(); - ep=0; - if (!c) return 0; /* memory fail */ - - end=parse_value(c,skip(value)); - if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} - if (return_parse_end) *return_parse_end=end; - return c; -} -/* Default options for cJSON_Parse */ -cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} - -/* Render a cJSON item/entity/structure to text. */ -char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} -char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} - -/* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item,const char *value) -{ - if (!value) return 0; /* Fail on null. */ - if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } - if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } - if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } - if (*value=='\"') { return parse_string(item,value); } - if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } - if (*value=='[') { return parse_array(item,value); } - if (*value=='{') { return parse_object(item,value); } - - ep=value;return 0; /* failure. */ -} - -/* Render a value to text. */ -static char *print_value(cJSON *item,int depth,int fmt) -{ - char *out=0; - if (!item) return 0; - switch ((item->type)&255) - { - case cJSON_NULL: out=cJSON_strdup("null"); break; - case cJSON_False: out=cJSON_strdup("false");break; - case cJSON_True: out=cJSON_strdup("true"); break; - case cJSON_Number: out=print_number(item);break; - case cJSON_String: out=print_string(item);break; - case cJSON_Array: out=print_array(item,depth,fmt);break; - case cJSON_Object: out=print_object(item,depth,fmt);break; - } - return out; -} - -/* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='[') {ep=value;return 0;} /* not an array! */ - - item->type=cJSON_Array; - value=skip(value+1); - if (*value==']') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; /* memory fail */ - value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item = cJSON_New_Item(); - if (!new_item) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_value(child,skip(value+1))); - if (!value) return 0; /* memory fail */ - } - - if (*value==']') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an array to text */ -static char *print_array(cJSON *item,int depth,int fmt) -{ - char **entries; - char *out=0,*ptr,*ret;int len=5; - cJSON *child=item->child; - int numentries=0,i=0,fail=0; - - /* How many entries in the array? */ - while (child) numentries++,child=child->next; - /* Explicitly handle numentries==0 */ - if (!numentries) - { - out=(char*)cJSON_malloc(3); - if (out) strcpy(out,"[]"); - return out; - } - /* Allocate an array to hold the values for each */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - memset(entries,0,numentries*sizeof(char*)); - /* Retrieve all the results: */ - child=item->child; - while (child && !fail) - { - ret=print_value(child,depth+1,fmt); - entries[i++]=ret; - if (ret) len+=(int)strlen(ret)+2+(fmt?1:0); else fail=1; - child=child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - /* If that fails, we fail. */ - if (!out) fail=1; - - /* Handle failure. */ - if (fail) - { - for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); - cJSON_free(entries); - return 0; - } - - /* Compose the output array. */ - *out='['; - ptr=out+1;*ptr=0; - for (i=0;i<numentries;i++) - { - strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); - if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} - cJSON_free(entries[i]); - } - cJSON_free(entries); - *ptr++=']';*ptr++=0; - return out; -} - -/* Build an object from the text. */ -static const char *parse_object(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='{') {ep=value;return 0;} /* not an object! */ - - item->type=cJSON_Object; - value=skip(value+1); - if (*value=='}') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; - value=skip(parse_string(child,skip(value))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item = cJSON_New_Item(); - if (!new_item) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_string(child,skip(value+1))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - } - - if (*value=='}') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an object to text. */ -static char *print_object(cJSON *item,int depth,int fmt) -{ - char **entries=0,**names=0; - char *out=0,*ptr,*ret,*str;int len=7,i=0,j; - cJSON *child=item->child; - int numentries=0,fail=0; - /* Count the number of entries. */ - while (child) numentries++,child=child->next; - /* Explicitly handle empty object case */ - if (!numentries) - { - out=(char*)cJSON_malloc(fmt?depth+3:3); - if (!out) return 0; - ptr=out;*ptr++='{'; - if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} - *ptr++='}';*ptr++=0; - return out; - } - /* Allocate space for the names and the objects */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - names=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!names) {cJSON_free(entries);return 0;} - memset(entries,0,sizeof(char*)*numentries); - memset(names,0,sizeof(char*)*numentries); - - /* Collect all the results into our arrays: */ - child=item->child;depth++;if (fmt) len+=depth; - while (child) - { - names[i]=str=print_string_ptr(child->string); - entries[i++]=ret=print_value(child,depth,fmt); - if (str && ret) len+=(int)(strlen(ret)+strlen(str))+2+(fmt?2+depth:0); else fail=1; - child=child->next; - } - - /* Try to allocate the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - if (!out) fail=1; - - /* Handle failure */ - if (fail) - { - for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} - cJSON_free(names);cJSON_free(entries); - return 0; - } - - /* Compose the output: */ - *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; - for (i=0;i<numentries;i++) - { - if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; - strcpy(ptr,names[i]);ptr+=strlen(names[i]); - *ptr++=':';if (fmt) *ptr++='\t'; - strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); - if (i!=numentries-1) *ptr++=','; - if (fmt) *ptr++='\n';*ptr=0; - cJSON_free(names[i]);cJSON_free(entries[i]); - } - - cJSON_free(names);cJSON_free(entries); - if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; - *ptr++='}';*ptr++=0; - return out; -} - -/* Get Array size/item / object item. */ -int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} -cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} -cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} -/* Utility for handling references. */ -static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} - -/* Add item to array/object. */ -void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} -void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} -void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} -void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} - -cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; - if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} -void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} -cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} -void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} - -/* Replace array/object items with new ones. */ -void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; - newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; - if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} -void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} - -/* Create basic types: */ -cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} -cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} -cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} -cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} -cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} -cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} -cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} -cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} - -/* Create Arrays: */ -cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} - -/* Duplication */ -cJSON *cJSON_Duplicate(cJSON *item,int recurse) -{ - cJSON *newitem,*cptr,*nptr=0,*newchild; - /* Bail on bad ptr */ - if (!item) return 0; - /* Create new item */ - newitem=cJSON_New_Item(); - if (!newitem) return 0; - /* Copy over all vars */ - newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; - if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} - if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} - /* If non-recursive, then we're done! */ - if (!recurse) return newitem; - /* Walk the ->next chain for the child. */ - cptr=item->child; - while (cptr) - { - newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) {cJSON_Delete(newitem);return 0;} - if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ - cptr=cptr->next; - } - return newitem; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h deleted file mode 100644 index 50ae02b6f9..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#ifndef cJSON__h -#define cJSON__h - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* cJSON Types: */ -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -#define cJSON_IsReference 256 - -/* The cJSON structure: */ -typedef struct cJSON { - struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - - int type; /* The type of the item, as above. */ - - char *valuestring; /* The item's string, if type==cJSON_String */ - int valueint; /* The item's number, if type==cJSON_Number */ - double valuedouble; /* The item's number, if type==cJSON_Number */ - - char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ -} cJSON; - -typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -/* Supply malloc, realloc and free functions to cJSON */ -extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -extern cJSON *cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -extern char *cJSON_Print(cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -extern char *cJSON_PrintUnformatted(cJSON *item); -/* Delete a cJSON entity and all subentities. */ -extern void cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -extern int cJSON_GetArraySize(cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); -/* Get item "string" from object. Case insensitive. */ -extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); - -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -extern const char *cJSON_GetErrorPtr(void); - -/* These calls create a cJSON item of the appropriate type. */ -extern cJSON *cJSON_CreateNull(void); -extern cJSON *cJSON_CreateTrue(void); -extern cJSON *cJSON_CreateFalse(void); -extern cJSON *cJSON_CreateBool(int b); -extern cJSON *cJSON_CreateNumber(double num); -extern cJSON *cJSON_CreateString(const char *string); -extern cJSON *cJSON_CreateArray(void); -extern cJSON *cJSON_CreateObject(void); - -/* These utilities create an Array of count items. */ -extern cJSON *cJSON_CreateIntArray(int *numbers,int count); -extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); -extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); -extern cJSON *cJSON_CreateStringArray(const char **strings,int count); - -/* Append item to the specified array/object. */ -extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); -extern void cJSON_DeleteItemFromArray(cJSON *array,int which); -extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); -extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); - -/* Update array items. */ -extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); -extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ - -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); - -/* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp deleted file mode 100644 index eaed596a00..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp +++ /dev/null @@ -1,825 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "hlslcc.hpp" -#include "stdlib.h" -#include "stdio.h" -#include "bstrlib.h" -#include <string> -#include <string.h> -#include "hash.h" -#include "serializeReflection.h" -#include "hlslcc_bin.hpp" - -#include <algorithm> -#include <cctype> - -#ifdef _WIN32 -#include <direct.h> -#else -#include <sys/stat.h> -#endif - -#include "timer.h" - -#if defined(_WIN32) && !defined(PORTABLE) -#define VALIDATE_OUTPUT -#endif - -#if defined(VALIDATE_OUTPUT) -#if defined(_WIN32) -#include <windows.h> -#include <gl/GL.h> - -#pragma comment(lib, "opengl32.lib") - -typedef char GLcharARB; /* native character */ -typedef unsigned int GLhandleARB; /* shader object handle */ -#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 -#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 -#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 -typedef void (WINAPI * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); -typedef GLhandleARB(WINAPI * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); -typedef void (WINAPI * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); -typedef void (WINAPI * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); -typedef void (WINAPI * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); -typedef void (WINAPI * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); -typedef GLhandleARB(WINAPI * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); -typedef void (WINAPI * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); -typedef void (WINAPI * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); -typedef void (WINAPI * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); -typedef void (WINAPI * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLcharARB* infoLog); - -static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; -static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; -static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; -static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; -static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; -static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; -static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; -static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; -static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; -static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; -static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; - -#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 -#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 -#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 -#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 -#define WGL_CONTEXT_FLAGS_ARB 0x2094 -#define ERROR_INVALID_VERSION_ARB 0x2095 -#define ERROR_INVALID_PROFILE_ARB 0x2096 - -#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 -#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 -#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 - -typedef HGLRC(WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); -static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; - -void InitOpenGL() -{ - HGLRC rc; - - // setup minimal required GL - HWND wnd = CreateWindowA( - "STATIC", - "GL", - WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, - 0, 0, 16, 16, - NULL, NULL, - GetModuleHandle(NULL), NULL); - HDC dc = GetDC(wnd); - - PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, - PFD_TYPE_RGBA, 32, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 16, 0, - 0, PFD_MAIN_PLANE, 0, 0, 0, 0 - }; - - int fmt = ChoosePixelFormat(dc, &pfd); - SetPixelFormat(dc, fmt, &pfd); - - rc = wglCreateContext(dc); - wglMakeCurrent(dc, rc); - - wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); - - if (wglCreateContextAttribsARB) - { - const int OpenGLContextAttribs[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 3, - WGL_CONTEXT_MINOR_VERSION_ARB, 3, -#if defined(_DEBUG) - //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, -#else - //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, -#endif - //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - 0, 0 - }; - - const HGLRC OpenGLContext = wglCreateContextAttribsARB(dc, 0, OpenGLContextAttribs); - - wglMakeCurrent(dc, OpenGLContext); - - wglDeleteContext(rc); - - rc = OpenGLContext; - } - - glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB"); - glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB"); - glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB"); - glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB"); - glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB"); - glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB"); - glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB"); - glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB"); - glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB"); - glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB"); - glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog"); -} -#endif - -void PrintSingleLineError(FILE* pFile, char* error) -{ - while (*error != '\0') - { - char* pLineEnd = strchr(error, '\n'); - if (pLineEnd == 0) - pLineEnd = error + strlen(error) - 1; - fwrite(error, 1, pLineEnd - error, pFile); - fwrite("\r", 1, 1, pFile); - error = pLineEnd + 1; - } -} - -int TryCompileShader(GLenum eShaderType, const char* inFilename, char* shader, double* pCompileTime, int useStdErr) -{ - GLint iCompileStatus; - GLuint hShader; - Timer_t timer; - - InitTimer(&timer); - - InitOpenGL(); - - hShader = glCreateShaderObjectARB(eShaderType); - glShaderSourceARB(hShader, 1, (const char **)&shader, NULL); - - ResetTimer(&timer); - glCompileShaderARB(hShader); - *pCompileTime = ReadTimer(&timer); - - /* Check it compiled OK */ - glGetObjectParameterivARB(hShader, GL_OBJECT_COMPILE_STATUS_ARB, &iCompileStatus); - - if (iCompileStatus != GL_TRUE) - { - FILE* errorFile = NULL; - GLint iInfoLogLength = 0; - char* pszInfoLog; - - glGetObjectParameterivARB(hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iInfoLogLength); - - pszInfoLog = new char[iInfoLogLength]; - - printf("Error: Failed to compile GLSL shader\n"); - - glGetInfoLogARB(hShader, iInfoLogLength, NULL, pszInfoLog); - - printf(pszInfoLog); - - if (!useStdErr) - { - std::string filename; - filename += inFilename; - filename += "_compileErrors.txt"; - - //Dump to file - errorFile = fopen(filename.c_str(), "w"); - - fclose(errorFile); - } - else - { - // Present error to stderror with no "new lines" as required by remote shader compiler - fprintf(stderr, "%s(-) error: ", inFilename); - PrintSingleLineError(stderr, pszInfoLog); - fprintf(stderr, "\rshader: "); - PrintSingleLineError(stderr, shader); - } - - delete[] pszInfoLog; - - return 0; - } - - return 1; -} -#endif - -int fileExists(const char* path) -{ - FILE* shaderFile; - shaderFile = fopen(path, "rb"); - - if (shaderFile) - { - fclose(shaderFile); - return 1; - } - return 0; -} - -ShaderLang LanguageFromString(const char* str) -{ - if (strcmp(str, "es100") == 0) - { - return LANG_ES_100; - } - if (strcmp(str, "es300") == 0) - { - return LANG_ES_300; - } - if (strcmp(str, "es310") == 0) - { - return LANG_ES_310; - } - if (strcmp(str, "120") == 0) - { - return LANG_120; - } - if (strcmp(str, "130") == 0) - { - return LANG_130; - } - if (strcmp(str, "140") == 0) - { - return LANG_140; - } - if (strcmp(str, "150") == 0) - { - return LANG_150; - } - if (strcmp(str, "330") == 0) - { - return LANG_330; - } - if (strcmp(str, "400") == 0) - { - return LANG_400; - } - if (strcmp(str, "410") == 0) - { - return LANG_410; - } - if (strcmp(str, "420") == 0) - { - return LANG_420; - } - if (strcmp(str, "430") == 0) - { - return LANG_430; - } - if (strcmp(str, "440") == 0) - { - return LANG_440; - } - if (strcmp(str, "metal") == 0) - { - return LANG_METAL; - } - return LANG_DEFAULT; -} - -#define MAX_PATH_CHARS 256 -#define MAX_FXC_CMD_CHARS 1024 -#define MAX_DEBUG_READ_CHARS 512 - -typedef struct -{ - ShaderLang language; - - int flags; - - const char* shaderFile; - char* outputShaderFile; - - char* reflectPath; - - char cacheKey[MAX_PATH_CHARS]; - - int bUseFxc; - std::string fxcCmdLine; -} Options; - -void InitOptions(Options* psOptions) -{ - psOptions->language = LANG_DEFAULT; - psOptions->flags = 0; - psOptions->reflectPath = NULL; - - psOptions->shaderFile = NULL; - - psOptions->bUseFxc = 0; -} - -void PrintHelp() -{ - printf("Command line options:\n"); - - printf("\t-lang=X \t Language to use. e.g. es100 or 140 or metal.\n"); - printf("\t-flags=X \t The integer value of the HLSLCC_FLAGS to used.\n"); - printf("\t-reflect=X \t File to write reflection JSON to.\n"); - printf("\t-in=X \t Shader file to compile.\n"); - printf("\t-out=X \t File to write the compiled shader from -in to.\n"); - - printf("\t-hashout=[dir/]out-file-name \t Output file name is a hash of 'out-file-name', put in the directory 'dir'.\n"); - - printf("\t-fxc=\"CMD\" HLSL compiler command line. If specified the input shader will be first compiled through this command first and then the resulting bytecode translated.\n"); - - printf("\n"); -} - -int GetOptions(int argc, char** argv, Options* psOptions) -{ - int i; - int fullShaderChain = -1; - - InitOptions(psOptions); - - for (i = 1; i < argc; i++) - { - char *option; - - option = strstr(argv[i], "-help"); - if (option != NULL) - { - PrintHelp(); - return 0; - } - - option = strstr(argv[i], "-reflect="); - if (option != NULL) - { - psOptions->reflectPath = option + strlen("-reflect="); - } - - option = strstr(argv[i], "-lang="); - if (option != NULL) - { - psOptions->language = LanguageFromString((&option[strlen("-lang=")])); - } - - option = strstr(argv[i], "-flags="); - if (option != NULL) - { - psOptions->flags = atol(&option[strlen("-flags=")]); - } - - option = strstr(argv[i], "-in="); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->shaderFile = option + strlen("-in="); - if (!fileExists(psOptions->shaderFile)) - { - printf("Invalid path: %s\n", psOptions->shaderFile); - return 0; - } - } - - option = strstr(argv[i], "-out="); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->outputShaderFile = option + strlen("-out="); - } - - option = strstr(argv[i], "-hashout"); - if (option != NULL) - { - fullShaderChain = 0; - psOptions->outputShaderFile = option + strlen("-hashout="); - - char* dir; - int64_t length; - - uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0); - - dir = strrchr(psOptions->outputShaderFile, '\\'); - - if (!dir) - { - dir = strrchr(psOptions->outputShaderFile, '//'); - } - - if (!dir) - { - length = 0; - } - else - { - length = (int)(dir - psOptions->outputShaderFile) + 1; - } - - for (i = 0; i < length; ++i) - { - psOptions->cacheKey[i] = psOptions->outputShaderFile[i]; - } - - //sprintf(psOptions->cacheKey, "%x%x", high, low); - sprintf(&psOptions->cacheKey[i], "%010llX", hash); - - psOptions->outputShaderFile = psOptions->cacheKey; - } - - option = strstr(argv[i], "-fxc="); - if (option != NULL) - { - char* cmdLine = option + strlen("-fxc="); - size_t cmdLineLen = strlen(cmdLine); - if (cmdLineLen == 0 || cmdLineLen + 1 >= MAX_FXC_CMD_CHARS) - return 0; - psOptions->fxcCmdLine = std::string(cmdLine, cmdLineLen); - psOptions->bUseFxc = 1; - } - } - - return 1; -} - -void *malloc_hook(size_t size) -{ - return malloc(size); -} -void *calloc_hook(size_t num, size_t size) -{ - return calloc(num, size); -} -void *realloc_hook(void *p, size_t size) -{ - return realloc(p, size); -} -void free_hook(void *p) -{ - free(p); -} - -int Run(const char* srcPath, const char* destPath, ShaderLang language, int flags, const char* reflectPath, Shader* shader, int useStdErr, [[maybe_unused]] const char *fxcCmdLine, [[maybe_unused]] const char *debugSrcPath) -{ - FILE* outputFile; - Shader tempShader; - Shader* result = shader ? shader : &tempShader; - Timer_t timer; - int compiledOK = 0; - double crossCompileTime = 0; - double glslCompileTime = 0; - - HLSLcc_SetMemoryFunctions(malloc_hook, calloc_hook, free_hook, realloc_hook); - - InitTimer(&timer); - - ResetTimer(&timer); - GlExtensions ext; - ext.ARB_explicit_attrib_location = 0; - ext.ARB_explicit_uniform_location = 0; - ext.ARB_shading_language_420pack = 0; - if (language == LANG_METAL) - { - compiledOK = TranslateHLSLFromFileToMETAL(srcPath, flags, language, result); - } - else - { - compiledOK = TranslateHLSLFromFileToGLSL(srcPath, flags, language, &ext, result); - } - crossCompileTime = ReadTimer(&timer); - - if (compiledOK) - { -#ifdef _DEBUG - bstring debugString = bfromcstr(result->sourceCode); - - bcatcstr(debugString, "\n\n// ------- DEBUG INFORMATION -------"); - - bformata(debugString, "\n// Shader Object Input: %s", srcPath); - bformata(debugString, "\n// Shader Output: %s", destPath); - if (debugSrcPath) - { - char debugStr[MAX_DEBUG_READ_CHARS]; - FILE* debugFile = fopen(debugSrcPath, "r"); - if (debugFile) - { - bformata(debugString, "\n// Shader HLSL Input: "); - while (!feof(debugFile)) - bformata(debugString, "// %s", fgets(debugStr, MAX_DEBUG_READ_CHARS, debugFile)); - fclose(debugFile); - } - } - if (fxcCmdLine) - bformata(debugString, "\n// FXC Command: %s", fxcCmdLine); - - result->sourceCode = bstr2cstr(debugString, '\0'); -#endif - printf("cc time: %.2f us\n", crossCompileTime); - -#if !defined(APPLE) - // https://msdn.microsoft.com/en-us/library/ms175782.aspx. As to disable the "("'n' format specifier disabled", 0)" assertion. - _set_printf_count_output(1); -#endif - - if (destPath) - { - //Dump to file - outputFile = fopen(destPath, "w"); - fprintf(outputFile, result->sourceCode); - - fclose(outputFile); - } - - if (reflectPath) - { - const char* jsonString = SerializeReflection(&result->reflection); - outputFile = fopen(reflectPath, "w"); - fprintf(outputFile, jsonString); - fclose(outputFile); - } - -#if defined(VALIDATE_OUTPUT) - if (language != LANG_METAL) - { - compiledOK = TryCompileShader(result->shaderType, destPath ? destPath : "", result->sourceCode, &glslCompileTime, useStdErr); - - if (compiledOK) - { - printf("glsl time: %.2f us\n", glslCompileTime); - } - } -#endif - - if (!shader) - FreeShader(result); - } - else if (useStdErr) - { - fprintf(stderr, "TranslateHLSLFromFile failed"); - } - - return compiledOK; -} - -struct SDXBCFile -{ - FILE* m_pFile; - - bool Read(void* pElements, size_t uSize) - { - return fread(pElements, 1, uSize, m_pFile) == uSize; - } - - bool Write(const void* pElements, size_t uSize) - { - return fwrite(pElements, 1, uSize, m_pFile) == uSize; - } - - bool SeekRel(int32_t iOffset) - { - return fseek(m_pFile, iOffset, SEEK_CUR) == 0; - } - - bool SeekAbs(uint32_t uPosition) - { - return fseek(m_pFile, uPosition, SEEK_SET) == 0; - } -}; - -int CombineDXBCWithGLSL(char* dxbcFileName, char* outputFileName, Shader* shader) -{ - SDXBCFile dxbcFile = { fopen(dxbcFileName, "rb") }; - SDXBCFile outputFile = { fopen(outputFileName, "wb") }; - - bool result = - dxbcFile.m_pFile != NULL && outputFile.m_pFile != NULL && - DXBCCombineWithGLSL(dxbcFile, outputFile, shader); - - if (dxbcFile.m_pFile != NULL) - fclose(dxbcFile.m_pFile); - if (outputFile.m_pFile != NULL) - fclose(outputFile.m_pFile); - - return result; -} - -#if !defined(_MSC_VER) -#define sprintf_s(dest, size, ...) sprintf(dest, __VA_ARGS__) -#endif - -#if defined(_WIN32) && defined(PORTABLE) - -DWORD FilterException(DWORD uExceptionCode) -{ - const char* szExceptionName; - char acTemp[10]; - switch (uExceptionCode) - { -#define _CASE(_Name) \ - case _Name: \ - szExceptionName = #_Name; \ - break; - _CASE(EXCEPTION_ACCESS_VIOLATION) - _CASE(EXCEPTION_DATATYPE_MISALIGNMENT) - _CASE(EXCEPTION_BREAKPOINT) - _CASE(EXCEPTION_SINGLE_STEP) - _CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) - _CASE(EXCEPTION_FLT_DENORMAL_OPERAND) - _CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO) - _CASE(EXCEPTION_FLT_INEXACT_RESULT) - _CASE(EXCEPTION_FLT_INVALID_OPERATION) - _CASE(EXCEPTION_FLT_OVERFLOW) - _CASE(EXCEPTION_FLT_STACK_CHECK) - _CASE(EXCEPTION_FLT_UNDERFLOW) - _CASE(EXCEPTION_INT_DIVIDE_BY_ZERO) - _CASE(EXCEPTION_INT_OVERFLOW) - _CASE(EXCEPTION_PRIV_INSTRUCTION) - _CASE(EXCEPTION_IN_PAGE_ERROR) - _CASE(EXCEPTION_ILLEGAL_INSTRUCTION) - _CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION) - _CASE(EXCEPTION_STACK_OVERFLOW) - _CASE(EXCEPTION_INVALID_DISPOSITION) - _CASE(EXCEPTION_GUARD_PAGE) - _CASE(EXCEPTION_INVALID_HANDLE) - //_CASE(EXCEPTION_POSSIBLE_DEADLOCK) -#undef _CASE - default: - sprintf_s(acTemp, "0x%08X", uExceptionCode); - szExceptionName = acTemp; - } - - fprintf(stderr, "Hardware exception thrown (%s)\n", szExceptionName); - return 1; -} - -#endif - -const char* PatchHLSLShaderFile(const char* path) -{ - // Need to transform "half" into "min16float" so FXC preserve min precision to the operands. - static char patchedFileName[MAX_PATH_CHARS]; - const char* defines = "#define half min16float\n" - "#define half2 min16float2\n" - "#define half3 min16float3\n" - "#define half4 min16float4\n"; - - sprintf_s(patchedFileName, sizeof(patchedFileName), "%s.hlslPatched", path); - FILE* shaderFile = fopen(path, "rb"); - if (!shaderFile) - { - return NULL; - } - - FILE* patchedFile = fopen(patchedFileName, "wb"); - if (!patchedFile) - { - return NULL; - } - - // Get size of file - bool result = false; - fseek(shaderFile, 0, SEEK_END); - long size = ftell(shaderFile); - fseek(shaderFile, 0, SEEK_SET); - unsigned char* data = new unsigned char[size + 1]; // Extra byte for the '/0' character. - if (fread(data, 1, size, shaderFile) == size) - { - data[size] = '\0'; - fprintf(patchedFile, "%s%s", defines, data); - result = true; - } - - if (shaderFile) - { - fclose(shaderFile); - } - - if (patchedFile) - { - fclose(patchedFile); - } - - delete[] data; - return result ? patchedFileName : NULL; -} - -int main(int argc, char** argv) -{ - Options options; - -#if defined(_WIN32) && defined(PORTABLE) - __try - { -#endif - - if (!GetOptions(argc, argv, &options)) - { - return 1; - } - - if (options.bUseFxc) - { - char dxbcFileName[MAX_PATH_CHARS]; - char glslFileName[MAX_PATH_CHARS]; - char fullFxcCmdLine[MAX_FXC_CMD_CHARS]; - int retValue; - - if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) - { - options.shaderFile = PatchHLSLShaderFile(options.shaderFile); - if (!options.shaderFile) - { - return 1; - } - } - - sprintf_s(dxbcFileName, sizeof(dxbcFileName), "%s.dxbc", options.shaderFile); - sprintf_s(glslFileName, sizeof(glslFileName), "%s.patched", options.shaderFile); - - // Need to extract the path to the executable so we can enclose it in quotes - // in case it contains spaces. - const std::string fxcExeName = "fxc.exe"; - - // Case insensitive search - std::string::iterator fxcPos = std::search( - options.fxcCmdLine.begin(), options.fxcCmdLine.end(), - fxcExeName.begin(), fxcExeName.end(), - [](char ch1, char ch2) { return std::tolower(ch1) == std::tolower(ch2); } - ); - - if (fxcPos == options.fxcCmdLine.end()) - { - fprintf(stderr, "Could not find fxc.exe in command line"); - return 1; - } - - // Add the fxcExeName so it gets copied to the fxcExe path. - fxcPos += fxcExeName.length(); - std::string fxcExe(options.fxcCmdLine.begin(), fxcPos); - std::string fxcArguments(fxcPos, options.fxcCmdLine.end()); - -#if defined(APPLE) - fprintf(stderr, "fxc.exe cannot be executed on Mac"); - return 1; -#else - // Need an extra set of quotes around the full command line because the way "system" executes it using cmd. - sprintf_s(fullFxcCmdLine, sizeof(fullFxcCmdLine), "\"\"%s\" %s \"%s\" \"%s\"\"", fxcExe.c_str(), fxcArguments.c_str(), dxbcFileName, options.shaderFile); -#endif - - retValue = system(fullFxcCmdLine); - - if (retValue == 0) - { - Shader shader; - retValue = !Run(dxbcFileName, glslFileName, options.language, options.flags, options.reflectPath, &shader, 1, fullFxcCmdLine, options.shaderFile); - - if (retValue == 0) - { - retValue = !CombineDXBCWithGLSL(dxbcFileName, options.outputShaderFile, &shader); - FreeShader(&shader); - } - } - - remove(dxbcFileName); - remove(glslFileName); - if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) - { - // Removed the hlsl patched file that was created. - remove(options.shaderFile); - } - - return retValue; - } - else if (options.shaderFile) - { - if (!Run(options.shaderFile, options.outputShaderFile, options.language, options.flags, options.reflectPath, NULL, 0, NULL, NULL)) - { - return 1; - } - } - -#if defined(_WIN32) && defined(PORTABLE) - } - __except (FilterException(GetExceptionCode())) - { - return 1; - } -#endif - - - return 0; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h deleted file mode 100644 index e480417717..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h +++ /dev/null @@ -1,128 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HASH_H_ -#define HASH_H_ - -/* --------------------------------------------------------------------- -mix -- mix 3 64-bit values reversibly. -mix() takes 48 machine instructions, but only 24 cycles on a superscalar - machine (like Intel's new MMX architecture). It requires 4 64-bit - registers for 4::2 parallelism. -All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of - (a,b,c), and all deltas of bottom bits were tested. All deltas were - tested both on random keys and on keys that were nearly all zero. - These deltas all cause every bit of c to change between 1/3 and 2/3 - of the time (well, only 113/400 to 287/400 of the time for some - 2-bit delta). These deltas all cause at least 80 bits to change - among (a,b,c) when the mix is run either forward or backward (yes it - is reversible). -This implies that a hash using mix64 has no funnels. There may be - characteristics with 3-bit deltas or bigger, I didn't test for - those. --------------------------------------------------------------------- -*/ -#define mix64(a,b,c) \ -{ \ - a -= b; a -= c; a ^= (c>>43); \ - b -= c; b -= a; b ^= (a<<9); \ - c -= a; c -= b; c ^= (b>>8); \ - a -= b; a -= c; a ^= (c>>38); \ - b -= c; b -= a; b ^= (a<<23); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>35); \ - b -= c; b -= a; b ^= (a<<49); \ - c -= a; c -= b; c ^= (b>>11); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<18); \ - c -= a; c -= b; c ^= (b>>22); \ -} - -/* --------------------------------------------------------------------- -hash64() -- hash a variable-length key into a 64-bit value - k : the key (the unaligned variable-length array of bytes) - len : the length of the key, counting by bytes - level : can be any 8-byte value -Returns a 64-bit value. Every bit of the key affects every bit of -the return value. No funnels. Every 1-bit and 2-bit delta achieves -avalanche. About 41+5len instructions. - -The best hash table sizes are powers of 2. There is no need to do -mod a prime (mod is sooo slow!). If you need less than 64 bits, -use a bitmask. For example, if you need only 10 bits, do - h = (h & hashmask(10)); -In which case, the hash table should have hashsize(10) elements. - -If you are hashing n strings (ub1 **)k, do it like this: - for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); - -By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may -use this code any way you wish, private, educational, or commercial, -but I would appreciate if you give me credit. - -See http://burtleburtle.net/bob/hash/evahash.html -Use for hash table lookup, or anything where one collision in 2^^64 -is acceptable. Do NOT use for cryptographic purposes. --------------------------------------------------------------------- -*/ - -static uint64_t hash64( const uint8_t *k, uint32_t length, uint64_t initval ) -{ - uint64_t a,b,c,len; - - /* Set up the internal state */ - len = length; - a = b = initval; /* the previous hash value */ - c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */ - - /*---------------------------------------- handle most of the key */ - while (len >= 24) - { - a += (k[0] +((uint64_t)k[ 1]<< 8)+((uint64_t)k[ 2]<<16)+((uint64_t)k[ 3]<<24) - +((uint64_t)k[4 ]<<32)+((uint64_t)k[ 5]<<40)+((uint64_t)k[ 6]<<48)+((uint64_t)k[ 7]<<56)); - b += (k[8] +((uint64_t)k[ 9]<< 8)+((uint64_t)k[10]<<16)+((uint64_t)k[11]<<24) - +((uint64_t)k[12]<<32)+((uint64_t)k[13]<<40)+((uint64_t)k[14]<<48)+((uint64_t)k[15]<<56)); - c += (k[16] +((uint64_t)k[17]<< 8)+((uint64_t)k[18]<<16)+((uint64_t)k[19]<<24) - +((uint64_t)k[20]<<32)+((uint64_t)k[21]<<40)+((uint64_t)k[22]<<48)+((uint64_t)k[23]<<56)); - mix64(a,b,c); - k += 24; len -= 24; - } - - /*------------------------------------- handle the last 23 bytes */ - c += length; - switch(len) /* all the case statements fall through */ - { - case 23: c+=((uint64_t)k[22]<<56); - case 22: c+=((uint64_t)k[21]<<48); - case 21: c+=((uint64_t)k[20]<<40); - case 20: c+=((uint64_t)k[19]<<32); - case 19: c+=((uint64_t)k[18]<<24); - case 18: c+=((uint64_t)k[17]<<16); - case 17: c+=((uint64_t)k[16]<<8); - /* the first byte of c is reserved for the length */ - case 16: b+=((uint64_t)k[15]<<56); - case 15: b+=((uint64_t)k[14]<<48); - case 14: b+=((uint64_t)k[13]<<40); - case 13: b+=((uint64_t)k[12]<<32); - case 12: b+=((uint64_t)k[11]<<24); - case 11: b+=((uint64_t)k[10]<<16); - case 10: b+=((uint64_t)k[ 9]<<8); - case 9: b+=((uint64_t)k[ 8]); - case 8: a+=((uint64_t)k[ 7]<<56); - case 7: a+=((uint64_t)k[ 6]<<48); - case 6: a+=((uint64_t)k[ 5]<<40); - case 5: a+=((uint64_t)k[ 4]<<32); - case 4: a+=((uint64_t)k[ 3]<<24); - case 3: a+=((uint64_t)k[ 2]<<16); - case 2: a+=((uint64_t)k[ 1]<<8); - case 1: a+=((uint64_t)k[ 0]); - /* case 0: nothing left to add */ - } - mix64(a,b,c); - /*-------------------------------------------- report the result */ - return c; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp deleted file mode 100644 index 15fe8d5b96..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "serializeReflection.h" -#include "cJSON.h" -#include <string> -#include <sstream> - -void* jsonMalloc(size_t sz) -{ - return new char[sz]; -} -void jsonFree(void* ptr) -{ - char* charPtr = static_cast<char*>(ptr); - delete [] charPtr; -} - -static void AppendIntToString(std::string& str, uint32_t num) -{ - std::stringstream ss; - ss << num; - str += ss.str(); -} - -static void WriteInOutSignature(InOutSignature* psSignature, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "SemanticName", cJSON_CreateString(psSignature->SemanticName)); - cJSON_AddItemToObject(obj, "ui32SemanticIndex", cJSON_CreateNumber(psSignature->ui32SemanticIndex)); - cJSON_AddItemToObject(obj, "eSystemValueType", cJSON_CreateNumber(psSignature->eSystemValueType)); - cJSON_AddItemToObject(obj, "eComponentType", cJSON_CreateNumber(psSignature->eComponentType)); - cJSON_AddItemToObject(obj, "ui32Register", cJSON_CreateNumber(psSignature->ui32Register)); - cJSON_AddItemToObject(obj, "ui32Mask", cJSON_CreateNumber(psSignature->ui32Mask)); - cJSON_AddItemToObject(obj, "ui32ReadWriteMask", cJSON_CreateNumber(psSignature->ui32ReadWriteMask)); -} - -static void WriteResourceBinding(ResourceBinding* psBinding, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psBinding->Name)); - cJSON_AddItemToObject(obj, "eType", cJSON_CreateNumber(psBinding->eType)); - cJSON_AddItemToObject(obj, "ui32BindPoint", cJSON_CreateNumber(psBinding->ui32BindPoint)); - cJSON_AddItemToObject(obj, "ui32BindCount", cJSON_CreateNumber(psBinding->ui32BindCount)); - cJSON_AddItemToObject(obj, "ui32Flags", cJSON_CreateNumber(psBinding->ui32Flags)); - cJSON_AddItemToObject(obj, "eDimension", cJSON_CreateNumber(psBinding->eDimension)); - cJSON_AddItemToObject(obj, "ui32ReturnType", cJSON_CreateNumber(psBinding->ui32ReturnType)); - cJSON_AddItemToObject(obj, "ui32NumSamples", cJSON_CreateNumber(psBinding->ui32NumSamples)); -} - -static void WriteShaderVar(ShaderVar* psVar, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psVar->Name)); - if(psVar->haveDefaultValue) - { - cJSON_AddItemToObject(obj, "aui32DefaultValues", cJSON_CreateIntArray((int*)psVar->pui32DefaultValues, psVar->ui32Size/4)); - } - cJSON_AddItemToObject(obj, "ui32StartOffset", cJSON_CreateNumber(psVar->ui32StartOffset)); - cJSON_AddItemToObject(obj, "ui32Size", cJSON_CreateNumber(psVar->ui32Size)); -} - -static void WriteConstantBuffer(ConstantBuffer* psCBuf, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psCBuf->Name)); - cJSON_AddItemToObject(obj, "ui32NumVars", cJSON_CreateNumber(psCBuf->ui32NumVars)); - - for(uint32_t i = 0; i < psCBuf->ui32NumVars; ++i) - { - std::string name; - name += "var"; - AppendIntToString(name, i); - - cJSON* varObj = cJSON_CreateObject(); - cJSON_AddItemToObject(obj, name.c_str(), varObj); - - WriteShaderVar(&psCBuf->asVars[i], varObj); - } - - cJSON_AddItemToObject(obj, "ui32TotalSizeInBytes", cJSON_CreateNumber(psCBuf->ui32TotalSizeInBytes)); -} - -static void WriteClassType(ClassType* psClassType, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassType->Name)); - cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassType->ui16ID)); - cJSON_AddItemToObject(obj, "ui16ConstBufStride", cJSON_CreateNumber(psClassType->ui16ConstBufStride)); - cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassType->ui16Texture)); - cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassType->ui16Sampler)); -} - -static void WriteClassInstance(ClassInstance* psClassInst, cJSON* obj) -{ - cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassInst->Name)); - cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassInst->ui16ID)); - cJSON_AddItemToObject(obj, "ui16ConstBuf", cJSON_CreateNumber(psClassInst->ui16ConstBuf)); - cJSON_AddItemToObject(obj, "ui16ConstBufOffset", cJSON_CreateNumber(psClassInst->ui16ConstBufOffset)); - cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassInst->ui16Texture)); - cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassInst->ui16Sampler)); -} - -const char* SerializeReflection(ShaderInfo* psReflection) -{ - cJSON* root; - - cJSON_Hooks hooks; - hooks.malloc_fn = jsonMalloc; - hooks.free_fn = jsonFree; - cJSON_InitHooks(&hooks); - - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "ui32MajorVersion", cJSON_CreateNumber(psReflection->ui32MajorVersion)); - cJSON_AddItemToObject(root, "ui32MinorVersion", cJSON_CreateNumber(psReflection->ui32MinorVersion)); - - cJSON_AddItemToObject(root, "ui32NumInputSignatures", cJSON_CreateNumber(psReflection->ui32NumInputSignatures)); - - for(uint32_t i = 0; i < psReflection->ui32NumInputSignatures; ++i) - { - std::string name; - name += "input"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteInOutSignature(psReflection->psInputSignatures+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumOutputSignatures", cJSON_CreateNumber(psReflection->ui32NumOutputSignatures)); - - for(uint32_t i = 0; i < psReflection->ui32NumOutputSignatures; ++i) - { - std::string name; - name += "output"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteInOutSignature(psReflection->psOutputSignatures+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumResourceBindings", cJSON_CreateNumber(psReflection->ui32NumResourceBindings)); - - for(uint32_t i = 0; i < psReflection->ui32NumResourceBindings; ++i) - { - std::string name; - name += "resource"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteResourceBinding(psReflection->psResourceBindings+i, obj); - } - - cJSON_AddItemToObject(root, "ui32NumConstantBuffers", cJSON_CreateNumber(psReflection->ui32NumConstantBuffers)); - - for(uint32_t i = 0; i < psReflection->ui32NumConstantBuffers; ++i) - { - std::string name; - name += "cbuf"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteConstantBuffer(psReflection->psConstantBuffers+i, obj); - } - - //psThisPointerConstBuffer is a cache. Don't need to write this out. - //It just points to the $ThisPointer cbuffer within the psConstantBuffers array. - - for(uint32_t i = 0; i < psReflection->ui32NumClassTypes; ++i) - { - std::string name; - name += "classType"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteClassType(psReflection->psClassTypes+i, obj); - } - - for(uint32_t i = 0; i < psReflection->ui32NumClassInstances; ++i) - { - std::string name; - name += "classInst"; - AppendIntToString(name, i); - - cJSON* obj = cJSON_CreateObject(); - cJSON_AddItemToObject(root, name.c_str(), obj); - - WriteClassInstance(psReflection->psClassInstances+i, obj); - } - - //psReflection->aui32TableIDToTypeID - //psReflection->aui32ConstBufferBindpointRemap - - cJSON_AddItemToObject(root, "eTessPartitioning", cJSON_CreateNumber(psReflection->eTessPartitioning)); - cJSON_AddItemToObject(root, "eTessOutPrim", cJSON_CreateNumber(psReflection->eTessOutPrim)); - - - const char* jsonString = cJSON_Print(root); - - cJSON_Delete(root); - - return jsonString; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h deleted file mode 100644 index c8c4175a6a..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h +++ /dev/null @@ -1,11 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef SERIALIZE_REFLECTION_H_ -#define SERIALIZE_REFLECTION_H_ - -#include "hlslcc.h" - -const char* SerializeReflection(ShaderInfo* psReflection); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp deleted file mode 100644 index c707e1bfa8..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "timer.h" - -void InitTimer(Timer_t* psTimer) -{ -#if defined(_WIN32) - QueryPerformanceFrequency(&psTimer->frequency); -#endif -} - -void ResetTimer(Timer_t* psTimer) -{ -#if defined(_WIN32) - QueryPerformanceCounter(&psTimer->startCount); -#else - gettimeofday(&psTimer->startCount, 0); -#endif -} - -/* Returns time in micro seconds */ -double ReadTimer(Timer_t* psTimer) -{ - double startTimeInMicroSec, endTimeInMicroSec; - -#if defined(_WIN32) - const double freq = (1000000.0 / psTimer->frequency.QuadPart); - QueryPerformanceCounter(&psTimer->endCount); - startTimeInMicroSec = psTimer->startCount.QuadPart * freq; - endTimeInMicroSec = psTimer->endCount.QuadPart * freq; -#else - gettimeofday(&psTimer->endCount, 0); - startTimeInMicroSec = (psTimer->startCount.tv_sec * 1000000.0) + psTimer->startCount.tv_usec; - endTimeInMicroSec = (psTimer->endCount.tv_sec * 1000000.0) + psTimer->endCount.tv_usec; -#endif - - return endTimeInMicroSec - startTimeInMicroSec; -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h deleted file mode 100644 index 3f4ea333fd..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h +++ /dev/null @@ -1,29 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TIMER_H -#define TIMER_H - -#ifdef _WIN32 -#include <Windows.h> -#else -#include <sys/time.h> -#endif - -typedef struct -{ -#ifdef _WIN32 - LARGE_INTEGER frequency; - LARGE_INTEGER startCount; - LARGE_INTEGER endCount; -#else - struct timeval startCount; - struct timeval endCount; -#endif -} Timer_t; - -void InitTimer(Timer_t* psTimer); -void ResetTimer(Timer_t* psTimer); -double ReadTimer(Timer_t* psTimer); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c deleted file mode 100644 index 3f24fa3341..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bsafe.c - * - * This is an optional module that can be used to help enforce a safety - * standard based on pervasive usage of bstrlib. This file is not necessarily - * portable, however, it has been tested to work correctly with Intel's C/C++ - * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. - */ - -#include <stdio.h> -#include <stdlib.h> -#include "bsafe.h" diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h deleted file mode 100644 index 3e18e33493..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bsafe.h - * - * This is an optional module that can be used to help enforce a safety - * standard based on pervasive usage of bstrlib. This file is not necessarily - * portable, however, it has been tested to work correctly with Intel's C/C++ - * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. - */ - -#ifndef BSTRLIB_BSAFE_INCLUDE -#define BSTRLIB_BSAFE_INCLUDE - -#ifdef __cplusplus -extern "C" { -#endif - -extern char * (strncpy) (char *dst, const char *src, size_t n); -extern char * (strncat) (char *dst, const char *src, size_t n); -extern char * (strtok) (char *s1, const char *s2); -extern char * (strdup) (const char *s); - -#undef strcpy -#undef strcat -#define strcpy(a,b) bsafe_strcpy(a,b) -#define strcat(a,b) bsafe_strcat(a,b) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c deleted file mode 100644 index 2dc7b04840..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c +++ /dev/null @@ -1,1134 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstraux.c - * - * This file is not necessarily part of the core bstring library itself, but - * is just an auxilliary module which includes miscellaneous or trivial - * functions. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> -#include "bstrlib.h" -#include "bstraux.h" - -/* bstring bTail (bstring b, int n) - * - * Return with a string of the last n characters of b. - */ -bstring bTail (bstring b, int n) { - if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; - if (n >= b->slen) return bstrcpy (b); - return bmidstr (b, b->slen - n, n); -} - -/* bstring bHead (bstring b, int n) - * - * Return with a string of the first n characters of b. - */ -bstring bHead (bstring b, int n) { - if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; - if (n >= b->slen) return bstrcpy (b); - return bmidstr (b, 0, n); -} - -/* int bFill (bstring a, char c, int len) - * - * Fill a given bstring with the character in parameter c, for a length n. - */ -int bFill (bstring b, char c, int len) { - if (b == NULL || len < 0 || (b->mlen < b->slen && b->mlen > 0)) return -__LINE__; - b->slen = 0; - return bsetstr (b, len, NULL, c); -} - -/* int bReplicate (bstring b, int n) - * - * Replicate the contents of b end to end n times and replace it in b. - */ -int bReplicate (bstring b, int n) { - return bpattern (b, n * b->slen); -} - -/* int bReverse (bstring b) - * - * Reverse the contents of b in place. - */ -int bReverse (bstring b) { -int i, n, m; -unsigned char t; - - if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; - n = b->slen; - if (2 <= n) { - m = ((unsigned)n) >> 1; - n--; - for (i=0; i < m; i++) { - t = b->data[n - i]; - b->data[n - i] = b->data[i]; - b->data[i] = t; - } - } - return 0; -} - -/* int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) - * - * Insert a repeated sequence of a given character into the string at - * position pos for a length len. - */ -int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) { - if (b == NULL || b->slen < 0 || b->mlen < b->slen || pos < 0 || len <= 0) return -__LINE__; - - if (pos > b->slen - && 0 > bsetstr (b, pos, NULL, fill)) return -__LINE__; - - if (0 > balloc (b, b->slen + len)) return -__LINE__; - if (pos < b->slen) memmove (b->data + pos + len, b->data + pos, b->slen - pos); - memset (b->data + pos, c, len); - b->slen += len; - b->data[b->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bJustifyLeft (bstring b, int space) - * - * Left justify a string. - */ -int bJustifyLeft (bstring b, int space) { -int j, i, s, t; -unsigned char c = (unsigned char) space; - - if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; - if (space != (int) c) return BSTR_OK; - - for (s=j=i=0; i < b->slen; i++) { - t = s; - s = c != (b->data[j] = b->data[i]); - j += (t|s); - } - if (j > 0 && b->data[j-1] == c) j--; - - b->data[j] = (unsigned char) '\0'; - b->slen = j; - return BSTR_OK; -} - -/* int bJustifyRight (bstring b, int width, int space) - * - * Right justify a string to within a given width. - */ -int bJustifyRight (bstring b, int width, int space) { -int ret; - if (width <= 0) return -__LINE__; - if (0 > (ret = bJustifyLeft (b, space))) return ret; - if (b->slen <= width) - return bInsertChrs (b, 0, width - b->slen, (unsigned char) space, (unsigned char) space); - return BSTR_OK; -} - -/* int bJustifyCenter (bstring b, int width, int space) - * - * Center a string's non-white space characters to within a given width by - * inserting whitespaces at the beginning. - */ -int bJustifyCenter (bstring b, int width, int space) { -int ret; - if (width <= 0) return -__LINE__; - if (0 > (ret = bJustifyLeft (b, space))) return ret; - if (b->slen <= width) - return bInsertChrs (b, 0, (width - b->slen + 1) >> 1, (unsigned char) space, (unsigned char) space); - return BSTR_OK; -} - -/* int bJustifyMargin (bstring b, int width, int space) - * - * Stretch a string to flush against left and right margins by evenly - * distributing additional white space between words. If the line is too - * long to be margin justified, it is left justified. - */ -int bJustifyMargin (bstring b, int width, int space) { -struct bstrList * sl; -int i, l, c; - - if (b == NULL || b->slen < 0 || b->mlen == 0 || b->mlen < b->slen) return -__LINE__; - if (NULL == (sl = bsplit (b, (unsigned char) space))) return -__LINE__; - for (l=c=i=0; i < sl->qty; i++) { - if (sl->entry[i]->slen > 0) { - c ++; - l += sl->entry[i]->slen; - } - } - - if (l + c >= width || c < 2) { - bstrListDestroy (sl); - return bJustifyLeft (b, space); - } - - b->slen = 0; - for (i=0; i < sl->qty; i++) { - if (sl->entry[i]->slen > 0) { - if (b->slen > 0) { - int s = (width - l + (c / 2)) / c; - bInsertChrs (b, b->slen, s, (unsigned char) space, (unsigned char) space); - l += s; - } - bconcat (b, sl->entry[i]); - c--; - if (c <= 0) break; - } - } - - bstrListDestroy (sl); - return BSTR_OK; -} - -static size_t readNothing (void *buff, size_t elsize, size_t nelem, void *parm) { - buff = buff; - elsize = elsize; - nelem = nelem; - parm = parm; - return 0; /* Immediately indicate EOF. */ -} - -/* struct bStream * bsFromBstr (const_bstring b); - * - * Create a bStream whose contents are a copy of the bstring passed in. - * This allows the use of all the bStream APIs with bstrings. - */ -struct bStream * bsFromBstr (const_bstring b) { -struct bStream * s = bsopen ((bNread) readNothing, NULL); - bsunread (s, b); /* Push the bstring data into the empty bStream. */ - return s; -} - -static size_t readRef (void *buff, size_t elsize, size_t nelem, void *parm) { -struct tagbstring * t = (struct tagbstring *) parm; -size_t tsz = elsize * nelem; - - if (tsz > (size_t) t->slen) tsz = (size_t) t->slen; - if (tsz > 0) { - memcpy (buff, t->data, tsz); - t->slen -= (int) tsz; - t->data += tsz; - return tsz / elsize; - } - return 0; -} - -/* The "by reference" version of the above function. This function puts - * a number of restrictions on the call site (the passed in struct - * tagbstring *will* be modified by this function, and the source data - * must remain alive and constant for the lifetime of the bStream). - * Hence it is not presented as an extern. - */ -static struct bStream * bsFromBstrRef (struct tagbstring * t) { - if (!t) return NULL; - return bsopen ((bNread) readRef, t); -} - -/* char * bStr2NetStr (const_bstring b) - * - * Convert a bstring to a netstring. See - * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. - * Note: 1) The value returned should be freed with a call to bcstrfree() at - * the point when it will no longer be referenced to avoid a memory - * leak. - * 2) If the returned value is non-NULL, then it also '\0' terminated - * in the character position one past the "," terminator. - */ -char * bStr2NetStr (const_bstring b) { -char strnum[sizeof (b->slen) * 3 + 1]; -bstring s; -unsigned char * buff; - - if (b == NULL || b->data == NULL || b->slen < 0) return NULL; - sprintf (strnum, "%d:", b->slen); - if (NULL == (s = bfromcstr (strnum)) - || bconcat (s, b) == BSTR_ERR || bconchar (s, (char) ',') == BSTR_ERR) { - bdestroy (s); - return NULL; - } - buff = s->data; - bcstrfree ((char *) s); - return (char *) buff; -} - -/* bstring bNetStr2Bstr (const char * buf) - * - * Convert a netstring to a bstring. See - * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. - * Note that the terminating "," *must* be present, however a following '\0' - * is *not* required. - */ -bstring bNetStr2Bstr (const char * buff) { -int i, x; -bstring b; - if (buff == NULL) return NULL; - x = 0; - for (i=0; buff[i] != ':'; i++) { - unsigned int v = buff[i] - '0'; - if (v > 9 || x > ((INT_MAX - (signed int)v) / 10)) return NULL; - x = (x * 10) + v; - } - - /* This thing has to be properly terminated */ - if (buff[i + 1 + x] != ',') return NULL; - - if (NULL == (b = bfromcstr (""))) return NULL; - if (balloc (b, x + 1) != BSTR_OK) { - bdestroy (b); - return NULL; - } - memcpy (b->data, buff + i + 1, x); - b->data[x] = (unsigned char) '\0'; - b->slen = x; - return b; -} - -static char b64ETable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* bstring bBase64Encode (const_bstring b) - * - * Generate a base64 encoding. See: RFC1341 - */ -bstring bBase64Encode (const_bstring b) { -int i, c0, c1, c2, c3; -bstring out; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - out = bfromcstr (""); - for (i=0; i + 2 < b->slen; i += 3) { - if (i && ((i % 57) == 0)) { - if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { - bdestroy (out); - return NULL; - } - } - c0 = b->data[i] >> 2; - c1 = ((b->data[i] << 4) | - (b->data[i+1] >> 4)) & 0x3F; - c2 = ((b->data[i+1] << 2) | - (b->data[i+2] >> 6)) & 0x3F; - c3 = b->data[i+2] & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, b64ETable[c2]) < 0 || - bconchar (out, b64ETable[c3]) < 0) { - bdestroy (out); - return NULL; - } - } - - if (i && ((i % 57) == 0)) { - if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { - bdestroy (out); - return NULL; - } - } - - switch (i + 2 - b->slen) { - case 0: c0 = b->data[i] >> 2; - c1 = ((b->data[i] << 4) | - (b->data[i+1] >> 4)) & 0x3F; - c2 = (b->data[i+1] << 2) & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, b64ETable[c2]) < 0 || - bconchar (out, (char) '=') < 0) { - bdestroy (out); - return NULL; - } - break; - case 1: c0 = b->data[i] >> 2; - c1 = (b->data[i] << 4) & 0x3F; - if (bconchar (out, b64ETable[c0]) < 0 || - bconchar (out, b64ETable[c1]) < 0 || - bconchar (out, (char) '=') < 0 || - bconchar (out, (char) '=') < 0) { - bdestroy (out); - return NULL; - } - break; - case 2: break; - } - - return out; -} - -#define B64_PAD (-2) -#define B64_ERR (-1) - -static int base64DecodeSymbol (unsigned char alpha) { - if ((alpha >= 'A') && (alpha <= 'Z')) return (int)(alpha - 'A'); - else if ((alpha >= 'a') && (alpha <= 'z')) - return 26 + (int)(alpha - 'a'); - else if ((alpha >= '0') && (alpha <= '9')) - return 52 + (int)(alpha - '0'); - else if (alpha == '+') return 62; - else if (alpha == '/') return 63; - else if (alpha == '=') return B64_PAD; - else return B64_ERR; -} - -/* bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) - * - * Decode a base64 block of data. All MIME headers are assumed to have been - * removed. See: RFC1341 - */ -bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) { -int i, v; -unsigned char c0, c1, c2; -bstring out; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - if (boolTruncError) *boolTruncError = 0; - out = bfromcstr (""); - i = 0; - for (;;) { - do { - if (i >= b->slen) return out; - if (b->data[i] == '=') { /* Bad "too early" truncation */ - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c0 = (unsigned char) (v << 2); - do { - if (i >= b->slen || b->data[i] == '=') { /* Bad "too early" truncation */ - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c0 |= (unsigned char) (v >> 4); - c1 = (unsigned char) (v << 4); - do { - if (i >= b->slen) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (b->data[i] == '=') { - i++; - if (i >= b->slen || b->data[i] != '=' || bconchar (out, c0) < 0) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); /* Missing "=" at the end. */ - return NULL; - } - return out; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c1 |= (unsigned char) (v >> 2); - c2 = (unsigned char) (v << 6); - do { - if (i >= b->slen) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (b->data[i] == '=') { - if (bconchar (out, c0) < 0 || bconchar (out, c1) < 0) { - if (boolTruncError) { - *boolTruncError = 1; - return out; - } - bdestroy (out); - return NULL; - } - if (boolTruncError) *boolTruncError = 0; - return out; - } - v = base64DecodeSymbol (b->data[i]); - i++; - } while (v < 0); - c2 |= (unsigned char) (v); - if (bconchar (out, c0) < 0 || - bconchar (out, c1) < 0 || - bconchar (out, c2) < 0) { - if (boolTruncError) { - *boolTruncError = -1; - return out; - } - bdestroy (out); - return NULL; - } - } -} - -#define UU_DECODE_BYTE(b) (((b) == (signed int)'`') ? 0 : (b) - (signed int)' ') - -struct bUuInOut { - bstring src, dst; - int * badlines; -}; - -#define UU_MAX_LINELEN 45 - -static int bUuDecLine (void * parm, int ofs, int len) { -struct bUuInOut * io = (struct bUuInOut *) parm; -bstring s = io->src; -bstring t = io->dst; -int i, llen, otlen, ret, c0, c1, c2, c3, d0, d1, d2, d3; - - if (len == 0) return 0; - llen = UU_DECODE_BYTE (s->data[ofs]); - ret = 0; - - otlen = t->slen; - - if (((unsigned) llen) > UU_MAX_LINELEN) { ret = -__LINE__; - goto bl; - } - - llen += t->slen; - - for (i=1; i < s->slen && t->slen < llen;i += 4) { - unsigned char outoctet[3]; - c0 = UU_DECODE_BYTE (d0 = (int) bchare (s, i+ofs+0, ' ' - 1)); - c1 = UU_DECODE_BYTE (d1 = (int) bchare (s, i+ofs+1, ' ' - 1)); - c2 = UU_DECODE_BYTE (d2 = (int) bchare (s, i+ofs+2, ' ' - 1)); - c3 = UU_DECODE_BYTE (d3 = (int) bchare (s, i+ofs+3, ' ' - 1)); - - if (((unsigned) (c0|c1) >= 0x40)) { if (!ret) ret = -__LINE__; - if (d0 > 0x60 || (d0 < (' ' - 1) && !isspace (d0)) || - d1 > 0x60 || (d1 < (' ' - 1) && !isspace (d1))) { - t->slen = otlen; - goto bl; - } - c0 = c1 = 0; - } - outoctet[0] = (unsigned char) ((c0 << 2) | ((unsigned) c1 >> 4)); - if (t->slen+1 >= llen) { - if (0 > bconchar (t, (char) outoctet[0])) return -__LINE__; - break; - } - if ((unsigned) c2 >= 0x40) { if (!ret) ret = -__LINE__; - if (d2 > 0x60 || (d2 < (' ' - 1) && !isspace (d2))) { - t->slen = otlen; - goto bl; - } - c2 = 0; - } - outoctet[1] = (unsigned char) ((c1 << 4) | ((unsigned) c2 >> 2)); - if (t->slen+2 >= llen) { - if (0 > bcatblk (t, outoctet, 2)) return -__LINE__; - break; - } - if ((unsigned) c3 >= 0x40) { if (!ret) ret = -__LINE__; - if (d3 > 0x60 || (d3 < (' ' - 1) && !isspace (d3))) { - t->slen = otlen; - goto bl; - } - c3 = 0; - } - outoctet[2] = (unsigned char) ((c2 << 6) | ((unsigned) c3)); - if (0 > bcatblk (t, outoctet, 3)) return -__LINE__; - } - if (t->slen < llen) { if (0 == ret) ret = -__LINE__; - t->slen = otlen; - } - bl:; - if (ret && io->badlines) { - (*io->badlines)++; - return 0; - } - return ret; -} - -/* bstring bUuDecodeEx (const_bstring src, int * badlines) - * - * Performs a UUDecode of a block of data. If there are errors in the - * decoding, they are counted up and returned in "badlines", if badlines is - * not NULL. It is assumed that the "begin" and "end" lines have already - * been stripped off. The potential security problem of writing the - * filename in the begin line is something that is beyond the scope of a - * portable library. - */ - -#ifdef _MSC_VER -#pragma warning(disable:4204) -#endif - -bstring bUuDecodeEx (const_bstring src, int * badlines) { -struct tagbstring t; -struct bStream * s; -struct bStream * d; -bstring b; - - if (!src) return NULL; - t = *src; /* Short lifetime alias to header of src */ - s = bsFromBstrRef (&t); /* t is undefined after this */ - if (!s) return NULL; - d = bsUuDecode (s, badlines); - b = bfromcstralloc (256, ""); - if (NULL == b || 0 > bsread (b, d, INT_MAX)) { - bdestroy (b); - bsclose (d); - bsclose (s); - return NULL; - } - return b; -} - -struct bsUuCtx { - struct bUuInOut io; - struct bStream * sInp; -}; - -static size_t bsUuDecodePart (void *buff, size_t elsize, size_t nelem, void *parm) { -static struct tagbstring eol = bsStatic ("\r\n"); -struct bsUuCtx * luuCtx = (struct bsUuCtx *) parm; -size_t tsz; -int l, lret; - - if (NULL == buff || NULL == parm) return 0; - tsz = elsize * nelem; - - CheckInternalBuffer:; - /* If internal buffer has sufficient data, just output it */ - if (((size_t) luuCtx->io.dst->slen) > tsz) { - memcpy (buff, luuCtx->io.dst->data, tsz); - bdelete (luuCtx->io.dst, 0, (int) tsz); - return nelem; - } - - DecodeMore:; - if (0 <= (l = binchr (luuCtx->io.src, 0, &eol))) { - int ol = 0; - struct tagbstring t; - bstring s = luuCtx->io.src; - luuCtx->io.src = &t; - - do { - if (l > ol) { - bmid2tbstr (t, s, ol, l - ol); - lret = bUuDecLine (&luuCtx->io, 0, t.slen); - if (0 > lret) { - luuCtx->io.src = s; - goto Done; - } - } - ol = l + 1; - if (((size_t) luuCtx->io.dst->slen) > tsz) break; - l = binchr (s, ol, &eol); - } while (BSTR_ERR != l); - bdelete (s, 0, ol); - luuCtx->io.src = s; - goto CheckInternalBuffer; - } - - if (BSTR_ERR != bsreada (luuCtx->io.src, luuCtx->sInp, bsbufflength (luuCtx->sInp, BSTR_BS_BUFF_LENGTH_GET))) { - goto DecodeMore; - } - - bUuDecLine (&luuCtx->io, 0, luuCtx->io.src->slen); - - Done:; - /* Output any lingering data that has been translated */ - if (((size_t) luuCtx->io.dst->slen) > 0) { - if (((size_t) luuCtx->io.dst->slen) > tsz) goto CheckInternalBuffer; - memcpy (buff, luuCtx->io.dst->data, luuCtx->io.dst->slen); - tsz = luuCtx->io.dst->slen / elsize; - luuCtx->io.dst->slen = 0; - if (tsz > 0) return tsz; - } - - /* Deallocate once EOF becomes triggered */ - bdestroy (luuCtx->io.dst); - bdestroy (luuCtx->io.src); - free (luuCtx); - return 0; -} - -/* bStream * bsUuDecode (struct bStream * sInp, int * badlines) - * - * Creates a bStream which performs the UUDecode of an an input stream. If - * there are errors in the decoding, they are counted up and returned in - * "badlines", if badlines is not NULL. It is assumed that the "begin" and - * "end" lines have already been stripped off. The potential security - * problem of writing the filename in the begin line is something that is - * beyond the scope of a portable library. - */ - -struct bStream * bsUuDecode (struct bStream * sInp, int * badlines) { -struct bsUuCtx * luuCtx = (struct bsUuCtx *) malloc (sizeof (struct bsUuCtx)); -struct bStream * sOut; - - if (NULL == luuCtx) return NULL; - - luuCtx->io.src = bfromcstr (""); - luuCtx->io.dst = bfromcstr (""); - if (NULL == luuCtx->io.dst || NULL == luuCtx->io.src) { - CleanUpFailureToAllocate:; - bdestroy (luuCtx->io.dst); - bdestroy (luuCtx->io.src); - free (luuCtx); - return NULL; - } - luuCtx->io.badlines = badlines; - if (badlines) *badlines = 0; - - luuCtx->sInp = sInp; - - sOut = bsopen ((bNread) bsUuDecodePart, luuCtx); - if (NULL == sOut) goto CleanUpFailureToAllocate; - return sOut; -} - -#define UU_ENCODE_BYTE(b) (char) (((b) == 0) ? '`' : ((b) + ' ')) - -/* bstring bUuEncode (const_bstring src) - * - * Performs a UUEncode of a block of data. The "begin" and "end" lines are - * not appended. - */ -bstring bUuEncode (const_bstring src) { -bstring out; -int i, j, jm; -unsigned int c0, c1, c2; - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - for (i=0; i < src->slen; i += UU_MAX_LINELEN) { - if ((jm = i + UU_MAX_LINELEN) > src->slen) jm = src->slen; - if (bconchar (out, UU_ENCODE_BYTE (jm - i)) < 0) { - bstrFree (out); - break; - } - for (j = i; j < jm; j += 3) { - c0 = (unsigned int) bchar (src, j ); - c1 = (unsigned int) bchar (src, j + 1); - c2 = (unsigned int) bchar (src, j + 2); - if (bconchar (out, UU_ENCODE_BYTE ( (c0 & 0xFC) >> 2)) < 0 || - bconchar (out, UU_ENCODE_BYTE (((c0 & 0x03) << 4) | ((c1 & 0xF0) >> 4))) < 0 || - bconchar (out, UU_ENCODE_BYTE (((c1 & 0x0F) << 2) | ((c2 & 0xC0) >> 6))) < 0 || - bconchar (out, UU_ENCODE_BYTE ( (c2 & 0x3F))) < 0) { - bstrFree (out); - goto End; - } - } - if (bconchar (out, (char) '\r') < 0 || bconchar (out, (char) '\n') < 0) { - bstrFree (out); - break; - } - } - End:; - return out; -} - -/* bstring bYEncode (const_bstring src) - * - * Performs a YEncode of a block of data. No header or tail info is - * appended. See: http://www.yenc.org/whatis.htm and - * http://www.yenc.org/yenc-draft.1.3.txt - */ -bstring bYEncode (const_bstring src) { -int i; -bstring out; -unsigned char c; - - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - for (i=0; i < src->slen; i++) { - c = (unsigned char)(src->data[i] + 42); - if (c == '=' || c == '\0' || c == '\r' || c == '\n') { - if (0 > bconchar (out, (char) '=')) { - bdestroy (out); - return NULL; - } - c += (unsigned char) 64; - } - if (0 > bconchar (out, c)) { - bdestroy (out); - return NULL; - } - } - return out; -} - -/* bstring bYDecode (const_bstring src) - * - * Performs a YDecode of a block of data. See: - * http://www.yenc.org/whatis.htm and http://www.yenc.org/yenc-draft.1.3.txt - */ -#define MAX_OB_LEN (64) - -bstring bYDecode (const_bstring src) { -int i; -bstring out; -unsigned char c; -unsigned char octetbuff[MAX_OB_LEN]; -int obl; - - if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; - if ((out = bfromcstr ("")) == NULL) return NULL; - - obl = 0; - - for (i=0; i < src->slen; i++) { - if ('=' == (c = src->data[i])) { /* The = escape mode */ - i++; - if (i >= src->slen) { - bdestroy (out); - return NULL; - } - c = (unsigned char) (src->data[i] - 64); - } else { - if ('\0' == c) { - bdestroy (out); - return NULL; - } - - /* Extraneous CR/LFs are to be ignored. */ - if (c == '\r' || c == '\n') continue; - } - - octetbuff[obl] = (unsigned char) ((int) c - 42); - obl++; - - if (obl >= MAX_OB_LEN) { - if (0 > bcatblk (out, octetbuff, obl)) { - bdestroy (out); - return NULL; - } - obl = 0; - } - } - - if (0 > bcatblk (out, octetbuff, obl)) { - bdestroy (out); - out = NULL; - } - return out; -} - -/* bstring bStrfTime (const char * fmt, const struct tm * timeptr) - * - * Takes a format string that is compatible with strftime and a struct tm - * pointer, formats the time according to the format string and outputs - * the bstring as a result. Note that if there is an early generation of a - * '\0' character, the bstring will be truncated to this end point. - */ -bstring bStrfTime (const char * fmt, const struct tm * timeptr) { -#if defined (__TURBOC__) && !defined (__BORLANDC__) -static struct tagbstring ns = bsStatic ("bStrfTime Not supported"); - fmt = fmt; - timeptr = timeptr; - return &ns; -#else -bstring buff; -int n; -size_t r; - - if (fmt == NULL) return NULL; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "strftime" call on increasing - potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < 16) n = 16; - buff = bfromcstralloc (n+2, ""); - - for (;;) { - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return NULL; - } - - r = strftime ((char *) buff->data, n + 1, fmt, timeptr); - - if (r > 0) { - buff->slen = (int) r; - break; - } - - n += n; - } - - return buff; -#endif -} - -/* int bSetCstrChar (bstring a, int pos, char c) - * - * Sets the character at position pos to the character c in the bstring a. - * If the character c is NUL ('\0') then the string is truncated at this - * point. Note: this does not enable any other '\0' character in the bstring - * as terminator indicator for the string. pos must be in the position - * between 0 and b->slen inclusive, otherwise BSTR_ERR will be returned. - */ -int bSetCstrChar (bstring b, int pos, char c) { - if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) - return BSTR_ERR; - if (pos < 0 || pos > b->slen) return BSTR_ERR; - - if (pos == b->slen) { - if ('\0' != c) return bconchar (b, c); - return 0; - } - - b->data[pos] = (unsigned char) c; - if ('\0' == c) b->slen = pos; - - return 0; -} - -/* int bSetChar (bstring b, int pos, char c) - * - * Sets the character at position pos to the character c in the bstring a. - * The string is not truncated if the character c is NUL ('\0'). pos must - * be in the position between 0 and b->slen inclusive, otherwise BSTR_ERR - * will be returned. - */ -int bSetChar (bstring b, int pos, char c) { - if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) - return BSTR_ERR; - if (pos < 0 || pos > b->slen) return BSTR_ERR; - - if (pos == b->slen) { - return bconchar (b, c); - } - - b->data[pos] = (unsigned char) c; - return 0; -} - -#define INIT_SECURE_INPUT_LENGTH (256) - -/* bstring bSecureInput (int maxlen, int termchar, - * bNgetc vgetchar, void * vgcCtx) - * - * Read input from an abstracted input interface, for a length of at most - * maxlen characters. If maxlen <= 0, then there is no length limit put - * on the input. The result is terminated early if vgetchar() return EOF - * or the user specified value termchar. - * - */ -bstring bSecureInput (int maxlen, int termchar, bNgetc vgetchar, void * vgcCtx) { -int i, m, c; -bstring b, t; - - if (!vgetchar) return NULL; - - b = bfromcstralloc (INIT_SECURE_INPUT_LENGTH, ""); - if ((c = UCHAR_MAX + 1) == termchar) c++; - - for (i=0; ; i++) { - if (termchar == c || (maxlen > 0 && i >= maxlen)) c = EOF; - else c = vgetchar (vgcCtx); - - if (EOF == c) break; - - if (i+1 >= b->mlen) { - - /* Double size, but deal with unusual case of numeric - overflows */ - - if ((m = b->mlen << 1) <= b->mlen && - (m = b->mlen + 1024) <= b->mlen && - (m = b->mlen + 16) <= b->mlen && - (m = b->mlen + 1) <= b->mlen) t = NULL; - else t = bfromcstralloc (m, ""); - - if (t) memcpy (t->data, b->data, i); - bSecureDestroy (b); /* Cleanse previous buffer */ - b = t; - if (!b) return b; - } - - b->data[i] = (unsigned char) c; - } - - b->slen = i; - b->data[i] = (unsigned char) '\0'; - return b; -} - -#define BWS_BUFF_SZ (1024) - -struct bwriteStream { - bstring buff; /* Buffer for underwrites */ - void * parm; /* The stream handle for core stream */ - bNwrite writeFn; /* fwrite work-a-like fnptr for core stream */ - int isEOF; /* track stream's EOF state */ - int minBuffSz; -}; - -/* struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) - * - * Wrap a given open stream (described by a fwrite work-a-like function - * pointer and stream handle) into an open bwriteStream suitable for write - * streaming functions. - */ -struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) { -struct bwriteStream * ws; - - if (NULL == writeFn) return NULL; - ws = (struct bwriteStream *) malloc (sizeof (struct bwriteStream)); - if (ws) { - if (NULL == (ws->buff = bfromcstr (""))) { - free (ws); - ws = NULL; - } else { - ws->parm = parm; - ws->writeFn = writeFn; - ws->isEOF = 0; - ws->minBuffSz = BWS_BUFF_SZ; - } - } - return ws; -} - -#define internal_bwswriteout(ws,b) { \ - if ((b)->slen > 0) { \ - if (1 != (ws->writeFn ((b)->data, (b)->slen, 1, ws->parm))) { \ - ws->isEOF = 1; \ - return BSTR_ERR; \ - } \ - } \ -} - -/* int bwsWriteFlush (struct bwriteStream * ws) - * - * Force any pending data to be written to the core stream. - */ -int bwsWriteFlush (struct bwriteStream * ws) { - if (NULL == ws || ws->isEOF || 0 >= ws->minBuffSz || - NULL == ws->writeFn || NULL == ws->buff) return BSTR_ERR; - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - return 0; -} - -/* int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) - * - * Send a bstring to a bwriteStream. If the stream is at EOF BSTR_ERR is - * returned. Note that there is no deterministic way to determine the exact - * cut off point where the core stream stopped accepting data. - */ -int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) { -struct tagbstring t; -int l; - - if (NULL == ws || NULL == b || NULL == ws->buff || - ws->isEOF || 0 >= ws->minBuffSz || NULL == ws->writeFn) - return BSTR_ERR; - - /* Buffer prepacking optimization */ - if (b->slen > 0 && ws->buff->mlen - ws->buff->slen > b->slen) { - static struct tagbstring empty = bsStatic (""); - if (0 > bconcat (ws->buff, b)) return BSTR_ERR; - return bwsWriteBstr (ws, &empty); - } - - if (0 > (l = ws->minBuffSz - ws->buff->slen)) { - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - l = ws->minBuffSz; - } - - if (b->slen < l) return bconcat (ws->buff, b); - - if (0 > bcatblk (ws->buff, b->data, l)) return BSTR_ERR; - internal_bwswriteout (ws, ws->buff); - ws->buff->slen = 0; - - bmid2tbstr (t, (bstring) b, l, b->slen); - - if (t.slen >= ws->minBuffSz) { - internal_bwswriteout (ws, &t); - return 0; - } - - return bassign (ws->buff, &t); -} - -/* int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) - * - * Send a block of data a bwriteStream. If the stream is at EOF BSTR_ERR is - * returned. - */ -int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) { -struct tagbstring t; - if (NULL == blk || len < 0) return BSTR_ERR; - blk2tbstr (t, blk, len); - return bwsWriteBstr (ws, &t); -} - -/* int bwsIsEOF (const struct bwriteStream * ws) - * - * Returns 0 if the stream is currently writable, 1 if the core stream has - * responded by not accepting the previous attempted write. - */ -int bwsIsEOF (const struct bwriteStream * ws) { - if (NULL == ws || NULL == ws->buff || 0 > ws->minBuffSz || - NULL == ws->writeFn) return BSTR_ERR; - return ws->isEOF; -} - -/* int bwsBuffLength (struct bwriteStream * ws, int sz) - * - * Set the length of the buffer used by the bwsStream. If sz is zero, the - * length is not set. This function returns with the previous length. - */ -int bwsBuffLength (struct bwriteStream * ws, int sz) { -int oldSz; - if (ws == NULL || sz < 0) return BSTR_ERR; - oldSz = ws->minBuffSz; - if (sz > 0) ws->minBuffSz = sz; - return oldSz; -} - -/* void * bwsClose (struct bwriteStream * s) - * - * Close the bwriteStream, and return the handle to the stream that was - * originally used to open the given stream. Note that even if the stream - * is at EOF it still needs to be closed with a call to bwsClose. - */ -void * bwsClose (struct bwriteStream * ws) { -void * parm; - if (NULL == ws || NULL == ws->buff || 0 >= ws->minBuffSz || - NULL == ws->writeFn) return NULL; - bwsWriteFlush (ws); - parm = ws->parm; - ws->parm = NULL; - ws->minBuffSz = -1; - ws->writeFn = NULL; - bstrFree (ws->buff); - free (ws); - return parm; -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h deleted file mode 100644 index e10c6e1a68..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstraux.h - * - * This file is not a necessary part of the core bstring library itself, but - * is just an auxilliary module which includes miscellaneous or trivial - * functions. - */ - -#ifndef BSTRAUX_INCLUDE -#define BSTRAUX_INCLUDE - -#include <time.h> -#include "bstrlib.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Safety mechanisms */ -#define bstrDeclare(b) bstring (b) = NULL; -#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }} - -/* Backward compatibilty with previous versions of Bstrlib */ -#define bAssign(a,b) ((bassign)((a), (b))) -#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) -#define bStrchr(b,c) ((bstrchr)((b), (c))) -#define bStrchrFast(b,c) ((bstrchr)((b), (c))) -#define bCatCstr(b,s) ((bcatcstr)((b), (s))) -#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) -#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1) -#define bTrunc(b,n) ((btrunc)((b), (n))) -#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos))) -#define bUppercase(b) ((btoupper)(b)) -#define bLowercase(b) ((btolower)(b)) -#define bCaselessCmp(a,b) ((bstricmp)((a), (b))) -#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n))) -#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL)) -#define bUuDecode(b) (bUuDecodeEx ((b), NULL)) - -/* Unusual functions */ -extern struct bStream * bsFromBstr (const_bstring b); -extern bstring bTail (bstring b, int n); -extern bstring bHead (bstring b, int n); -extern int bSetCstrChar (bstring a, int pos, char c); -extern int bSetChar (bstring b, int pos, char c); -extern int bFill (bstring a, char c, int len); -extern int bReplicate (bstring b, int n); -extern int bReverse (bstring b); -extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill); -extern bstring bStrfTime (const char * fmt, const struct tm * timeptr); -#define bAscTime(t) (bStrfTime ("%c\n", (t))) -#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL) - -/* Spacing formatting */ -extern int bJustifyLeft (bstring b, int space); -extern int bJustifyRight (bstring b, int width, int space); -extern int bJustifyMargin (bstring b, int width, int space); -extern int bJustifyCenter (bstring b, int width, int space); - -/* Esoteric standards specific functions */ -extern char * bStr2NetStr (const_bstring b); -extern bstring bNetStr2Bstr (const char * buf); -extern bstring bBase64Encode (const_bstring b); -extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError); -extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines); -extern bstring bUuDecodeEx (const_bstring src, int * badlines); -extern bstring bUuEncode (const_bstring src); -extern bstring bYEncode (const_bstring src); -extern bstring bYDecode (const_bstring src); - -/* Writable stream */ -typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm); - -struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm); -int bwsWriteBstr (struct bwriteStream * stream, const_bstring b); -int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len); -int bwsWriteFlush (struct bwriteStream * stream); -int bwsIsEOF (const struct bwriteStream * stream); -int bwsBuffLength (struct bwriteStream * stream, int sz); -void * bwsClose (struct bwriteStream * stream); - -/* Security functions */ -#define bSecureDestroy(b) { \ -bstring bstr__tmp = (b); \ - if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \ - (void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \ - bdestroy (bstr__tmp); \ - } \ -} -#define bSecureWriteProtect(t) { \ - if ((t).mlen >= 0) { \ - if ((t).mlen > (t).slen)) { \ - (void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \ - } \ - (t).mlen = -1; \ - } \ -} -extern bstring bSecureInput (int maxlen, int termchar, - bNgetc vgetchar, void * vgcCtx); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c deleted file mode 100644 index 61c8c60ee1..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c +++ /dev/null @@ -1,2976 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstrlib.c - * - * This file is the core module for implementing the bstring functions. - */ - -#include <stdio.h> -#include <stddef.h> -#include <stdarg.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include "bstrlib.h" -#include "../internal_includes/hlslcc_malloc.h" - -/* Optionally include a mechanism for debugging memory */ - -#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) -#include "memdbg.h" -#endif - -#ifndef bstr__alloc -#define bstr__alloc(x) malloc (x) -#endif - -#ifndef bstr__free -#define bstr__free(p) free (p) -#endif - -#ifndef bstr__realloc -#define bstr__realloc(p,x) realloc ((p), (x)) -#endif - -#ifndef bstr__memcpy -#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) -#endif - -#ifndef bstr__memmove -#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) -#endif - -#ifndef bstr__memset -#define bstr__memset(d,c,l) memset ((d), (c), (l)) -#endif - -#ifndef bstr__memcmp -#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) -#endif - -#ifndef bstr__memchr -#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) -#endif - -/* Just a length safe wrapper for memmove. */ - -#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } - -/* Compute the snapped size for a given requested size. By snapping to powers - of 2 like this, repeated reallocations are avoided. */ -static int snapUpSize (int i) { - if (i < 8) { - i = 8; - } else { - unsigned int j; - j = (unsigned int) i; - - j |= (j >> 1); - j |= (j >> 2); - j |= (j >> 4); - j |= (j >> 8); /* Ok, since int >= 16 bits */ -#if (UINT_MAX != 0xffff) - j |= (j >> 16); /* For 32 bit int systems */ -#if (UINT_MAX > 0xffffffffUL) - j |= (j >> 32); /* For 64 bit int systems */ -#endif -#endif - /* Least power of two greater than i */ - j++; - if ((int) j >= i) i = (int) j; - } - return i; -} - -/* int balloc (bstring b, int len) - * - * Increase the size of the memory backing the bstring b to at least len. - */ -int balloc (bstring b, int olen) { - int len; - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || - b->mlen < b->slen || olen <= 0) { - return BSTR_ERR; - } - - if (olen >= b->mlen) { - unsigned char * x; - - if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; - - /* Assume probability of a non-moving realloc is 0.125 */ - if (7 * b->mlen < 8 * b->slen) { - - /* If slen is close to mlen in size then use realloc to reduce - the memory defragmentation */ - - reallocStrategy:; - - x = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (x == NULL) { - - /* Since we failed, try allocating the tighest possible - allocation */ - - if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { - return BSTR_ERR; - } - } - } else { - - /* If slen is not close to mlen then avoid the penalty of copying - the extra bytes that are allocated, but not considered part of - the string */ - - if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { - - /* Perhaps there is no available memory for the two - allocations to be in memory at once */ - - goto reallocStrategy; - - } else { - if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); - bstr__free (b->data); - } - } - b->data = x; - b->mlen = len; - b->data[b->slen] = (unsigned char) '\0'; - } - - return BSTR_OK; -} - -/* int ballocmin (bstring b, int len) - * - * Set the size of the memory backing the bstring b to len or b->slen+1, - * whichever is larger. Note that repeated use of this function can degrade - * performance. - */ -int ballocmin (bstring b, int len) { - unsigned char * s; - - if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || - b->mlen < b->slen || len <= 0) { - return BSTR_ERR; - } - - if (len < b->slen + 1) len = b->slen + 1; - - if (len != b->mlen) { - s = (unsigned char *) bstr__realloc (b->data, (size_t) len); - if (NULL == s) return BSTR_ERR; - s[b->slen] = (unsigned char) '\0'; - b->data = s; - b->mlen = len; - } - - return BSTR_OK; -} - -/* bstring bfromcstr (const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. - */ -bstring bfromcstr (const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; - b->slen = (int) j; - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring bfromcstralloc (int mlen, const char * str) - * - * Create a bstring which contains the contents of the '\0' terminated char * - * buffer str. The memory buffer backing the string is at least len - * characters in length. - */ -bstring bfromcstralloc (int mlen, const char * str) { -bstring b; -int i; -size_t j; - - if (str == NULL) return NULL; - j = (strlen) (str); - i = snapUpSize ((int) (j + (2 - (j != 0)))); - if (i <= (int) j) return NULL; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = (int) j; - if (i < mlen) i = mlen; - - if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { - bstr__free (b); - return NULL; - } - - bstr__memcpy (b->data, str, j+1); - return b; -} - -/* bstring blk2bstr (const void * blk, int len) - * - * Create a bstring which contains the content of the block blk of length - * len. - */ -bstring blk2bstr (const void * blk, int len) { -bstring b; -int i; - - if (blk == NULL || len < 0) return NULL; - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b == NULL) return NULL; - b->slen = len; - - i = len + (2 - (len != 0)); - i = snapUpSize (i); - - b->mlen = i; - - b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); - b->data[len] = (unsigned char) '\0'; - - return b; -} - -/* char * bstr2cstr (const_bstring s, char z) - * - * Create a '\0' terminated char * buffer which is equal to the contents of - * the bstring s, except that any contained '\0' characters are converted - * to the character in z. This returned value should be freed with a - * bcstrfree () call, by the calling application. - */ -char * bstr2cstr (const_bstring b, char z) { -int i, l; -char * r; - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - l = b->slen; - r = (char *) bstr__alloc ((size_t) (l + 1)); - if (r == NULL) return r; - - for (i=0; i < l; i ++) { - r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); - } - - r[l] = (unsigned char) '\0'; - - return r; -} - -/* int bcstrfree (char * s) - * - * Frees a C-string generated by bstr2cstr (). This is normally unnecessary - * since it just wraps a call to bstr__free (), however, if bstr__alloc () - * and bstr__free () have been redefined as a macros within the bstrlib - * module (via defining them in memdbg.h after defining - * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std - * library functions, then this allows a correct way of freeing the memory - * that allows higher level code to be independent from these macro - * redefinitions. - */ -int bcstrfree (char * s) { - if (s) { - bstr__free (s); - return BSTR_OK; - } - return BSTR_ERR; -} - -/* int bconcat (bstring b0, const_bstring b1) - * - * Concatenate the bstring b1 to the bstring b0. - */ -int bconcat (bstring b0, const_bstring b1) { -int len, d; -bstring aux = (bstring) b1; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; - - d = b0->slen; - len = b1->slen; - if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; - - if (b0->mlen <= d + len + 1) { - ptrdiff_t pd = b1->data - b0->data; - if (0 <= pd && pd < b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - if (balloc (b0, d + len + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - } - - bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); - b0->data[d + len] = (unsigned char) '\0'; - b0->slen = d + len; - if (aux != b1) bdestroy (aux); - return BSTR_OK; -} - -/* int bconchar (bstring b, char c) -/ * - * Concatenate the single character c to the bstring b. - */ -int bconchar (bstring b, char c) { -int d; - - if (b == NULL) return BSTR_ERR; - d = b->slen; - if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - b->data[d] = (unsigned char) c; - b->data[d + 1] = (unsigned char) '\0'; - b->slen++; - return BSTR_OK; -} - -/* int bcatcstr (bstring b, const char * s) - * - * Concatenate a char * string to a bstring. - */ -int bcatcstr (bstring b, const char * s) { -char * d; -int i, l; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL) return BSTR_ERR; - - /* Optimistically concatenate directly */ - l = b->mlen - b->slen; - d = (char *) &b->data[b->slen]; - for (i=0; i < l; i++) { - if ((*d++ = *s++) == '\0') { - b->slen += i; - return BSTR_OK; - } - } - b->slen += i; - - /* Need to explicitely resize and concatenate tail */ - return bcatblk (b, (const void *) s, (int) strlen (s)); -} - -/* int bcatblk (bstring b, const void * s, int len) - * - * Concatenate a fixed length buffer to a bstring. - */ -int bcatblk (bstring b, const void * s, int len) { -int nl; - - if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen - || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; - - if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ - if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; - - bBlockCopy (&b->data[b->slen], s, (size_t) len); - b->slen = nl; - b->data[nl] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bstrcpy (const_bstring b) - * - * Create a copy of the bstring b. - */ -bstring bstrcpy (const_bstring b) { -bstring b0; -int i,j; - - /* Attempted to copy an invalid string? */ - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (b0 == NULL) { - /* Unable to allocate memory for string header */ - return NULL; - } - - i = b->slen; - j = snapUpSize (i + 1); - - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - j = i + 1; - b0->data = (unsigned char *) bstr__alloc (j); - if (b0->data == NULL) { - /* Unable to allocate memory for string data */ - bstr__free (b0); - return NULL; - } - } - - b0->mlen = j; - b0->slen = i; - - if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); - b0->data[b0->slen] = (unsigned char) '\0'; - - return b0; -} - -/* int bassign (bstring a, const_bstring b) - * - * Overwrite the string a with the contents of string b. - */ -int bassign (bstring a, const_bstring b) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - if (b->slen != 0) { - if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data, b->slen); - } else { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - } - a->data[b->slen] = (unsigned char) '\0'; - a->slen = b->slen; - return BSTR_OK; -} - -/* int bassignmidstr (bstring a, const_bstring b, int left, int len) - * - * Overwrite the string a with the middle of contents of string b - * starting from position left and running for a length len. left and - * len are clamped to the ends of b as with the function bmidstr. - */ -int bassignmidstr (bstring a, const_bstring b, int left, int len) { - if (b == NULL || b->data == NULL || b->slen < 0) - return BSTR_ERR; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0) - return BSTR_ERR; - - if (len > 0) { - if (balloc (a, len) != BSTR_OK) return BSTR_ERR; - bstr__memmove (a->data, b->data + left, len); - a->slen = len; - } else { - a->slen = 0; - } - a->data[a->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bassigncstr (bstring a, const char * str) - * - * Overwrite the string a with the contents of char * string str. Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned however a may be partially overwritten. - */ -int bassigncstr (bstring a, const char * str) { -int i; -size_t len; - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == str) - return BSTR_ERR; - - for (i=0; i < a->mlen; i++) { - if ('\0' == (a->data[i] = str[i])) { - a->slen = i; - return BSTR_OK; - } - } - - a->slen = i; - len = strlen (str + i); - if (len > INT_MAX || i + len + 1 > INT_MAX || - 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; - bBlockCopy (a->data + i, str + i, (size_t) len + 1); - a->slen += (int) len; - return BSTR_OK; -} - -/* int bassignblk (bstring a, const void * s, int len) - * - * Overwrite the string a with the contents of the block (s, len). Note that - * the bstring a must be a well defined and writable bstring. If an error - * occurs BSTR_ERR is returned and a is not overwritten. - */ -int bassignblk (bstring a, const void * s, int len) { - if (a == NULL || a->data == NULL || a->mlen < a->slen || - a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) - return BSTR_ERR; - if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; - bBlockCopy (a->data, s, (size_t) len); - a->data[len] = (unsigned char) '\0'; - a->slen = len; - return BSTR_OK; -} - -/* int btrunc (bstring b, int n) - * - * Truncate the bstring to at most n characters. - */ -int btrunc (bstring b, int n) { - if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - if (b->slen > n) { - b->slen = n; - b->data[n] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -#define upcase(c) (toupper ((unsigned char) c)) -#define downcase(c) (tolower ((unsigned char) c)) -#define wspace(c) (isspace ((unsigned char) c)) - -/* int btoupper (bstring b) - * - * Convert contents of bstring to upper case. - */ -int btoupper (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) upcase (b->data[i]); - } - return BSTR_OK; -} - -/* int btolower (bstring b) - * - * Convert contents of bstring to lower case. - */ -int btolower (bstring b) { -int i, len; - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - for (i=0, len = b->slen; i < len; i++) { - b->data[i] = (unsigned char) downcase (b->data[i]); - } - return BSTR_OK; -} - -/* int bstricmp (const_bstring b0, const_bstring b1) - * - * Compare two strings without differentiating between case. The return - * value is the difference of the values of the characters where the two - * strings first differ after lower case transformation, otherwise 0 is - * returned indicating that the strings are equal. If the lengths are - * different, then a difference from 0 is given, but if the first extra - * character is '\0', then it is taken to be the value UCHAR_MAX+1. - */ -int bstricmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; - if ((n = b0->slen) > b1->slen) n = b1->slen; - else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = (char) downcase (b0->data[i]) - - (char) downcase (b1->data[i]); - if (0 != v) return v; - } - - if (b0->slen > n) { - v = (char) downcase (b0->data[n]); - if (v) return v; - return UCHAR_MAX + 1; - } - if (b1->slen > n) { - v = - (char) downcase (b1->data[n]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); - } - return BSTR_OK; -} - -/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) - * - * Compare two strings without differentiating between case for at most n - * characters. If the position where the two strings first differ is - * before the nth position, the return value is the difference of the values - * of the characters, otherwise 0 is returned. If the lengths are different - * and less than n characters, then a difference from 0 is given, but if the - * first extra character is '\0', then it is taken to be the value - * UCHAR_MAX+1. - */ -int bstrnicmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = (char) downcase (b0->data[i]); - v -= (char) downcase (b1->data[i]); - if (v != 0) return b0->data[i] - b1->data[i]; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) { - v = (char) downcase (b0->data[m]); - if (v) return v; - return UCHAR_MAX + 1; - } - - v = - (char) downcase (b1->data[m]); - if (v) return v; - return - (int) (UCHAR_MAX + 1); -} - -/* int biseqcaseless (const_bstring b0, const_bstring b1) - * - * Compare two strings for equality without differentiating between case. - * If the strings differ other than in case, 0 is returned, if the strings - * are the same, 1 is returned, if there is an error, -1 is returned. If - * the length of the strings are different, this function is O(1). '\0' - * termination characters are not treated in any special way. - */ -int biseqcaseless (const_bstring b0, const_bstring b1) { -int i, n; - - if (bdata (b0) == NULL || b0->slen < 0 || - bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - for (i=0, n=b0->slen; i < n; i++) { - if (b0->data[i] != b1->data[i]) { - unsigned char c = (unsigned char) downcase (b0->data[i]); - if (c != (unsigned char) downcase (b1->data[i])) return 0; - } - } - return 1; -} - -/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len - * without differentiating between case for equality. If the beginning of b0 - * differs from the memory block other than in case (or if b0 is too short), - * 0 is returned, if the strings are the same, 1 is returned, if there is an - * error, -1 is returned. '\0' characters are not treated in any special - * way. - */ -int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) { - if (downcase (b0->data[i]) != - downcase (((const unsigned char *) blk)[i])) return 0; - } - } - return 1; -} - -/* - * int bltrimws (bstring b) - * - * Delete whitespace contiguous from the left end of the string. - */ -int bltrimws (bstring b) { -int i, len; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (len = b->slen, i = 0; i < len; i++) { - if (!wspace (b->data[i])) { - return bdelete (b, 0, i); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int brtrimws (bstring b) - * - * Delete whitespace contiguous from the right end of the string. - */ -int brtrimws (bstring b) { -int i; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - return BSTR_OK; - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* - * int btrimws (bstring b) - * - * Delete whitespace contiguous from both ends of the string. - */ -int btrimws (bstring b) { -int i, j; - - if (b == NULL || b->data == NULL || b->mlen < b->slen || - b->slen < 0 || b->mlen <= 0) return BSTR_ERR; - - for (i = b->slen - 1; i >= 0; i--) { - if (!wspace (b->data[i])) { - if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; - b->slen = i + 1; - for (j = 0; wspace (b->data[j]); j++) {} - return bdelete (b, 0, j); - } - } - - b->data[0] = (unsigned char) '\0'; - b->slen = 0; - return BSTR_OK; -} - -/* int biseq (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If the strings differ, 0 is returned, if - * the strings are the same, 1 is returned, if there is an error, -1 is - * returned. If the length of the strings are different, this function is - * O(1). '\0' termination characters are not treated in any special way. - */ -int biseq (const_bstring b0, const_bstring b1) { - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return BSTR_ERR; - if (b0->slen != b1->slen) return BSTR_OK; - if (b0->data == b1->data || b0->slen == 0) return 1; - return !bstr__memcmp (b0->data, b1->data, b0->slen); -} - -/* int bisstemeqblk (const_bstring b0, const void * blk, int len) - * - * Compare beginning of string b0 with a block of memory of length len for - * equality. If the beginning of b0 differs from the memory block (or if b0 - * is too short), 0 is returned, if the strings are the same, 1 is returned, - * if there is an error, -1 is returned. '\0' characters are not treated in - * any special way. - */ -int bisstemeqblk (const_bstring b0, const void * blk, int len) { -int i; - - if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) - return BSTR_ERR; - if (b0->slen < len) return BSTR_OK; - if (b0->data == (const unsigned char *) blk || len == 0) return 1; - - for (i = 0; i < len; i ++) { - if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; - } - return 1; -} - -/* int biseqcstr (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical with the bstring b with no '\0' - * characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal when comparing them in the same format after converting one or the - * other. If the strings are equal 1 is returned, if they are unequal 0 is - * returned and if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstr (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int biseqcstrcaseless (const_bstring b, const char *s) - * - * Compare the bstring b and char * string s. The C string s must be '\0' - * terminated at exactly the length of the bstring b, and the contents - * between the two must be identical except for case with the bstring b with - * no '\0' characters for the two contents to be considered equal. This is - * equivalent to the condition that their current contents will be always be - * equal ignoring case when comparing them in the same format after - * converting one or the other. If the strings are equal, except for case, - * 1 is returned, if they are unequal regardless of case 0 is returned and - * if there is a detectable error BSTR_ERR is returned. - */ -int biseqcstrcaseless (const_bstring b, const char * s) { -int i; - if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; - for (i=0; i < b->slen; i++) { - if (s[i] == '\0' || - (b->data[i] != (unsigned char) s[i] && - downcase (b->data[i]) != (unsigned char) downcase (s[i]))) - return BSTR_OK; - } - return s[i] == '\0'; -} - -/* int bstrcmp (const_bstring b0, const_bstring b1) - * - * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, - * otherwise a value less than or greater than zero, indicating that the - * string pointed to by b0 is lexicographically less than or greater than - * the string pointed to by b1 is returned. If the the string lengths are - * unequal but the characters up until the length of the shorter are equal - * then a value less than, or greater than zero, indicating that the string - * pointed to by b0 is shorter or longer than the string pointed to by b1 is - * returned. 0 is returned if and only if the two strings are the same. If - * the length of the strings are different, this function is O(n). Like its - * standard C library counter part strcmp, the comparison does not proceed - * past any '\0' termination characters encountered. - */ -int bstrcmp (const_bstring b0, const_bstring b1) { -int i, v, n; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - n = b0->slen; if (n > b1->slen) n = b1->slen; - if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) - return BSTR_OK; - - for (i = 0; i < n; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - - if (b0->slen > n) return 1; - if (b1->slen > n) return -1; - return BSTR_OK; -} - -/* int bstrncmp (const_bstring b0, const_bstring b1, int n) - * - * Compare the string b0 and b1 for at most n characters. If there is an - * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and - * b1 were first truncated to at most n characters then bstrcmp was called - * with these new strings are paremeters. If the length of the strings are - * different, this function is O(n). Like its standard C library counter - * part strcmp, the comparison does not proceed past any '\0' termination - * characters encountered. - */ -int bstrncmp (const_bstring b0, const_bstring b1, int n) { -int i, v, m; - - if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || - b0->slen < 0 || b1->slen < 0) return SHRT_MIN; - m = n; - if (m > b0->slen) m = b0->slen; - if (m > b1->slen) m = b1->slen; - - if (b0->data != b1->data) { - for (i = 0; i < m; i ++) { - v = ((char) b0->data[i]) - ((char) b1->data[i]); - if (v != 0) return v; - if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; - } - } - - if (n == m || b0->slen == b1->slen) return BSTR_OK; - - if (b0->slen > m) return 1; - return -1; -} - -/* bstring bmidstr (const_bstring b, int left, int len) - * - * Create a bstring which is the substring of b starting from position left - * and running for a length len (clamped by the end of the bstring b.) If - * b is detectably invalid, then NULL is returned. The section described - * by (left, len) is clamped to the boundaries of b. - */ -bstring bmidstr (const_bstring b, int left, int len) { - - if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; - - if (left < 0) { - len += left; - left = 0; - } - - if (len > b->slen - left) len = b->slen - left; - - if (len <= 0) return bfromcstr (""); - return blk2bstr (b->data + left, len); -} - -/* int bdelete (bstring b, int pos, int len) - * - * Removes characters from pos to pos+len-1 inclusive and shifts the tail of - * the bstring starting from pos+len to pos. len must be positive for this - * call to have any effect. The section of the string described by (pos, - * len) is clamped to boundaries of the bstring b. - */ -int bdelete (bstring b, int pos, int len) { - /* Clamp to left side of bstring */ - if (pos < 0) { - len += pos; - pos = 0; - } - - if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || - b->mlen < b->slen || b->mlen <= 0) - return BSTR_ERR; - if (len > 0 && pos < b->slen) { - if (pos + len >= b->slen) { - b->slen = pos; - } else { - bBlockCopy ((char *) (b->data + pos), - (char *) (b->data + pos + len), - b->slen - (pos+len)); - b->slen -= len; - } - b->data[b->slen] = (unsigned char) '\0'; - } - return BSTR_OK; -} - -/* int bdestroy (bstring b) - * - * Free up the bstring. Note that if b is detectably invalid or not writable - * then no action is performed and BSTR_ERR is returned. Like a freed memory - * allocation, dereferences, writes or any other action on b after it has - * been bdestroyed is undefined. - */ -int bdestroy (bstring b) { - if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || - b->data == NULL) - return BSTR_ERR; - - bstr__free (b->data); - - /* In case there is any stale usage, there is one more chance to - notice this error. */ - - b->slen = -1; - b->mlen = -__LINE__; - b->data = NULL; - - bstr__free (b); - return BSTR_OK; -} - -/* int binstr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstr (const_bstring b1, int pos, const_bstring b2) { -int j, ii, ll, lf; -unsigned char * d0; -unsigned char c0; -register unsigned char * d1; -register unsigned char c1; -register int i; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* No space to find such a string? */ - if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return 0; - - i = pos; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - /* Peel off the b2->slen == 1 case */ - c0 = d0[0]; - if (1 == ll) { - for (;i < lf; i++) if (c0 == d1[i]) return i; - return BSTR_ERR; - } - - c1 = c0; - j = 0; - lf = b1->slen - 1; - - ii = -1; - if (i < lf) do { - /* Unrolled current character test */ - if (c1 != d1[i]) { - if (c1 != d1[1+i]) { - i += 2; - continue; - } - i++; - } - - /* Take note if this is the start of a potential match */ - if (0 == j) ii = i; - - /* Shift the test character down by one */ - j++; - i++; - - /* If this isn't past the last character continue */ - if (j < ll) { - c1 = d0[j]; - continue; - } - - N0:; - - /* If no characters mismatched, then we matched */ - if (i == ii+j) return ii; - - /* Shift back to the beginning */ - i -= j; - j = 0; - c1 = c0; - } while (i < lf); - - /* Deal with last case if unrolling caused a misalignment */ - if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; - - return BSTR_ERR; -} - -/* int binstrr (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward. If it is found then return with the first position where it is - * found, otherwise return BSTR_ERR. Note that this is just a brute force - * string searcher that does not attempt clever things like the Boyer-Moore - * search algorithm. Because of this there are many degenerate cases where - * this can take much longer than it needs to. - */ -int binstrr (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j]) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * forward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l, ll; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - l = b1->slen - b2->slen + 1; - - /* No space to find such a string? */ - if (l <= pos) return BSTR_ERR; - - /* An obvious alias case */ - if (b1->data == b2->data && pos == 0) return BSTR_OK; - - i = pos; - j = 0; - - d0 = b2->data; - d1 = b1->data; - ll = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= ll) return i; - } else { - i ++; - if (i >= l) break; - j=0; - } - } - - return BSTR_ERR; -} - -/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) - * - * Search for the bstring b2 in b1 starting from position pos, and searching - * backward but without regard to case. If it is found then return with the - * first position where it is found, otherwise return BSTR_ERR. Note that - * this is just a brute force string searcher that does not attempt clever - * things like the Boyer-Moore search algorithm. Because of this there are - * many degenerate cases where this can take much longer than it needs to. - */ -int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { -int j, i, l; -unsigned char * d0, * d1; - - if (b1 == NULL || b1->data == NULL || b1->slen < 0 || - b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; - if (b1->slen == pos && b2->slen == 0) return pos; - if (b1->slen < pos || pos < 0) return BSTR_ERR; - if (b2->slen == 0) return pos; - - /* Obvious alias case */ - if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; - - i = pos; - if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; - - /* If no space to find such a string then snap back */ - if (l + 1 <= i) i = l; - j = 0; - - d0 = b2->data; - d1 = b1->data; - l = b2->slen; - - for (;;) { - if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { - j ++; - if (j >= l) return i; - } else { - i --; - if (i < 0) break; - j=0; - } - } - - return BSTR_ERR; -} - - -/* int bstrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b forwards from the position pos - * (inclusive). - */ -int bstrchrp (const_bstring b, int c, int pos) { -unsigned char * p; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); - if (p) return (int) (p - b->data); - return BSTR_ERR; -} - -/* int bstrrchrp (const_bstring b, int c, int pos) - * - * Search for the character c in b backwards from the position pos in string - * (inclusive). - */ -int bstrrchrp (const_bstring b, int c, int pos) { -int i; - - if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; - for (i=pos; i >= 0; i--) { - if (b->data[i] == (unsigned char) c) return i; - } - return BSTR_ERR; -} - -#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) -#define LONG_LOG_BITS_QTY (3) -#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) -#define LONG_TYPE unsigned char - -#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) -struct charField { LONG_TYPE content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) -#define setInCharField(cf,idx) { \ - unsigned int c = (unsigned int) (idx); \ - (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ -} - -#else - -#define CFCLEN (1 << CHAR_BIT) -struct charField { unsigned char content[CFCLEN]; }; -#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) -#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 - -#endif - -/* Convert a bstring to charField */ -static int buildCharField (struct charField * cf, const_bstring b) { -int i; - if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; - memset ((void *) cf->content, 0, sizeof (struct charField)); - for (i=0; i < b->slen; i++) { - setInCharField (cf, b->data[i]); - } - return BSTR_OK; -} - -static void invertCharField (struct charField * cf) { -int i; - for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; -} - -/* Inner engine for binchr */ -static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { -int i; - for (i=pos; i < len; i++) { - unsigned char c = (unsigned char) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * one of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int binchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* Inner engine for binchrr */ -static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { -int i; - for (i=pos; i >= 0; i--) { - unsigned int c = (unsigned int) data[i]; - if (testInCharField (cf, c)) return i; - } - return BSTR_ERR; -} - -/* int binchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which one of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int binchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); - if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bninchr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the first position in b0 starting from pos or after, in which - * none of the characters in b1 is found and return it. If such a position - * does not exist in b0, then BSTR_ERR is returned. - */ -int bninchr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen <= pos) return BSTR_ERR; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrCF (b0->data, b0->slen, pos, &chrs); -} - -/* int bninchrr (const_bstring b0, int pos, const_bstring b1); - * - * Search for the last position in b0 no greater than pos, in which none of - * the characters in b1 is found and return it. If such a position does not - * exist in b0, then BSTR_ERR is returned. - */ -int bninchrr (const_bstring b0, int pos, const_bstring b1) { -struct charField chrs; - if (pos < 0 || b0 == NULL || b0->data == NULL || - b0->slen < pos) return BSTR_ERR; - if (pos == b0->slen) pos--; - if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; - invertCharField (&chrs); - return binchrrCF (b0->data, pos, &chrs); -} - -/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) - * - * Overwrite the string b0 starting at position pos with the string b1. If - * the position pos is past the end of b0, then the character "fill" is - * appended as necessary to make up the gap between the end of b0 and pos. - * If b1 is NULL, it behaves as if it were a 0-length string. - */ -int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { -int d, newlen; -ptrdiff_t pd; -bstring aux = (bstring) b1; - - if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || - b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; - if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; - - d = pos; - - /* Aliasing case */ - if (NULL != aux) { - if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { - if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; - } - d += aux->slen; - } - - /* Increase memory size if necessary */ - if (balloc (b0, d + 1) != BSTR_OK) { - if (aux != b1) bdestroy (aux); - return BSTR_ERR; - } - - newlen = b0->slen; - - /* Fill in "fill" character as necessary */ - if (pos > newlen) { - bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); - newlen = pos; - } - - /* Copy b1 to position pos in b0. */ - if (aux != NULL) { - bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); - if (aux != b1) bdestroy (aux); - } - - /* Indicate the potentially increased size of b0 */ - if (d > newlen) newlen = d; - - b0->slen = newlen; - b0->data[newlen] = (unsigned char) '\0'; - - return BSTR_OK; -} - -/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) - * - * Inserts the string b2 into b1 at position pos. If the position pos is - * past the end of b1, then the character "fill" is appended as necessary to - * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert - * does not allow b2 to be NULL. - */ -int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { -int d, l; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || - b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - /* Compute the two possible end pointers */ - d = b1->slen + aux->slen; - l = pos + aux->slen; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b1, l + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); - b1->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b1, d + 1) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - bBlockCopy (b1->data + l, b1->data + pos, d - l); - b1->slen = d; - } - bBlockCopy (b1->data + pos, aux->data, aux->slen); - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* int breplace (bstring b1, int pos, int len, bstring b2, - * unsigned char fill) - * - * Replace a section of a string from pos for a length len with the string b2. - * fill is used is pos > b1->slen. - */ -int breplace (bstring b1, int pos, int len, const_bstring b2, - unsigned char fill) { -int pl, ret; -ptrdiff_t pd; -bstring aux = (bstring) b2; - - if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || - b2 == NULL || b1->data == NULL || b2->data == NULL || - b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || - b1->mlen <= 0) return BSTR_ERR; - - /* Straddles the end? */ - if (pl >= b1->slen) { - if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; - if (pos + b2->slen < b1->slen) { - b1->slen = pos + b2->slen; - b1->data[b1->slen] = (unsigned char) '\0'; - } - return ret; - } - - /* Aliasing case */ - if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { - if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; - } - - if (aux->slen > len) { - if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { - if (aux != b2) bdestroy (aux); - return BSTR_ERR; - } - } - - if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); - bstr__memcpy (b1->data + pos, aux->data, aux->slen); - b1->slen += aux->slen - len; - b1->data[b1->slen] = (unsigned char) '\0'; - if (aux != b2) bdestroy (aux); - return BSTR_OK; -} - -/* - * findreplaceengine is used to implement bfindreplace and - * bfindreplacecaseless. It works by breaking the three cases of - * expansion, reduction and replacement, and solving each of these - * in the most efficient way possible. - */ - -typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); - -#define INITIAL_STATIC_FIND_INDEX_COUNT 32 - -static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { -int i, ret, slen, mlen, delta, acc; -int * d; -int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */ -ptrdiff_t pd; -bstring auxf = (bstring) find; -bstring auxr = (bstring) repl; - - if (b == NULL || b->data == NULL || find == NULL || - find->data == NULL || repl == NULL || repl->data == NULL || - pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || - b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; - if (pos > b->slen - find->slen) return BSTR_OK; - - /* Alias with find string */ - pd = (ptrdiff_t) (find->data - b->data); - if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; - } - - /* Alias with repl string */ - pd = (ptrdiff_t) (repl->data - b->data); - if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { - if (NULL == (auxr = bstrcpy (repl))) { - if (auxf != find) bdestroy (auxf); - return BSTR_ERR; - } - } - - delta = auxf->slen - auxr->slen; - - /* in-place replacement since find and replace strings are of equal - length */ - if (delta == 0) { - while ((pos = instr (b, pos, auxf)) >= 0) { - bstr__memcpy (b->data + pos, auxr->data, auxr->slen); - pos += auxf->slen; - } - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* shrinking replacement since auxf->slen > auxr->slen */ - if (delta > 0) { - acc = 0; - - while ((i = instr (b, pos, auxf)) >= 0) { - if (acc && i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - if (auxr->slen) - bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); - acc += delta; - pos = i + auxf->slen; - } - - if (acc) { - i = b->slen; - if (i > pos) - bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); - b->slen -= acc; - b->data[b->slen] = (unsigned char) '\0'; - } - - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return BSTR_OK; - } - - /* expanding replacement since find->slen < repl->slen. Its a lot - more complicated. This works by first finding all the matches and - storing them to a growable array, then doing at most one resize of - the destination bstring and then performing the direct memory transfers - of the string segment pieces to form the final result. The growable - array of matches uses a deferred doubling reallocing strategy. What - this means is that it starts as a reasonably fixed sized auto array in - the hopes that many if not most cases will never need to grow this - array. But it switches as soon as the bounds of the array will be - exceeded. An extra find result is always appended to this array that - corresponds to the end of the destination string, so slen is checked - against mlen - 1 rather than mlen before resizing. - */ - - mlen = INITIAL_STATIC_FIND_INDEX_COUNT; - d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ - acc = slen = 0; - - while ((pos = instr (b, pos, auxf)) >= 0) { - if (slen >= mlen - 1) { - int sl, *t; - - mlen += mlen; - sl = sizeof (int *) * mlen; - if (static_d == d) d = NULL; /* static_d cannot be realloced */ - if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { - ret = BSTR_ERR; - goto done; - } - if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); - d = t; - } - d[slen] = pos; - slen++; - acc -= delta; - pos += auxf->slen; - if (pos < 0 || acc < 0) { - ret = BSTR_ERR; - goto done; - } - } - - /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ - d[slen] = b->slen; - - if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { - b->slen += acc; - for (i = slen-1; i >= 0; i--) { - int s, l; - s = d[i] + auxf->slen; - l = d[i+1] - s; /* d[slen] may be accessed here. */ - if (l) { - bstr__memmove (b->data + s + acc, b->data + s, l); - } - if (auxr->slen) { - bstr__memmove (b->data + s + acc - auxr->slen, - auxr->data, auxr->slen); - } - acc += delta; - } - b->data[b->slen] = (unsigned char) '\0'; - } - - done:; - if (static_d == d) d = NULL; - bstr__free (d); - if (auxf != find) bdestroy (auxf); - if (auxr != repl) bdestroy (auxr); - return ret; -} - -/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string with a replace string after a - * given point in a bstring. - */ -int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstr); -} - -/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, - * int pos) - * - * Replace all occurrences of a find string, ignoring case, with a replace - * string after a given point in a bstring. - */ -int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { - return findreplaceengine (b, find, repl, pos, binstrcaseless); -} - -/* int binsertch (bstring b, int pos, int len, unsigned char fill) - * - * Inserts the character fill repeatedly into b at position pos for a - * length len. If the position pos is past the end of b, then the - * character "fill" is appended as necessary to make up the gap between the - * end of b and the position pos + len. - */ -int binsertch (bstring b, int pos, int len, unsigned char fill) { -int d, l, i; - - if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || len < 0) return BSTR_ERR; - - /* Compute the two possible end pointers */ - d = b->slen + len; - l = pos + len; - if ((d|l) < 0) return BSTR_ERR; - - if (l > d) { - /* Inserting past the end of the string */ - if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; - pos = b->slen; - b->slen = l; - } else { - /* Inserting in the middle of the string */ - if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; - for (i = d - 1; i >= l; i--) { - b->data[i] = b->data[i - len]; - } - b->slen = d; - } - - for (i=pos; i < l; i++) b->data[i] = fill; - b->data[b->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bpattern (bstring b, int len) - * - * Replicate the bstring, b in place, end to end repeatedly until it - * surpasses len characters, then chop the result to exactly len characters. - * This function operates in-place. The function will return with BSTR_ERR - * if b is NULL or of length 0, otherwise BSTR_OK is returned. - */ -int bpattern (bstring b, int len) { -int i, d; - - d = blength (b); - if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; - if (len > 0) { - if (d == 1) return bsetstr (b, len, NULL, b->data[0]); - for (i = d; i < len; i++) b->data[i] = b->data[i - d]; - } - b->data[len] = (unsigned char) '\0'; - b->slen = len; - return BSTR_OK; -} - -#define BS_BUFF_SZ (1024) - -/* int breada (bstring b, bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to concatenate to the - * bstring b the entire contents of file-like source data in a roughly - * efficient way. - */ -int breada (bstring b, bNread readPtr, void * parm) { -int i, l, n; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; - - i = b->slen; - for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { - if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; - l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); - i += l; - b->slen = i; - if (i < n) break; - } - - b->data[i] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* bstring bread (bNread readPtr, void * parm) - * - * Use a finite buffer fread-like function readPtr to create a bstring - * filled with the entire contents of file-like source data in a roughly - * efficient way. - */ -bstring bread (bNread readPtr, void * parm) { -bstring buff; - - if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { - bdestroy (buff); - return NULL; - } - return buff; -} - -/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result in b. If there is an empty partial - * result, 1 is returned. If no characters are read, or there is some other - * detectable error, BSTR_ERR is returned. - */ -int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = 0; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated to the end of the - * bstring b. The stream read is terminated by the passed in terminator - * parameter. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * function returns with a partial result concatentated to b. If there is - * an empty partial result, 1 is returned. If no characters are read, or - * there is some other detectable error, BSTR_ERR is returned. - */ -int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { -int c, d, e; - - if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || - b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; - d = b->slen; - e = b->mlen - 2; - - while ((c = getcPtr (parm)) >= 0) { - if (d > e) { - b->slen = d; - if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; - e = b->mlen - 2; - } - b->data[d] = (unsigned char) c; - d++; - if (c == terminator) break; - } - - b->data[d] = (unsigned char) '\0'; - b->slen = d; - - return d == 0 && c < 0; -} - -/* bstring bgets (bNgetc getcPtr, void * parm, char terminator) - * - * Use an fgetc-like single character stream reading function (getcPtr) to - * obtain a sequence of characters which are concatenated into a bstring. - * The stream read is terminated by the passed in terminator function. - * - * If getcPtr returns with a negative number, or the terminator character - * (which is appended) is read, then the stream reading is halted and the - * result obtained thus far is returned. If no characters are read, or - * there is some other detectable error, NULL is returned. - */ -bstring bgets (bNgetc getcPtr, void * parm, char terminator) { -bstring buff; - - if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { - bdestroy (buff); - buff = NULL; - } - return buff; -} - -struct bStream { - bstring buff; /* Buffer for over-reads */ - void * parm; /* The stream handle for core stream */ - bNread readFnPtr; /* fread compatible fnptr for core stream */ - int isEOF; /* track file's EOF state */ - int maxBuffSz; -}; - -/* struct bStream * bsopen (bNread readPtr, void * parm) - * - * Wrap a given open stream (described by a fread compatible function - * pointer and stream handle) into an open bStream suitable for the bstring - * library streaming functions. - */ -struct bStream * bsopen (bNread readPtr, void * parm) { -struct bStream * s; - - if (readPtr == NULL) return NULL; - s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); - if (s == NULL) return NULL; - s->parm = parm; - s->buff = bfromcstr (""); - s->readFnPtr = readPtr; - s->maxBuffSz = BS_BUFF_SZ; - s->isEOF = 0; - return s; -} - -/* int bsbufflength (struct bStream * s, int sz) - * - * Set the length of the buffer used by the bStream. If sz is zero, the - * length is not set. This function returns with the previous length. - */ -int bsbufflength (struct bStream * s, int sz) { -int oldSz; - if (s == NULL || sz < 0) return BSTR_ERR; - oldSz = s->maxBuffSz; - if (sz > 0) s->maxBuffSz = sz; - return oldSz; -} - -int bseof (const struct bStream * s) { - if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; - return s->isEOF && (s->buff->slen == 0); -} - -/* void * bsclose (struct bStream * s) - * - * Close the bStream, and return the handle to the stream that was originally - * used to open the given stream. - */ -void * bsclose (struct bStream * s) { -void * parm; - if (s == NULL) return NULL; - s->readFnPtr = NULL; - if (s->buff) bdestroy (s->buff); - s->buff = NULL; - parm = s->parm; - s->parm = NULL; - s->isEOF = 1; - bstr__free (s); - return parm; -} - -/* int bsreadlna (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadlna (bstring r, struct bStream * s, char terminator) { -int i, l, ret, rlo; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || - r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - /* First check if the current buffer holds the terminator */ - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - b[l] = terminator; /* Set sentinel */ - for (i=0; b[i] != terminator; i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { -int i, l, ret, rlo; -unsigned char * b; -struct tagbstring x; -struct charField cf; - - if (s == NULL || s->buff == NULL || r == NULL || term == NULL || - term->data == NULL || r->mlen <= 0 || r->slen < 0 || - r->mlen < r->slen) return BSTR_ERR; - if (term->slen == 1) return bsreadlna (r, s, term->data[0]); - if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; - - l = s->buff->slen; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) s->buff->data; - x.data = b; - - /* First check if the current buffer holds the terminator */ - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) { - x.slen = i + 1; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); - return BSTR_OK; - } - - rlo = r->slen; - - /* If not then just concatenate the entire buffer to the output */ - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; - - /* Perform direct in-place reads into the destination to allow for - the minimum of data-copies */ - for (;;) { - if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; - b = (unsigned char *) (r->data + r->slen); - l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); - if (l <= 0) { - r->data[r->slen] = (unsigned char) '\0'; - s->buff->slen = 0; - s->isEOF = 1; - /* If nothing was read return with an error message */ - return BSTR_ERR & -(r->slen == rlo); - } - - b[l] = term->data[0]; /* Set sentinel */ - for (i=0; !testInCharField (&cf, b[i]); i++) ; - if (i < l) break; - r->slen += l; - } - - /* Terminator found, push over-read back to buffer */ - i++; - r->slen += i; - s->buff->slen = l - i; - bstr__memcpy (s->buff->data, b + i, l - i); - r->data[r->slen] = (unsigned char) '\0'; - return BSTR_OK; -} - -/* int bsreada (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsreada (bstring r, struct bStream * s, int n) { -int l, ret, orslen; -char * b; -struct tagbstring x; - - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; - - n += r->slen; - if (n <= 0) return BSTR_ERR; - - l = s->buff->slen; - - orslen = r->slen; - - if (0 == l) { - if (s->isEOF) return BSTR_ERR; - if (r->mlen > n) { - l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); - if (0 >= l || l > n - r->slen) { - s->isEOF = 1; - return BSTR_ERR; - } - r->slen += l; - r->data[r->slen] = (unsigned char) '\0'; - return 0; - } - } - - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - b = (char *) s->buff->data; - x.data = (unsigned char *) b; - - do { - if (l + r->slen >= n) { - x.slen = n - r->slen; - ret = bconcat (r, &x); - s->buff->slen = l; - if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); - return BSTR_ERR & -(r->slen == orslen); - } - - x.slen = l; - if (BSTR_OK != bconcat (r, &x)) break; - - l = n - r->slen; - if (l > s->maxBuffSz) l = s->maxBuffSz; - - l = (int) s->readFnPtr (b, 1, l, s->parm); - - } while (l > 0); - if (l < 0) l = 0; - if (l == 0) s->isEOF = 1; - s->buff->slen = l; - return BSTR_ERR & -(r->slen == orslen); -} - -/* int bsreadln (bstring r, struct bStream * s, char terminator) - * - * Read a bstring terminated by the terminator character or the end of the - * stream from the bStream (s) and return it into the parameter r. This - * function may read additional characters from the core stream that are not - * returned, but will be retained for subsequent read operations. - */ -int bsreadln (bstring r, struct bStream * s, char terminator) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) - return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlna (r, s, terminator); -} - -/* int bsreadlns (bstring r, struct bStream * s, bstring term) - * - * Read a bstring terminated by any character in the term string or the end - * of the stream from the bStream (s) and return it into the parameter r. - * This function may read additional characters from the core stream that - * are not returned, but will be retained for subsequent read operations. - */ -int bsreadlns (bstring r, struct bStream * s, const_bstring term) { - if (s == NULL || s->buff == NULL || r == NULL || term == NULL - || term->data == NULL || r->mlen <= 0) return BSTR_ERR; - if (term->slen == 1) return bsreadln (r, s, term->data[0]); - if (term->slen < 1) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreadlnsa (r, s, term); -} - -/* int bsread (bstring r, struct bStream * s, int n) - * - * Read a bstring of length n (or, if it is fewer, as many bytes as is - * remaining) from the bStream. This function may read additional - * characters from the core stream that are not returned, but will be - * retained for subsequent read operations. This function will not read - * additional characters from the core stream beyond virtual stream pointer. - */ -int bsread (bstring r, struct bStream * s, int n) { - if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 - || n <= 0) return BSTR_ERR; - if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; - r->slen = 0; - return bsreada (r, s, n); -} - -/* int bsunread (struct bStream * s, const_bstring b) - * - * Insert a bstring into the bStream at the current position. These - * characters will be read prior to those that actually come from the core - * stream. - */ -int bsunread (struct bStream * s, const_bstring b) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return binsert (s->buff, 0, b, (unsigned char) '?'); -} - -/* int bspeek (bstring r, const struct bStream * s) - * - * Return the currently buffered characters from the bStream that will be - * read prior to reads from the core stream. - */ -int bspeek (bstring r, const struct bStream * s) { - if (s == NULL || s->buff == NULL) return BSTR_ERR; - return bassign (r, s->buff); -} - -/* bstring bjoin (const struct bstrList * bl, const_bstring sep); - * - * Join the entries of a bstrList into one bstring by sequentially - * concatenating them with the sep string in between. If there is an error - * NULL is returned, otherwise a bstring with the correct result is returned. - */ -bstring bjoin (const struct bstrList * bl, const_bstring sep) { -bstring b; -int i, c, v; - - if (bl == NULL || bl->qty < 0) return NULL; - if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; - - for (i = 0, c = 1; i < bl->qty; i++) { - v = bl->entry[i]->slen; - if (v < 0) return NULL; /* Invalid input */ - c += v; - if (c < 0) return NULL; /* Wrap around ?? */ - } - - if (sep != NULL) c += (bl->qty - 1) * sep->slen; - - b = (bstring) bstr__alloc (sizeof (struct tagbstring)); - if (NULL == b) return NULL; /* Out of memory */ - b->data = (unsigned char *) bstr__alloc (c); - if (b->data == NULL) { - bstr__free (b); - return NULL; - } - - b->mlen = c; - b->slen = c-1; - - for (i = 0, c = 0; i < bl->qty; i++) { - if (i > 0 && sep != NULL) { - bstr__memcpy (b->data + c, sep->data, sep->slen); - c += sep->slen; - } - v = bl->entry[i]->slen; - bstr__memcpy (b->data + c, bl->entry[i]->data, v); - c += v; - } - b->data[c] = (unsigned char) '\0'; - return b; -} - -#define BSSSC_BUFF_LEN (256) - -/* int bssplitscb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by any of the characters in splitStr. An empty splitStr causes - * the whole stream to be iterated once. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -struct charField chrs; -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; - if ((ret = cb (parm, 0, buff)) > 0) - ret = 0; - } else { - buildCharField (&chrs, splitStr); - ret = p = i = 0; - for (;;) { - if (i >= buff->slen) { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (i >= buff->slen) { - if (0 < (ret = cb (parm, p, buff))) ret = 0; - break; - } - } - if (testInCharField (&chrs, buff->data[i])) { - struct tagbstring t; - unsigned char c; - - blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); - if ((ret = bsunread (s, &t)) < 0) break; - buff->slen = i; - c = buff->data[i]; - buff->data[i] = (unsigned char) '\0'; - if ((ret = cb (parm, p, buff)) < 0) break; - buff->data[i] = c; - buff->slen = 0; - p += i + 1; - i = -1; - } - i++; - } - } - - bdestroy (buff); - return ret; -} - -/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, - * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) - * - * Iterate the set of disjoint sequential substrings read from a stream - * divided by the entire substring splitStr. An empty splitStr causes - * each character of the stream to be iterated. - * - * Note: At the point of calling the cb function, the bStream pointer is - * pointed exactly at the position right after having read the split - * character. The cb function can act on the stream by causing the bStream - * pointer to move, and bssplitscb will continue by starting the next split - * at the position of the pointer after the return from cb. - * - * However, if the cb causes the bStream s to be destroyed then the cb must - * return with a negative value, otherwise bssplitscb will continue in an - * undefined manner. - */ -int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { -bstring buff; -int i, p, ret; - - if (cb == NULL || s == NULL || s->readFnPtr == NULL - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); - - if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; - - if (splitStr->slen == 0) { - for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { - if ((ret = cb (parm, 0, buff)) < 0) { - bdestroy (buff); - return ret; - } - buff->slen = 0; - } - return BSTR_OK; - } else { - ret = p = i = 0; - for (i=p=0;;) { - if ((ret = binstr (buff, 0, splitStr)) >= 0) { - struct tagbstring t; - blk2tbstr (t, buff->data, ret); - i = ret + splitStr->slen; - if ((ret = cb (parm, p, &t)) < 0) break; - p += i; - bdelete (buff, 0, i); - } else { - bsreada (buff, s, BSSSC_BUFF_LEN); - if (bseof (s)) { - if ((ret = cb (parm, p, buff)) > 0) ret = 0; - break; - } - } - } - } - - bdestroy (buff); - return ret; -} - -/* int bstrListCreate (void) - * - * Create a bstrList. - */ -struct bstrList * bstrListCreate (void) { -struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (sl) { - sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); - if (!sl->entry) { - bstr__free (sl); - sl = NULL; - } else { - sl->qty = 0; - sl->mlen = 1; - } - } - return sl; -} - -/* int bstrListDestroy (struct bstrList * sl) - * - * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. - */ -int bstrListDestroy (struct bstrList * sl) { -int i; - if (sl == NULL || sl->qty < 0) return BSTR_ERR; - for (i=0; i < sl->qty; i++) { - if (sl->entry[i]) { - bdestroy (sl->entry[i]); - sl->entry[i] = NULL; - } - } - sl->qty = -1; - sl->mlen = -1; - bstr__free (sl->entry); - sl->entry = NULL; - bstr__free (sl); - return BSTR_OK; -} - -/* int bstrListAlloc (struct bstrList * sl, int msz) - * - * Ensure that there is memory for at least msz number of entries for the - * list. - */ -int bstrListAlloc (struct bstrList * sl, int msz) { -bstring * l; -int smsz; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (sl->mlen >= msz) return BSTR_OK; - smsz = snapUpSize (msz); - nsz = ((size_t) smsz) * sizeof (bstring); - if (nsz < (size_t) smsz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) { - smsz = msz; - nsz = ((size_t) smsz) * sizeof (bstring); - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - } - sl->mlen = smsz; - sl->entry = l; - return BSTR_OK; -} - -/* int bstrListAllocMin (struct bstrList * sl, int msz) - * - * Try to allocate the minimum amount of memory for the list to include at - * least msz entries or sl->qty whichever is greater. - */ -int bstrListAllocMin (struct bstrList * sl, int msz) { -bstring * l; -size_t nsz; - if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; - if (msz < sl->qty) msz = sl->qty; - if (sl->mlen == msz) return BSTR_OK; - nsz = ((size_t) msz) * sizeof (bstring); - if (nsz < (size_t) msz) return BSTR_ERR; - l = (bstring *) bstr__realloc (sl->entry, nsz); - if (!l) return BSTR_ERR; - sl->mlen = msz; - sl->entry = l; - return BSTR_OK; -} - -/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * character in splitChar. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitcb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitcb will continue in an undefined manner. - */ -int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) - return BSTR_ERR; - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (str->data[i] == splitChar) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by any - * of the characters in splitStr. An empty splitStr causes the whole str to - * be iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitscb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -struct charField chrs; -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - if (splitStr->slen == 0) { - if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; - return ret; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - buildCharField (&chrs, splitStr); - - p = pos; - do { - for (i=p; i < str->slen; i++) { - if (testInCharField (&chrs, str->data[i])) break; - } - if ((ret = cb (parm, p, i - p)) < 0) return ret; - p = i + 1; - } while (p <= str->slen); - return BSTR_OK; -} - -/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - * int (* cb) (void * parm, int ofs, int len), void * parm) - * - * Iterate the set of disjoint sequential substrings over str divided by the - * substring splitStr. An empty splitStr causes the whole str to be - * iterated once. - * - * Note: Non-destructive modification of str from within the cb function - * while performing this split is not undefined. bsplitstrcb behaves in - * sequential lock step with calls to cb. I.e., after returning from a cb - * that return a non-negative integer, bsplitscb continues from the position - * 1 character after the last detected split character and it will halt - * immediately if the length of str falls below this point. However, if the - * cb function destroys str, then it *must* return with a negative value, - * otherwise bsplitscb will continue in an undefined manner. - */ -int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm) { -int i, p, ret; - - if (cb == NULL || str == NULL || pos < 0 || pos > str->slen - || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; - - if (0 == splitStr->slen) { - for (i=pos; i < str->slen; i++) { - if ((ret = cb (parm, i, 1)) < 0) return ret; - } - return BSTR_OK; - } - - if (splitStr->slen == 1) - return bsplitcb (str, splitStr->data[0], pos, cb, parm); - - for (i=p=pos; i <= str->slen - splitStr->slen; i++) { - if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { - if ((ret = cb (parm, p, i - p)) < 0) return ret; - i += splitStr->slen; - p = i; - } - } - if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; - return BSTR_OK; -} - -struct genBstrList { - bstring b; - struct bstrList * bl; -}; - -static int bscb (void * parm, int ofs, int len) { -struct genBstrList * g = (struct genBstrList *) parm; - if (g->bl->qty >= g->bl->mlen) { - int mlen = g->bl->mlen * 2; - bstring * tbl; - - while (g->bl->qty >= mlen) { - if (mlen < g->bl->mlen) return BSTR_ERR; - mlen += mlen; - } - - tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); - if (tbl == NULL) return BSTR_ERR; - - g->bl->entry = tbl; - g->bl->mlen = mlen; - } - - g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); - g->bl->qty++; - return BSTR_OK; -} - -/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) - * - * Create an array of sequential substrings from str divided by the character - * splitChar. - */ -struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) - * - * Create an array of sequential substrings from str divided by the entire - * substring splitStr. - */ -struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if (str == NULL || str->data == NULL || str->slen < 0) return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - - g.b = (bstring) str; - g.bl->qty = 0; - if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -/* struct bstrList * bsplits (const_bstring str, bstring splitStr) - * - * Create an array of sequential substrings from str divided by any of the - * characters in splitStr. An empty splitStr causes a single entry bstrList - * containing a copy of str to be returned. - */ -struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { -struct genBstrList g; - - if ( str == NULL || str->slen < 0 || str->data == NULL || - splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) - return NULL; - - g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); - if (g.bl == NULL) return NULL; - g.bl->mlen = 4; - g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); - if (NULL == g.bl->entry) { - bstr__free (g.bl); - return NULL; - } - g.b = (bstring) str; - g.bl->qty = 0; - - if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { - bstrListDestroy (g.bl); - return NULL; - } - return g.bl; -} - -#if defined (__TURBOC__) && !defined (__BORLANDC__) -# ifndef BSTRLIB_NOVSNP -# define BSTRLIB_NOVSNP -# endif -#endif - -/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ -#if defined(__WATCOMC__) || defined(_MSC_VER) -#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} -#else -#ifdef BSTRLIB_NOVSNP -/* This is just a hack. If you are using a system without a vsnprintf, it is - not recommended that bformat be used at all. */ -#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} -#define START_VSNBUFF (256) -#else - -#ifdef __GNUC__ -/* Something is making gcc complain about this prototype not being here, so - I've just gone ahead and put it in. */ -//extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); -#endif - -#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} -#endif -#endif - -#if !defined (BSTRLIB_NOVSNP) - -#ifndef START_VSNBUFF -#define START_VSNBUFF (16) -#endif - -/* On IRIX vsnprintf returns n-1 when the operation would overflow the target - buffer, WATCOM and MSVC both return -1, while C99 requires that the - returned value be exactly what the length would be if the buffer would be - large enough. This leads to the idea that if the return value is larger - than n, then changing n to the return value will reduce the number of - iterations required. */ - -/* int bformata (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it appends the results to - * a bstring which contains what would have been output. Note that if there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bformata (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bconcat (b, buff); - bdestroy (buff); - return r; -} - -/* int bassignformat (bstring b, const char * fmt, ...) - * - * After the first parameter, it takes the same parameters as printf (), but - * rather than outputting results to stdio, it outputs the results to - * the bstring parameter b. Note that if there is an early generation of a - * '\0' character, the bstring will be truncated to this end point. - */ -int bassignformat (bstring b, const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 - || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return BSTR_ERR; - } - } - - r = bassign (b, buff); - bdestroy (buff); - return r; -} - -/* bstring bformat (const char * fmt, ...) - * - * Takes the same parameters as printf (), but rather than outputting results - * to stdio, it forms a bstring which contains what would have been output. - * Note that if there is an early generation of a '\0' character, the - * bstring will be truncated to this end point. - */ -bstring bformat (const char * fmt, ...) { -va_list arglist; -bstring buff; -int n, r; - - if (fmt == NULL) return NULL; - - /* Since the length is not determinable beforehand, a search is - performed using the truncating "vsnprintf" call (to avoid buffer - overflows) on increasing potential sizes for the output result. */ - - if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) { - n = 1; - if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; - } - - for (;;) { - va_start (arglist, fmt); - exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); - va_end (arglist); - - buff->data[n] = (unsigned char) '\0'; - buff->slen = (int) (strlen) ((char *) buff->data); - - if (buff->slen < n) break; - - if (r > n) n = r; else n += n; - - if (BSTR_OK != balloc (buff, n + 2)) { - bdestroy (buff); - return NULL; - } - } - - return buff; -} - -/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) - * - * The bvcformata function formats data under control of the format control - * string fmt and attempts to append the result to b. The fmt parameter is - * the same as that of the printf function. The variable argument list is - * replaced with arglist, which has been initialized by the va_start macro. - * The size of the appended output is upper bounded by count. If the - * required output exceeds count, the string b is not augmented with any - * contents and a value below BSTR_ERR is returned. If a value below -count - * is returned then it is recommended that the negative of this value be - * used as an update to the count in a subsequent pass. On other errors, - * such as running out of memory, parameter errors or numeric wrap around - * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully - * generated and appended to b. - * - * Note: There is no sanity checking of arglist, and this function is - * destructive of the contents of b from the b->slen point onward. If there - * is an early generation of a '\0' character, the bstring will be truncated - * to this end point. - */ -int bvcformata (bstring b, int count, const char * fmt, va_list arg) { -int n, r, l; - - if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL - || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; - - if (count > (n = b->slen + count) + 2) return BSTR_ERR; - if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; - - exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); - - /* Did the operation complete successfully within bounds? */ - for (l = b->slen; l <= n; l++) { - if ('\0' == b->data[l]) { - b->slen = l; - return BSTR_OK; - } - } - - /* Abort, since the buffer was not large enough. The return value - tries to help set what the retry length should be. */ - - b->data[b->slen] = '\0'; - if (r > count + 1) { /* Does r specify a particular target length? */ - n = r; - } else { - n = count + count; /* If not, just double the size of count */ - if (count > n) n = INT_MAX; - } - n = -n; - - if (n > BSTR_ERR-1) n = BSTR_ERR-1; - return n; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h deleted file mode 100644 index edf8c00fc6..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * This source file is part of the bstring string library. This code was - * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause - * BSD open source license or GPL v2.0. Refer to the accompanying documentation - * for details on usage and license. - */ -// Modifications copyright Amazon.com, Inc. or its affiliates - -/* - * bstrlib.h - * - * This file is the header file for the core module for implementing the - * bstring functions. - */ - -#ifndef BSTRLIB_INCLUDE -#define BSTRLIB_INCLUDE - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdarg.h> -#include <string.h> -#include <limits.h> -#include <ctype.h> - -#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) -# if defined (__TURBOC__) && !defined (__BORLANDC__) -# define BSTRLIB_NOVSNP -# endif -#endif - -#define BSTR_ERR (-1) -#define BSTR_OK (0) -#define BSTR_BS_BUFF_LENGTH_GET (0) - -typedef struct tagbstring * bstring; -typedef const struct tagbstring * const_bstring; - -/* Copy functions */ -#define cstr2bstr bfromcstr -extern bstring bfromcstr (const char * str); -extern bstring bfromcstralloc (int mlen, const char * str); -extern bstring blk2bstr (const void * blk, int len); -extern char * bstr2cstr (const_bstring s, char z); -extern int bcstrfree (char * s); -extern bstring bstrcpy (const_bstring b1); -extern int bassign (bstring a, const_bstring b); -extern int bassignmidstr (bstring a, const_bstring b, int left, int len); -extern int bassigncstr (bstring a, const char * str); -extern int bassignblk (bstring a, const void * s, int len); - -/* Destroy function */ -extern int bdestroy (bstring b); - -/* Space allocation hinting functions */ -extern int balloc (bstring s, int len); -extern int ballocmin (bstring b, int len); - -/* Substring extraction */ -extern bstring bmidstr (const_bstring b, int left, int len); - -/* Various standard manipulations */ -extern int bconcat (bstring b0, const_bstring b1); -extern int bconchar (bstring b0, char c); -extern int bcatcstr (bstring b, const char * s); -extern int bcatblk (bstring b, const void * s, int len); -extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); -extern int binsertch (bstring s1, int pos, int len, unsigned char fill); -extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); -extern int bdelete (bstring s1, int pos, int len); -extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); -extern int btrunc (bstring b, int n); - -/* Scan/search functions */ -extern int bstricmp (const_bstring b0, const_bstring b1); -extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); -extern int biseqcaseless (const_bstring b0, const_bstring b1); -extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); -extern int biseq (const_bstring b0, const_bstring b1); -extern int bisstemeqblk (const_bstring b0, const void * blk, int len); -extern int biseqcstr (const_bstring b, const char * s); -extern int biseqcstrcaseless (const_bstring b, const char * s); -extern int bstrcmp (const_bstring b0, const_bstring b1); -extern int bstrncmp (const_bstring b0, const_bstring b1, int n); -extern int binstr (const_bstring s1, int pos, const_bstring s2); -extern int binstrr (const_bstring s1, int pos, const_bstring s2); -extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); -extern int bstrchrp (const_bstring b, int c, int pos); -extern int bstrrchrp (const_bstring b, int c, int pos); -#define bstrchr(b,c) bstrchrp ((b), (c), 0) -#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) -extern int binchr (const_bstring b0, int pos, const_bstring b1); -extern int binchrr (const_bstring b0, int pos, const_bstring b1); -extern int bninchr (const_bstring b0, int pos, const_bstring b1); -extern int bninchrr (const_bstring b0, int pos, const_bstring b1); -extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); -extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); - -/* List of string container functions */ -struct bstrList { - int qty, mlen; - bstring * entry; -}; -extern struct bstrList * bstrListCreate (void); -extern int bstrListDestroy (struct bstrList * sl); -extern int bstrListAlloc (struct bstrList * sl, int msz); -extern int bstrListAllocMin (struct bstrList * sl, int msz); - -/* String split and join functions */ -extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); -extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); -extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); -extern bstring bjoin (const struct bstrList * bl, const_bstring sep); -extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); -extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - -/* Miscellaneous functions */ -extern int bpattern (bstring b, int len); -extern int btoupper (bstring b); -extern int btolower (bstring b); -extern int bltrimws (bstring b); -extern int brtrimws (bstring b); -extern int btrimws (bstring b); - -/* <*>printf format functions */ -#if !defined (BSTRLIB_NOVSNP) -extern bstring bformat (const char * fmt, ...); -extern int bformata (bstring b, const char * fmt, ...); -extern int bassignformat (bstring b, const char * fmt, ...); -extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); - -#define bvformata(ret, b, fmt, lastarg) { \ -bstring bstrtmp_b = (b); \ -const char * bstrtmp_fmt = (fmt); \ -int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ - for (;;) { \ - va_list bstrtmp_arglist; \ - va_start (bstrtmp_arglist, lastarg); \ - bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ - va_end (bstrtmp_arglist); \ - if (bstrtmp_r >= 0) { /* Everything went ok */ \ - bstrtmp_r = BSTR_OK; \ - break; \ - } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ - bstrtmp_r = BSTR_ERR; \ - break; \ - } \ - bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ - } \ - ret = bstrtmp_r; \ -} - -#endif - -typedef int (*bNgetc) (void *parm); -typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); - -/* Input functions */ -extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); -extern bstring bread (bNread readPtr, void * parm); -extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); -extern int breada (bstring b, bNread readPtr, void * parm); - -/* Stream functions */ -extern struct bStream * bsopen (bNread readPtr, void * parm); -extern void * bsclose (struct bStream * s); -extern int bsbufflength (struct bStream * s, int sz); -extern int bsreadln (bstring b, struct bStream * s, char terminator); -extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); -extern int bsread (bstring b, struct bStream * s, int n); -extern int bsreadlna (bstring b, struct bStream * s, char terminator); -extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); -extern int bsreada (bstring b, struct bStream * s, int n); -extern int bsunread (struct bStream * s, const_bstring b); -extern int bspeek (bstring r, const struct bStream * s); -extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); -extern int bseof (const struct bStream * s); - -struct tagbstring { - int mlen; - int slen; - unsigned char * data; -}; - -/* Accessor macros */ -#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) -#define blength(b) (blengthe ((b), 0)) -#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) -#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) -#define bdatae(b, e) (bdataofse (b, 0, e)) -#define bdata(b) (bdataofs (b, 0)) -#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) -#define bchar(b, p) bchare ((b), (p), '\0') - -/* Static constant string initialization macro */ -#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} -#if defined(_MSC_VER) -/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ -# define bsStatic(q) bsStaticMlen(q,-32) -#endif -#ifndef bsStatic -# define bsStatic(q) bsStaticMlen(q,-__LINE__) -#endif - -/* Static constant block parameter pair */ -#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) - -/* Reference building macros */ -#define cstr2tbstr btfromcstr -#define btfromcstr(t,s) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ - (t).mlen = -1; \ -} -#define blk2tbstr(t,s,l) { \ - (t).data = (unsigned char *) (s); \ - (t).slen = l; \ - (t).mlen = -1; \ -} -#define btfromblk(t,s,l) blk2tbstr(t,s,l) -#define bmid2tbstr(t,b,p,l) { \ - const_bstring bstrtmp_s = (b); \ - if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ - int bstrtmp_left = (p); \ - int bstrtmp_len = (l); \ - if (bstrtmp_left < 0) { \ - bstrtmp_len += bstrtmp_left; \ - bstrtmp_left = 0; \ - } \ - if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ - bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ - if (bstrtmp_len <= 0) { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } else { \ - (t).data = bstrtmp_s->data + bstrtmp_left; \ - (t).slen = bstrtmp_len; \ - } \ - } else { \ - (t).data = (unsigned char *)""; \ - (t).slen = 0; \ - } \ - (t).mlen = -__LINE__; \ -} -#define btfromblkltrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l); \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} -#define btfromblkrtrimws(t,s,l) { \ - int bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_len >= 0; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s; \ - (t).slen = bstrtmp_len + 1; \ - (t).mlen = -__LINE__; \ -} -#define btfromblktrimws(t,s,l) { \ - int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ - unsigned char * bstrtmp_s = (s); \ - if (bstrtmp_s && bstrtmp_len >= 0) { \ - for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ - if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ - } \ - for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ - if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ - } \ - } \ - (t).data = bstrtmp_s + bstrtmp_idx; \ - (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ - (t).mlen = -__LINE__; \ -} - -/* Write protection macros */ -#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } -#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } -#define biswriteprotected(t) ((t).mlen <= 0) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt deleted file mode 100644 index 8ebb188853..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt +++ /dev/null @@ -1,3201 +0,0 @@ -Better String library ---------------------- - -by Paul Hsieh - -The bstring library is an attempt to provide improved string processing -functionality to the C and C++ language. At the heart of the bstring library -(Bstrlib for short) is the management of "bstring"s which are a significant -improvement over '\0' terminated char buffers. - -=============================================================================== - -Motivation ----------- - -The standard C string library has serious problems: - - 1) Its use of '\0' to denote the end of the string means knowing a - string's length is O(n) when it could be O(1). - 2) It imposes an interpretation for the character value '\0'. - 3) gets() always exposes the application to a buffer overflow. - 4) strtok() modifies the string its parsing and thus may not be usable in - programs which are re-entrant or multithreaded. - 5) fgets has the unusual semantic of ignoring '\0's that occur before - '\n's are consumed. - 6) There is no memory management, and actions performed such as strcpy, - strcat and sprintf are common places for buffer overflows. - 7) strncpy() doesn't '\0' terminate the destination in some cases. - 8) Passing NULL to C library string functions causes an undefined NULL - pointer access. - 9) Parameter aliasing (overlapping, or self-referencing parameters) - within most C library functions has undefined behavior. - 10) Many C library string function calls take integer parameters with - restricted legal ranges. Parameters passed outside these ranges are - not typically detected and cause undefined behavior. - -So the desire is to create an alternative string library that does not suffer -from the above problems and adds in the following functionality: - - 1) Incorporate string functionality seen from other languages. - a) MID$() - from BASIC - b) split()/join() - from Python - c) string/char x n - from Perl - 2) Implement analogs to functions that combine stream IO and char buffers - without creating a dependency on stream IO functionality. - 3) Implement the basic text editor-style functions insert, delete, find, - and replace. - 4) Implement reference based sub-string access (as a generalization of - pointer arithmetic.) - 5) Implement runtime write protection for strings. - -There is also a desire to avoid "API-bloat". So functionality that can be -implemented trivially in other functionality is omitted. So there is no -left$() or right$() or reverse() or anything like that as part of the core -functionality. - -Explaining Bstrings -------------------- - -A bstring is basically a header which wraps a pointer to a char buffer. Lets -start with the declaration of a struct tagbstring: - - struct tagbstring { - int mlen; - int slen; - unsigned char * data; - }; - -This definition is considered exposed, not opaque (though it is neither -necessary nor recommended that low level maintenance of bstrings be performed -whenever the abstract interfaces are sufficient). The mlen field (usually) -describes a lower bound for the memory allocated for the data field. The -slen field describes the exact length for the bstring. The data field is a -single contiguous buffer of unsigned chars. Note that the existence of a '\0' -character in the unsigned char buffer pointed to by the data field does not -necessarily denote the end of the bstring. - -To be a well formed modifiable bstring the mlen field must be at least the -length of the slen field, and slen must be non-negative. Furthermore, the -data field must point to a valid buffer in which access to the first mlen -characters has been acquired. So the minimal check for correctness is: - - (slen >= 0 && mlen >= slen && data != NULL) - -bstrings returned by bstring functions can be assumed to be either NULL or -satisfy the above property. (When bstrings are only readable, the mlen >= -slen restriction is not required; this is discussed later in this section.) -A bstring itself is just a pointer to a struct tagbstring: - - typedef struct tagbstring * bstring; - -Note that use of the prefix "tag" in struct tagbstring is required to work -around the inconsistency between C and C++'s struct namespace usage. This -definition is also considered exposed. - -Bstrlib basically manages bstrings allocated as a header and an associated -data-buffer. Since the implementation is exposed, they can also be -constructed manually. Functions which mutate bstrings assume that the header -and data buffer have been malloced; the bstring library may perform free() or -realloc() on both the header and data buffer of any bstring parameter. -Functions which return bstring's create new bstrings. The string memory is -freed by a bdestroy() call (or using the bstrFree macro). - -The following related typedef is also provided: - - typedef const struct tagbstring * const_bstring; - -which is also considered exposed. These are directly bstring compatible (no -casting required) but are just used for parameters which are meant to be -non-mutable. So in general, bstring parameters which are read as input but -not meant to be modified will be declared as const_bstring, and bstring -parameters which may be modified will be declared as bstring. This convention -is recommended for user written functions as well. - -Since bstrings maintain interoperability with C library char-buffer style -strings, all functions which modify, update or create bstrings also append a -'\0' character into the position slen + 1. This trailing '\0' character is -not required for bstrings input to the bstring functions; this is provided -solely as a convenience for interoperability with standard C char-buffer -functionality. - -Analogs for the ANSI C string library functions have been created when they -are necessary, but have also been left out when they are not. In particular -there are no functions analogous to fwrite, or puts just for the purposes of -bstring. The ->data member of any string is exposed, and therefore can be -used just as easily as char buffers for C functions which read strings. - -For those that wish to hand construct bstrings, the following should be kept -in mind: - - 1) While bstrlib can accept constructed bstrings without terminating - '\0' characters, the rest of the C language string library will not - function properly on such non-terminated strings. This is obvious - but must be kept in mind. - 2) If it is intended that a constructed bstring be written to by the - bstring library functions then the data portion should be allocated - by the malloc function and the slen and mlen fields should be entered - properly. The struct tagbstring header is not reallocated, and only - freed by bdestroy. - 3) Writing arbitrary '\0' characters at various places in the string - will not modify its length as perceived by the bstring library - functions. In fact, '\0' is a legitimate non-terminating character - for a bstring to contain. - 4) For read only parameters, bstring functions do not check the mlen. - I.e., the minimal correctness requirements are reduced to: - - (slen >= 0 && data != NULL) - -Better pointer arithmetic -------------------------- - -One built-in feature of '\0' terminated char * strings, is that its very easy -and fast to obtain a reference to the tail of any string using pointer -arithmetic. Bstrlib does one better by providing a way to get a reference to -any substring of a bstring (or any other length delimited block of memory.) -So rather than just having pointer arithmetic, with bstrlib one essentially -has segment arithmetic. This is achieved using the macro blk2tbstr() which -builds a reference to a block of memory and the macro bmid2tbstr() which -builds a reference to a segment of a bstring. Bstrlib also includes -functions for direct consumption of memory blocks into bstrings, namely -bcatblk () and blk2bstr (). - -One scenario where this can be extremely useful is when string contains many -substrings which one would like to pass as read-only reference parameters to -some string consuming function without the need to allocate entire new -containers for the string data. More concretely, imagine parsing a command -line string whose parameters are space delimited. This can only be done for -tails of the string with '\0' terminated char * strings. - -Improved NULL semantics and error handling ------------------------------------------- - -Unless otherwise noted, if a NULL pointer is passed as a bstring or any other -detectably illegal parameter, the called function will return with an error -indicator (either NULL or BSTR_ERR) rather than simply performing a NULL -pointer access, or having undefined behavior. - -To illustrate the value of this, consider the following example: - - strcpy (p = malloc (13 * sizeof (char)), "Hello,"); - strcat (p, " World"); - -This is not correct because malloc may return NULL (due to an out of memory -condition), and the behaviour of strcpy is undefined if either of its -parameters are NULL. However: - - bstrcat (p = bfromcstr ("Hello,"), q = bfromcstr (" World")); - bdestroy (q); - -is well defined, because if either p or q are assigned NULL (indicating a -failure to allocate memory) both bstrcat and bdestroy will recognize it and -perform no detrimental action. - -Note that it is not necessary to check any of the members of a returned -bstring for internal correctness (in particular the data member does not need -to be checked against NULL when the header is non-NULL), since this is -assured by the bstring library itself. - -bStreams --------- - -In addition to the bgets and bread functions, bstrlib can abstract streams -with a high performance read only stream called a bStream. In general, the -idea is to open a core stream (with something like fopen) then pass its -handle as well as a bNread function pointer (like fread) to the bsopen -function which will return a handle to an open bStream. Then the functions -bsread, bsreadln or bsreadlns can be called to read portions of the stream. -Finally, the bsclose function is called to close the bStream -- it will -return a handle to the original (core) stream. So bStreams, essentially, -wrap other streams. - -The bStreams have two main advantages over the bgets and bread (as well as -fgets/ungetc) paradigms: - -1) Improved functionality via the bunread function which allows a stream to - unread characters, giving the bStream stack-like functionality if so - desired. -2) A very high performance bsreadln function. The C library function fgets() - (and the bgets function) can typically be written as a loop on top of - fgetc(), thus paying all of the overhead costs of calling fgetc on a per - character basis. bsreadln will read blocks at a time, thus amortizing the - overhead of fread calls over many characters at once. - -However, clearly bStreams are suboptimal or unusable for certain kinds of -streams (stdin) or certain usage patterns (a few spotty, or non-sequential -reads from a slow stream.) For those situations, using bgets will be more -appropriate. - -The semantics of bStreams allows practical construction of layerable data -streams. What this means is that by writing a bNread compatible function on -top of a bStream, one can construct a new bStream on top of it. This can be -useful for writing multi-pass parsers that don't actually read the entire -input more than once and don't require the use of intermediate storage. - -Aliasing --------- - -Aliasing occurs when a function is given two parameters which point to data -structures which overlap in the memory they occupy. While this does not -disturb read only functions, for many libraries this can make functions that -write to these memory locations malfunction. This is a common problem of the -C standard library and especially the string functions in the C standard -library. - -The C standard string library is entirely char by char oriented (as is -bstring) which makes conforming implementations alias safe for some -scenarios. However no actual detection of aliasing is typically performed, -so it is easy to find cases where the aliasing will cause anomolous or -undesirable behaviour (consider: strcat (p, p).) The C99 standard includes -the "restrict" pointer modifier which allows the compiler to document and -assume a no-alias condition on usage. However, only the most trivial cases -can be caught (if at all) by the compiler at compile time, and thus there is -no actual enforcement of non-aliasing. - -Bstrlib, by contrast, permits aliasing and is completely aliasing safe, in -the C99 sense of aliasing. That is to say, under the assumption that -pointers of incompatible types from distinct objects can never alias, bstrlib -is completely aliasing safe. (In practice this means that the data buffer -portion of any bstring and header of any bstring are assumed to never alias.) -With the exception of the reference building macros, the library behaves as -if all read-only parameters are first copied and replaced by temporary -non-aliased parameters before any writing to any output bstring is performed -(though actual copying is extremely rarely ever done.) - -Besides being a useful safety feature, bstring searching/comparison -functions can improve to O(1) execution when aliasing is detected. - -Note that aliasing detection and handling code in Bstrlib is generally -extremely cheap. There is almost never any appreciable performance penalty -for using aliased parameters. - -Reenterancy ------------ - -Nearly every function in Bstrlib is a leaf function, and is completely -reenterable with the exception of writing to common bstrings. The split -functions which use a callback mechanism requires only that the source string -not be destroyed by the callback function unless the callback function returns -with an error status (note that Bstrlib functions which return an error do -not modify the string in any way.) The string can in fact be modified by the -callback and the behaviour is deterministic. See the documentation of the -various split functions for more details. - -Undefined scenarios -------------------- - -One of the basic important premises for Bstrlib is to not to increase the -propogation of undefined situations from parameters that are otherwise legal -in of themselves. In particular, except for extremely marginal cases, usages -of bstrings that use the bstring library functions alone cannot lead to any -undefined action. But due to C/C++ language and library limitations, there -is no way to define a non-trivial library that is completely without -undefined operations. All such possible undefined operations are described -below: - -1) bstrings or struct tagbstrings that are not explicitely initialized cannot - be passed as a parameter to any bstring function. -2) The members of the NULL bstring cannot be accessed directly. (Though all - APIs and macros detect the NULL bstring.) -3) A bstring whose data member has not been obtained from a malloc or - compatible call and which is write accessible passed as a writable - parameter will lead to undefined results. (i.e., do not writeAllow any - constructed bstrings unless the data portion has been obtained from the - heap.) -4) If the headers of two strings alias but are not identical (which can only - happen via a defective manual construction), then passing them to a - bstring function in which one is writable is not defined. -5) If the mlen member is larger than the actual accessible length of the data - member for a writable bstring, or if the slen member is larger than the - readable length of the data member for a readable bstring, then the - corresponding bstring operations are undefined. -6) Any bstring definition whose header or accessible data portion has been - assigned to inaccessible or otherwise illegal memory clearly cannot be - acted upon by the bstring library in any way. -7) Destroying the source of an incremental split from within the callback - and not returning with a negative value (indicating that it should abort) - will lead to undefined behaviour. (Though *modifying* or adjusting the - state of the source data, even if those modification fail within the - bstrlib API, has well defined behavior.) -8) Modifying a bstring which is write protected by direct access has - undefined behavior. - -While this may seem like a long list, with the exception of invalid uses of -the writeAllow macro, and source destruction during an iterative split -without an accompanying abort, no usage of the bstring API alone can cause -any undefined scenario to occurr. I.e., the policy of restricting usage of -bstrings to the bstring API can significantly reduce the risk of runtime -errors (in practice it should eliminate them) related to string manipulation -due to undefined action. - -C++ wrapper ------------ - -A C++ wrapper has been created to enable bstring functionality for C++ in the -most natural (for C++ programers) way possible. The mandate for the C++ -wrapper is different from the base C bstring library. Since the C++ language -has far more abstracting capabilities, the CBString structure is considered -fully abstracted -- i.e., hand generated CBStrings are not supported (though -conversion from a struct tagbstring is allowed) and all detectable errors are -manifest as thrown exceptions. - -- The C++ class definitions are all under the namespace Bstrlib. bstrwrap.h - enables this namespace (with a using namespace Bstrlib; directive at the - end) unless the macro BSTRLIB_DONT_ASSUME_NAMESPACE has been defined before - it is included. - -- Erroneous accesses results in an exception being thrown. The exception - parameter is of type "struct CBStringException" which is derived from - std::exception if STL is used. A verbose description of the error message - can be obtained from the what() method. - -- CBString is a C++ structure derived from a struct tagbstring. An address - of a CBString cast to a bstring must not be passed to bdestroy. The bstring - C API has been made C++ safe and can be used directly in a C++ project. - -- It includes constructors which can take a char, '\0' terminated char - buffer, tagbstring, (char, repeat-value), a length delimited buffer or a - CBStringList to initialize it. - -- Concatenation is performed with the + and += operators. Comparisons are - done with the ==, !=, <, >, <= and >= operators. Note that == and != use - the biseq call, while <, >, <= and >= use bstrcmp. - -- CBString's can be directly cast to const character buffers. - -- CBString's can be directly cast to double, float, int or unsigned int so - long as the CBString are decimal representations of those types (otherwise - an exception will be thrown). Converting the other way should be done with - the format(a) method(s). - -- CBString contains the length, character and [] accessor methods. The - character and [] accessors are aliases of each other. If the bounds for - the string are exceeded, an exception is thrown. To avoid the overhead for - this check, first cast the CBString to a (const char *) and use [] to - dereference the array as normal. Note that the character and [] accessor - methods allows both reading and writing of individual characters. - -- The methods: format, formata, find, reversefind, findcaseless, - reversefindcaseless, midstr, insert, insertchrs, replace, findreplace, - findreplacecaseless, remove, findchr, nfindchr, alloc, toupper, tolower, - gets, read are analogous to the functions that can be found in the C API. - -- The caselessEqual and caselessCmp methods are analogous to biseqcaseless - and bstricmp functions respectively. - -- Note that just like the bformat function, the format and formata methods do - not automatically cast CBStrings into char * strings for "%s"-type - substitutions: - - CBString w("world"); - CBString h("Hello"); - CBString hw; - - /* The casts are necessary */ - hw.format ("%s, %s", (const char *)h, (const char *)w); - -- The methods trunc and repeat have been added instead of using pattern. - -- ltrim, rtrim and trim methods have been added. These remove characters - from a given character string set (defaulting to the whitespace characters) - from either the left, right or both ends of the CBString, respectively. - -- The method setsubstr is also analogous in functionality to bsetstr, except - that it cannot be passed NULL. Instead the method fill and the fill-style - constructor have been supplied to enable this functionality. - -- The writeprotect(), writeallow() and iswriteprotected() methods are - analogous to the bwriteprotect(), bwriteallow() and biswriteprotected() - macros in the C API. Write protection semantics in CBString are stronger - than with the C API in that indexed character assignment is checked for - write protection. However, unlike with the C API, a write protected - CBString can be destroyed by the destructor. - -- CBStream is a C++ structure which wraps a struct bStream (its not derived - from it, since destruction is slightly different). It is constructed by - passing in a bNread function pointer and a stream parameter cast to void *. - This structure includes methods for detecting eof, setting the buffer - length, reading the whole stream or reading entries line by line or block - by block, an unread function, and a peek function. - -- If STL is available, the CBStringList structure is derived from a vector of - CBString with various split methods. The split method has been overloaded - to accept either a character or CBString as the second parameter (when the - split parameter is a CBString any character in that CBString is used as a - seperator). The splitstr method takes a CBString as a substring seperator. - Joins can be performed via a CBString constructor which takes a - CBStringList as a parameter, or just using the CBString::join() method. - -- If there is proper support for std::iostreams, then the >> and << operators - and the getline() function have been added (with semantics the same as - those for std::string). - -Multithreading --------------- - -A mutable bstring is kind of analogous to a small (two entry) linked list -allocated by malloc, with all aliasing completely under programmer control. -I.e., manipulation of one bstring will never affect any other distinct -bstring unless explicitely constructed to do so by the programmer via hand -construction or via building a reference. Bstrlib also does not use any -static or global storage, so there are no hidden unremovable race conditions. -Bstrings are also clearly not inherently thread local. So just like -char *'s, bstrings can be passed around from thread to thread and shared and -so on, so long as modifications to a bstring correspond to some kind of -exclusive access lock as should be expected (or if the bstring is read-only, -which can be enforced by bstring write protection) for any sort of shared -object in a multithreaded environment. - -Bsafe module ------------- - -For convenience, a bsafe module has been included. The idea is that if this -module is included, inadvertant usage of the most dangerous C functions will -be overridden and lead to an immediate run time abort. Of course, it should -be emphasized that usage of this module is completely optional. The -intention is essentially to provide an option for creating project safety -rules which can be enforced mechanically rather than socially. This is -useful for larger, or open development projects where its more difficult to -enforce social rules or "coding conventions". - -Problems not solved -------------------- - -Bstrlib is written for the C and C++ languages, which have inherent weaknesses -that cannot be easily solved: - -1. Memory leaks: Forgetting to call bdestroy on a bstring that is about to be - unreferenced, just as forgetting to call free on a heap buffer that is - about to be dereferenced. Though bstrlib itself is leak free. -2. Read before write usage: In C, declaring an auto bstring does not - automatically fill it with legal/valid contents. This problem has been - somewhat mitigated in C++. (The bstrDeclare and bstrFree macros from - bstraux can be used to help mitigate this problem.) - -Other problems not addressed: - -3. Built-in mutex usage to automatically avoid all bstring internal race - conditions in multitasking environments: The problem with trying to - implement such things at this low a level is that it is typically more - efficient to use locks in higher level primitives. There is also no - platform independent way to implement locks or mutexes. -4. Unicode/widecharacter support. - -Note that except for spotty support of wide characters, the default C -standard library does not address any of these problems either. - -Configurable compilation options --------------------------------- - -All configuration options are meant solely for the purpose of compiler -compatibility. Configuration options are not meant to change the semantics -or capabilities of the library, except where it is unavoidable. - -Since some C++ compilers don't include the Standard Template Library and some -have the options of disabling exception handling, a number of macros can be -used to conditionally compile support for each of this: - -BSTRLIB_CAN_USE_STL - - - defining this will enable the used of the Standard Template Library. - Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. - -BSTRLIB_CANNOT_USE_STL - - - defining this will disable the use of the Standard Template Library. - Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. - -BSTRLIB_CAN_USE_IOSTREAM - - - defining this will enable the used of streams from class std. Defining - BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. - -BSTRLIB_CANNOT_USE_IOSTREAM - - - defining this will disable the use of streams from class std. Defining - BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. - -BSTRLIB_THROWS_EXCEPTIONS - - - defining this will enable the exception handling within bstring. - Defining BSTRLIB_THROWS_EXCEPTIONS overrides the - BSTRLIB_DOESNT_THROWS_EXCEPTIONS macro. - -BSTRLIB_DOESNT_THROW_EXCEPTIONS - - - defining this will disable the exception handling within bstring. - Defining BSTRLIB_THROWS_EXCEPTIONS overrides the - BSTRLIB_DOESNT_THROW_EXCEPTIONS macro. - -Note that these macros must be defined consistently throughout all modules -that use CBStrings including bstrwrap.cpp. - -Some older C compilers do not support functions such as vsnprintf. This is -handled by the following macro variables: - -BSTRLIB_NOVSNP - - - defining this indicates that the compiler does not support vsnprintf. - This will cause bformat and bformata to not be declared. Note that - for some compilers, such as Turbo C, this is set automatically. - Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. - -BSTRLIB_VSNP_OK - - - defining this will disable the autodetection of compilers the do not - support of compilers that do not support vsnprintf. - Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. - -Semantic compilation options ----------------------------- - -Bstrlib comes with very few compilation options for changing the semantics of -of the library. These are described below. - -BSTRLIB_DONT_ASSUME_NAMESPACE - - - Defining this before including bstrwrap.h will disable the automatic - enabling of the Bstrlib namespace for the C++ declarations. - -BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR - - - Defining this will make the CBString destructor non-virtual. - -BSTRLIB_MEMORY_DEBUG - - - Defining this will cause the bstrlib modules bstrlib.c and bstrwrap.cpp - to invoke a #include "memdbg.h". memdbg.h has to be supplied by the user. - -Note that these macros must be defined consistently throughout all modules -that use bstrings or CBStrings including bstrlib.c, bstraux.c and -bstrwrap.cpp. - -=============================================================================== - -Files ------ - -bstrlib.c - C implementaion of bstring functions. -bstrlib.h - C header file for bstring functions. -bstraux.c - C example that implements trivial additional functions. -bstraux.h - C header for bstraux.c -bstest.c - C unit/regression test for bstrlib.c - -bstrwrap.cpp - C++ implementation of CBString. -bstrwrap.h - C++ header file for CBString. -test.cpp - C++ unit/regression test for bstrwrap.cpp - -bsafe.c - C runtime stubs to abort usage of unsafe C functions. -bsafe.h - C header file for bsafe.c functions. - -C projects need only include bstrlib.h and compile/link bstrlib.c to use the -bstring library. C++ projects need to additionally include bstrwrap.h and -compile/link bstrwrap.cpp. For both, there may be a need to make choices -about feature configuration as described in the "Configurable compilation -options" in the section above. - -Other files that are included in this archive are: - -license.txt - The 3 clause BSD license for Bstrlib -gpl.txt - The GPL version 2 -security.txt - A security statement useful for auditting Bstrlib -porting.txt - A guide to porting Bstrlib -bstrlib.txt - This file - -=============================================================================== - -The functions -------------- - - extern bstring bfromcstr (const char * str); - - Take a standard C library style '\0' terminated char buffer and generate - a bstring with the same contents as the char buffer. If an error occurs - NULL is returned. - - So for example: - - bstring b = bfromcstr ("Hello"); - if (!b) { - fprintf (stderr, "Out of memory"); - } else { - puts ((char *) b->data); - } - - .......................................................................... - - extern bstring bfromcstralloc (int mlen, const char * str); - - Create a bstring which contains the contents of the '\0' terminated - char * buffer str. The memory buffer backing the bstring is at least - mlen characters in length. If an error occurs NULL is returned. - - So for example: - - bstring b = bfromcstralloc (64, someCstr); - if (b) b->data[63] = 'x'; - - The idea is that this will set the 64th character of b to 'x' if it is at - least 64 characters long otherwise do nothing. And we know this is well - defined so long as b was successfully created, since it will have been - allocated with at least 64 characters. - - .......................................................................... - - extern bstring blk2bstr (const void * blk, int len); - - Create a bstring whose contents are described by the contiguous buffer - pointing to by blk with a length of len bytes. Note that this function - creates a copy of the data in blk, rather than simply referencing it. - Compare with the blk2tbstr macro. If an error occurs NULL is returned. - - .......................................................................... - - extern char * bstr2cstr (const_bstring s, char z); - - Create a '\0' terminated char buffer which contains the contents of the - bstring s, except that any contained '\0' characters are converted to the - character in z. This returned value should be freed with bcstrfree(), by - the caller. If an error occurs NULL is returned. - - .......................................................................... - - extern int bcstrfree (char * s); - - Frees a C-string generated by bstr2cstr (). This is normally unnecessary - since it just wraps a call to free (), however, if malloc () and free () - have been redefined as a macros within the bstrlib module (via macros in - the memdbg.h backdoor) with some difference in behaviour from the std - library functions, then this allows a correct way of freeing the memory - that allows higher level code to be independent from these macro - redefinitions. - - .......................................................................... - - extern bstring bstrcpy (const_bstring b1); - - Make a copy of the passed in bstring. The copied bstring is returned if - there is no error, otherwise NULL is returned. - - .......................................................................... - - extern int bassign (bstring a, const_bstring b); - - Overwrite the bstring a with the contents of bstring b. Note that the - bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - int bassigncstr (bstring a, const char * str); - - Overwrite the string a with the contents of char * string str. Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a may be partially overwritten. - - .......................................................................... - - int bassignblk (bstring a, const void * s, int len); - - Overwrite the string a with the contents of the block (s, len). Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - extern int bassignmidstr (bstring a, const_bstring b, int left, int len); - - Overwrite the bstring a with the middle of contents of bstring b - starting from position left and running for a length len. left and - len are clamped to the ends of b as with the function bmidstr. Note that - the bstring a must be a well defined and writable bstring. If an error - occurs BSTR_ERR is returned and a is not overwritten. - - .......................................................................... - - extern bstring bmidstr (const_bstring b, int left, int len); - - Create a bstring which is the substring of b starting from position left - and running for a length len (clamped by the end of the bstring b.) If - there was no error, the value of this constructed bstring is returned - otherwise NULL is returned. - - .......................................................................... - - extern int bdelete (bstring s1, int pos, int len); - - Removes characters from pos to pos+len-1 and shifts the tail of the - bstring starting from pos+len to pos. len must be positive for this call - to have any effect. The section of the bstring described by (pos, len) - is clamped to boundaries of the bstring b. The value BSTR_OK is returned - if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int bconcat (bstring b0, const_bstring b1); - - Concatenate the bstring b1 to the end of bstring b0. The value BSTR_OK - is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bconchar (bstring b, char c); - - Concatenate the character c to the end of bstring b. The value BSTR_OK - is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bcatcstr (bstring b, const char * s); - - Concatenate the char * string s to the end of bstring b. The value - BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int bcatblk (bstring b, const void * s, int len); - - Concatenate a fixed length buffer (s, len) to the end of bstring b. The - value BSTR_OK is returned if the operation is successful, otherwise - BSTR_ERR is returned. - - .......................................................................... - - extern int biseq (const_bstring b0, const_bstring b1); - - Compare the bstring b0 and b1 for equality. If the bstrings differ, 0 - is returned, if the bstrings are the same, 1 is returned, if there is an - error, -1 is returned. If the length of the bstrings are different, this - function has O(1) complexity. Contained '\0' characters are not treated - as a termination character. - - Note that the semantics of biseq are not completely compatible with - bstrcmp because of its different treatment of the '\0' character. - - .......................................................................... - - extern int bisstemeqblk (const_bstring b, const void * blk, int len); - - Compare beginning of bstring b0 with a block of memory of length len for - equality. If the beginning of b0 differs from the memory block (or if b0 - is too short), 0 is returned, if the bstrings are the same, 1 is returned, - if there is an error, -1 is returned. - - .......................................................................... - - extern int biseqcaseless (const_bstring b0, const_bstring b1); - - Compare two bstrings for equality without differentiating between case. - If the bstrings differ other than in case, 0 is returned, if the bstrings - are the same, 1 is returned, if there is an error, -1 is returned. If - the length of the bstrings are different, this function is O(1). '\0' - termination characters are not treated in any special way. - - .......................................................................... - - extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); - - Compare beginning of bstring b0 with a block of memory of length len - without differentiating between case for equality. If the beginning of b0 - differs from the memory block other than in case (or if b0 is too short), - 0 is returned, if the bstrings are the same, 1 is returned, if there is an - error, -1 is returned. - - .......................................................................... - - extern int biseqcstr (const_bstring b, const char *s); - - Compare the bstring b and char * bstring s. The C string s must be '\0' - terminated at exactly the length of the bstring b, and the contents - between the two must be identical with the bstring b with no '\0' - characters for the two contents to be considered equal. This is - equivalent to the condition that their current contents will be always be - equal when comparing them in the same format after converting one or the - other. If they are equal 1 is returned, if they are unequal 0 is - returned and if there is a detectable error BSTR_ERR is returned. - - .......................................................................... - - extern int biseqcstrcaseless (const_bstring b, const char *s); - - Compare the bstring b and char * string s. The C string s must be '\0' - terminated at exactly the length of the bstring b, and the contents - between the two must be identical except for case with the bstring b with - no '\0' characters for the two contents to be considered equal. This is - equivalent to the condition that their current contents will be always be - equal ignoring case when comparing them in the same format after - converting one or the other. If they are equal, except for case, 1 is - returned, if they are unequal regardless of case 0 is returned and if - there is a detectable error BSTR_ERR is returned. - - .......................................................................... - - extern int bstrcmp (const_bstring b0, const_bstring b1); - - Compare the bstrings b0 and b1 for ordering. If there is an error, - SHRT_MIN is returned, otherwise a value less than or greater than zero, - indicating that the bstring pointed to by b0 is lexicographically less - than or greater than the bstring pointed to by b1 is returned. If the - bstring lengths are unequal but the characters up until the length of the - shorter are equal then a value less than, or greater than zero, - indicating that the bstring pointed to by b0 is shorter or longer than the - bstring pointed to by b1 is returned. 0 is returned if and only if the - two bstrings are the same. If the length of the bstrings are different, - this function is O(n). Like its standard C library counter part, the - comparison does not proceed past any '\0' termination characters - encountered. - - The seemingly odd error return value, merely provides slightly more - granularity than the undefined situation given in the C library function - strcmp. The function otherwise behaves very much like strcmp(). - - Note that the semantics of bstrcmp are not completely compatible with - biseq because of its different treatment of the '\0' termination - character. - - .......................................................................... - - extern int bstrncmp (const_bstring b0, const_bstring b1, int n); - - Compare the bstrings b0 and b1 for ordering for at most n characters. If - there is an error, SHRT_MIN is returned, otherwise a value is returned as - if b0 and b1 were first truncated to at most n characters then bstrcmp - was called with these new bstrings are paremeters. If the length of the - bstrings are different, this function is O(n). Like its standard C - library counter part, the comparison does not proceed past any '\0' - termination characters encountered. - - The seemingly odd error return value, merely provides slightly more - granularity than the undefined situation given in the C library function - strncmp. The function otherwise behaves very much like strncmp(). - - .......................................................................... - - extern int bstricmp (const_bstring b0, const_bstring b1); - - Compare two bstrings without differentiating between case. The return - value is the difference of the values of the characters where the two - bstrings first differ, otherwise 0 is returned indicating that the - bstrings are equal. If the lengths are different, then a difference from - 0 is given, but if the first extra character is '\0', then it is taken to - be the value UCHAR_MAX+1. - - .......................................................................... - - extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); - - Compare two bstrings without differentiating between case for at most n - characters. If the position where the two bstrings first differ is - before the nth position, the return value is the difference of the values - of the characters, otherwise 0 is returned. If the lengths are different - and less than n characters, then a difference from 0 is given, but if the - first extra character is '\0', then it is taken to be the value - UCHAR_MAX+1. - - .......................................................................... - - extern int bdestroy (bstring b); - - Deallocate the bstring passed. Passing NULL in as a parameter will have - no effect. Note that both the header and the data portion of the bstring - will be freed. No other bstring function which modifies one of its - parameters will free or reallocate the header. Because of this, in - general, bdestroy cannot be called on any declared struct tagbstring even - if it is not write protected. A bstring which is write protected cannot - be destroyed via the bdestroy call. Any attempt to do so will result in - no action taken, and BSTR_ERR will be returned. - - Note to C++ users: Passing in a CBString cast to a bstring will lead to - undefined behavior (free will be called on the header, rather than the - CBString destructor.) Instead just use the ordinary C++ language - facilities to dealloc a CBString. - - .......................................................................... - - extern int binstr (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - forward (increasing) direction. If it is found then it returns with the - first position after pos where it is found, otherwise it returns BSTR_ERR. - The algorithm used is brute force; O(m*n). - - .......................................................................... - - extern int binstrr (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - backward (decreasing) direction. If it is found then it returns with the - first position after pos where it is found, otherwise return BSTR_ERR. - Note that the current position at pos is tested as well -- so to be - disjoint from a previous forward search it is recommended that the - position be backed up (decremented) by one position. The algorithm used - is brute force; O(m*n). - - .......................................................................... - - extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - forward (increasing) direction but without regard to case. If it is - found then it returns with the first position after pos where it is - found, otherwise it returns BSTR_ERR. The algorithm used is brute force; - O(m*n). - - .......................................................................... - - extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); - - Search for the bstring s2 in s1 starting at position pos and looking in a - backward (decreasing) direction but without regard to case. If it is - found then it returns with the first position after pos where it is - found, otherwise return BSTR_ERR. Note that the current position at pos - is tested as well -- so to be disjoint from a previous forward search it - is recommended that the position be backed up (decremented) by one - position. The algorithm used is brute force; O(m*n). - - .......................................................................... - - extern int binchr (const_bstring b0, int pos, const_bstring b1); - - Search for the first position in b0 starting from pos or after, in which - one of the characters in b1 is found. This function has an execution - time of O(b0->slen + b1->slen). If such a position does not exist in b0, - then BSTR_ERR is returned. - - .......................................................................... - - extern int binchrr (const_bstring b0, int pos, const_bstring b1); - - Search for the last position in b0 no greater than pos, in which one of - the characters in b1 is found. This function has an execution time - of O(b0->slen + b1->slen). If such a position does not exist in b0, - then BSTR_ERR is returned. - - .......................................................................... - - extern int bninchr (const_bstring b0, int pos, const_bstring b1); - - Search for the first position in b0 starting from pos or after, in which - none of the characters in b1 is found and return it. This function has - an execution time of O(b0->slen + b1->slen). If such a position does - not exist in b0, then BSTR_ERR is returned. - - .......................................................................... - - extern int bninchrr (const_bstring b0, int pos, const_bstring b1); - - Search for the last position in b0 no greater than pos, in which none of - the characters in b1 is found and return it. This function has an - execution time of O(b0->slen + b1->slen). If such a position does not - exist in b0, then BSTR_ERR is returned. - - .......................................................................... - - extern int bstrchr (const_bstring b, int c); - - Search for the character c in the bstring b forwards from the start of - the bstring. Returns the position of the found character or BSTR_ERR if - it is not found. - - NOTE: This has been implemented as a macro on top of bstrchrp (). - - .......................................................................... - - extern int bstrrchr (const_bstring b, int c); - - Search for the character c in the bstring b backwards from the end of the - bstring. Returns the position of the found character or BSTR_ERR if it is - not found. - - NOTE: This has been implemented as a macro on top of bstrrchrp (). - - .......................................................................... - - extern int bstrchrp (const_bstring b, int c, int pos); - - Search for the character c in b forwards from the position pos - (inclusive). Returns the position of the found character or BSTR_ERR if - it is not found. - - .......................................................................... - - extern int bstrrchrp (const_bstring b, int c, int pos); - - Search for the character c in b backwards from the position pos in bstring - (inclusive). Returns the position of the found character or BSTR_ERR if - it is not found. - - .......................................................................... - - extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); - - Overwrite the bstring b0 starting at position pos with the bstring b1. If - the position pos is past the end of b0, then the character "fill" is - appended as necessary to make up the gap between the end of b0 and pos. - If b1 is NULL, it behaves as if it were a 0-length bstring. The value - BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is - returned. - - .......................................................................... - - extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); - - Inserts the bstring s2 into s1 at position pos. If the position pos is - past the end of s1, then the character "fill" is appended as necessary to - make up the gap between the end of s1 and pos. The value BSTR_OK is - returned if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int binsertch (bstring s1, int pos, int len, unsigned char fill); - - Inserts the character fill repeatedly into s1 at position pos for a - length len. If the position pos is past the end of s1, then the - character "fill" is appended as necessary to make up the gap between the - end of s1 and the position pos + len (exclusive). The value BSTR_OK is - returned if the operation is successful, otherwise BSTR_ERR is returned. - - .......................................................................... - - extern int breplace (bstring b1, int pos, int len, const_bstring b2, - unsigned char fill); - - Replace a section of a bstring from pos for a length len with the bstring - b2. If the position pos is past the end of b1 then the character "fill" - is appended as necessary to make up the gap between the end of b1 and - pos. - - .......................................................................... - - extern int bfindreplace (bstring b, const_bstring find, - const_bstring replace, int position); - - Replace all occurrences of the find substring with a replace bstring - after a given position in the bstring b. The find bstring must have a - length > 0 otherwise BSTR_ERR is returned. This function does not - perform recursive per character replacement; that is to say successive - searches resume at the position after the last replace. - - So for example: - - bfindreplace (a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"), - a2 = bfromcstr("aa"), 0); - - Should result in changing a0 to "aaaabaaAb". - - This function performs exactly (b->slen - position) bstring comparisons, - and data movement is bounded above by character volume equivalent to size - of the output bstring. - - .......................................................................... - - extern int bfindreplacecaseless (bstring b, const_bstring find, - const_bstring replace, int position); - - Replace all occurrences of the find substring, ignoring case, with a - replace bstring after a given position in the bstring b. The find bstring - must have a length > 0 otherwise BSTR_ERR is returned. This function - does not perform recursive per character replacement; that is to say - successive searches resume at the position after the last replace. - - So for example: - - bfindreplacecaseless (a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"), - a2 = bfromcstr("aa"), 0); - - Should result in changing a0 to "aaaabaaaab". - - This function performs exactly (b->slen - position) bstring comparisons, - and data movement is bounded above by character volume equivalent to size - of the output bstring. - - .......................................................................... - - extern int balloc (bstring b, int length); - - Increase the allocated memory backing the data buffer for the bstring b - to a length of at least length. If the memory backing the bstring b is - already large enough, not action is performed. This has no effect on the - bstring b that is visible to the bstring API. Usually this function will - only be used when a minimum buffer size is required coupled with a direct - access to the ->data member of the bstring structure. - - Be warned that like any other bstring function, the bstring must be well - defined upon entry to this function. I.e., doing something like: - - b->slen *= 2; /* ?? Most likely incorrect */ - balloc (b, b->slen); - - is invalid, and should be implemented as: - - int t; - if (BSTR_OK == balloc (b, t = (b->slen * 2))) b->slen = t; - - This function will return with BSTR_ERR if b is not detected as a valid - bstring or length is not greater than 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int ballocmin (bstring b, int length); - - Change the amount of memory backing the bstring b to at least length. - This operation will never truncate the bstring data including the - extra terminating '\0' and thus will not decrease the length to less than - b->slen + 1. Note that repeated use of this function may cause - performance problems (realloc may be called on the bstring more than - the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b - is not detected as a valid bstring or length is not greater than 0, - otherwise BSTR_OK is returned. - - So for example: - - if (BSTR_OK == ballocmin (b, 64)) b->data[63] = 'x'; - - The idea is that this will set the 64th character of b to 'x' if it is at - least 64 characters long otherwise do nothing. And we know this is well - defined so long as the ballocmin call was successfully, since it will - ensure that b has been allocated with at least 64 characters. - - .......................................................................... - - int btrunc (bstring b, int n); - - Truncate the bstring to at most n characters. This function will return - with BSTR_ERR if b is not detected as a valid bstring or n is less than - 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bpattern (bstring b, int len); - - Replicate the starting bstring, b, end to end repeatedly until it - surpasses len characters, then chop the result to exactly len characters. - This function operates in-place. This function will return with BSTR_ERR - if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int btoupper (bstring b); - - Convert contents of bstring to upper case. This function will return with - BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int btolower (bstring b); - - Convert contents of bstring to lower case. This function will return with - BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bltrimws (bstring b); - - Delete whitespace contiguous from the left end of the bstring. This - function will return with BSTR_ERR if b is NULL or of length 0, otherwise - BSTR_OK is returned. - - .......................................................................... - - extern int brtrimws (bstring b); - - Delete whitespace contiguous from the right end of the bstring. This - function will return with BSTR_ERR if b is NULL or of length 0, otherwise - BSTR_OK is returned. - - .......................................................................... - - extern int btrimws (bstring b); - - Delete whitespace contiguous from both ends of the bstring. This function - will return with BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK - is returned. - - .......................................................................... - - extern int bstrListCreate (void); - - Create an empty struct bstrList. The struct bstrList output structure is - declared as follows: - - struct bstrList { - int qty, mlen; - bstring * entry; - }; - - The entry field actually is an array with qty number entries. The mlen - record counts the maximum number of bstring's for which there is memory - in the entry record. - - The Bstrlib API does *NOT* include a comprehensive set of functions for - full management of struct bstrList in an abstracted way. The reason for - this is because aliasing semantics of the list are best left to the user - of this function, and performance varies wildly depending on the - assumptions made. For a complete list of bstring data type it is - recommended that the C++ public std::vector<CBString> be used, since its - semantics are usage are more standard. - - .......................................................................... - - extern int bstrListDestroy (struct bstrList * sl); - - Destroy a struct bstrList structure that was returned by the bsplit - function. Note that this will destroy each bstring in the ->entry array - as well. See bstrListCreate() above for structure of struct bstrList. - - .......................................................................... - - extern int bstrListAlloc (struct bstrList * sl, int msz); - - Ensure that there is memory for at least msz number of entries for the - list. - - .......................................................................... - - extern int bstrListAllocMin (struct bstrList * sl, int msz); - - Try to allocate the minimum amount of memory for the list to include at - least msz entries or sl->qty whichever is greater. - - .......................................................................... - - extern struct bstrList * bsplit (bstring str, unsigned char splitChar); - - Create an array of sequential substrings from str divided by the - character splitChar. Successive occurrences of the splitChar will be - divided by empty bstring entries, following the semantics from the Python - programming language. To reclaim the memory from this output structure, - bstrListDestroy () should be called. See bstrListCreate() above for - structure of struct bstrList. - - .......................................................................... - - extern struct bstrList * bsplits (bstring str, const_bstring splitStr); - - Create an array of sequential substrings from str divided by any - character contained in splitStr. An empty splitStr causes a single entry - bstrList containing a copy of str to be returned. See bstrListCreate() - above for structure of struct bstrList. - - .......................................................................... - - extern struct bstrList * bsplitstr (bstring str, const_bstring splitStr); - - Create an array of sequential substrings from str divided by the entire - substring splitStr. An empty splitStr causes a single entry bstrList - containing a copy of str to be returned. See bstrListCreate() above for - structure of struct bstrList. - - .......................................................................... - - extern bstring bjoin (const struct bstrList * bl, const_bstring sep); - - Join the entries of a bstrList into one bstring by sequentially - concatenating them with the sep bstring in between. If sep is NULL, it - is treated as if it were the empty bstring. Note that: - - bjoin (l = bsplit (b, s->data[0]), s); - - should result in a copy of b, if s->slen is 1. If there is an error NULL - is returned, otherwise a bstring with the correct result is returned. - See bstrListCreate() above for structure of struct bstrList. - - .......................................................................... - - extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by the character splitChar. The parm passed to - bsplitcb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitcb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitcb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitcb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplit that is - abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by any of the characters in splitStr. An empty - splitStr causes the whole str to be iterated once. The parm passed to - bsplitcb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitscb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitscb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitscb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplits that - is abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, - int (* cb) (void * parm, int ofs, int len), void * parm); - - Iterate the set of disjoint sequential substrings over str starting at - position pos divided by the entire substring splitStr. An empty splitStr - causes each character of str to be iterated. The parm passed to bsplitcb - is passed on to cb. If the function cb returns a value < 0, then further - iterating is halted and this value is returned by bsplitcb. - - Note: Non-destructive modification of str from within the cb function - while performing this split is not undefined. bsplitstrcb behaves in - sequential lock step with calls to cb. I.e., after returning from a cb - that return a non-negative integer, bsplitstrcb continues from the position - 1 character after the last detected split character and it will halt - immediately if the length of str falls below this point. However, if the - cb function destroys str, then it *must* return with a negative value, - otherwise bsplitscb will continue in an undefined manner. - - This function is provided as an incremental alternative to bsplitstr that - is abortable and which does not impose additional memory allocation. - - .......................................................................... - - extern bstring bformat (const char * fmt, ...); - - Takes the same parameters as printf (), but rather than outputting - results to stdio, it forms a bstring which contains what would have been - output. Note that if there is an early generation of a '\0' character, - the bstring will be truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - b0 = bformat ("Hello, %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bformat function is not present. - - .......................................................................... - - extern int bformata (bstring b, const char * fmt, ...); - - In addition to the initial output buffer b, bformata takes the same - parameters as printf (), but rather than outputting results to stdio, it - appends the results to the initial bstring parameter. Note that if - there is an early generation of a '\0' character, the bstring will be - truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bformata function is not present. - - .......................................................................... - - extern int bassignformat (bstring b, const char * fmt, ...); - - After the first parameter, it takes the same parameters as printf (), but - rather than outputting results to stdio, it outputs the results to - the bstring parameter b. Note that if there is an early generation of a - '\0' character, the bstring will be truncated to this end point. - - Note that %s format tokens correspond to '\0' terminated char * buffers, - not bstrings. To print a bstring, first dereference data element of the - the bstring: - - /* b1->data needs to be '\0' terminated, so tagbstrings generated - by blk2tbstr () might not be suitable. */ - bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data); - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bassignformat function is not present. - - .......................................................................... - - extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); - - The bvcformata function formats data under control of the format control - string fmt and attempts to append the result to b. The fmt parameter is - the same as that of the printf function. The variable argument list is - replaced with arglist, which has been initialized by the va_start macro. - The size of the output is upper bounded by count. If the required output - exceeds count, the string b is not augmented with any contents and a value - below BSTR_ERR is returned. If a value below -count is returned then it - is recommended that the negative of this value be used as an update to the - count in a subsequent pass. On other errors, such as running out of - memory, parameter errors or numeric wrap around BSTR_ERR is returned. - BSTR_OK is returned when the output is successfully generated and - appended to b. - - Note: There is no sanity checking of arglist, and this function is - destructive of the contents of b from the b->slen point onward. If there - is an early generation of a '\0' character, the bstring will be truncated - to this end point. - - Although this function is part of the external API for Bstrlib, the - interface and semantics (length limitations, and unusual return codes) - are fairly atypical. The real purpose for this function is to provide an - engine for the bvformata macro. - - Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been - compiled the bvcformata function is not present. - - .......................................................................... - - extern bstring bread (bNread readPtr, void * parm); - typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, - void *parm); - - Read an entire stream into a bstring, verbatum. The readPtr function - pointer is compatible with fread sematics, except that it need not obtain - the stream data from a file. The intention is that parm would contain - the stream data context/state required (similar to the role of the FILE* - I/O stream parameter of fread.) - - Abstracting the block read function allows for block devices other than - file streams to be read if desired. Note that there is an ANSI - compatibility issue if "fread" is used directly; see the ANSI issues - section below. - - .......................................................................... - - extern int breada (bstring b, bNread readPtr, void * parm); - - Read an entire stream and append it to a bstring, verbatum. Behaves - like bread, except that it appends it results to the bstring b. - BSTR_ERR is returned on error, otherwise 0 is returned. - - .......................................................................... - - extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); - typedef int (* bNgetc) (void * parm); - - Read a bstring from a stream. As many bytes as is necessary are read - until the terminator is consumed or no more characters are available from - the stream. If read from the stream, the terminator character will be - appended to the end of the returned bstring. The getcPtr function must - have the same semantics as the fgetc C library function (i.e., returning - an integer whose value is negative when there are no more characters - available, otherwise the value of the next available unsigned character - from the stream.) The intention is that parm would contain the stream - data context/state required (similar to the role of the FILE* I/O stream - parameter of fgets.) If no characters are read, or there is some other - detectable error, NULL is returned. - - bgets will never call the getcPtr function more often than necessary to - construct its output (including a single call, if required, to determine - that the stream contains no more characters.) - - Abstracting the character stream function and terminator character allows - for different stream devices and string formats other than '\n' - terminated lines in a file if desired (consider \032 terminated email - messages, in a UNIX mailbox for example.) - - For files, this function can be used analogously as fgets as follows: - - fp = fopen ( ... ); - if (fp) b = bgets ((bNgetc) fgetc, fp, '\n'); - - (Note that only one terminator character can be used, and that '\0' is - not assumed to terminate the stream in addition to the terminator - character. This is consistent with the semantics of fgets.) - - .......................................................................... - - extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); - - Read from a stream and concatenate to a bstring. Behaves like bgets, - except that it appends it results to the bstring b. The value 1 is - returned if no characters are read before a negative result is returned - from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned - in other normal cases. - - .......................................................................... - - extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); - - Read from a stream and concatenate to a bstring. Behaves like bgets, - except that it assigns the results to the bstring b. The value 1 is - returned if no characters are read before a negative result is returned - from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned - in other normal cases. - - .......................................................................... - - extern struct bStream * bsopen (bNread readPtr, void * parm); - - Wrap a given open stream (described by a fread compatible function - pointer and stream handle) into an open bStream suitable for the bstring - library streaming functions. - - .......................................................................... - - extern void * bsclose (struct bStream * s); - - Close the bStream, and return the handle to the stream that was - originally used to open the given stream. If s is NULL or detectably - invalid, NULL will be returned. - - .......................................................................... - - extern int bsbufflength (struct bStream * s, int sz); - - Set the length of the buffer used by the bStream. If sz is the macro - BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not set. If s is - NULL or sz is negative, the function will return with BSTR_ERR, otherwise - this function returns with the previous length. - - .......................................................................... - - extern int bsreadln (bstring r, struct bStream * s, char terminator); - - Read a bstring terminated by the terminator character or the end of the - stream from the bStream (s) and return it into the parameter r. The - matched terminator, if found, appears at the end of the line read. If - the stream has been exhausted of all available data, before any can be - read, BSTR_ERR is returned. This function may read additional characters - into the stream buffer from the core stream that are not returned, but - will be retained for subsequent read operations. When reading from high - speed streams, this function can perform significantly faster than bgets. - - .......................................................................... - - extern int bsreadlna (bstring r, struct bStream * s, char terminator); - - Read a bstring terminated by the terminator character or the end of the - stream from the bStream (s) and concatenate it to the parameter r. The - matched terminator, if found, appears at the end of the line read. If - the stream has been exhausted of all available data, before any can be - read, BSTR_ERR is returned. This function may read additional characters - into the stream buffer from the core stream that are not returned, but - will be retained for subsequent read operations. When reading from high - speed streams, this function can perform significantly faster than bgets. - - .......................................................................... - - extern int bsreadlns (bstring r, struct bStream * s, bstring terminators); - - Read a bstring terminated by any character in the terminators bstring or - the end of the stream from the bStream (s) and return it into the - parameter r. This function may read additional characters from the core - stream that are not returned, but will be retained for subsequent read - operations. - - .......................................................................... - - extern int bsreadlnsa (bstring r, struct bStream * s, bstring terminators); - - Read a bstring terminated by any character in the terminators bstring or - the end of the stream from the bStream (s) and concatenate it to the - parameter r. If the stream has been exhausted of all available data, - before any can be read, BSTR_ERR is returned. This function may read - additional characters from the core stream that are not returned, but - will be retained for subsequent read operations. - - .......................................................................... - - extern int bsread (bstring r, struct bStream * s, int n); - - Read a bstring of length n (or, if it is fewer, as many bytes as is - remaining) from the bStream. This function will read the minimum - required number of additional characters from the core stream. When the - stream is at the end of the file BSTR_ERR is returned, otherwise BSTR_OK - is returned. - - .......................................................................... - - extern int bsreada (bstring r, struct bStream * s, int n); - - Read a bstring of length n (or, if it is fewer, as many bytes as is - remaining) from the bStream and concatenate it to the parameter r. This - function will read the minimum required number of additional characters - from the core stream. When the stream is at the end of the file BSTR_ERR - is returned, otherwise BSTR_OK is returned. - - .......................................................................... - - extern int bsunread (struct bStream * s, const_bstring b); - - Insert a bstring into the bStream at the current position. These - characters will be read prior to those that actually come from the core - stream. - - .......................................................................... - - extern int bspeek (bstring r, const struct bStream * s); - - Return the number of currently buffered characters from the bStream that - will be read prior to reads from the core stream, and append it to the - the parameter r. - - .......................................................................... - - extern int bssplitscb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); - - Iterate the set of disjoint sequential substrings over the stream s - divided by any character from the bstring splitStr. The parm passed to - bssplitscb is passed on to cb. If the function cb returns a value < 0, - then further iterating is halted and this return value is returned by - bssplitscb. - - Note: At the point of calling the cb function, the bStream pointer is - pointed exactly at the position right after having read the split - character. The cb function can act on the stream by causing the bStream - pointer to move, and bssplitscb will continue by starting the next split - at the position of the pointer after the return from cb. - - However, if the cb causes the bStream s to be destroyed then the cb must - return with a negative value, otherwise bssplitscb will continue in an - undefined manner. - - This function is provided as way to incrementally parse through a file - or other generic stream that in total size may otherwise exceed the - practical or desired memory available. As with the other split callback - based functions this is abortable and does not impose additional memory - allocation. - - .......................................................................... - - extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, - int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); - - Iterate the set of disjoint sequential substrings over the stream s - divided by the entire substring splitStr. The parm passed to - bssplitstrcb is passed on to cb. If the function cb returns a - value < 0, then further iterating is halted and this return value is - returned by bssplitstrcb. - - Note: At the point of calling the cb function, the bStream pointer is - pointed exactly at the position right after having read the split - character. The cb function can act on the stream by causing the bStream - pointer to move, and bssplitstrcb will continue by starting the next - split at the position of the pointer after the return from cb. - - However, if the cb causes the bStream s to be destroyed then the cb must - return with a negative value, otherwise bssplitscb will continue in an - undefined manner. - - This function is provided as way to incrementally parse through a file - or other generic stream that in total size may otherwise exceed the - practical or desired memory available. As with the other split callback - based functions this is abortable and does not impose additional memory - allocation. - - .......................................................................... - - extern int bseof (const struct bStream * s); - - Return the defacto "EOF" (end of file) state of a stream (1 if the - bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or - detectably erroneous.) When the readPtr callback returns a value <= 0 - the stream reaches its "EOF" state. Note that bunread with non-empty - content will essentially turn off this state, and the stream will not be - in its "EOF" state so long as its possible to read more data out of it. - - Also note that the semantics of bseof() are slightly different from - something like feof(). I.e., reaching the end of the stream does not - necessarily guarantee that bseof() will return with a value indicating - that this has happened. bseof() will only return indicating that it has - reached the "EOF" and an attempt has been made to read past the end of - the bStream. - -The macros ----------- - - The macros described below are shown in a prototype form indicating their - intended usage. Note that the parameters passed to these macros will be - referenced multiple times. As with all macros, programmer care is - required to guard against unintended side effects. - - int blengthe (const_bstring b, int err); - - Returns the length of the bstring. If the bstring is NULL err is - returned. - - .......................................................................... - - int blength (const_bstring b); - - Returns the length of the bstring. If the bstring is NULL, the length - returned is 0. - - .......................................................................... - - int bchare (const_bstring b, int p, int c); - - Returns the p'th character of the bstring b. If the position p refers to - a position that does not exist in the bstring or the bstring is NULL, - then c is returned. - - .......................................................................... - - char bchar (const_bstring b, int p); - - Returns the p'th character of the bstring b. If the position p refers to - a position that does not exist in the bstring or the bstring is NULL, - then '\0' is returned. - - .......................................................................... - - char * bdatae (bstring b, char * err); - - Returns the char * data portion of the bstring b. If b is NULL, err is - returned. - - .......................................................................... - - char * bdata (bstring b); - - Returns the char * data portion of the bstring b. If b is NULL, NULL is - returned. - - .......................................................................... - - char * bdataofse (bstring b, int ofs, char * err); - - Returns the char * data portion of the bstring b offset by ofs. If b is - NULL, err is returned. - - .......................................................................... - - char * bdataofs (bstring b, int ofs); - - Returns the char * data portion of the bstring b offset by ofs. If b is - NULL, NULL is returned. - - .......................................................................... - - struct tagbstring var = bsStatic ("..."); - - The bsStatic macro allows for static declarations of literal string - constants as struct tagbstring structures. The resulting tagbstring does - not need to be freed or destroyed. Note that this macro is only well - defined for string literal arguments. For more general string pointers, - use the btfromcstr macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - <void * blk, int len> <- bsStaticBlkParms ("...") - - The bsStaticBlkParms macro emits a pair of comma seperated parameters - corresponding to the block parameters for the block functions in Bstrlib - (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk.) - Note that this macro is only well defined for string literal arguments. - - Examples: - - bstring b = blk2bstr (bsStaticBlkParms ("Fast init. ")); - bcatblk (b, bsStaticBlkParms ("No frills fast concatenation.")); - - These are faster than using bfromcstr() and bcatcstr() respectively - because the length of the inline string is known as a compile time - constant. Also note that seperate struct tagbstring declarations for - holding the output of a bsStatic() macro are not required. - - .......................................................................... - - void btfromcstr (struct tagbstring& t, const char * s); - - Fill in the tagbstring t with the '\0' terminated char buffer s. This - action is purely reference oriented; no memory management is done. The - data member is just assigned s, and slen is assigned the strlen of s. - The s parameter is accessed exactly once in this macro. - - The resulting struct tagbstring is initially write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoke the - bwriteallow on this struct tagbstring to make it writeable (though this - requires that s be obtained from a function compatible with malloc.) - - .......................................................................... - - void btfromblk (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len. This - action is purely reference oriented; no memory management is done. The - data member of t is just assigned s, and slen is assigned len. Note that - the buffer is not appended with a '\0' character. The s and len - parameters are accessed exactly once each in this macro. - - The resulting struct tagbstring is initially write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoke the - bwriteallow on this struct tagbstring to make it writeable (though this - requires that s be obtained from a function compatible with malloc.) - - .......................................................................... - - void btfromblkltrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been left trimmed. This action is purely reference oriented; no - memory management is done. The data member of t is just assigned to a - pointer inside the buffer s. Note that the buffer is not appended with a - '\0' character. The s and len parameters are accessed exactly once each - in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void btfromblkrtrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been right trimmed. This action is purely reference oriented; no - memory management is done. The data member of t is just assigned to a - pointer inside the buffer s. Note that the buffer is not appended with a - '\0' character. The s and len parameters are accessed exactly once each - in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void btfromblktrimws (struct tagbstring& t, void * s, int len); - - Fill in the tagbstring t with the data buffer s with length len after it - has been left and right trimmed. This action is purely reference - oriented; no memory management is done. The data member of t is just - assigned to a pointer inside the buffer s. Note that the buffer is not - appended with a '\0' character. The s and len parameters are accessed - exactly once each in this macro. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct - tagbstring has no effect. - - .......................................................................... - - void bmid2tbstr (struct tagbstring& t, bstring b, int pos, int len); - - Fill the tagbstring t with the substring from b, starting from position - pos with a length len. The segment is clamped by the boundaries of - the bstring b. This action is purely reference oriented; no memory - management is done. Note that the buffer is not appended with a '\0' - character. Note that the t parameter to this macro may be accessed - multiple times. Note that the contents of t will become undefined - if the contents of b change or are destroyed. - - The resulting struct tagbstring is permanently write protected. Attempts - to write to this struct tagbstring in a write protected state from any - bstrlib function will lead to BSTR_ERR being returned. Invoking the - bwriteallow macro on this struct tagbstring will have no effect. - - .......................................................................... - - void bvformata (int& ret, bstring b, const char * format, lastarg); - - Append the bstring b with printf like formatting with the format control - string, and the arguments taken from the ... list of arguments after - lastarg passed to the containing function. If the containing function - does not have ... parameters or lastarg is not the last named parameter - before the ... then the results are undefined. If successful, the - results are appended to b and BSTR_OK is assigned to ret. Otherwise - BSTR_ERR is assigned to ret. - - Example: - - void dbgerror (FILE * fp, const char * fmt, ...) { - int ret; - bstring b; - bvformata (ret, b = bfromcstr ("DBG: "), fmt, fmt); - if (BSTR_OK == ret) fputs ((char *) bdata (b), fp); - bdestroy (b); - } - - Note that if the BSTRLIB_NOVSNP macro was set when bstrlib had been - compiled the bvformata macro will not link properly. If the - BSTRLIB_NOVSNP macro has been set, the bvformata macro will not be - available. - - .......................................................................... - - void bwriteprotect (struct tagbstring& t); - - Disallow bstring from being written to via the bstrlib API. Attempts to - write to the resulting tagbstring from any bstrlib function will lead to - BSTR_ERR being returned. - - Note: bstrings which are write protected cannot be destroyed via bdestroy. - - Note to C++ users: Setting a CBString as write protected will not prevent - it from being destroyed by the destructor. - - .......................................................................... - - void bwriteallow (struct tagbstring& t); - - Allow bstring to be written to via the bstrlib API. Note that such an - action makes the bstring both writable and destroyable. If the bstring is - not legitimately writable (as is the case for struct tagbstrings - initialized with a bsStatic value), the results of this are undefined. - - Note that invoking the bwriteallow macro may increase the number of - reallocs by one more than necessary for every call to bwriteallow - interleaved with any bstring API which writes to this bstring. - - .......................................................................... - - int biswriteprotected (struct tagbstring& t); - - Returns 1 if the bstring is write protected, otherwise 0 is returned. - -=============================================================================== - -The bstest module ------------------ - -The bstest module is just a unit test for the bstrlib module. For correct -implementations of bstrlib, it should execute with 0 failures being reported. -This test should be utilized if modifications/customizations to bstrlib have -been performed. It tests each core bstrlib function with bstrings of every -mode (read-only, NULL, static and mutable) and ensures that the expected -semantics are observed (including results that should indicate an error). It -also tests for aliasing support. Passing bstest is a necessary but not a -sufficient condition for ensuring the correctness of the bstrlib module. - - -The test module ---------------- - -The test module is just a unit test for the bstrwrap module. For correct -implementations of bstrwrap, it should execute with 0 failures being -reported. This test should be utilized if modifications/customizations to -bstrwrap have been performed. It tests each core bstrwrap function with -CBStrings write protected or not and ensures that the expected semantics are -observed (including expected exceptions.) Note that exceptions cannot be -disabled to run this test. Passing test is a necessary but not a sufficient -condition for ensuring the correctness of the bstrwrap module. - -=============================================================================== - -Using Bstring and CBString as an alternative to the C library -------------------------------------------------------------- - -First let us give a table of C library functions and the alternative bstring -functions and CBString methods that should be used instead of them. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -gets bgets ::gets -strcpy bassign = operator -strncpy bassignmidstr ::midstr -strcat bconcat += operator -strncat bconcat + btrunc += operator + ::trunc -strtok bsplit, bsplits ::split -sprintf b(assign)format ::format -snprintf b(assign)format + btrunc ::format + ::trunc -vsprintf bvformata bvformata - -vsnprintf bvformata + btrunc bvformata + btrunc -vfprintf bvformata + fputs use bvformata + fputs -strcmp biseq, bstrcmp comparison operators. -strncmp bstrncmp, memcmp bstrncmp, memcmp -strlen ->slen, blength ::length -strdup bstrcpy constructor -strset bpattern ::fill -strstr binstr ::find -strpbrk binchr ::findchr -stricmp bstricmp cast & use bstricmp -strlwr btolower cast & use btolower -strupr btoupper cast & use btoupper -strrev bReverse (aux module) cast & use bReverse -strchr bstrchr cast & use bstrchr -strspnp use strspn use strspn -ungetc bsunread bsunread - -The top 9 C functions listed here are troublesome in that they impose memory -management in the calling function. The Bstring and CBstring interfaces have -built-in memory management, so there is far less code with far less potential -for buffer overrun problems. strtok can only be reliably called as a "leaf" -calculation, since it (quite bizarrely) maintains hidden internal state. And -gets is well known to be broken no matter what. The Bstrlib alternatives do -not suffer from those sorts of problems. - -The substitute for strncat can be performed with higher performance by using -the blk2tbstr macro to create a presized second operand for bconcat. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -strspn strspn acceptable strspn acceptable -strcspn strcspn acceptable strcspn acceptable -strnset strnset acceptable strnset acceptable -printf printf acceptable printf acceptable -puts puts acceptable puts acceptable -fprintf fprintf acceptable fprintf acceptable -fputs fputs acceptable fputs acceptable -memcmp memcmp acceptable memcmp acceptable - -Remember that Bstring (and CBstring) functions will automatically append the -'\0' character to the character data buffer. So by simply accessing the data -buffer directly, ordinary C string library functions can be called directly -on them. Note that bstrcmp is not the same as memcmp in exactly the same way -that strcmp is not the same as memcmp. - -C-library Bstring alternative CBString alternative ---------- ------------------- -------------------- -fread balloc + fread ::alloc + fread -fgets balloc + fgets ::alloc + fgets - -These are odd ones because of the exact sizing of the buffer required. The -Bstring and CBString alternatives requires that the buffers are forced to -hold at least the prescribed length, then just use fread or fgets directly. -However, typically the automatic memory management of Bstring and CBstring -will make the typical use of fgets and fread to read specifically sized -strings unnecessary. - -Implementation Choices ----------------------- - -Overhead: -......... - -The bstring library has more overhead versus straight char buffers for most -functions. This overhead is essentially just the memory management and -string header allocation. This overhead usually only shows up for small -string manipulations. The performance loss has to be considered in -light of the following: - -1) What would be the performance loss of trying to write this management - code in one's own application? -2) Since the bstring library source code is given, a sufficiently powerful - modern inlining globally optimizing compiler can remove function call - overhead. - -Since the data type is exposed, a developer can replace any unsatisfactory -function with their own inline implementation. And that is besides the main -point of what the better string library is mainly meant to provide. Any -overhead lost has to be compared against the value of the safe abstraction -for coupling memory management and string functionality. - -Performance of the C interface: -............................... - -The algorithms used have performance advantages versus the analogous C -library functions. For example: - -1. bfromcstr/blk2str/bstrcpy versus strcpy/strdup. By using memmove instead - of strcpy, the break condition of the copy loop is based on an independent - counter (that should be allocated in a register) rather than having to - check the results of the load. Modern out-of-order executing CPUs can - parallelize the final branch mis-predict penality with the loading of the - source string. Some CPUs will also tend to have better built-in hardware - support for counted memory moves than load-compare-store. (This is a - minor, but non-zero gain.) -2. biseq versus strcmp. If the strings are unequal in length, bsiseq will - return in O(1) time. If the strings are aliased, or have aliased data - buffers, biseq will return in O(1) time. strcmp will always be O(k), - where k is the length of the common prefix or the whole string if they are - identical. -3. ->slen versus strlen. ->slen is obviously always O(1), while strlen is - always O(n) where n is the length of the string. -4. bconcat versus strcat. Both rely on precomputing the length of the - destination string argument, which will favor the bstring library. On - iterated concatenations the performance difference can be enormous. -5. bsreadln versus fgets. The bsreadln function reads large blocks at a time - from the given stream, then parses out lines from the buffers directly. - Some C libraries will implement fgets as a loop over single fgetc calls. - Testing indicates that the bsreadln approach can be several times faster - for fast stream devices (such as a file that has been entirely cached.) -6. bsplits/bsplitscb versus strspn. Accelerators for the set of match - characters are generated only once. -7. binstr versus strstr. The binstr implementation unrolls the loops to - help reduce loop overhead. This will matter if the target string is - long and source string is not found very early in the target string. - With strstr, while it is possible to unroll the source contents, it is - not possible to do so with the destination contents in a way that is - effective because every destination character must be tested against - '\0' before proceeding to the next character. -8. bReverse versus strrev. The C function must find the end of the string - first before swaping character pairs. -9. bstrrchr versus no comparable C function. Its not hard to write some C - code to search for a character from the end going backwards. But there - is no way to do this without computing the length of the string with - strlen. - -Practical testing indicates that in general Bstrlib is never signifcantly -slower than the C library for common operations, while very often having a -performance advantage that ranges from significant to massive. Even for -functions like b(n)inchr versus str(c)spn() (where, in theory, there is no -advantage for the Bstrlib architecture) the performance of Bstrlib is vastly -superior to most tested C library implementations. - -Some of Bstrlib's extra functionality also lead to inevitable performance -advantages over typical C solutions. For example, using the blk2tbstr macro, -one can (in O(1) time) generate an internal substring by reference while not -disturbing the original string. If disturbing the original string is not an -option, typically, a comparable char * solution would have to make a copy of -the substring to provide similar functionality. Another example is reverse -character set scanning -- the str(c)spn functions only scan in a forward -direction which can complicate some parsing algorithms. - -Where high performance char * based algorithms are available, Bstrlib can -still leverage them by accessing the ->data field on bstrings. So -realistically Bstrlib can never be significantly slower than any standard -'\0' terminated char * based solutions. - -Performance of the C++ interface: -................................. - -The C++ interface has been designed with an emphasis on abstraction and safety -first. However, since it is substantially a wrapper for the C bstring -functions, for longer strings the performance comments described in the -"Performance of the C interface" section above still apply. Note that the -(CBString *) type can be directly cast to a (bstring) type, and passed as -parameters to the C functions (though a CBString must never be passed to -bdestroy.) - -Probably the most controversial choice is performing full bounds checking on -the [] operator. This decision was made because 1) the fast alternative of -not bounds checking is still available by first casting the CBString to a -(const char *) buffer or to a (struct tagbstring) then derefencing .data and -2) because the lack of bounds checking is seen as one of the main weaknesses -of C/C++ versus other languages. This check being done on every access leads -to individual character extraction being actually slower than other languages -in this one respect (other language's compilers will normally dedicate more -resources on hoisting or removing bounds checking as necessary) but otherwise -bring C++ up to the level of other languages in terms of functionality. - -It is common for other C++ libraries to leverage the abstractions provided by -C++ to use reference counting and "copy on write" policies. While these -techniques can speed up some scenarios, they impose a problem with respect to -thread safety. bstrings and CBStrings can be properly protected with -"per-object" mutexes, meaning that two bstrlib calls can be made and execute -simultaneously, so long as the bstrings and CBstrings are distinct. With a -reference count and alias before copy on write policy, global mutexes are -required that prevent multiple calls to the strings library to execute -simultaneously regardless of whether or not the strings represent the same -string. - -One interesting trade off in CBString is that the default constructor is not -trivial. I.e., it always prepares a ready to use memory buffer. The purpose -is to ensure that there is a uniform internal composition for any functioning -CBString that is compatible with bstrings. It also means that the other -methods in the class are not forced to perform "late initialization" checks. -In the end it means that construction of CBStrings are slower than other -comparable C++ string classes. Initial testing, however, indicates that -CBString outperforms std::string and MFC's CString, for example, in all other -operations. So to work around this weakness it is recommended that CBString -declarations be pushed outside of inner loops. - -Practical testing indicates that with the exception of the caveats given -above (constructors and safe index character manipulations) the C++ API for -Bstrlib generally outperforms popular standard C++ string classes. Amongst -the standard libraries and compilers, the quality of concatenation operations -varies wildly and very little care has gone into search functions. Bstrlib -dominates those performance benchmarks. - -Memory management: -.................. - -The bstring functions which write and modify bstrings will automatically -reallocate the backing memory for the char buffer whenever it is required to -grow. The algorithm for resizing chosen is to snap up to sizes that are a -power of two which are sufficient to hold the intended new size. Memory -reallocation is not performed when the required size of the buffer is -decreased. This behavior can be relied on, and is necessary to make the -behaviour of balloc deterministic. This trades off additional memory usage -for decreasing the frequency for required reallocations: - -1. For any bstring whose size never exceeds n, its buffer is not ever - reallocated more than log_2(n) times for its lifetime. -2. For any bstring whose size never exceeds n, its buffer is never more than - 2*(n+1) in length. (The extra characters beyond 2*n are to allow for the - implicit '\0' which is always added by the bstring modifying functions.) - -Decreasing the buffer size when the string decreases in size would violate 1) -above and in real world case lead to pathological heap thrashing. Similarly, -allocating more tightly than "least power of 2 greater than necessary" would -lead to a violation of 1) and have the same potential for heap thrashing. - -Property 2) needs emphasizing. Although the memory allocated is always a -power of 2, for a bstring that grows linearly in size, its buffer memory also -grows linearly, not exponentially. The reason is that the amount of extra -space increases with each reallocation, which decreases the frequency of -future reallocations. - -Obviously, given that bstring writing functions may reallocate the data -buffer backing the target bstring, one should not attempt to cache the data -buffer address and use it after such bstring functions have been called. -This includes making reference struct tagbstrings which alias to a writable -bstring. - -balloc or bfromcstralloc can be used to preallocate the minimum amount of -space used for a given bstring. This will reduce even further the number of -times the data portion is reallocated. If the length of the string is never -more than one less than the memory length then there will be no further -reallocations. - -Note that invoking the bwriteallow macro may increase the number of reallocs -by one more than necessary for every call to bwriteallow interleaved with any -bstring API which writes to this bstring. - -The library does not use any mechanism for automatic clean up for the C API. -Thus explicit clean up via calls to bdestroy() are required to avoid memory -leaks. - -Constant and static tagbstrings: -................................ - -A struct tagbstring can be write protected from any bstrlib function using -the bwriteprotect macro. A write protected struct tagbstring can then be -reset to being writable via the bwriteallow macro. There is, of course, no -protection from attempts to directly access the bstring members. Modifying a -bstring which is write protected by direct access has undefined behavior. - -static struct tagbstrings can be declared via the bsStatic macro. They are -considered permanently unwritable. Such struct tagbstrings's are declared -such that attempts to write to it are not well defined. Invoking either -bwriteallow or bwriteprotect on static struct tagbstrings has no effect. - -struct tagbstring's initialized via btfromcstr or blk2tbstr are protected by -default but can be made writeable via the bwriteallow macro. If bwriteallow -is called on such struct tagbstring's, it is the programmer's responsibility -to ensure that: - -1) the buffer supplied was allocated from the heap. -2) bdestroy is not called on this tagbstring (unless the header itself has - also been allocated from the heap.) -3) free is called on the buffer to reclaim its memory. - -bwriteallow and bwriteprotect can be invoked on ordinary bstrings (they have -to be dereferenced with the (*) operator to get the levels of indirection -correct) to give them write protection. - -Buffer declaration: -................... - -The memory buffer is actually declared "unsigned char *" instead of "char *". -The reason for this is to trigger compiler warnings whenever uncasted char -buffers are assigned to the data portion of a bstring. This will draw more -diligent programmers into taking a second look at the code where they -have carelessly left off the typically required cast. (Research from -AT&T/Lucent indicates that additional programmer eyeballs is one of the most -effective mechanisms at ferreting out bugs.) - -Function pointers: -.................. - -The bgets, bread and bStream functions use function pointers to obtain -strings from data streams. The function pointer declarations have been -specifically chosen to be compatible with the fgetc and fread functions. -While this may seem to be a convoluted way of implementing fgets and fread -style functionality, it has been specifically designed this way to ensure -that there is no dependency on a single narrowly defined set of device -interfaces, such as just stream I/O. In the embedded world, its quite -possible to have environments where such interfaces may not exist in the -standard C library form. Furthermore, the generalization that this opens up -allows for more sophisticated uses for these functions (performing an fgets -like function on a socket, for example.) By using function pointers, it also -allows such abstract stream interfaces to be created using the bstring library -itself while not creating a circular dependency. - -Use of int's for sizes: -....................... - -This is just a recognition that 16bit platforms with requirements for strings -that are larger than 64K and 32bit+ platforms with requirements for strings -that are larger than 4GB are pretty marginal. The main focus is for 32bit -platforms, and emerging 64bit platforms with reasonable < 4GB string -requirements. Using ints allows for negative values which has meaning -internally to bstrlib. - -Semantic consideration: -....................... - -Certain care needs to be taken when copying and aliasing bstrings. A bstring -is essentially a pointer type which points to a multipart abstract data -structure. Thus usage, and lifetime of bstrings have semantics that follow -these considerations. For example: - - bstring a, b; - struct tagbstring t; - - a = bfromcstr("Hello"); /* Create new bstring and copy "Hello" into it. */ - b = a; /* Alias b to the contents of a. */ - t = *a; /* Create a current instance pseudo-alias of a. */ - bconcat (a, b); /* Double a and b, t is now undefined. */ - bdestroy (a); /* Destroy the contents of both a and b. */ - -Variables of type bstring are really just references that point to real -bstring objects. The equal operator (=) creates aliases, and the asterisk -dereference operator (*) creates a kind of alias to the current instance (which -is generally not useful for any purpose.) Using bstrcpy() is the correct way -of creating duplicate instances. The ampersand operator (&) is useful for -creating aliases to struct tagbstrings (remembering that constructed struct -tagbstrings are not writable by default.) - -CBStrings use complete copy semantics for the equal operator (=), and thus do -not have these sorts of issues. - -Debugging: -.......... - -Bstrings have a simple, exposed definition and construction, and the library -itself is open source. So most debugging is going to be fairly straight- -forward. But the memory for bstrings come from the heap, which can often be -corrupted indirectly, and it might not be obvious what has happened even from -direct examination of the contents in a debugger or a core dump. There are -some tools such as Purify, Insure++ and Electric Fence which can help solve -such problems, however another common approach is to directly instrument the -calls to malloc, realloc, calloc, free, memcpy, memmove and/or other calls -by overriding them with macro definitions. - -Although the user could hack on the Bstrlib sources directly as necessary to -perform such an instrumentation, Bstrlib comes with a built-in mechanism for -doing this. By defining the macro BSTRLIB_MEMORY_DEBUG and providing an -include file named memdbg.h this will force the core Bstrlib modules to -attempt to include this file. In such a file, macros could be defined which -overrides Bstrlib's useage of the C standard library. - -Rather than calling malloc, realloc, free, memcpy or memmove directly, Bstrlib -emits the macros bstr__alloc, bstr__realloc, bstr__free, bstr__memcpy and -bstr__memmove in their place respectively. By default these macros are simply -assigned to be equivalent to their corresponding C standard library function -call. However, if they are given earlier macro definitions (via the back -door include file) they will not be given their default definition. In this -way Bstrlib's interface to the standard library can be changed but without -having to directly redefine or link standard library symbols (both of which -are not strictly ANSI C compliant.) - -An example definition might include: - - #define bstr__alloc(sz) X_malloc ((sz), __LINE__, __FILE__) - -which might help contextualize heap entries in a debugging environment. - -The NULL parameter and sanity checking of bstrings is part of the Bstrlib -API, and thus Bstrlib itself does not present any different modes which would -correspond to "Debug" or "Release" modes. Bstrlib always contains mechanisms -which one might think of as debugging features, but retains the performance -and small memory footprint one would normally associate with release mode -code. - -Integration Microsoft's Visual Studio debugger: -............................................... - -Microsoft's Visual Studio debugger has a capability of customizable mouse -float over data type descriptions. This is accomplished by editting the -AUTOEXP.DAT file to include the following: - - ; new for CBString - tagbstring =slen=<slen> mlen=<mlen> <data,st> - Bstrlib::CBStringList =count=<size()> - -In Visual C++ 6.0 this file is located in the directory: - - C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin - -and in Visual Studio .NET 2003 its located here: - - C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger - -This will improve the ability of debugging with Bstrlib under Visual Studio. - -Security --------- - -Bstrlib does not come with explicit security features outside of its fairly -comprehensive error detection, coupled with its strict semantic support. -That is to say that certain common security problems, such as buffer overrun, -constant overwrite, arbitrary truncation etc, are far less likely to happen -inadvertently. Where it does help, Bstrlib maximizes its advantage by -providing developers a simple adoption path that lets them leave less secure -string mechanisms behind. The library will not leave developers wanting, so -they will be less likely to add new code using a less secure string library -to add functionality that might be missing from Bstrlib. - -That said there are a number of security ideas not addressed by Bstrlib: - -1. Race condition exploitation (i.e., verifying a string's contents, then -raising the privilege level and execute it as a shell command as two -non-atomic steps) is well beyond the scope of what Bstrlib can provide. It -should be noted that MFC's built-in string mutex actually does not solve this -problem either -- it just removes immediate data corruption as a possible -outcome of such exploit attempts (it can be argued that this is worse, since -it will leave no trace of the exploitation). In general race conditions have -to be dealt with by careful design and implementation; it cannot be assisted -by a string library. - -2. Any kind of access control or security attributes to prevent usage in -dangerous interfaces such as system(). Perl includes a "trust" attribute -which can be endowed upon strings that are intended to be passed to such -dangerous interfaces. However, Perl's solution reflects its own limitations --- notably that it is not a strongly typed language. In the example code for -Bstrlib, there is a module called taint.cpp. It demonstrates how to write a -simple wrapper class for managing "untainted" or trusted strings using the -type system to prevent questionable mixing of ordinary untrusted strings with -untainted ones then passing them to dangerous interfaces. In this way the -security correctness of the code reduces to auditing the direct usages of -dangerous interfaces or promotions of tainted strings to untainted ones. - -3. Encryption of string contents is way beyond the scope of Bstrlib. -Maintaining encrypted string contents in the futile hopes of thwarting things -like using system-level debuggers to examine sensitive string data is likely -to be a wasted effort (imagine a debugger that runs at a higher level than a -virtual processor where the application runs). For more standard encryption -usages, since the bstring contents are simply binary blocks of data, this -should pose no problem for usage with other standard encryption libraries. - -Compatibility -------------- - -The Better String Library is known to compile and function correctly with the -following compilers: - - - Microsoft Visual C++ - - Watcom C/C++ - - Intel's C/C++ compiler (Windows) - - The GNU C/C++ compiler (cygwin and Linux on PPC64) - - Borland C - - Turbo C - -Setting of configuration options should be unnecessary for these compilers -(unless exceptions are being disabled or STLport has been added to WATCOM -C/C++). Bstrlib has been developed with an emphasis on portability. As such -porting it to other compilers should be straight forward. This package -includes a porting guide (called porting.txt) which explains what issues may -exist for porting Bstrlib to different compilers and environments. - -ANSI issues ------------ - -1. The function pointer types bNgetc and bNread have prototypes which are very -similar to, but not exactly the same as fgetc and fread respectively. -Basically the FILE * parameter is replaced by void *. The purpose of this -was to allow one to create other functions with fgetc and fread like -semantics without being tied to ANSI C's file streaming mechanism. I.e., one -could very easily adapt it to sockets, or simply reading a block of memory, -or procedurally generated strings (for fractal generation, for example.) - -The problem is that invoking the functions (bNgetc)fgetc and (bNread)fread is -not technically legal in ANSI C. The reason being that the compiler is only -able to coerce the function pointers themselves into the target type, however -are unable to perform any cast (implicit or otherwise) on the parameters -passed once invoked. I.e., if internally void * and FILE * need some kind of -mechanical coercion, the compiler will not properly perform this conversion -and thus lead to undefined behavior. - -Apparently a platform from Data General called "Eclipse" and another from -Tandem called "NonStop" have a different representation for pointers to bytes -and pointers to words, for example, where coercion via casting is necessary. -(Actual confirmation of the existence of such machines is hard to come by, so -it is prudent to be skeptical about this information.) However, this is not -an issue for any known contemporary platforms. One may conclude that such -platforms are effectively apocryphal even if they do exist. - -To correctly work around this problem to the satisfaction of the ANSI -limitations, one needs to create wrapper functions for fgets and/or -fread with the prototypes of bNgetc and/or bNread respectively which performs -no other action other than to explicitely cast the void * parameter to a -FILE *, and simply pass the remaining parameters straight to the function -pointer call. - -The wrappers themselves are trivial: - - size_t freadWrap (void * buff, size_t esz, size_t eqty, void * parm) { - return fread (buff, esz, eqty, (FILE *) parm); - } - - int fgetcWrap (void * parm) { - return fgetc ((FILE *) parm); - } - -These have not been supplied in bstrlib or bstraux to prevent unnecessary -linking with file I/O functions. - -2. vsnprintf is not available on all compilers. Because of this, the bformat -and bformata functions (and format and formata methods) are not guaranteed to -work properly. For those compilers that don't have vsnprintf, the -BSTRLIB_NOVSNP macro should be set before compiling bstrlib, and the format -functions/method will be disabled. - -The more recent ANSI C standards have specified the required inclusion of a -vsnprintf function. - -3. The bstrlib function names are not unique in the first 6 characters. This -is only an issue for older C compiler environments which do not store more -than 6 characters for function names. - -4. The bsafe module defines macros and function names which are part of the -C library. This simply overrides the definition as expected on all platforms -tested, however it is not sanctioned by the ANSI standard. This module is -clearly optional and should be omitted on platforms which disallow its -undefined semantics. - -In practice the real issue is that some compilers in some modes of operation -can/will inline these standard library functions on a module by module basis -as they appear in each. The linker will thus have no opportunity to override -the implementation of these functions for those cases. This can lead to -inconsistent behaviour of the bsafe module on different platforms and -compilers. - -=============================================================================== - -Comparison with Microsoft's CString class ------------------------------------------ - -Although developed independently, CBStrings have very similar functionality to -Microsoft's CString class. However, the bstring library has significant -advantages over CString: - -1. Bstrlib is a C-library as well as a C++ library (using the C++ wrapper). - - - Thus it is compatible with more programming environments and - available to a wider population of programmers. - -2. The internal structure of a bstring is considered exposed. - - - A single contiguous block of data can be cut into read-only pieces by - simply creating headers, without allocating additional memory to create - reference copies of each of these sub-strings. - - In this way, using bstrings in a totally abstracted way becomes a choice - rather than an imposition. Further this choice can be made differently - at different layers of applications that use it. - -3. Static declaration support precludes the need for constructor - invocation. - - - Allows for static declarations of constant strings that has no - additional constructor overhead. - -4. Bstrlib is not attached to another library. - - - Bstrlib is designed to be easily plugged into any other library - collection, without dependencies on other libraries or paradigms (such - as "MFC".) - -The bstring library also comes with a few additional functions that are not -available in the CString class: - - - bsetstr - - bsplit - - bread - - breplace (this is different from CString::Replace()) - - Writable indexed characters (for example a[i]='x') - -Interestingly, although Microsoft did implement mid$(), left$() and right$() -functional analogues (these are functions from GWBASIC) they seem to have -forgotten that mid$() could be also used to write into the middle of a string. -This functionality exists in Bstrlib with the bsetstr() and breplace() -functions. - -Among the disadvantages of Bstrlib is that there is no special support for -localization or wide characters. Such things are considered beyond the scope -of what bstrings are trying to deliver. CString essentially supports the -older UCS-2 version of Unicode via widechar_t as an application-wide compile -time switch. - -CString's also use built-in mechanisms for ensuring thread safety under all -situations. While this makes writing thread safe code that much easier, this -built-in safety feature has a price -- the inner loops of each CString method -runs in its own critical section (grabbing and releasing a light weight mutex -on every operation.) The usual way to decrease the impact of a critical -section performance penalty is to amortize more operations per critical -section. But since the implementation of CStrings is fixed as a one critical -section per-operation cost, there is no way to leverage this common -performance enhancing idea. - -The search facilities in Bstrlib are comparable to those in MFC's CString -class, though it is missing locale specific collation. But because Bstrlib -is interoperable with C's char buffers, it will allow programmers to write -their own string searching mechanism (such as Boyer-Moore), or be able to -choose from a variety of available existing string searching libraries (such -as those for regular expressions) without difficulty. - -Microsoft used a very non-ANSI conforming trick in its implementation to -allow printf() to use the "%s" specifier to output a CString correctly. This -can be convenient, but it is inherently not portable. CBString requires an -explicit cast, while bstring requires the data member to be dereferenced. -Microsoft's own documentation recommends casting, instead of relying on this -feature. - -Comparison with C++'s std::string ---------------------------------- - -This is the C++ language's standard STL based string class. - -1. There is no C implementation. -2. The [] operator is not bounds checked. -3. Missing a lot of useful functions like printf-like formatting. -4. Some sub-standard std::string implementations (SGI) are necessarily unsafe - to use with multithreading. -5. Limited by STL's std::iostream which in turn is limited by ifstream which - can only take input from files. (Compare to CBStream's API which can take - abstracted input.) -6. Extremely uneven performance across implementations. - -Comparison with ISO C TR 24731 proposal ---------------------------------------- - -Following the ISO C99 standard, Microsoft has proposed a group of C library -extensions which are supposedly "safer and more secure". This proposal is -expected to be adopted by the ISO C standard which follows C99. - -The proposal reveals itself to be very similar to Microsoft's "StrSafe" -library. The functions are basically the same as other standard C library -string functions except that destination parameters are paired with an -additional length parameter of type rsize_t. rsize_t is the same as size_t, -however, the range is checked to make sure its between 1 and RSIZE_MAX. Like -Bstrlib, the functions perform a "parameter check". Unlike Bstrlib, when a -parameter check fails, rather than simply outputing accumulatable error -statuses, they call a user settable global error function handler, and upon -return of control performs no (additional) detrimental action. The proposal -covers basic string functions as well as a few non-reenterable functions -(asctime, ctime, and strtok). - -1. Still based solely on char * buffers (and therefore strlen() and strcat() - is still O(n), and there are no faster streq() comparison functions.) -2. No growable string semantics. -3. Requires manual buffer length synchronization in the source code. -4. No attempt to enhance functionality of the C library. -5. Introduces a new error scenario (strings exceeding RSIZE_MAX length). - -The hope is that by exposing the buffer length requirements there will be -fewer buffer overrun errors. However, the error modes are really just -transformed, rather than removed. The real problem of buffer overflows is -that they all happen as a result of erroneous programming. So forcing -programmers to manually deal with buffer limits, will make them more aware of -the problem but doesn't remove the possibility of erroneous programming. So -a programmer that erroneously mixes up the rsize_t parameters is no better off -from a programmer that introduces potential buffer overflows through other -more typical lapses. So at best this may reduce the rate of erroneous -programming, rather than making any attempt at removing failure modes. - -The error handler can discriminate between types of failures, but does not -take into account any callsite context. So the problem is that the error is -going to be manifest in a piece of code, but there is no pointer to that -code. It would seem that passing in the call site __FILE__, __LINE__ as -parameters would be very useful, but the API clearly doesn't support such a -thing (it would increase code bloat even more than the extra length -parameter does, and would require macro tricks to implement). - -The Bstrlib C API takes the position that error handling needs to be done at -the callsite, and just tries to make it as painless as possible. Furthermore, -error modes are removed by supporting auto-growing strings and aliasing. For -capturing errors in more central code fragments, Bstrlib's C++ API uses -exception handling extensively, which is superior to the leaf-only error -handler approach. - -Comparison with Managed String Library CERT proposal ----------------------------------------------------- - -The main webpage for the managed string library: -http://www.cert.org/secure-coding/managedstring.html - -Robert Seacord at CERT has proposed a C string library that he calls the -"Managed String Library" for C. Like Bstrlib, it introduces a new type -which is called a managed string. The structure of a managed string -(string_m) is like a struct tagbstring but missing the length field. This -internal structure is considered opaque. The length is, like the C standard -library, always computed on the fly by searching for a terminating NUL on -every operation that requires it. So it suffers from every performance -problem that the C standard library suffers from. Interoperating with C -string APIs (like printf, fopen, or anything else that takes a string -parameter) requires copying to additionally allocating buffers that have to -be manually freed -- this makes this library probably slower and more -cumbersome than any other string library in existence. - -The library gives a fully populated error status as the return value of every -string function. The hope is to be able to diagnose all problems -specifically from the return code alone. Comparing this to Bstrlib, which -aways returns one consistent error message, might make it seem that Bstrlib -would be harder to debug; but this is not true. With Bstrlib, if an error -occurs there is always enough information from just knowing there was an error -and examining the parameters to deduce exactly what kind of error has -happened. The managed string library thus gives up nested function calls -while achieving little benefit, while Bstrlib does not. - -One interesting feature that "managed strings" has is the idea of data -sanitization via character set whitelisting. That is to say, a globally -definable filter that makes any attempt to put invalid characters into strings -lead to an error and not modify the string. The author gives the following -example: - - // create valid char set - if (retValue = strcreate_m(&str1, "abc") ) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - if (retValue = setcharset(str1)) { - fprintf( - stderr, - "Error %d from setcharset().\n", - retValue - ); - } - if (retValue = strcreate_m(&str1, "aabbccabc")) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - // create string with invalid char set - if (retValue = strcreate_m(&str1, "abbccdabc")) { - fprintf( - stderr, - "Error %d from strcreate_m.\n", - retValue - ); - } - -Which we can compare with a more Bstrlib way of doing things: - - bstring bCreateWithFilter (const char * cstr, const_bstring filter) { - bstring b = bfromcstr (cstr); - if (BSTR_ERR != bninchr (b, filter) && NULL != b) { - fprintf (stderr, "Filter violation.\n"); - bdestroy (b); - b = NULL; - } - return b; - } - - struct tagbstring charFilter = bsStatic ("abc"); - bstring str1 = bCreateWithFilter ("aabbccabc", &charFilter); - bstring str2 = bCreateWithFilter ("aabbccdabc", &charFilter); - -The first thing we should notice is that with the Bstrlib approach you can -have different filters for different strings if necessary. Furthermore, -selecting a charset filter in the Managed String Library is uni-contextual. -That is to say, there can only be one such filter active for the entire -program, which means its usage is not well defined for intermediate library -usage (a library that uses it will interfere with user code that uses it, and -vice versa.) It is also likely to be poorly defined in multi-threading -environments. - -There is also a question as to whether the data sanitization filter is checked -on every operation, or just on creation operations. Since the charset can be -set arbitrarily at run time, it might be set *after* some managed strings have -been created. This would seem to imply that all functions should run this -additional check every time if there is an attempt to enforce this. This -would make things tremendously slow. On the other hand, if it is assumed that -only creates and other operations that take char *'s as input need be checked -because the charset was only supposed to be called once at and before any -other managed string was created, then one can see that its easy to cover -Bstrlib with equivalent functionality via a few wrapper calls such as the -example given above. - -And finally we have to question the value of sanitation in the first place. -For example, for httpd servers, there is generally a requirement that the -URLs parsed have some form that avoids undesirable translation to local file -system filenames or resources. The problem is that the way URLs can be -encoded, it must be completely parsed and translated to know if it is using -certain invalid character combinations. That is to say, merely filtering -each character one at a time is not necessarily the right way to ensure that -a string has safe contents. - -In the article that describes this proposal, it is claimed that it fairly -closely approximates the existing C API semantics. On this point we should -compare this "closeness" with Bstrlib: - - Bstrlib Managed String Library - ------- ---------------------- - -Pointer arithmetic Segment arithmetic N/A - -Use in C Std lib ->data, or bdata{e} getstr_m(x,*) ... free(x) - -String literals bsStatic, bsStaticBlk strcreate_m() - -Transparency Complete None - -Its pretty clear that the semantic mapping from C strings to Bstrlib is fairly -straightforward, and that in general semantic capabilities are the same or -superior in Bstrlib. On the other hand the Managed String Library is either -missing semantics or changes things fairly significantly. - -Comparison with Annexia's c2lib library ---------------------------------------- - -This library is available at: -http://www.annexia.org/freeware/c2lib - -1. Still based solely on char * buffers (and therefore strlen() and strcat() - is still O(n), and there are no faster streq() comparison functions.) - Their suggestion that alternatives which wrap the string data type (such as - bstring does) imposes a difficulty in interoperating with the C langauge's - ordinary C string library is not founded. -2. Introduction of memory (and vector?) abstractions imposes a learning - curve, and some kind of memory usage policy that is outside of the strings - themselves (and therefore must be maintained by the developer.) -3. The API is massive, and filled with all sorts of trivial (pjoin) and - controvertial (pmatch -- regular expression are not sufficiently - standardized, and there is a very large difference in performance between - compiled and non-compiled, REs) functions. Bstrlib takes a decidely - minimal approach -- none of the functionality in c2lib is difficult or - challenging to implement on top of Bstrlib (except the regex stuff, which - is going to be difficult, and controvertial no matter what.) -4. Understanding why c2lib is the way it is pretty much requires a working - knowledge of Perl. bstrlib requires only knowledge of the C string library - while providing just a very select few worthwhile extras. -5. It is attached to a lot of cruft like a matrix math library (that doesn't - include any functions for getting the determinant, eigenvectors, - eigenvalues, the matrix inverse, test for singularity, test for - orthogonality, a grahm schmit orthogonlization, LU decomposition ... I - mean why bother?) - -Convincing a development house to use c2lib is likely quite difficult. It -introduces too much, while not being part of any kind of standards body. The -code must therefore be trusted, or maintained by those that use it. While -bstring offers nothing more on this front, since its so much smaller, covers -far less in terms of scope, and will typically improve string performance, -the barrier to usage should be much smaller. - -Comparison with stralloc/qmail ------------------------------- - -More information about this library can be found here: -http://www.canonical.org/~kragen/stralloc.html or here: -http://cr.yp.to/lib/stralloc.html - -1. Library is very very minimal. A little too minimal. -2. Untargetted source parameters are not declared const. -3. Slightly different expected emphasis (like _cats function which takes an - ordinary C string char buffer as a parameter.) Its clear that the - remainder of the C string library is still required to perform more - useful string operations. - -The struct declaration for their string header is essentially the same as that -for bstring. But its clear that this was a quickly written hack whose goals -are clearly a subset of what Bstrlib supplies. For anyone who is served by -stralloc, Bstrlib is complete substitute that just adds more functionality. - -stralloc actually uses the interesting policy that a NULL data pointer -indicates an empty string. In this way, non-static empty strings can be -declared without construction. This advantage is minimal, since static empty -bstrings can be declared inline without construction, and if the string needs -to be written to it should be constructed from an empty string (or its first -initializer) in any event. - -wxString class --------------- - -This is the string class used in the wxWindows project. A description of -wxString can be found here: -http://www.wxwindows.org/manuals/2.4.2/wx368.htm#wxstring - -This C++ library is similar to CBString. However, it is littered with -trivial functions (IsAscii, UpperCase, RemoveLast etc.) - -1. There is no C implementation. -2. The memory management strategy is to allocate a bounded fixed amount of - additional space on each resize, meaning that it does not have the - log_2(n) property that Bstrlib has (it will thrash very easily, cause - massive fragmentation in common heap implementations, and can easily be a - common source of performance problems). -3. The library uses a "copy on write" strategy, meaning that it has to deal - with multithreading problems. - -Vstr ----- - -This is a highly orthogonal C string library with an emphasis on -networking/realtime programming. It can be found here: -http://www.and.org/vstr/ - -1. The convoluted internal structure does not contain a '\0' char * compatible - buffer, so interoperability with the C library a non-starter. -2. The API and implementation is very large (owing to its orthogonality) and - can lead to difficulty in understanding its exact functionality. -3. An obvious dependency on gnu tools (confusing make configure step) -4. Uses a reference counting system, meaning that it is not likely to be - thread safe. - -The implementation has an extreme emphasis on performance for nontrivial -actions (adds, inserts and deletes are all constant or roughly O(#operations) -time) following the "zero copy" principle. This trades off performance of -trivial functions (character access, char buffer access/coersion, alias -detection) which becomes significantly slower, as well as incremental -accumulative costs for its searching/parsing functions. Whether or not Vstr -wins any particular performance benchmark will depend a lot on the benchmark, -but it should handily win on some, while losing dreadfully on others. - -The learning curve for Vstr is very steep, and it doesn't come with any -obvious way to build for Windows or other platforms without gnu tools. At -least one mechanism (the iterator) introduces a new undefined scenario -(writing to a Vstr while iterating through it.) Vstr has a very large -footprint, and is very ambitious in its total functionality. Vstr has no C++ -API. - -Vstr usage requires context initialization via vstr_init() which must be run -in a thread-local context. Given the totally reference based architecture -this means that sharing Vstrings across threads is not well defined, or at -least not safe from race conditions. This API is clearly geared to the older -standard of fork() style multitasking in UNIX, and is not safely transportable -to modern shared memory multithreading available in Linux and Windows. There -is no portable external solution making the library thread safe (since it -requires a mutex around each Vstr context -- not each string.) - -In the documentation for this library, a big deal is made of its self hosted -s(n)printf-like function. This is an issue for older compilers that don't -include vsnprintf(), but also an issue because Vstr has a slow conversion to -'\0' terminated char * mechanism. That is to say, using "%s" to format data -that originates from Vstr would be slow without some sort of native function -to do so. Bstrlib sidesteps the issue by relying on what snprintf-like -functionality does exist and having a high performance conversion to a char * -compatible string so that "%s" can be used directly. - -Str Library ------------ - -This is a fairly extensive string library, that includes full unicode support -and targetted at the goal of out performing MFC and STL. The architecture, -similarly to MFC's CStrings, is a copy on write reference counting mechanism. - -http://www.utilitycode.com/str/default.aspx - -1. Commercial. -2. C++ only. - -This library, like Vstr, uses a ref counting system. There is only so deeply -I can analyze it, since I don't have a license for it. However, performance -improvements over MFC's and STL, doesn't seem like a sufficient reason to -move your source base to it. For example, in the future, Microsoft may -improve the performance CString. - -It should be pointed out that performance testing of Bstrlib has indicated -that its relative performance advantage versus MFC's CString and STL's -std::string is at least as high as that for the Str library. - -libmib astrings ---------------- - -A handful of functional extensions to the C library that add dynamic string -functionality. -http://www.mibsoftware.com/libmib/astring/ - -This package basically references strings through char ** pointers and assumes -they are pointing to the top of an allocated heap entry (or NULL, in which -case memory will be newly allocated from the heap.) So its still up to user -to mix and match the older C string functions with these functions whenever -pointer arithmetic is used (i.e., there is no leveraging of the type system -to assert semantic differences between references and base strings as Bstrlib -does since no new types are introduced.) Unlike Bstrlib, exact string length -meta data is not stored, thus requiring a strlen() call on *every* string -writing operation. The library is very small, covering only a handful of C's -functions. - -While this is better than nothing, it is clearly slower than even the -standard C library, less safe and less functional than Bstrlib. - -To explain the advantage of using libmib, their website shows an example of -how dangerous C code: - - char buf[256]; - char *pszExtraPath = ";/usr/local/bin"; - - strcpy(buf,getenv("PATH")); /* oops! could overrun! */ - strcat(buf,pszExtraPath); /* Could overrun as well! */ - - printf("Checking...%s\n",buf); /* Some printfs overrun too! */ - -is avoided using libmib: - - char *pasz = 0; /* Must initialize to 0 */ - char *paszOut = 0; - char *pszExtraPath = ";/usr/local/bin"; - - if (!astrcpy(&pasz,getenv("PATH"))) /* malloc error */ exit(-1); - if (!astrcat(&pasz,pszExtraPath)) /* malloc error */ exit(-1); - - /* Finally, a "limitless" printf! we can use */ - asprintf(&paszOut,"Checking...%s\n",pasz);fputs(paszOut,stdout); - - astrfree(&pasz); /* Can use free(pasz) also. */ - astrfree(&paszOut); - -However, compare this to Bstrlib: - - bstring b, out; - - bcatcstr (b = bfromcstr (getenv ("PATH")), ";/usr/local/bin"); - out = bformat ("Checking...%s\n", bdatae (b, "<Out of memory>")); - /* if (out && b) */ fputs (bdatae (out, "<Out of memory>"), stdout); - bdestroy (b); - bdestroy (out); - -Besides being shorter, we can see that error handling can be deferred right -to the very end. Also, unlike the above two versions, if getenv() returns -with NULL, the Bstrlib version will not exhibit undefined behavior. -Initialization starts with the relevant content rather than an extra -autoinitialization step. - -libclc ------- - -An attempt to add to the standard C library with a number of common useful -functions, including additional string functions. -http://libclc.sourceforge.net/ - -1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass - the responsibility to guard against aliasing to the programmer. -2. Adds no safety or memory management whatsoever. -3. Most of the supplied string functions are completely trivial. - -The goals of libclc and Bstrlib are clearly quite different. - -fireString ----------- - -http://firestuff.org/ - -1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass - the responsibility to guard against aliasing to the programmer. -2. Mixes char * and length wrapped buffers (estr) functions, doubling the API - size, with safety limited to only half of the functions. - -Firestring was originally just a wrapper of char * functionality with extra -length parameters. However, it has been augmented with the inclusion of the -estr type which has similar functionality to stralloc. But firestring does -not nearly cover the functional scope of Bstrlib. - -Safe C String Library ---------------------- - -A library written for the purpose of increasing safety and power to C's string -handling capabilities. -http://www.zork.org/safestr/safestr.html - -1. While the safestr_* functions are safe in of themselves, interoperating - with char * string has dangerous unsafe modes of operation. -2. The architecture of safestr's causes the base pointer to change. Thus, - its not practical/safe to store a safestr in multiple locations if any - single instance can be manipulated. -3. Dependent on an additional error handling library. -4. Uses reference counting, meaning that it is either not thread safe or - slow and not portable. - -I think the idea of reallocating (and hence potentially changing) the base -pointer is a serious design flaw that is fatal to this architecture. True -safety is obtained by having automatic handling of all common scenarios -without creating implicit constraints on the user. - -Because of its automatic temporary clean up system, it cannot use "const" -semantics on input arguments. Interesting anomolies such as: - - safestr_t s, t; - s = safestr_replace (t = SAFESTR_TEMP ("This is a test"), - SAFESTR_TEMP (" "), SAFESTR_TEMP (".")); - /* t is now undefined. */ - -are possible. If one defines a function which takes a safestr_t as a -parameter, then the function would not know whether or not the safestr_t is -defined after it passes it to a safestr library function. The author -recommended method for working around this problem is to examine the -attributes of the safestr_t within the function which is to modify any of -its parameters and play games with its reference count. I think, therefore, -that the whole SAFESTR_TEMP idea is also fatally broken. - -The library implements immutability, optional non-resizability, and a "trust" -flag. This trust flag is interesting, and suggests that applying any -arbitrary sequence of safestr_* function calls on any set of trusted strings -will result in a trusted string. It seems to me, however, that if one wanted -to implement a trusted string semantic, one might do so by actually creating -a different *type* and only implement the subset of string functions that are -deemed safe (i.e., user input would be excluded, for example.) This, in -essence, would allow the compiler to enforce trust propogation at compile -time rather than run time. Non-resizability is also interesting, however, -it seems marginal (i.e., to want a string that cannot be resized, yet can be -modified and yet where a fixed sized buffer is undesirable.) - -=============================================================================== - -Examples --------- - - Dumping a line numbered file: - - FILE * fp; - int i, ret; - struct bstrList * lines; - struct tagbstring prefix = bsStatic ("-> "); - - if (NULL != (fp = fopen ("bstrlib.txt", "rb"))) { - bstring b = bread ((bNread) fread, fp); - fclose (fp); - if (NULL != (lines = bsplit (b, '\n'))) { - for (i=0; i < lines->qty; i++) { - binsert (lines->entry[i], 0, &prefix, '?'); - printf ("%04d: %s\n", i, bdatae (lines->entry[i], "NULL")); - } - bstrListDestroy (lines); - } - bdestroy (b); - } - -For numerous other examples, see bstraux.c, bstraux.h and the example archive. - -=============================================================================== - -License -------- - -The Better String Library is available under either the 3 clause BSD license -(see the accompanying license.txt) or the Gnu Public License version 2 (see -the accompanying gpl.txt) at the option of the user. - -=============================================================================== - -Acknowledgements ----------------- - -The following individuals have made significant contributions to the design -and testing of the Better String Library: - -Bjorn Augestad -Clint Olsen -Darryl Bleau -Fabian Cenedese -Graham Wideman -Ignacio Burgueno -International Business Machines Corporation -Ira Mica -John Kortink -Manuel Woelker -Marcel van Kervinck -Michael Hsieh -Richard A. Smith -Simon Ekstrom -Wayne Scott - -=============================================================================== diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt deleted file mode 100644 index cf78a984cc..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt +++ /dev/null @@ -1,29 +0,0 @@ -Copyright (c) 2002-2008 Paul Hsieh -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Neither the name of bstrlib nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt deleted file mode 100644 index 11d8d13130..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt +++ /dev/null @@ -1,172 +0,0 @@ -Better String library Porting Guide ------------------------------------ - -by Paul Hsieh - -The bstring library is an attempt to provide improved string processing -functionality to the C and C++ language. At the heart of the bstring library -is the management of "bstring"s which are a significant improvement over '\0' -terminated char buffers. See the accompanying documenation file bstrlib.txt -for more information. - -=============================================================================== - -Identifying the Compiler ------------------------- - -Bstrlib has been tested on the following compilers: - - Microsoft Visual C++ - Watcom C/C++ (32 bit flat) - Intel's C/C++ compiler (on Windows) - The GNU C/C++ compiler (on Windows/Linux on x86 and PPC64) - Borland C++ - Turbo C - -There are slight differences in these compilers which requires slight -differences in the implementation of Bstrlib. These are accomodated in the -same sources using #ifdef/#if defined() on compiler specific macros. To -port Bstrlib to a new compiler not listed above, it is recommended that the -same strategy be followed. If you are unaware of the compiler specific -identifying preprocessor macro for your compiler you might find it here: - -http://predef.sourceforge.net/precomp.html - -Note that Intel C/C++ on Windows sets the Microsoft identifier: _MSC_VER. - -16-bit vs. 32-bit vs. 64-bit Systems ------------------------------------- - -Bstrlib has been architected to deal with strings of length between 0 and -INT_MAX (inclusive). Since the values of int are never higher than size_t -there will be no issue here. Note that on most 64-bit systems int is 32-bit. - -Dependency on The C-Library ---------------------------- - -Bstrlib uses the functions memcpy, memmove, malloc, realloc, free and -vsnprintf. Many free standing C compiler implementations that have a mode in -which the C library is not available will typically not include these -functions which will make porting Bstrlib to it onerous. Bstrlib is not -designed for such bare bones compiler environments. This usually includes -compilers that target ROM environments. - -Porting Issues --------------- - -Bstrlib has been written completely in ANSI/ISO C and ISO C++, however, there -are still a few porting issues. These are described below. - -1. The vsnprintf () function. - -Unfortunately, the earlier ANSI/ISO C standards did not include this function. -If the compiler of interest does not support this function then the -BSTRLIB_NOVSNP should be defined via something like: - - #if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) - # if defined (__TURBOC__) || defined (__COMPILERVENDORSPECIFICMACRO__) - # define BSTRLIB_NOVSNP - # endif - #endif - -which appears at the top of bstrlib.h. Note that the bformat(a) functions -will not be declared or implemented if the BSTRLIB_NOVSNP macro is set. If -the compiler has renamed vsnprintf() to some other named function, then -search for the definition of the exvsnprintf macro in bstrlib.c file and be -sure its defined appropriately: - - #if defined (__COMPILERVENDORSPECIFICMACRO__) - # define exvsnprintf(r,b,n,f,a) {r=__compiler_specific_vsnprintf(b,n,f,a);} - #else - # define exvsnprintf(r,b,n,f,a) {r=vsnprintf(b,n,f,a);} - #endif - -Take notice of the return value being captured in the variable r. It is -assumed that r exceeds n if and only if the underlying vsnprintf function has -determined what the true maximal output length would be for output if the -buffer were large enough to hold it. Non-modern implementations must output a -lesser number (the macro can and should be modified to ensure this). - -2. Weak C++ compiler. - -C++ is a much more complicated language to implement than C. This has lead -to varying quality of compiler implementations. The weaknesses isolated in -the initial ports are inclusion of the Standard Template Library, -std::iostream and exception handling. By default it is assumed that the C++ -compiler supports all of these things correctly. If your compiler does not -support one or more of these define the corresponding macro: - - BSTRLIB_CANNOT_USE_STL - BSTRLIB_CANNOT_USE_IOSTREAM - BSTRLIB_DOESNT_THROW_EXCEPTIONS - -The compiler specific detected macro should be defined at the top of -bstrwrap.h in the Configuration defines section. Note that these disabling -macros can be overrided with the associated enabling macro if a subsequent -version of the compiler gains support. (For example, its possible to rig -up STLport to provide STL support for WATCOM C/C++, so -DBSTRLIB_CAN_USE_STL -can be passed in as a compiler option.) - -3. The bsafe module, and reserved words. - -The bsafe module is in gross violation of the ANSI/ISO C standard in the -sense that it redefines what could be implemented as reserved words on a -given compiler. The typical problem is that a compiler may inline some of the -functions and thus not be properly overridden by the definitions in the bsafe -module. It is also possible that a compiler may prohibit the redefinitions in -the bsafe module. Compiler specific action will be required to deal with -these situations. - -Platform Specific Files ------------------------ - -The makefiles for the examples are basically setup of for particular -environments for each platform. In general these makefiles are not portable -and should be constructed as necessary from scratch for each platform. - -Testing a port --------------- - -To test that a port compiles correctly do the following: - -1. Build a sample project that includes the bstrlib, bstraux, bstrwrap, and - bsafe modules. -2. Compile bstest against the bstrlib module. -3. Run bstest and ensure that 0 errors are reported. -4. Compile test against the bstrlib and bstrwrap modules. -5. Run test and ensure that 0 errors are reported. -6. Compile each of the examples (except for the "re" example, which may be - complicated and is not a real test of bstrlib and except for the mfcbench - example which is Windows specific.) -7. Run each of the examples. - -The builds must have 0 errors, and should have the absolute minimum number of -warnings (in most cases can be reduced to 0.) The result of execution should -be essentially identical on each platform. - -Performance ------------ - -Different CPU and compilers have different capabilities in terms of -performance. It is possible for Bstrlib to assume performance -characteristics that a platform doesn't have (since it was primarily -developed on just one platform). The goal of Bstrlib is to provide very good -performance on all platforms regardless of this but without resorting to -extreme measures (such as using assembly language, or non-portable intrinsics -or library extensions.) - -There are two performance benchmarks that can be found in the example/ -directory. They are: cbench.c and cppbench.cpp. These are variations and -expansions of a benchmark for another string library. They don't cover all -string functionality, but do include the most basic functions which will be -common in most string manipulation kernels. - -............................................................................... - -Feedback --------- - -In all cases, you may email issues found to the primary author of Bstrlib at -the email address: websnarf@users.sourceforge.net - -=============================================================================== diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt deleted file mode 100644 index 9761409f56..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt +++ /dev/null @@ -1,221 +0,0 @@ -Better String library Security Statement ----------------------------------------- - -by Paul Hsieh - -=============================================================================== - -Introduction ------------- - -The Better String library (hereafter referred to as Bstrlib) is an attempt to -provide improved string processing functionality to the C and C++ languages. -At the heart of the Bstrlib is the management of "bstring"s which are a -significant improvement over '\0' terminated char buffers. See the -accompanying documenation file bstrlib.txt for more information. - -DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Like any software, there is always a possibility of failure due to a flawed -implementation. Nevertheless a good faith effort has been made to minimize -such flaws in Bstrlib. Also, use of Bstrlib by itself will not make an -application secure or free from implementation failures. However, it is the -author's conviction that use of Bstrlib can greatly facilitate the creation -of software meeting the highest possible standards of security. - -Part of the reason why this document has been created, is for the purpose of -security auditing, or the creation of further "Statements on Security" for -software that is created that uses Bstrlib. An auditor may check the claims -below against Bstrlib, and use this as a basis for analysis of software which -uses Bstrlib. - -=============================================================================== - -Statement on Security ---------------------- - -This is a document intended to give consumers of the Better String Library -who are interested in security an idea of where the Better String Library -stands on various security issues. Any deviation observed in the actual -library itself from the descriptions below should be considered an -implementation error, not a design flaw. - -This statement is not an analytical proof of correctness or an outline of one -but rather an assertion similar to a scientific claim or hypothesis. By use, -testing and open independent examination (otherwise known as scientific -falsifiability), the credibility of the claims made below can rise to the -level of an established theory. - -Common security issues: -....................... - -1. Buffer Overflows - -The Bstrlib API allows the programmer a way to deal with strings without -having to deal with the buffers containing them. Ordinary usage of the -Bstrlib API itself makes buffer overflows impossible. - -Furthermore, the Bstrlib API has a superset of basic string functionality as -compared to the C library's char * functions, C++'s std::string class and -Microsoft's MFC based CString class. It also has abstracted mechanisms for -dealing with IO. This is important as it gives developers a way of migrating -all their code from a functionality point of view. - -2. Memory size overflow/wrap around attack - -Bstrlib is, by design, impervious to memory size overflow attacks. The -reason is it is resiliant to length overflows is that bstring lengths are -bounded above by INT_MAX, instead of ~(size_t)0. So length addition -overflows cause a wrap around of the integer value making them negative -causing balloc() to fail before an erroneous operation can occurr. Attempted -conversions of char * strings which may have lengths greater than INT_MAX are -detected and the conversion is aborted. - -It is unknown if this property holds on machines that don't represent -integers as 2s complement. It is recommended that Bstrlib be carefully -auditted by anyone using a system which is not 2s complement based. - -3. Constant string protection - -Bstrlib implements runtime enforced constant and read-only string semantics. -I.e., bstrings which are declared as constant via the bsStatic() macro cannot -be modified or deallocated directly through the Bstrlib API, and this cannot -be subverted by casting or other type coercion. This is independent of the -use of the const_bstring data type. - -The Bstrlib C API uses the type const_bstring to specify bstring parameters -whose contents do not change. Although the C language cannot enforce this, -this is nevertheless guaranteed by the implementation of the Bstrlib library -of C functions. The C++ API enforces the const attribute on CBString types -correctly. - -4. Aliased bstring support - -Bstrlib detects and supports aliased parameter management throughout the API. -The kind of aliasing that is allowed is the one where pointers of the same -basic type may be pointing to overlapping objects (this is the assumption the -ANSI C99 specification makes.) Each function behaves as if all read-only -parameters were copied to temporaries which are used in their stead before -the function is enacted (it rarely actually does this). No function in the -Bstrlib uses the "restrict" parameter attribute from the ANSI C99 -specification. - -5. Information leaking - -In bstraux.h, using the semantically equivalent macros bSecureDestroy() and -bSecureWriteProtect() in place of bdestroy() and bwriteprotect() respectively -will ensure that stale data does not linger in the heap's free space after -strings have been released back to memory. Created bstrings or CBStrings -are not linked to anything external to themselves, and thus cannot expose -deterministic data leaking. If a bstring is resized, the preimage may exist -as a copy that is released to the heap. Thus for sensitive data, the bstring -should be sufficiently presized before manipulated so that it is not resized. -bSecureInput() has been supplied in bstraux.c, which can be used to obtain -input securely without any risk of leaving any part of the input image in the -heap except for the allocated bstring that is returned. - -6. Memory leaking - -Bstrlib can be built using memdbg.h enabled via the BSTRLIB_MEMORY_DEBUG -macro. User generated definitions for malloc, realloc and free can then be -supplied which can implement special strategies for memory corruption -detection or memory leaking. Otherwise, bstrlib does not do anything out of -the ordinary to attempt to deal with the standard problem of memory leaking -(i.e., losing references to allocated memory) when programming in the C and -C++ languages. However, it does not compound the problem any more than exists -either, as it doesn't have any intrinsic inescapable leaks in it. Bstrlib -does not preclude the use of automatic garbage collection mechanisms such as -the Boehm garbage collector. - -7. Encryption - -Bstrlib does not present any built-in encryption mechanism. However, it -supports full binary contents in its data buffers, so any standard block -based encryption mechanism can make direct use of bstrings/CBStrings for -buffer management. - -8. Double freeing - -Freeing a pointer that is already free is an extremely rare, but nevertheless -a potentially ruthlessly corrupting operation (its possible to cause Win 98 to -reboot, by calling free mulitiple times on already freed data using the WATCOM -CRT.) Bstrlib invalidates the bstring header data before freeing, so that in -many cases a double free will be detected and an error will be reported -(though this behaviour is not guaranteed and should not be relied on). - -Using bstrFree pervasively (instead of bdestroy) can lead to somewhat -improved invalid free avoidance (it is completely safe whenever bstring -instances are only stored in unique variables). For example: - - struct tagbstring hw = bsStatic ("Hello, world"); - bstring cpHw = bstrcpy (&hw); - - #ifdef NOT_QUITE_AS_SAFE - bdestroy (cpHw); /* Never fail */ - bdestroy (cpHw); /* Error sometimes detected at runtime */ - bdestroy (&hw); /* Error detected at run time */ - #else - bstrFree (cpHw); /* Never fail */ - bstrFree (cpHw); /* Will do nothing */ - bstrFree (&hw); /* Will lead to a compile time error */ - #endif - -9. Resource based denial of service - -bSecureInput() has been supplied in bstraux.c. It has an optional upper limit -for input length. But unlike fgets(), it is also easily determined if the -buffer has been truncated early. In this way, a program can set an upper limit -on input sizes while still allowing for implementing context specific -truncation semantics (i.e., does the program consume but dump the extra -input, or does it consume it in later inputs?) - -10. Mixing char *'s and bstrings - -The bstring and char * representations are not identical. So there is a risk -when converting back and forth that data may lost. Essentially bstrings can -contain '\0' as a valid non-terminating character, while char * strings -cannot and in fact must use the character as a terminator. The risk of data -loss is very low, since: - - A) the simple method of only using bstrings in a char * semantically - compatible way is both easy to achieve and pervasively supported. - B) obtaining '\0' content in a string is either deliberate or indicative - of another, likely more serious problem in the code. - C) the library comes with various functions which deal with this issue - (namely: bfromcstr(), bstr2cstr (), and bSetCstrChar ()) - -Marginal security issues: -......................... - -11. 8-bit versus 9-bit portability - -Bstrlib uses CHAR_BIT and other limits.h constants to the maximum extent -possible to avoid portability problems. However, Bstrlib has not been tested -on any system that does not represent char as 8-bits. So whether or not it -works on 9-bit systems is an open question. It is recommended that Bstrlib be -carefully auditted by anyone using a system in which CHAR_BIT is not 8. - -12. EBCDIC/ASCII/UTF-8 data representation attacks. - -Bstrlib uses ctype.h functions to ensure that it remains portable to non- -ASCII systems. It also checks range to make sure it is well defined even for -data that ANSI does not define for the ctype functions. - -Obscure issues: -............... - -13. Data attributes - -There is no support for a Perl-like "taint" attribute, however, an example of -how to do this using C++'s type system is given as an example. - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c b/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c deleted file mode 100644 index ce19d481d7..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c +++ /dev/null @@ -1,1750 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/tokens.h" -#include "internal_includes/structs.h" -#include "internal_includes/decode.h" -#include "stdlib.h" -#include "stdio.h" -#include "internal_includes/reflect.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/toGLSLOperand.h" - -#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) -enum -{ - FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C') -}; //DirectX byte code -enum -{ - FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R') -}; //Shader model 4 code -enum -{ - FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X') -}; //Shader model 5 code -enum -{ - FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F') -}; //Resource definition (e.g. constant buffers) -enum -{ - FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N') -}; //Input signature -enum -{ - FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E') -}; //Interface (for dynamic linking) -enum -{ - FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N') -}; //Output signature -enum -{ - FOURCC_PSGN = FOURCC('P', 'C', 'S', 'G') -}; //Patch-constant signature -enum -{ - FOURCC_FX10 = FOURCC('F', 'X', '1', '0') -}; //Effects 10 Binary data - -enum -{ - FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1') -}; //Input signature with Stream and MinPrecision -enum -{ - FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1') -}; //Output signature with Stream and MinPrecision -enum -{ - FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5') -}; //Output signature with Stream - -typedef struct DXBCContainerHeaderTAG -{ - unsigned fourcc; - uint32_t unk[4]; - uint32_t one; - uint32_t totalSize; - uint32_t chunkCount; -} DXBCContainerHeader; - -typedef struct DXBCChunkHeaderTAG -{ - unsigned fourcc; - unsigned size; -} DXBCChunkHeader; - -#ifdef _DEBUG -static uint64_t operandID = 0; -static uint64_t instructionID = 0; -#endif - -#if defined(_WIN32) -#define osSprintf(dest, size, src) sprintf_s(dest, size, src) -#else -#define osSprintf(dest, size, src) sprintf(dest, src) -#endif - -void DecodeNameToken(const uint32_t* pui32NameToken, Operand* psOperand) -{ - const size_t MAX_BUFFER_SIZE = sizeof(psOperand->pszSpecialName); - psOperand->eSpecialName = DecodeOperandSpecialName(*pui32NameToken); - switch (psOperand->eSpecialName) - { - case NAME_UNDEFINED: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "undefined"); - break; - } - case NAME_POSITION: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "position"); - break; - } - case NAME_CLIP_DISTANCE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "clipDistance"); - break; - } - case NAME_CULL_DISTANCE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "cullDistance"); - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "renderTargetArrayIndex"); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "viewportArrayIndex"); - break; - } - case NAME_VERTEX_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "vertexID"); - break; - } - case NAME_PRIMITIVE_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "primitiveID"); - break; - } - case NAME_INSTANCE_ID: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "instanceID"); - break; - } - case NAME_IS_FRONT_FACE: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "isFrontFace"); - break; - } - case NAME_SAMPLE_INDEX: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "sampleIndex"); - break; - } - //For the quadrilateral domain, there are 6 factors (4 sides, 2 inner). - case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: - case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: - case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: - - //For the triangular domain, there are 4 factors (3 sides, 1 inner) - case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: - case NAME_FINAL_TRI_INSIDE_TESSFACTOR: - - //For the isoline domain, there are 2 factors (detail and density). - case NAME_FINAL_LINE_DETAIL_TESSFACTOR: - case NAME_FINAL_LINE_DENSITY_TESSFACTOR: - { - osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "tessFactor"); - break; - } - default: - { - ASSERT(0); - break; - } - } - - return; -} - -// Find the declaration of the texture described by psTextureOperand and -// mark it as a shadow type. (e.g. accessed via sampler2DShadow rather than sampler2D) -void MarkTextureAsShadow(ShaderInfo* psShaderInfo, Declaration* psDeclList, const uint32_t ui32DeclCount, const Operand* psTextureOperand) -{ - (void)psShaderInfo; - - Declaration* psDecl = psDeclList; - uint32_t i; - - ASSERT(psTextureOperand->eType == OPERAND_TYPE_RESOURCE); - - for (i = 0; i < ui32DeclCount; ++i) - { - if (psDecl->eOpcode == OPCODE_DCL_RESOURCE) - { - if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && - psDecl->asOperands[0].ui32RegisterNumber == psTextureOperand->ui32RegisterNumber) - { - psDecl->ui32IsShadowTex = 1; - break; - } - } - psDecl++; - } -} - -// Search through the list. Return the index if the value is found, return 0xffffffff if not found -static uint32_t Find(uint32_t* psList, uint32_t ui32Count, uint32_t ui32Value) -{ - uint32_t i; - for (i = 0; i < ui32Count; i++) - { - if (psList[i] == ui32Value) - { - return i; - } - } - return 0xffffffff; -} - -void MarkTextureSamplerPair(ShaderInfo* psShaderInfo, Declaration* psDeclList, const uint32_t ui32DeclCount, const Operand* psTextureOperand, const Operand* psSamplerOperand, TextureSamplerInfo* psTextureSamplerInfo) -{ - Declaration* psDecl = psDeclList; - uint32_t i; - bstring combinedname; - const char* cstr; - - ASSERT(psTextureOperand->eType == OPERAND_TYPE_RESOURCE); - ASSERT(psSamplerOperand->eType == OPERAND_TYPE_SAMPLER); - - for (i = 0; i < ui32DeclCount; ++i) - { - if (psDecl->eOpcode == OPCODE_DCL_RESOURCE) - { - if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && - psDecl->asOperands[0].ui32RegisterNumber == psTextureOperand->ui32RegisterNumber) - { - // psDecl is the texture resource referenced by psTextureOperand - ASSERT(psDecl->ui32SamplerUsedCount < MAX_TEXTURE_SAMPLERS_PAIRS); - - // add psSamplerOperand->ui32RegisterNumber to list of samplers that use this texture - if (Find(psDecl->ui32SamplerUsed, psDecl->ui32SamplerUsedCount, psSamplerOperand->ui32RegisterNumber) == 0xffffffff) - { - psDecl->ui32SamplerUsed[psDecl->ui32SamplerUsedCount++] = psSamplerOperand->ui32RegisterNumber; - - // Record the texturename_X_samplername string in the TextureSamplerPair array that we return to the client - ASSERT(psTextureSamplerInfo->ui32NumTextureSamplerPairs < MAX_RESOURCE_BINDINGS); - combinedname = TextureSamplerName(psShaderInfo, psTextureOperand->ui32RegisterNumber, psSamplerOperand->ui32RegisterNumber, psDecl->ui32IsShadowTex); - cstr = bstr2cstr(combinedname, '\0'); - bdestroy(combinedname); - strcpy(psTextureSamplerInfo->aTextureSamplerPair[psTextureSamplerInfo->ui32NumTextureSamplerPairs++].Name, cstr); - } - break; - } - } - psDecl++; - } -} - -uint32_t DecodeOperand (const uint32_t* pui32Tokens, Operand* psOperand) -{ - int i; - uint32_t ui32NumTokens = 1; - OPERAND_NUM_COMPONENTS eNumComponents; - -#ifdef _DEBUG - psOperand->id = operandID++; -#endif - - //Some defaults - psOperand->iWriteMaskEnabled = 1; - psOperand->iGSInput = 0; - psOperand->aeDataType[0] = SVT_FLOAT; - psOperand->aeDataType[1] = SVT_FLOAT; - psOperand->aeDataType[2] = SVT_FLOAT; - psOperand->aeDataType[3] = SVT_FLOAT; - - psOperand->iExtended = DecodeIsOperandExtended(*pui32Tokens); - - - psOperand->eModifier = OPERAND_MODIFIER_NONE; - psOperand->psSubOperand[0] = 0; - psOperand->psSubOperand[1] = 0; - psOperand->psSubOperand[2] = 0; - - psOperand->eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; - - /* Check if this instruction is extended. If it is, - * we need to print the information first */ - if (psOperand->iExtended) - { - /* OperandToken1 is the second token */ - ui32NumTokens++; - - if (DecodeExtendedOperandType(pui32Tokens[1]) == EXTENDED_OPERAND_MODIFIER) - { - psOperand->eModifier = DecodeExtendedOperandModifier(pui32Tokens[1]); - psOperand->eMinPrecision = DecodeOperandMinPrecision(pui32Tokens[1]); - } - } - - psOperand->iIndexDims = DecodeOperandIndexDimension(*pui32Tokens); - psOperand->eType = DecodeOperandType(*pui32Tokens); - - psOperand->ui32RegisterNumber = 0; - - eNumComponents = DecodeOperandNumComponents(*pui32Tokens); - - if (psOperand->eType == OPERAND_TYPE_INPUT_GS_INSTANCE_ID) - { - eNumComponents = OPERAND_1_COMPONENT; - psOperand->aeDataType[0] = SVT_UINT; - } - - switch (eNumComponents) - { - case OPERAND_1_COMPONENT: - { - psOperand->iNumComponents = 1; - break; - } - case OPERAND_4_COMPONENT: - { - psOperand->iNumComponents = 4; - break; - } - default: - { - psOperand->iNumComponents = 0; - break; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - psOperand->eSelMode = DecodeOperand4CompSelMode(*pui32Tokens); - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - psOperand->ui32CompMask = DecodeOperand4CompMask(*pui32Tokens); - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - psOperand->ui32Swizzle = DecodeOperand4CompSwizzle(*pui32Tokens); - - if (psOperand->ui32Swizzle != NO_SWIZZLE) - { - psOperand->aui32Swizzle[0] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 0); - psOperand->aui32Swizzle[1] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 1); - psOperand->aui32Swizzle[2] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 2); - psOperand->aui32Swizzle[3] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 3); - } - else - { - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; - psOperand->aui32Swizzle[1] = OPERAND_4_COMPONENT_Y; - psOperand->aui32Swizzle[2] = OPERAND_4_COMPONENT_Z; - psOperand->aui32Swizzle[3] = OPERAND_4_COMPONENT_W; - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psOperand->aui32Swizzle[0] = DecodeOperand4CompSel1(*pui32Tokens); - } - } - - //Set externally to this function based on the instruction opcode. - psOperand->iIntegerImmediate = 0; - - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) - { - for (i = 0; i < psOperand->iNumComponents; ++i) - { - psOperand->afImmediates[i] = *((float*)(&pui32Tokens[ui32NumTokens])); - ui32NumTokens++; - } - } - else - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - for (i = 0; i < psOperand->iNumComponents; ++i) - { - psOperand->adImmediates[i] = *((double*)(&pui32Tokens[ui32NumTokens])); - ui32NumTokens += 2; - } - } - - if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) - { - psOperand->ui32RegisterNumber = -1; - psOperand->ui32CompMask = -1; - } - - for (i = 0; i < psOperand->iIndexDims; ++i) - { - OPERAND_INDEX_REPRESENTATION eRep = DecodeOperandIndexRepresentation(i, *pui32Tokens); - - psOperand->eIndexRep[i] = eRep; - - psOperand->aui32ArraySizes[i] = 0; - psOperand->ui32RegisterNumber = 0; - - switch (eRep) - { - case OPERAND_INDEX_IMMEDIATE32: - { - psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); - psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; - break; - } - case OPERAND_INDEX_RELATIVE: - { - psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); - DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); - - ui32NumTokens++; - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); - psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; - - ui32NumTokens++; - - psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); - DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); - - ui32NumTokens++; - break; - } - default: - { - ASSERT(0); - break; - } - } - - ui32NumTokens++; - } - - psOperand->pszSpecialName[0] = '\0'; - - return ui32NumTokens; -} - -const uint32_t* DecodeDeclaration(ShaderData* psShader, const uint32_t* pui32Token, Declaration* psDecl) -{ - uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); - const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); - const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); - uint32_t ui32OperandOffset = 1; - - if (eOpcode < NUM_OPCODES && eOpcode >= 0) - { - psShader->aiOpcodeUsed[eOpcode] = 1; - } - - psDecl->eOpcode = eOpcode; - - psDecl->ui32IsShadowTex = 0; - - if (bExtended) - { - ui32OperandOffset = 2; - } - - switch (eOpcode) - { - case OPCODE_DCL_RESOURCE: // DCL* opcodes have - { - psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); - psDecl->ui32NumOperands = 1; - psDecl->ui32SamplerUsedCount = 0; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. - { - psDecl->value.eCBAccessPattern = DecodeConstantBufferAccessPattern(*pui32Token); - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_SAMPLER: - { - ResourceBinding* psBinding = 0; - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_SAMPLER && - GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) - { - psDecl->bIsComparisonSampler = psBinding->ui32Flags & SHADER_INPUT_FLAG_COMPARISON_SAMPLER; - } - break; - } - case OPCODE_DCL_INDEX_RANGE: - { - psDecl->ui32NumOperands = 1; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - psDecl->value.ui32IndexRange = pui32Token[ui32OperandOffset]; - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) - { - uint32_t i; - const uint32_t indexRange = psDecl->value.ui32IndexRange; - const uint32_t reg = psDecl->asOperands[0].ui32RegisterNumber; - - psShader->aIndexedInput[reg] = indexRange; - psShader->aIndexedInputParents[reg] = reg; - - //-1 means don't declare this input because it falls in - //the range of an already declared array. - for (i = reg + 1; i < reg + indexRange; ++i) - { - psShader->aIndexedInput[i] = -1; - psShader->aIndexedInputParents[i] = reg; - } - } - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) - { - psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.ui32IndexRange; - } - break; - } - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - { - psDecl->value.eOutputPrimitiveTopology = DecodeGSOutputPrimitiveTopology(*pui32Token); - break; - } - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - { - psDecl->value.eInputPrimitive = DecodeGSInputPrimitive(*pui32Token); - break; - } - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - { - psDecl->value.ui32MaxOutputVertexCount = pui32Token[1]; - break; - } - case OPCODE_DCL_TESS_PARTITIONING: - { - psDecl->value.eTessPartitioning = DecodeTessPartitioning(*pui32Token); - break; - } - case OPCODE_DCL_TESS_DOMAIN: - { - psDecl->value.eTessDomain = DecodeTessDomain(*pui32Token); - break; - } - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - { - psDecl->value.eTessOutPrim = DecodeTessOutPrim(*pui32Token); - break; - } - case OPCODE_DCL_THREAD_GROUP: - { - psDecl->value.aui32WorkGroupSize[0] = pui32Token[1]; - psDecl->value.aui32WorkGroupSize[1] = pui32Token[2]; - psDecl->value.aui32WorkGroupSize[2] = pui32Token[3]; - break; - } - case OPCODE_DCL_INPUT: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_SIV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - if (psShader->eShaderType == PIXEL_SHADER) - { - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - } - break; - } - case OPCODE_DCL_INPUT_PS: - { - psDecl->ui32NumOperands = 1; - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_PS_SGV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_INPUT_PS_SIV: - { - psDecl->ui32NumOperands = 1; - psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_OUTPUT: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_OUTPUT_SGV: - { - break; - } - case OPCODE_DCL_OUTPUT_SIV: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_TEMPS: - { - psDecl->value.ui32NumTemps = *(pui32Token + ui32OperandOffset); - break; - } - case OPCODE_DCL_INDEXABLE_TEMP: - { - psDecl->sIdxTemp.ui32RegIndex = *(pui32Token + ui32OperandOffset); - psDecl->sIdxTemp.ui32RegCount = *(pui32Token + ui32OperandOffset + 1); - psDecl->sIdxTemp.ui32RegComponentSize = *(pui32Token + ui32OperandOffset + 2); - break; - } - case OPCODE_DCL_GLOBAL_FLAGS: - { - psDecl->value.ui32GlobalFlags = DecodeGlobalFlags(*pui32Token); - break; - } - case OPCODE_DCL_INTERFACE: - { - uint32_t func = 0, numClassesImplementingThisInterface, arrayLen, interfaceID; - interfaceID = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - psDecl->ui32TableLength = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - - numClassesImplementingThisInterface = DecodeInterfaceTableLength(*(pui32Token + ui32OperandOffset)); - arrayLen = DecodeInterfaceArrayLength(*(pui32Token + ui32OperandOffset)); - - ui32OperandOffset++; - - psDecl->value.interface.ui32InterfaceID = interfaceID; - psDecl->value.interface.ui32NumFuncTables = numClassesImplementingThisInterface; - psDecl->value.interface.ui32ArraySize = arrayLen; - - psShader->funcPointer[interfaceID].ui32NumBodiesPerTable = psDecl->ui32TableLength; - - for (; func < numClassesImplementingThisInterface; ++func) - { - uint32_t ui32FuncTable = *(pui32Token + ui32OperandOffset); - psShader->aui32FuncTableToFuncPointer[ui32FuncTable] = interfaceID; - - psShader->funcPointer[interfaceID].aui32FuncTables[func] = ui32FuncTable; - ui32OperandOffset++; - } - - break; - } - case OPCODE_DCL_FUNCTION_BODY: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_FUNCTION_TABLE: - { - uint32_t ui32Func; - const uint32_t ui32FuncTableID = pui32Token[ui32OperandOffset++]; - const uint32_t ui32NumFuncsInTable = pui32Token[ui32OperandOffset++]; - - for (ui32Func = 0; ui32Func < ui32NumFuncsInTable; ++ui32Func) - { - const uint32_t ui32FuncBodyID = pui32Token[ui32OperandOffset++]; - - psShader->aui32FuncBodyToFuncTable[ui32FuncBodyID] = ui32FuncTableID; - - psShader->funcTable[ui32FuncTableID].aui32FuncBodies[ui32Func] = ui32FuncBodyID; - } - - // OpcodeToken0 is followed by a DWORD that represents the function table - // identifier and another DWORD (TableLength) that gives the number of - // functions in the table. - // - // This is followed by TableLength DWORDs which are function body indices. - // - - break; - } - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_HS_DECLS: - { - break; - } - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - { - psDecl->value.ui32MaxOutputVertexCount = DecodeOutputControlPointCount(*pui32Token); - break; - } - case OPCODE_HS_JOIN_PHASE: - case OPCODE_HS_FORK_PHASE: - case OPCODE_HS_CONTROL_POINT_PHASE: - { - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - ASSERT(psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount != 0); //Check for wrapping when we decrement. - psDecl->value.aui32HullPhaseInstanceInfo[0] = psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount - 1; - psDecl->value.aui32HullPhaseInstanceInfo[1] = pui32Token[1]; - break; - } - case OPCODE_CUSTOMDATA: - { - ui32TokenLength = pui32Token[1]; - { - const uint32_t ui32NumVec4 = (ui32TokenLength - 2) / 4; - uint32_t uIdx = 0; - - ICBVec4 const* pVec4Array = (void*) (pui32Token + 2); - - //The buffer will contain at least one value, but not more than 4096 scalars/1024 vec4's. - ASSERT(ui32NumVec4 < MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE); - - /* must be a multiple of 4 */ - ASSERT(((ui32TokenLength - 2) % 4) == 0); - - for (uIdx = 0; uIdx < ui32NumVec4; uIdx++) - { - psDecl->asImmediateConstBuffer[uIdx] = pVec4Array[uIdx]; - } - - psDecl->ui32NumOperands = ui32NumVec4; - } - break; - } - case OPCODE_DCL_HS_MAX_TESSFACTOR: - { - psDecl->value.fMaxTessFactor = *((float*)&pui32Token[1]); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - { - psDecl->ui32NumOperands = 2; - psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - psDecl->sUAV.Type = DecodeResourceReturnType(0, pui32Token[ui32OperandOffset]); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - { - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - //This should be a RTYPE_UAV_RWBYTEADDRESS buffer. It is memory backed by - //a shader storage buffer whose is unknown at compile time. - psDecl->sUAV.ui32BufferSize = 0; - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - { - ResourceBinding* psBinding = NULL; - ConstantBuffer* psBuffer = NULL; - - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); - psDecl->sUAV.bCounter = 0; - psDecl->sUAV.ui32BufferSize = 0; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding); - - GetConstantBufferFromBindingPoint(RGROUP_UAV, psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); - psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; - switch (psBinding->eType) - { - case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: - case RTYPE_UAV_APPEND_STRUCTURED: - case RTYPE_UAV_CONSUME_STRUCTURED: - psDecl->sUAV.bCounter = 1; - break; - default: - break; - } - break; - } - case OPCODE_DCL_RESOURCE_STRUCTURED: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_RESOURCE_RAW: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - { - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = 0; - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - psDecl->sTGSM.ui32Stride = pui32Token[ui32OperandOffset++]; - psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - { - psDecl->ui32NumOperands = 1; - psDecl->sUAV.ui32GloballyCoherentAccess = 0; - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - - psDecl->sTGSM.ui32Stride = 4; - psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; - break; - } - case OPCODE_DCL_STREAM: - { - psDecl->ui32NumOperands = 1; - DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); - break; - } - case OPCODE_DCL_GS_INSTANCE_COUNT: - { - psDecl->ui32NumOperands = 0; - psDecl->value.ui32GSInstanceCount = pui32Token[1]; - break; - } - default: - { - //Reached end of declarations - return 0; - } - } - - return pui32Token + ui32TokenLength; -} - -const uint32_t* DeocdeInstruction(const uint32_t* pui32Token, Instruction* psInst, ShaderData* psShader) -{ - uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); - const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); - const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); - uint32_t ui32OperandOffset = 1; - -#ifdef _DEBUG - psInst->id = instructionID++; -#endif - - psInst->eOpcode = eOpcode; - - psInst->bSaturate = DecodeInstructionSaturate(*pui32Token); - - psInst->bAddressOffset = 0; - - psInst->ui32FirstSrc = 1; - - if (bExtended) - { - do - { - const uint32_t ui32ExtOpcodeToken = pui32Token[ui32OperandOffset]; - const EXTENDED_OPCODE_TYPE eExtType = DecodeExtendedOpcodeType(ui32ExtOpcodeToken); - - if (eExtType == EXTENDED_OPCODE_SAMPLE_CONTROLS) - { - struct - { - int i4 : 4; - } sU; - struct - { - int i4 : 4; - } sV; - struct - { - int i4 : 4; - } sW; - - psInst->bAddressOffset = 1; - - sU.i4 = DecodeImmediateAddressOffset( - IMMEDIATE_ADDRESS_OFFSET_U, ui32ExtOpcodeToken); - sV.i4 = DecodeImmediateAddressOffset( - IMMEDIATE_ADDRESS_OFFSET_V, ui32ExtOpcodeToken); - sW.i4 = DecodeImmediateAddressOffset( - IMMEDIATE_ADDRESS_OFFSET_W, ui32ExtOpcodeToken); - - psInst->iUAddrOffset = sU.i4; - psInst->iVAddrOffset = sV.i4; - psInst->iWAddrOffset = sW.i4; - } - else if (eExtType == EXTENDED_OPCODE_RESOURCE_RETURN_TYPE) - { - psInst->xType = DecodeExtendedResourceReturnType(0, ui32ExtOpcodeToken); - psInst->yType = DecodeExtendedResourceReturnType(1, ui32ExtOpcodeToken); - psInst->zType = DecodeExtendedResourceReturnType(2, ui32ExtOpcodeToken); - psInst->wType = DecodeExtendedResourceReturnType(3, ui32ExtOpcodeToken); - } - else if (eExtType == EXTENDED_OPCODE_RESOURCE_DIM) - { - psInst->eResDim = DecodeExtendedResourceDimension(ui32ExtOpcodeToken); - } - - ui32OperandOffset++; - } - while (DecodeIsOpcodeExtended(pui32Token[ui32OperandOffset - 1])); - } - - if (eOpcode < NUM_OPCODES && eOpcode >= 0) - { - psShader->aiOpcodeUsed[eOpcode] = 1; - } - - switch (eOpcode) - { - //no operands - case OPCODE_CUT: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_RET: - case OPCODE_LOOP: - case OPCODE_ENDLOOP: - case OPCODE_BREAK: - case OPCODE_ELSE: - case OPCODE_ENDIF: - case OPCODE_CONTINUE: - case OPCODE_DEFAULT: - case OPCODE_ENDSWITCH: - case OPCODE_NOP: - case OPCODE_HS_CONTROL_POINT_PHASE: - case OPCODE_HS_FORK_PHASE: - case OPCODE_HS_JOIN_PHASE: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - break; - } - case OPCODE_SYNC: - { - psInst->ui32NumOperands = 0; - psInst->ui32FirstSrc = 0; - psInst->ui32SyncFlags = DecodeSyncFlags(*pui32Token); - break; - } - - //1 operand - case OPCODE_EMIT_STREAM: - case OPCODE_CUT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - case OPCODE_CASE: - case OPCODE_SWITCH: - case OPCODE_LABEL: - { - psInst->ui32NumOperands = 1; - psInst->ui32FirstSrc = 0; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - - if (eOpcode == OPCODE_CASE) - { - psInst->asOperands[0].iIntegerImmediate = 1; - } - break; - } - - case OPCODE_INTERFACE_CALL: - { - psInst->ui32NumOperands = 1; - psInst->ui32FirstSrc = 0; - psInst->ui32FuncIndexWithinInterface = pui32Token[ui32OperandOffset]; - ui32OperandOffset++; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - - break; - } - - /* Floating point instruction decodes */ - - //Instructions with two operands go here - case OPCODE_MOV: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - - //Mov with an integer dest. If src is an immediate then it must be encoded as an integer. - if (psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_SINT_16 || - psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_UINT_16) - { - psInst->asOperands[1].iIntegerImmediate = 1; - } - break; - } - case OPCODE_LOG: - case OPCODE_RSQ: - case OPCODE_EXP: - case OPCODE_SQRT: - case OPCODE_ROUND_PI: - case OPCODE_ROUND_NI: - case OPCODE_ROUND_Z: - case OPCODE_ROUND_NE: - case OPCODE_FRC: - case OPCODE_FTOU: - case OPCODE_FTOI: - case OPCODE_UTOF: - case OPCODE_ITOF: - case OPCODE_INEG: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - case OPCODE_DMOV: - case OPCODE_DTOF: - case OPCODE_FTOD: - case OPCODE_DRCP: - case OPCODE_COUNTBITS: - case OPCODE_FIRSTBIT_HI: - case OPCODE_FIRSTBIT_LO: - case OPCODE_FIRSTBIT_SHI: - case OPCODE_BFREV: - case OPCODE_F32TOF16: - case OPCODE_F16TOF32: - case OPCODE_RCP: - case OPCODE_DERIV_RTX: - case OPCODE_DERIV_RTY: - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_NOT: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - - //Instructions with three operands go here - case OPCODE_SINCOS: - { - psInst->ui32FirstSrc = 2; - //Intentional fall-through - } - case OPCODE_IMIN: - case OPCODE_MIN: - case OPCODE_UMIN: - case OPCODE_IMAX: - case OPCODE_MAX: - case OPCODE_UMAX: - case OPCODE_MUL: - case OPCODE_DIV: - case OPCODE_ADD: - case OPCODE_DP2: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_NE: - case OPCODE_OR: - case OPCODE_XOR: - case OPCODE_LT: - case OPCODE_IEQ: - case OPCODE_IADD: - case OPCODE_AND: - case OPCODE_GE: - case OPCODE_IGE: - case OPCODE_EQ: - case OPCODE_USHR: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_LD: - case OPCODE_ILT: - case OPCODE_INE: - case OPCODE_UGE: - case OPCODE_ULT: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_UMIN: - case OPCODE_DADD: - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DDIV: - { - psInst->ui32NumOperands = 3; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - //Instructions with four operands go here - case OPCODE_MAD: - case OPCODE_MOVC: - case OPCODE_IMAD: - case OPCODE_UDIV: - case OPCODE_LOD: - case OPCODE_SAMPLE: - case OPCODE_GATHER4: - case OPCODE_LD_MS: - case OPCODE_UBFE: - case OPCODE_IBFE: - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_DMOVC: - case OPCODE_DFMA: - case OPCODE_IMUL: - { - psInst->ui32NumOperands = 4; - - if (eOpcode == OPCODE_IMUL) - { - psInst->ui32FirstSrc = 2; - } - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - break; - } - case OPCODE_GATHER4_PO: - case OPCODE_SAMPLE_L: - case OPCODE_BFI: - case OPCODE_SWAPC: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - psInst->ui32NumOperands = 5; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - break; - } - case OPCODE_GATHER4_C: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_B: - { - psInst->ui32NumOperands = 5; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - - /* sample_b is not a shadow sampler, others need flagging */ - if (eOpcode != OPCODE_SAMPLE_B) - { - MarkTextureAsShadow(&psShader->sInfo, - psShader->asPhase[MAIN_PHASE].ppsDecl[0], - psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], &psInst->asOperands[2]); - } - - break; - } - case OPCODE_GATHER4_PO_C: - case OPCODE_SAMPLE_D: - { - psInst->ui32NumOperands = 6; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[5]); - - /* sample_d is not a shadow sampler, others need flagging */ - if (eOpcode != OPCODE_SAMPLE_D) - { - MarkTextureAsShadow(&psShader->sInfo, - psShader->asPhase[MAIN_PHASE].ppsDecl[0], - psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], &psInst->asOperands[2]); - } - break; - } - case OPCODE_IF: - case OPCODE_BREAKC: - case OPCODE_CONTINUEC: - case OPCODE_RETC: - case OPCODE_DISCARD: - { - psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); - psInst->ui32NumOperands = 1; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - break; - } - case OPCODE_CALLC: - { - psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - case OPCODE_CUSTOMDATA: - { - psInst->ui32NumOperands = 0; - ui32TokenLength = pui32Token[1]; - break; - } - case OPCODE_EVAL_CENTROID: - { - psInst->ui32NumOperands = 2; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - break; - } - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_SNAPPED: - case OPCODE_STORE_UAV_TYPED: - case OPCODE_LD_UAV_TYPED: - case OPCODE_LD_RAW: - case OPCODE_STORE_RAW: - { - psInst->ui32NumOperands = 3; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - case OPCODE_STORE_STRUCTURED: - case OPCODE_LD_STRUCTURED: - { - psInst->ui32NumOperands = 4; - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); - break; - } - case OPCODE_RESINFO: - { - psInst->ui32NumOperands = 3; - - psInst->eResInfoReturnType = DecodeResInfoReturnType(pui32Token[0]); - - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); - ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); - break; - } - case OPCODE_MSAD: - default: - { - ASSERT(0); - break; - } - } - - // For opcodes that sample textures, mark which samplers are used by each texture - { - uint32_t ui32TextureRegisterNumber; - uint32_t ui32SamplerRegisterNumber; - uint32_t bTextureSampleInstruction = 0; - switch (eOpcode) - { - case OPCODE_GATHER4: - // dest, coords, tex, sampler - ui32TextureRegisterNumber = 2; - ui32SamplerRegisterNumber = 3; - bTextureSampleInstruction = 1; - break; - case OPCODE_GATHER4_PO: - //dest, coords, offset, tex, sampler - ui32TextureRegisterNumber = 3; - ui32SamplerRegisterNumber = 4; - bTextureSampleInstruction = 1; - break; - case OPCODE_GATHER4_C: - //dest, coords, tex, sampler srcReferenceValue - ui32TextureRegisterNumber = 2; - ui32SamplerRegisterNumber = 3; - bTextureSampleInstruction = 1; - break; - case OPCODE_GATHER4_PO_C: - //dest, coords, offset, tex, sampler, srcReferenceValue - ui32TextureRegisterNumber = 3; - ui32SamplerRegisterNumber = 4; - bTextureSampleInstruction = 1; - break; - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_B: - case OPCODE_SAMPLE_D: - // dest, coords, tex, sampler [, reference] - ui32TextureRegisterNumber = 2; - ui32SamplerRegisterNumber = 3; - bTextureSampleInstruction = 1; - break; - } - - if (bTextureSampleInstruction) - { - MarkTextureSamplerPair(&psShader->sInfo, - psShader->asPhase[MAIN_PHASE].ppsDecl[0], - psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], - &psInst->asOperands[ui32TextureRegisterNumber], - &psInst->asOperands[ui32SamplerRegisterNumber], - &psShader->textureSamplerInfo); - } - } - - UpdateOperandReferences(psShader, psInst); - - return pui32Token + ui32TokenLength; -} - -void BindTextureToSampler(ShaderData* psShader, uint32_t ui32TextureRegister, uint32_t ui32SamplerRegister) -{ - ASSERT(ui32TextureRegister < MAX_RESOURCE_BINDINGS && - (psShader->sInfo.aui32SamplerMap[ui32TextureRegister] == MAX_RESOURCE_BINDINGS || - psShader->sInfo.aui32SamplerMap[ui32TextureRegister] == ui32SamplerRegister)); - ASSERT(ui32SamplerRegister < MAX_RESOURCE_BINDINGS); - psShader->sInfo.aui32SamplerMap[ui32TextureRegister] = ui32SamplerRegister; -} - -void UpdateOperandReferences(ShaderData* psShader, Instruction* psInst) -{ - uint32_t ui32Operand; - const uint32_t ui32NumOperands = psInst->ui32NumOperands; - for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) - { - Operand* psOperand = &psInst->asOperands[ui32Operand]; - if (psOperand->eType == OPERAND_TYPE_INPUT || - psOperand->eType == OPERAND_TYPE_INPUT_CONTROL_POINT) - { - if (psOperand->iIndexDims == INDEX_2D) - { - if (psOperand->aui32ArraySizes[1] != 0)//gl_in[].gl_Position - { - psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; - } - } - else - { - psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; - } - } - } - - switch (psInst->eOpcode) - { - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_B: - case OPCODE_SAMPLE_D: - case OPCODE_GATHER4: - case OPCODE_GATHER4_C: - BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber); - break; - case OPCODE_GATHER4_PO: - case OPCODE_GATHER4_PO_C: - BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber); - break; - } -} - -const uint32_t* DecodeShaderPhase(const uint32_t* pui32Tokens, - ShaderData* psShader, - const uint32_t ui32Phase) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - const uint32_t ui32InstanceIndex = psShader->asPhase[ui32Phase].ui32InstanceCount; - - Instruction* psInst; - - //Declarations - Declaration* psDecl; - - //Using ui32ShaderLength as the declaration and instruction count - //will allocate more than enough memory. Avoids having to - //traverse the entire shader just to get the real counts. - - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - psShader->asPhase[ui32Phase].ppsDecl[ui32InstanceIndex] = psDecl; - psShader->asPhase[ui32Phase].pui32DeclCount[ui32InstanceIndex] = 0; - - psShader->asPhase[ui32Phase].ui32InstanceCount++; - - while (1) //Keep going until we reach the first non-declaration token, or the end of the shader. - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - psShader->asPhase[ui32Phase].pui32DeclCount[ui32InstanceIndex]++; - psDecl++; - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - - //Instructions - psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); - psShader->asPhase[ui32Phase].ppsInst[ui32InstanceIndex] = psInst; - psShader->asPhase[ui32Phase].pui32InstCount[ui32InstanceIndex] = 0; - - while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) - { - const uint32_t* nextInstr = DeocdeInstruction(pui32CurrentToken, psInst, psShader); - -#ifdef _DEBUG - if (nextInstr == pui32CurrentToken) - { - ASSERT(0); - break; - } -#endif - - if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) - { - return pui32CurrentToken; - } - else if (psInst->eOpcode == OPCODE_HS_JOIN_PHASE) - { - return pui32CurrentToken; - } - pui32CurrentToken = nextInstr; - psShader->asPhase[ui32Phase].pui32InstCount[ui32InstanceIndex]++; - - psInst++; - } - - return pui32CurrentToken; -} - -void AllocateHullPhaseArrays(const uint32_t* pui32Tokens, - ShaderData* psShader, - uint32_t ui32Phase, - OPCODE_TYPE ePhaseOpcode) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - uint32_t ui32InstanceCount = 0; - - while (1) //Keep going until we reach the first non-declaration token, or the end of the shader. - { - uint32_t ui32TokenLength = DecodeInstructionLength(*pui32CurrentToken); - const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32CurrentToken); - - if (eOpcode == OPCODE_CUSTOMDATA) - { - ui32TokenLength = pui32CurrentToken[1]; - } - - pui32CurrentToken = pui32CurrentToken + ui32TokenLength; - - if (eOpcode == ePhaseOpcode) - { - ui32InstanceCount++; - } - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - - if (ui32InstanceCount) - { - psShader->asPhase[ui32Phase].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t) * ui32InstanceCount); - psShader->asPhase[ui32Phase].ppsDecl = hlslcc_malloc(sizeof(Declaration*) * ui32InstanceCount); - psShader->asPhase[ui32Phase].pui32DeclCount[0] = 0; - - psShader->asPhase[ui32Phase].pui32InstCount = hlslcc_malloc(sizeof(uint32_t) * ui32InstanceCount); - psShader->asPhase[ui32Phase].ppsInst = hlslcc_malloc(sizeof(Instruction*) * ui32InstanceCount); - psShader->asPhase[ui32Phase].pui32InstCount[0] = 0; - } -} - -const uint32_t* DecodeHullShader(const uint32_t* pui32Tokens, ShaderData* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; - Declaration* psDecl; - - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); - - psShader->asPhase[HS_GLOBAL_DECL].ppsInst = 0; - psShader->asPhase[HS_GLOBAL_DECL].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); - psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0] = psDecl; - psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0] = 0; - psShader->asPhase[HS_GLOBAL_DECL].ui32InstanceCount = 1; - - AllocateHullPhaseArrays(pui32Tokens, psShader, HS_CTRL_POINT_PHASE, OPCODE_HS_CONTROL_POINT_PHASE); - AllocateHullPhaseArrays(pui32Tokens, psShader, HS_FORK_PHASE, OPCODE_HS_FORK_PHASE); - AllocateHullPhaseArrays(pui32Tokens, psShader, HS_JOIN_PHASE, OPCODE_HS_JOIN_PHASE); - - //Keep going until we have done all phases or the end of the shader. - while (1) - { - const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); - - if (pui32Result) - { - pui32CurrentToken = pui32Result; - - if (psDecl->eOpcode == OPCODE_HS_CONTROL_POINT_PHASE) - { - pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_CTRL_POINT_PHASE); - } - else if (psDecl->eOpcode == OPCODE_HS_FORK_PHASE) - { - pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_FORK_PHASE); - } - else if (psDecl->eOpcode == OPCODE_HS_JOIN_PHASE) - { - pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_JOIN_PHASE); - } - else - { - psDecl++; - psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]++; - } - - if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) - { - break; - } - } - else - { - break; - } - } - - return pui32CurrentToken; -} - -void Decode(const uint32_t* pui32Tokens, ShaderData* psShader) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - const uint32_t ui32ShaderLength = pui32Tokens[1]; - - psShader->ui32MajorVersion = DecodeProgramMajorVersion(*pui32CurrentToken); - psShader->ui32MinorVersion = DecodeProgramMinorVersion(*pui32CurrentToken); - psShader->eShaderType = DecodeShaderType(*pui32CurrentToken); - - pui32CurrentToken++;//Move to shader length - psShader->ui32ShaderLength = ui32ShaderLength; - pui32CurrentToken++;//Move to after shader length (usually a declaration) - - psShader->pui32FirstToken = pui32Tokens; - - if (psShader->eShaderType == HULL_SHADER) - { - pui32CurrentToken = DecodeHullShader(pui32CurrentToken, psShader); - return; - } - - psShader->asPhase[MAIN_PHASE].ui32InstanceCount = 0; - psShader->asPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->asPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); - psShader->asPhase[MAIN_PHASE].pui32DeclCount[0] = 0; - - psShader->asPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->asPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); - psShader->asPhase[MAIN_PHASE].pui32InstCount[0] = 0; - - DecodeShaderPhase(pui32CurrentToken, psShader, MAIN_PHASE); -} - -ShaderData* DecodeDXBC(uint32_t* data) -{ - ShaderData* psShader; - DXBCContainerHeader* header = (DXBCContainerHeader*)data; - uint32_t i; - uint32_t chunkCount; - uint32_t* chunkOffsets; - ReflectionChunks refChunks; - uint32_t* shaderChunk = 0; - - if (header->fourcc != FOURCC_DXBC) - { - //Could be SM1/2/3. If the shader type token - //looks valid then we continue - uint32_t type = DecodeShaderTypeDX9(data[0]); - - if (type != INVALID_SHADER) - { - return DecodeDX9BC(data); - } - return 0; - } - - refChunks.pui32Inputs = NULL; - refChunks.pui32Interfaces = NULL; - refChunks.pui32Outputs = NULL; - refChunks.pui32Resources = NULL; - refChunks.pui32Inputs11 = NULL; - refChunks.pui32Outputs11 = NULL; - refChunks.pui32OutputsWithStreams = NULL; - refChunks.pui32PatchConstants = NULL; - refChunks.pui32Effects10Data = NULL; - - chunkOffsets = (uint32_t*)(header + 1); - - chunkCount = header->chunkCount; - - for (i = 0; i < chunkCount; ++i) - { - uint32_t offset = chunkOffsets[i]; - - DXBCChunkHeader* chunk = (DXBCChunkHeader*)((char*)data + offset); - - switch (chunk->fourcc) - { - case FOURCC_ISGN: - { - refChunks.pui32Inputs = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_ISG1: - { - refChunks.pui32Inputs11 = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_RDEF: - { - refChunks.pui32Resources = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_IFCE: - { - refChunks.pui32Interfaces = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSGN: - { - refChunks.pui32Outputs = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSG1: - { - refChunks.pui32Outputs11 = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_OSG5: - { - refChunks.pui32OutputsWithStreams = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_SHDR: - case FOURCC_SHEX: - { - shaderChunk = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_PSGN: - { - refChunks.pui32PatchConstants = (uint32_t*)(chunk + 1); - break; - } - case FOURCC_FX10: - { - refChunks.pui32Effects10Data = (uint32_t*)(chunk + 1); - break; - } - default: - { - break; - } - } - } - - if (shaderChunk) - { - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - - psShader = hlslcc_calloc(1, sizeof(ShaderData)); - - ui32MajorVersion = DecodeProgramMajorVersion(*shaderChunk); - ui32MinorVersion = DecodeProgramMinorVersion(*shaderChunk); - - LoadShaderInfo(ui32MajorVersion, - ui32MinorVersion, - &refChunks, - &psShader->sInfo); - - Decode(shaderChunk, psShader); - - return psShader; - } - - return 0; -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c b/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c deleted file mode 100644 index f33c5b4b0e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c +++ /dev/null @@ -1,1133 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/debug.h" -#include "internal_includes/decode.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/reflect.h" -#include "internal_includes/structs.h" -#include "internal_includes/tokens.h" -#include "stdio.h" -#include "stdlib.h" - -#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) -enum -{ - FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B') -}; // Constant table - -#ifdef _DEBUG -static uint64_t dx9operandID = 0; -static uint64_t dx9instructionID = 0; -#endif - -static uint32_t aui32ImmediateConst[256]; -static uint32_t ui32MaxTemp = 0; - -uint32_t DX9_DECODE_OPERAND_IS_SRC = 0x1; -uint32_t DX9_DECODE_OPERAND_IS_DEST = 0x2; -uint32_t DX9_DECODE_OPERAND_IS_DECL = 0x4; - -uint32_t DX9_DECODE_OPERAND_IS_CONST = 0x8; -uint32_t DX9_DECODE_OPERAND_IS_ICONST = 0x10; -uint32_t DX9_DECODE_OPERAND_IS_BCONST = 0x20; - -#define MAX_INPUTS 64 - -static DECLUSAGE_DX9 aeInputUsage[MAX_INPUTS]; -static uint32_t aui32InputUsageIndex[MAX_INPUTS]; - -static void DecodeOperandDX9(const ShaderData* psShader, const uint32_t ui32Token, const uint32_t ui32Token1, uint32_t ui32Flags, Operand* psOperand) -{ - const uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token); - const uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token); - const uint32_t bRelativeAddr = DecodeOperandIsRelativeAddressModeDX9(ui32Token); - - const uint32_t ui32WriteMask = DecodeDestWriteMaskDX9(ui32Token); - const uint32_t ui32Swizzle = DecodeOperandSwizzleDX9(ui32Token); - - SHADER_VARIABLE_TYPE ConstType; - - psOperand->ui32RegisterNumber = ui32RegNum; - - psOperand->iNumComponents = 4; - -#ifdef _DEBUG - psOperand->id = dx9operandID++; -#endif - - psOperand->iWriteMaskEnabled = 0; - psOperand->iGSInput = 0; - psOperand->iExtended = 0; - psOperand->psSubOperand[0] = 0; - psOperand->psSubOperand[1] = 0; - psOperand->psSubOperand[2] = 0; - - psOperand->iIndexDims = INDEX_0D; - - psOperand->iIntegerImmediate = 0; - - psOperand->pszSpecialName[0] = '\0'; - - psOperand->eModifier = OPERAND_MODIFIER_NONE; - if (ui32Flags & DX9_DECODE_OPERAND_IS_SRC) - { - uint32_t ui32Modifier = DecodeSrcModifierDX9(ui32Token); - - switch (ui32Modifier) - { - case SRCMOD_DX9_NONE: - { - break; - } - case SRCMOD_DX9_NEG: - { - psOperand->eModifier = OPERAND_MODIFIER_NEG; - break; - } - case SRCMOD_DX9_ABS: - { - psOperand->eModifier = OPERAND_MODIFIER_ABS; - break; - } - case SRCMOD_DX9_ABSNEG: - { - psOperand->eModifier = OPERAND_MODIFIER_ABSNEG; - break; - } - default: - { - ASSERT(0); - break; - } - } - } - - if ((ui32Flags & DX9_DECODE_OPERAND_IS_DECL) == 0) - { - if (ui32Flags & DX9_DECODE_OPERAND_IS_DEST) - { - if (ui32WriteMask != DX9_WRITEMASK_ALL) - { - psOperand->iWriteMaskEnabled = 1; - psOperand->eSelMode = OPERAND_4_COMPONENT_MASK_MODE; - - if (ui32WriteMask & DX9_WRITEMASK_0) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_X; - } - if (ui32WriteMask & DX9_WRITEMASK_1) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Y; - } - if (ui32WriteMask & DX9_WRITEMASK_2) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Z; - } - if (ui32WriteMask & DX9_WRITEMASK_3) - { - psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_W; - } - } - } - else if (ui32Swizzle != NO_SWIZZLE_DX9) - { - uint32_t component; - - psOperand->iWriteMaskEnabled = 1; - psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE; - - psOperand->ui32Swizzle = 1; - - /* Add the swizzle */ - if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(0)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(1)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Y; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(2)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Z; - } - else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(3)) - { - psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; - psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_W; - } - else - { - for (component = 0; component < 4; component++) - { - uint32_t ui32CompSwiz = ui32Swizzle & (3 << (DX9_SWIZZLE_SHIFT + (component * 2))); - ui32CompSwiz >>= (DX9_SWIZZLE_SHIFT + (component * 2)); - - if (ui32CompSwiz == 0) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_X; - } - else if (ui32CompSwiz == 1) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Y; - } - else if (ui32CompSwiz == 2) - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Z; - } - else - { - psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_W; - } - } - } - } - - if (bRelativeAddr) - { - psOperand->psSubOperand[0] = hlslcc_malloc(sizeof(Operand)); - DecodeOperandDX9(psShader, ui32Token1, 0, ui32Flags, psOperand->psSubOperand[0]); - - psOperand->iIndexDims = INDEX_1D; - - psOperand->eIndexRep[0] = OPERAND_INDEX_RELATIVE; - - psOperand->aui32ArraySizes[0] = 0; - } - } - - if (ui32RegType == OPERAND_TYPE_DX9_CONSTBOOL) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; - ConstType = SVT_BOOL; - } - else if (ui32RegType == OPERAND_TYPE_DX9_CONSTINT) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; - ConstType = SVT_INT; - } - else if (ui32RegType == OPERAND_TYPE_DX9_CONST) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; - ConstType = SVT_FLOAT; - } - - switch (ui32RegType) - { - case OPERAND_TYPE_DX9_TEMP: - { - psOperand->eType = OPERAND_TYPE_TEMP; - - if (ui32MaxTemp < ui32RegNum + 1) - { - ui32MaxTemp = ui32RegNum + 1; - } - break; - } - case OPERAND_TYPE_DX9_INPUT: - { - psOperand->eType = OPERAND_TYPE_INPUT; - - ASSERT(ui32RegNum < MAX_INPUTS); - - if (psShader->eShaderType == PIXEL_SHADER) - { - if (aeInputUsage[ui32RegNum] == DECLUSAGE_TEXCOORD) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - psOperand->ui32RegisterNumber = aui32InputUsageIndex[ui32RegNum]; - } - else - // 0 = base colour, 1 = offset colour. - if (ui32RegNum == 0) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; - } - else - { - ASSERT(ui32RegNum == 1); - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; - } - } - break; - } - // Same value as OPERAND_TYPE_DX9_TEXCRDOUT - // OPERAND_TYPE_DX9_TEXCRDOUT is the pre-SM3 equivalent - case OPERAND_TYPE_DX9_OUTPUT: - { - psOperand->eType = OPERAND_TYPE_OUTPUT; - - if (psShader->eShaderType == VERTEX_SHADER) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - } - break; - } - case OPERAND_TYPE_DX9_RASTOUT: - { - // RegNum: - // 0=POSIION - // 1=FOG - // 2=POINTSIZE - psOperand->eType = OPERAND_TYPE_OUTPUT; - switch (ui32RegNum) - { - case 0: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_POSITION; - break; - } - case 1: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_FOG; - break; - } - case 2: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_POINTSIZE; - psOperand->iNumComponents = 1; - break; - } - } - break; - } - case OPERAND_TYPE_DX9_ATTROUT: - { - ASSERT(psShader->eShaderType == VERTEX_SHADER); - - psOperand->eType = OPERAND_TYPE_OUTPUT; - - // 0 = base colour, 1 = offset colour. - if (ui32RegNum == 0) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; - } - else - { - ASSERT(ui32RegNum == 1); - psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; - } - - break; - } - case OPERAND_TYPE_DX9_COLOROUT: - { - ASSERT(psShader->eShaderType == PIXEL_SHADER); - psOperand->eType = OPERAND_TYPE_OUTPUT; - break; - } - case OPERAND_TYPE_DX9_CONSTBOOL: - case OPERAND_TYPE_DX9_CONSTINT: - case OPERAND_TYPE_DX9_CONST: - { - // c# = constant float - // i# = constant int - // b# = constant bool - - // c0 might be an immediate while i0 is in the constant buffer - if (aui32ImmediateConst[ui32RegNum] & ui32Flags) - { - if (ConstType != SVT_FLOAT) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; - } - else - { - psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONST; - } - } - else - { - psOperand->eType = OPERAND_TYPE_CONSTANT_BUFFER; - psOperand->aui32ArraySizes[1] = psOperand->ui32RegisterNumber; - } - break; - } - case OPERAND_TYPE_DX9_ADDR: - { - // Vertex shader: address register (only have one of these) - // Pixel shader: texture coordinate register (a few of these) - if (psShader->eShaderType == PIXEL_SHADER) - { - psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; - } - else - { - psOperand->eType = OPERAND_TYPE_SPECIAL_ADDRESS; - } - break; - } - case OPERAND_TYPE_DX9_SAMPLER: - { - psOperand->eType = OPERAND_TYPE_RESOURCE; - break; - } - case OPERAND_TYPE_DX9_LOOP: - { - psOperand->eType = OPERAND_TYPE_SPECIAL_LOOPCOUNTER; - break; - } - default: - { - ASSERT(0); - break; - } - } -} - -static void DeclareNumTemps(ShaderData* psShader, const uint32_t ui32NumTemps, Declaration* psDecl) -{ - (void)psShader; - - psDecl->eOpcode = OPCODE_DCL_TEMPS; - psDecl->value.ui32NumTemps = ui32NumTemps; -} - -static void SetupRegisterUsage(const ShaderData* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1) -{ - (void)psShader; - - DECLUSAGE_DX9 eUsage = DecodeUsageDX9(ui32Token0); - uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0); - uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token1); - uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); - - if (ui32RegType == OPERAND_TYPE_DX9_INPUT) - { - ASSERT(ui32RegNum < MAX_INPUTS); - aeInputUsage[ui32RegNum] = eUsage; - aui32InputUsageIndex[ui32RegNum] = ui32UsageIndex; - } -} - -// Declaring one constant from a constant buffer will cause all constants in the buffer decalared. -// In dx9 there is only one constant buffer per shader. -static void DeclareConstantBuffer(const ShaderData* psShader, Declaration* psDecl) -{ - // Pick any constant register in the table. Might not start at c0 (e.g. when register(cX) is used). - uint32_t ui32RegNum = psShader->sInfo.psConstantBuffers->asVars[0].ui32StartOffset / 16; - OPERAND_TYPE_DX9 ui32RegType = OPERAND_TYPE_DX9_CONST; - - if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_INT) - { - ui32RegType = OPERAND_TYPE_DX9_CONSTINT; - } - else if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_BOOL) - { - ui32RegType = OPERAND_TYPE_DX9_CONSTBOOL; - } - - if (psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_INPUT; - } - else - { - psDecl->eOpcode = OPCODE_DCL_INPUT_PS; - } - psDecl->ui32NumOperands = 1; - - DecodeOperandDX9(psShader, CreateOperandTokenDX9(ui32RegNum, ui32RegType), 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); - - ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER); - - psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index - psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. -} - -static void DecodeDeclarationDX9(const ShaderData* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1, Declaration* psDecl) -{ - /*uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0);*/ - uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); - - if (psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_INPUT; - } - else - { - psDecl->eOpcode = OPCODE_DCL_INPUT_PS; - } - psDecl->ui32NumOperands = 1; - DecodeOperandDX9(psShader, ui32Token1, 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); - - if (ui32RegType == OPERAND_TYPE_DX9_SAMPLER) - { - const RESOURCE_DIMENSION eResDim = DecodeTextureTypeMaskDX9(ui32Token0); - psDecl->value.eResourceDimension = eResDim; - psDecl->ui32IsShadowTex = 0; - psDecl->eOpcode = OPCODE_DCL_RESOURCE; - } - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) - { - psDecl->eOpcode = OPCODE_DCL_OUTPUT; - - if (psDecl->asOperands[0].ui32RegisterNumber == 0 && psShader->eShaderType == VERTEX_SHADER) - { - psDecl->eOpcode = OPCODE_DCL_OUTPUT_SIV; - // gl_Position - psDecl->asOperands[0].eSpecialName = NAME_POSITION; - } - } - else if (psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index - psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. - } -} - -static void DefineDX9(ShaderData* psShader, - const uint32_t ui32RegNum, - const uint32_t ui32Flags, - const uint32_t c0, - const uint32_t c1, - const uint32_t c2, - const uint32_t c3, - Declaration* psDecl) -{ - (void)psShader; - (void)psDecl; - - psDecl->eOpcode = OPCODE_SPECIAL_DCL_IMMCONST; - psDecl->ui32NumOperands = 2; - - memset(&psDecl->asOperands[0], 0, sizeof(Operand)); - psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONST; - - psDecl->asOperands[0].ui32RegisterNumber = ui32RegNum; - - if (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) - { - psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; - } - - aui32ImmediateConst[ui32RegNum] |= ui32Flags; - - memset(&psDecl->asOperands[1], 0, sizeof(Operand)); - psDecl->asOperands[1].eType = OPERAND_TYPE_IMMEDIATE32; - psDecl->asOperands[1].iNumComponents = 4; - psDecl->asOperands[1].iIntegerImmediate = (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) ? 1 : 0; - psDecl->asOperands[1].afImmediates[0] = *((float*)&c0); - psDecl->asOperands[1].afImmediates[1] = *((float*)&c1); - psDecl->asOperands[1].afImmediates[2] = *((float*)&c2); - psDecl->asOperands[1].afImmediates[3] = *((float*)&c3); -} - -static void CreateD3D10Instruction(ShaderData* psShader, - Instruction* psInst, - const OPCODE_TYPE eType, - const uint32_t bHasDest, - const uint32_t ui32SrcCount, - const uint32_t* pui32Tokens) -{ - uint32_t ui32Src; - uint32_t ui32Offset = 1; - - memset(psInst, 0, sizeof(Instruction)); - -#ifdef _DEBUG - psInst->id = dx9instructionID++; -#endif - - psInst->eOpcode = eType; - psInst->ui32NumOperands = ui32SrcCount; - - if (bHasDest) - { - ++psInst->ui32NumOperands; - - DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_DEST, &psInst->asOperands[0]); - - if (DecodeDestModifierDX9(pui32Tokens[ui32Offset]) & DESTMOD_DX9_SATURATE) - { - psInst->bSaturate = 1; - } - - ui32Offset++; - psInst->ui32FirstSrc = 1; - } - - for (ui32Src = 0; ui32Src < ui32SrcCount; ++ui32Src) - { - DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_SRC, &psInst->asOperands[bHasDest + ui32Src]); - - ui32Offset++; - } -} - -ShaderData* DecodeDX9BC(const uint32_t* pui32Tokens) -{ - const uint32_t* pui32CurrentToken = pui32Tokens; - uint32_t ui32NumInstructions = 0; - uint32_t ui32NumDeclarations = 0; - Instruction* psInst; - Declaration* psDecl; - uint32_t decl, inst; - uint32_t bDeclareConstantTable = 0; - ShaderData* psShader = hlslcc_calloc(1, sizeof(ShaderData)); - - memset(aui32ImmediateConst, 0, 256); - - psShader->ui32MajorVersion = DecodeProgramMajorVersionDX9(*pui32CurrentToken); - psShader->ui32MinorVersion = DecodeProgramMinorVersionDX9(*pui32CurrentToken); - psShader->eShaderType = DecodeShaderTypeDX9(*pui32CurrentToken); - - pui32CurrentToken++; - - // Work out how many instructions and declarations we need to allocate memory for. - while (1) - { - OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); - uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); - - if (eOpcode == OPCODE_DX9_END) - { - // SM4+ always end with RET. - // Insert a RET instruction on END to - // replicate this behaviour. - ++ui32NumInstructions; - break; - } - else if (eOpcode == OPCODE_DX9_COMMENT) - { - ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); - if (pui32CurrentToken[1] == FOURCC_CTAB) - { - LoadD3D9ConstantTable((char*)(&pui32CurrentToken[2]), &psShader->sInfo); - - ASSERT(psShader->sInfo.ui32NumConstantBuffers); - - if (psShader->sInfo.psConstantBuffers[0].ui32NumVars) - { - ++ui32NumDeclarations; - bDeclareConstantTable = 1; - } - } - } - else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) - { - ++ui32NumDeclarations; - } - else if (eOpcode == OPCODE_DX9_DCL) - { - const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); - uint32_t ignoreDCL = 0; - - // Inputs and outputs are declared in AddVersionDependentCode - if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) - { - ignoreDCL = 1; - } - if (!ignoreDCL) - { - ++ui32NumDeclarations; - } - } - else - { - switch (eOpcode) - { - case OPCODE_DX9_NRM: - { - // Emulate with dp4 and rsq - ui32NumInstructions += 2; - break; - } - default: - { - ++ui32NumInstructions; - break; - } - } - } - - pui32CurrentToken += ui32InstLen + 1; - } - - psInst = hlslcc_malloc(sizeof(Instruction) * ui32NumInstructions); - psShader->asPhase[MAIN_PHASE].ui32InstanceCount = 1; - psShader->asPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); - psShader->asPhase[MAIN_PHASE].ppsInst[0] = psInst; - psShader->asPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->asPhase[MAIN_PHASE].pui32InstCount[0] = ui32NumInstructions; - - if (psShader->eShaderType == VERTEX_SHADER) - { - // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not - ui32NumDeclarations++; - } - - // For declaring temps. - ui32NumDeclarations++; - - psDecl = hlslcc_malloc(sizeof(Declaration) * ui32NumDeclarations); - psShader->asPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); - psShader->asPhase[MAIN_PHASE].ppsDecl[0] = psDecl; - psShader->asPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->asPhase[MAIN_PHASE].pui32DeclCount[0] = ui32NumDeclarations; - - pui32CurrentToken = pui32Tokens + 1; - - inst = 0; - decl = 0; - while (1) - { - OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); - uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); - - if (eOpcode == OPCODE_DX9_END) - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); - inst++; - break; - } - else if (eOpcode == OPCODE_DX9_COMMENT) - { - ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); - } - else if (eOpcode == OPCODE_DX9_DCL) - { - const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); - uint32_t ignoreDCL = 0; - // Inputs and outputs are declared in AddVersionDependentCode - if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) - { - ignoreDCL = 1; - } - - SetupRegisterUsage(psShader, pui32CurrentToken[1], pui32CurrentToken[2]); - - if (!ignoreDCL) - { - DecodeDeclarationDX9(psShader, pui32CurrentToken[1], pui32CurrentToken[2], &psDecl[decl]); - decl++; - } - } - else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) - { - const uint32_t ui32Const0 = *(pui32CurrentToken + 2); - const uint32_t ui32Const1 = *(pui32CurrentToken + 3); - const uint32_t ui32Const2 = *(pui32CurrentToken + 4); - const uint32_t ui32Const3 = *(pui32CurrentToken + 5); - uint32_t ui32Flags = 0; - - if (eOpcode == OPCODE_DX9_DEF) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; - } - else if (eOpcode == OPCODE_DX9_DEFI) - { - ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; - } - else - { - ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; - } - - DefineDX9(psShader, DecodeOperandRegisterNumberDX9(pui32CurrentToken[1]), ui32Flags, ui32Const0, ui32Const1, ui32Const2, ui32Const3, &psDecl[decl]); - decl++; - } - else - { - switch (eOpcode) - { - case OPCODE_DX9_MOV: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOV, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_LIT: - { - /*Dest.x = 1 - Dest.y = (Src0.x > 0) ? Src0.x : 0 - Dest.z = (Src0.x > 0 && Src0.y > 0) ? pow(Src0.y, Src0.w) : 0 - Dest.w = 1 - */ - ASSERT(0); - break; - } - case OPCODE_DX9_ADD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SUB: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); - ASSERT(psInst[inst].asOperands[2].eModifier == OPERAND_MODIFIER_NONE); - psInst[inst].asOperands[2].eModifier = OPERAND_MODIFIER_NEG; - break; - } - case OPCODE_DX9_MAD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAD, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_MUL: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MUL, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_RCP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RCP, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_RSQ: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP3: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP3, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP4: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_MIN: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MIN, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_MAX: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAX, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SLT: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LT, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_SGE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_GE, 1, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_EXP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_EXP, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_LOG: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOG, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_NRM: - { - // Convert NRM RESULT, SRCA into: - // dp4 RESULT, SRCA, SRCA - // rsq RESULT, RESULT - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 1, pui32CurrentToken); - memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); - psInst[inst].ui32NumOperands++; - ++inst; - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 0, 0, pui32CurrentToken); - memcpy(&psInst[inst].asOperands[0], &psInst[inst - 1].asOperands[0], sizeof(Operand)); - memcpy(&psInst[inst].asOperands[1], &psInst[inst - 1].asOperands[0], sizeof(Operand)); - psInst[inst].ui32NumOperands++; - psInst[inst].ui32NumOperands++; - break; - } - case OPCODE_DX9_SINCOS: - { - // Before SM3, SINCOS has 2 extra constant sources -D3DSINCOSCONST1 and D3DSINCOSCONST2. - // Ignore them. - - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SINCOS, 1, 1, pui32CurrentToken); - // Pre-SM4: - // If the write mask is .x: dest.x = cos( V ) - // If the write mask is .y: dest.y = sin( V ) - // If the write mask is .xy: - // dest.x = cos( V ) - // dest.y = sin( V ) - - // SM4+ - // destSin destCos Angle - - psInst[inst].ui32NumOperands = 3; - - // Set the angle - memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); - - // Set the cosine dest - memcpy(&psInst[inst].asOperands[1], &psInst[inst].asOperands[0], sizeof(Operand)); - - // Set write masks - psInst[inst].asOperands[0].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_Y; - if (psInst[inst].asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - // Need cosine - } - else - { - psInst[inst].asOperands[0].eType = OPERAND_TYPE_NULL; - } - psInst[inst].asOperands[1].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_X; - if (psInst[inst].asOperands[1].ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - // Need sine - } - else - { - psInst[inst].asOperands[1].eType = OPERAND_TYPE_NULL; - } - - break; - } - case OPCODE_DX9_FRC: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_FRC, 1, 1, pui32CurrentToken); - break; - } - - case OPCODE_DX9_MOVA: - { - // MOVA preforms RoundToNearest on the src data. - // The only rounding functions available in all GLSL version are ceil and floor. - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ROUND_NI, 1, 1, pui32CurrentToken); - break; - } - - case OPCODE_DX9_TEX: - { - // texld r0, t0, s0 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE, 1, 2, pui32CurrentToken); - psInst[inst].asOperands[2].ui32RegisterNumber = 0; - - break; - } - case OPCODE_DX9_TEXLDL: - { - // texld r0, t0, s0 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_L, 1, 2, pui32CurrentToken); - psInst[inst].asOperands[2].ui32RegisterNumber = 0; - - // Lod comes from fourth coordinate of address. - memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[1], sizeof(Operand)); - - psInst[inst].ui32NumOperands = 5; - - break; - } - - case OPCODE_DX9_IF: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 1, pui32CurrentToken); - psInst[inst].eDX9TestType = D3DSPC_BOOLEAN; - break; - } - - case OPCODE_DX9_IFC: - { - const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 2, pui32CurrentToken); - psInst[inst].eDX9TestType = eCmpOp; - break; - } - case OPCODE_DX9_ELSE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ELSE, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_CMP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOVC, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_REP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_REP, 0, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDREP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDREP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_BREAKC: - { - const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAKC, 0, 2, pui32CurrentToken); - psInst[inst].eDX9TestType = eCmpOp; - break; - } - - case OPCODE_DX9_DSX: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTX, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_DSY: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTY, 1, 1, pui32CurrentToken); - break; - } - case OPCODE_DX9_TEXKILL: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DISCARD, 1, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_TEXLDD: - { - // texldd, dst, src0, src1, src2, src3 - // srcAddress[.swizzle], srcResource[.swizzle], srcSampler, XGradient, YGradient - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_D, 1, 4, pui32CurrentToken); - - // Move the gradients one slot up - memcpy(&psInst[inst].asOperands[5], &psInst[inst].asOperands[4], sizeof(Operand)); - memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[3], sizeof(Operand)); - - // Sampler register - psInst[inst].asOperands[3].ui32RegisterNumber = 0; - psInst[inst].ui32NumOperands = 6; - break; - } - case OPCODE_DX9_LRP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LRP, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_DP2ADD: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP2ADD, 1, 3, pui32CurrentToken); - break; - } - case OPCODE_DX9_POW: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_POW, 1, 2, pui32CurrentToken); - break; - } - - case OPCODE_DX9_DST: - case OPCODE_DX9_M4x4: - case OPCODE_DX9_M4x3: - case OPCODE_DX9_M3x4: - case OPCODE_DX9_M3x3: - case OPCODE_DX9_M3x2: - case OPCODE_DX9_CALL: - case OPCODE_DX9_CALLNZ: - case OPCODE_DX9_LABEL: - - case OPCODE_DX9_CRS: - case OPCODE_DX9_SGN: - case OPCODE_DX9_ABS: - - case OPCODE_DX9_TEXCOORD: - case OPCODE_DX9_TEXBEM: - case OPCODE_DX9_TEXBEML: - case OPCODE_DX9_TEXREG2AR: - case OPCODE_DX9_TEXREG2GB: - case OPCODE_DX9_TEXM3x2PAD: - case OPCODE_DX9_TEXM3x2TEX: - case OPCODE_DX9_TEXM3x3PAD: - case OPCODE_DX9_TEXM3x3TEX: - case OPCODE_DX9_TEXM3x3SPEC: - case OPCODE_DX9_TEXM3x3VSPEC: - case OPCODE_DX9_EXPP: - case OPCODE_DX9_LOGP: - case OPCODE_DX9_CND: - case OPCODE_DX9_TEXREG2RGB: - case OPCODE_DX9_TEXDP3TEX: - case OPCODE_DX9_TEXM3x2DEPTH: - case OPCODE_DX9_TEXDP3: - case OPCODE_DX9_TEXM3x3: - case OPCODE_DX9_TEXDEPTH: - case OPCODE_DX9_BEM: - case OPCODE_DX9_SETP: - case OPCODE_DX9_BREAKP: - { - ASSERT(0); - break; - } - case OPCODE_DX9_NOP: - case OPCODE_DX9_PHASE: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_NOP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_LOOP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOOP, 0, 2, pui32CurrentToken); - break; - } - case OPCODE_DX9_RET: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDLOOP: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDLOOP, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_ENDIF: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDIF, 0, 0, pui32CurrentToken); - break; - } - case OPCODE_DX9_BREAK: - { - CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAK, 0, 0, pui32CurrentToken); - break; - } - default: - { - ASSERT(0); - break; - } - } - - UpdateOperandReferences(psShader, &psInst[inst]); - - inst++; - } - - pui32CurrentToken += ui32InstLen + 1; - } - - DeclareNumTemps(psShader, ui32MaxTemp, &psDecl[decl]); - ++decl; - - if (psShader->eShaderType == VERTEX_SHADER) - { - // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not - if (bDeclareConstantTable) - { - DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl + 1]); - } - else - { - DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl]); - } - } - - if (bDeclareConstantTable) - { - DeclareConstantBuffer(psShader, &psDecl[decl]); - } - - return psShader; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h deleted file mode 100644 index 5b071709bc..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h +++ /dev/null @@ -1,21 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef DEBUG_H_ -#define DEBUG_H_ - -#ifdef _DEBUG -#include "assert.h" -#define ASSERT(expr) CustomAssert(expr) -static void CustomAssert(int expression) -{ - if(!expression) - { - assert(0); - } -} -#else -#define ASSERT(expr) -#endif - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h deleted file mode 100644 index f0981cb15c..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h +++ /dev/null @@ -1,18 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef DECODE_H -#define DECODE_H - -#include "internal_includes/structs.h" - -ShaderData* DecodeDXBC(uint32_t* data); - -//You don't need to call this directly because DecodeDXBC -//will call DecodeDX9BC if the shader looks -//like it is SM1/2/3. -ShaderData* DecodeDX9BC(const uint32_t* pui32Tokens); - -void UpdateOperandReferences(ShaderData* psShader, Instruction* psInst); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c deleted file mode 100644 index 57c86655b7..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c +++ /dev/null @@ -1,37 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include <stdlib.h> - -#ifdef __APPLE_CC__ - #include <malloc/malloc.h> -#else -#include <malloc.h> -#endif - -// Wrapping these functions since we are taking the address of them and the std functions are dllimport which produce -// warning C4232 -void* std_malloc(size_t size) -{ - return malloc(size); -} - -void* std_calloc(size_t num, size_t size) -{ - return calloc(num, size); -} - -void std_free(void* p) -{ - free(p); -} - -void* std_realloc(void* p, size_t size) -{ - return realloc(p, size); -} - -void* (*hlslcc_malloc)(size_t size) = std_malloc; -void* (*hlslcc_calloc)(size_t num,size_t size) = std_calloc; -void (*hlslcc_free)(void *p) = std_free; -void* (*hlslcc_realloc)(void *p,size_t size) = std_realloc; diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h deleted file mode 100644 index 493aa1fe1e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h +++ /dev/null @@ -1,15 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef __HLSCC_MALLOC_H -#define __HLSCC_MALLOC_H - -extern void* (*hlslcc_malloc)(size_t size); -extern void* (*hlslcc_calloc)(size_t num,size_t size); -extern void (*hlslcc_free)(void *p); -extern void* (*hlslcc_realloc)(void *p,size_t size); - -#define bstr__alloc hlslcc_malloc -#define bstr__free hlslcc_free -#define bstr__realloc hlslcc_realloc -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h deleted file mode 100644 index 35d7a9b125..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h +++ /dev/null @@ -1,213 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef LANGUAGES_H -#define LANGUAGES_H - -#include "hlslcc.h" - -static int InOutSupported(const ShaderLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 0; - } - return 1; -} - -static int WriteToFragData(const ShaderLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 1; - } - return 0; -} - -static int ShaderBitEncodingSupported(const ShaderLang eLang) -{ - if( eLang != LANG_ES_300 && - eLang != LANG_ES_310 && - eLang < LANG_330) - { - return 0; - } - return 1; -} - -static int HaveOverloadedTextureFuncs(const ShaderLang eLang) -{ - if(eLang == LANG_ES_100 || eLang == LANG_120) - { - return 0; - } - return 1; -} - -//Only enable for ES. -//Not present in 120, ignored in other desktop languages. -static int HavePrecisionQualifers(const ShaderLang eLang) -{ - if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310) - { - return 1; - } - return 0; -} - -//Only on vertex inputs and pixel outputs. -static int HaveLimitedInOutLocationQualifier(const ShaderLang eLang, unsigned int flags) -{ - (void)flags; - - if(eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveInOutLocationQualifier(const ShaderLang eLang,const struct GlExtensions *extensions, unsigned int flags) -{ - (void)flags; - - if(eLang >= LANG_410 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_attrib_location)) - { - return 1; - } - return 0; -} - -//layout(binding = X) uniform {uniformA; uniformB;} -//layout(location = X) uniform uniform_name; -static int HaveUniformBindingsAndLocations(const ShaderLang eLang,const struct GlExtensions *extensions, unsigned int flags) -{ - if (flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS) - return 0; - - if (eLang >= LANG_430 || eLang == LANG_ES_310 || - (extensions && ((GlExtensions*)extensions)->ARB_explicit_uniform_location && ((GlExtensions*)extensions)->ARB_shading_language_420pack)) - { - return 1; - } - return 0; -} - -static int DualSourceBlendSupported(const ShaderLang eLang) -{ - if(eLang >= LANG_330) - { - return 1; - } - return 0; -} - -static int SubroutinesSupported(const ShaderLang eLang) -{ - if(eLang >= LANG_400) - { - return 1; - } - return 0; -} - -//Before 430, flat/smooth/centroid/noperspective must match -//between fragment and its previous stage. -//HLSL bytecode only tells us the interpolation in pixel shader. -static int PixelInterpDependency(const ShaderLang eLang) -{ - if(eLang < LANG_430) - { - return 1; - } - return 0; -} - -static int HaveUVec(const ShaderLang eLang) -{ - switch(eLang) - { - case LANG_ES_100: - case LANG_120: - return 0; - default: - break; - } - return 1; -} - -static int HaveGather(const ShaderLang eLang) -{ - if(eLang >= LANG_400 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveGatherNonConstOffset(const ShaderLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - - -static int HaveQueryLod(const ShaderLang eLang) -{ - if(eLang >= LANG_400) - { - return 1; - } - return 0; -} - -static int HaveQueryLevels(const ShaderLang eLang) -{ - if(eLang >= LANG_430) - { - return 1; - } - return 0; -} - - -static int HaveAtomicCounter(const ShaderLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveAtomicMem(const ShaderLang eLang) -{ - if(eLang >= LANG_430) - { - return 1; - } - return 0; -} - -static int HaveCompute(const ShaderLang eLang) -{ - if(eLang >= LANG_430 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -static int HaveImageLoadStore(const ShaderLang eLang) -{ - if(eLang >= LANG_420 || eLang == LANG_ES_310) - { - return 1; - } - return 0; -} - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h deleted file mode 100644 index 6db63de4ca..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h +++ /dev/null @@ -1,73 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef REFLECT_H -#define REFLECT_H - -#include "hlslcc.h" - -ResourceGroup ResourceTypeToResourceGroup(ResourceType); - -int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding); - -void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf); - -int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); - -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); -int GetOutputSignatureFromRegister(const uint32_t currentPhase, - const uint32_t ui32Register, - const uint32_t ui32Stream, - const uint32_t ui32CompMask, - ShaderInfo* psShaderInfo, - InOutSignature** ppsOut); - -int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); - -int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, - const uint32_t* pui32Swizzle, - ConstantBuffer* psCBuf, - ShaderVarType** ppsShaderVar, - int32_t* pi32Index, - int32_t* pi32Rebase); - -typedef struct -{ - uint32_t* pui32Inputs; - uint32_t* pui32Outputs; - uint32_t* pui32Resources; - uint32_t* pui32Interfaces; - uint32_t* pui32Inputs11; - uint32_t* pui32Outputs11; - uint32_t* pui32OutputsWithStreams; - uint32_t* pui32PatchConstants; - uint32_t* pui32Effects10Data; -} ReflectionChunks; - -void LoadShaderInfo(const uint32_t ui32MajorVersion, - const uint32_t ui32MinorVersion, - const ReflectionChunks* psChunks, - ShaderInfo* psInfo); - -void LoadD3D9ConstantTable(const char* data, - ShaderInfo* psInfo); - -void FreeShaderInfo(ShaderInfo* psShaderInfo); - -#if 0 -//--- Utility functions --- - -//Returns 0 if not found, 1 otherwise. -int GetResourceFromName(const char* name, ShaderInfo* psShaderInfo, ResourceBinding* psBinding); - -//These call into OpenGL and modify the uniforms of the currently bound program. -void SetResourceValueF(ResourceBinding* psBinding, float* value); -void SetResourceValueI(ResourceBinding* psBinding, int* value); -void SetResourceValueStr(ResourceBinding* psBinding, char* value); //Used for interfaces/subroutines. Also for constant buffers? - -void CreateUniformBufferObjectFromResource(ResourceBinding* psBinding, uint32_t* ui32GLHandle); -//------------------------ -#endif - -#endif - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h deleted file mode 100644 index 3561f7c78b..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h +++ /dev/null @@ -1,14 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef HLSLCC_SHADER_LIMITS_H -#define HLSLCC_SHADER_LIMITS_H - -static enum {MAX_SHADER_VEC4_OUTPUT = 512}; -static enum {MAX_SHADER_VEC4_INPUT = 512}; -static enum {MAX_TEXTURES = 128}; -static enum {MAX_FUNCTION_BODIES = 1024}; -static enum {MAX_CLASS_TYPES = 1024}; -static enum {MAX_FUNCTION_POINTERS = 128}; - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h deleted file mode 100644 index 541b28d86b..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h +++ /dev/null @@ -1,338 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef STRUCTS_H -#define STRUCTS_H - -#include "hlslcc.h" -#include "bstrlib.h" - -#include "internal_includes/tokens.h" -#include "internal_includes/reflect.h" - -enum -{ - MAX_SUB_OPERANDS = 3 -}; - -typedef struct Operand_TAG -{ - int iExtended; - OPERAND_TYPE eType; - OPERAND_MODIFIER eModifier; - OPERAND_MIN_PRECISION eMinPrecision; - int iIndexDims; - int indexRepresentation[4]; - int writeMask; - int iGSInput; - int iWriteMaskEnabled; - - int iNumComponents; - - OPERAND_4_COMPONENT_SELECTION_MODE eSelMode; - uint32_t ui32CompMask; - uint32_t ui32Swizzle; - uint32_t aui32Swizzle[4]; - - uint32_t aui32ArraySizes[3]; - uint32_t ui32RegisterNumber; - //If eType is OPERAND_TYPE_IMMEDIATE32 - float afImmediates[4]; - //If eType is OPERAND_TYPE_IMMEDIATE64 - double adImmediates[4]; - - int iIntegerImmediate; - - SPECIAL_NAME eSpecialName; - char pszSpecialName[64]; - - OPERAND_INDEX_REPRESENTATION eIndexRep[3]; - - struct Operand_TAG* psSubOperand[MAX_SUB_OPERANDS]; - - //One type for each component. - SHADER_VARIABLE_TYPE aeDataType[4]; - -#ifdef _DEBUG - uint64_t id; -#endif -} Operand; - -typedef struct Instruction_TAG -{ - OPCODE_TYPE eOpcode; - INSTRUCTION_TEST_BOOLEAN eBooleanTestType; - COMPARISON_DX9 eDX9TestType; - uint32_t ui32SyncFlags; - uint32_t ui32NumOperands; - uint32_t ui32FirstSrc; - Operand asOperands[6]; - uint32_t bSaturate; - uint32_t ui32FuncIndexWithinInterface; - RESINFO_RETURN_TYPE eResInfoReturnType; - - int bAddressOffset; - int8_t iUAddrOffset; - int8_t iVAddrOffset; - int8_t iWAddrOffset; - RESOURCE_RETURN_TYPE xType, yType, zType, wType; - RESOURCE_DIMENSION eResDim; - -#ifdef _DEBUG - uint64_t id; -#endif -} Instruction; - -enum -{ - MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE = 1024 -}; -enum -{ - MAX_TEXTURE_SAMPLERS_PAIRS = 32 -}; - -typedef struct ICBVec4_TAG -{ - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; -} ICBVec4; - -typedef struct Declaration_TAG -{ - OPCODE_TYPE eOpcode; - - uint32_t ui32NumOperands; - - Operand asOperands[2]; - - ICBVec4 asImmediateConstBuffer[MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE]; - //The declaration can set one of these - //values depending on the opcode. - union - { - uint32_t ui32GlobalFlags; - uint32_t ui32NumTemps; - RESOURCE_DIMENSION eResourceDimension; - CONSTANT_BUFFER_ACCESS_PATTERN eCBAccessPattern; - INTERPOLATION_MODE eInterpolation; - PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology; - PRIMITIVE eInputPrimitive; - uint32_t ui32MaxOutputVertexCount; - TESSELLATOR_DOMAIN eTessDomain; - TESSELLATOR_PARTITIONING eTessPartitioning; - TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; - uint32_t aui32WorkGroupSize[3]; - //Fork phase index followed by the instance count. - uint32_t aui32HullPhaseInstanceInfo[2]; - float fMaxTessFactor; - uint32_t ui32IndexRange; - uint32_t ui32GSInstanceCount; - - struct Interface_TAG - { - uint32_t ui32InterfaceID; - uint32_t ui32NumFuncTables; - uint32_t ui32ArraySize; - } interface; - } value; - - struct UAV_TAG - { - uint32_t ui32GloballyCoherentAccess; - uint32_t ui32BufferSize; - uint8_t bCounter; - RESOURCE_RETURN_TYPE Type; - } sUAV; - - struct TGSM_TAG - { - uint32_t ui32Stride; - uint32_t ui32Count; - } sTGSM; - - struct IndexableTemp_TAG - { - uint32_t ui32RegIndex; - uint32_t ui32RegCount; - uint32_t ui32RegComponentSize; - } sIdxTemp; - - uint32_t ui32TableLength; - - uint32_t ui32IsShadowTex; - - uint32_t ui32SamplerUsed[MAX_TEXTURE_SAMPLERS_PAIRS]; - uint32_t ui32SamplerUsedCount; - - uint32_t bIsComparisonSampler; -} Declaration; - -enum -{ - MAX_TEMP_VEC4 = 512 -}; - -enum -{ - MAX_GROUPSHARED = 8 -}; - -enum -{ - MAX_COLOR_MRT = 8 -}; - -enum -{ - MAX_DX9_IMMCONST = 256 -}; - -static const uint32_t MAIN_PHASE = 0; -static const uint32_t HS_GLOBAL_DECL = 1; -static const uint32_t HS_CTRL_POINT_PHASE = 2; -static const uint32_t HS_FORK_PHASE = 3; -static const uint32_t HS_JOIN_PHASE = 4; -enum -{ - NUM_PHASES = 5 -}; - -typedef struct ShaderPhase_TAG -{ - //How many instances of this phase type are there? - uint32_t ui32InstanceCount; - - uint32_t* pui32DeclCount; - Declaration** ppsDecl; - - uint32_t* pui32InstCount; - Instruction** ppsInst; -} ShaderPhase; - -typedef struct Shader_TAG -{ - uint32_t ui32MajorVersion; - uint32_t ui32MinorVersion; - SHADER_TYPE eShaderType; - - ShaderLang eTargetLanguage; - const struct GlExtensions* extensions; - - int fp64; - - //DWORDs in program code, including version and length tokens. - uint32_t ui32ShaderLength; - - //Instruction* functions;//non-main subroutines - - uint32_t aui32FuncTableToFuncPointer[MAX_FUNCTION_TABLES];//FIXME dynamic alloc - uint32_t aui32FuncBodyToFuncTable[MAX_FUNCTION_BODIES]; - - struct - { - uint32_t aui32FuncBodies[MAX_FUNCTION_BODIES]; - }funcTable[MAX_FUNCTION_TABLES]; - - struct - { - uint32_t aui32FuncTables[MAX_FUNCTION_TABLES]; - uint32_t ui32NumBodiesPerTable; - }funcPointer[MAX_FUNCTION_POINTERS]; - - uint32_t ui32NextClassFuncName[MAX_CLASS_TYPES]; - - const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream. - - ShaderPhase asPhase[NUM_PHASES]; - - ShaderInfo sInfo; - - int abScalarInput[MAX_SHADER_VEC4_INPUT]; - - int aIndexedOutput[MAX_SHADER_VEC4_OUTPUT]; - - int aIndexedInput[MAX_SHADER_VEC4_INPUT]; - int aIndexedInputParents[MAX_SHADER_VEC4_INPUT]; - - RESOURCE_DIMENSION aeResourceDims[MAX_TEXTURES]; - - int aiInputDeclaredSize[MAX_SHADER_VEC4_INPUT]; - - int aiOutputDeclared[MAX_SHADER_VEC4_OUTPUT]; - - //Does not track built-in inputs. - int abInputReferencedByInstruction[MAX_SHADER_VEC4_INPUT]; - - int aiOpcodeUsed[NUM_OPCODES]; - - uint32_t ui32CurrentVertexOutputStream; - - uint32_t ui32NumDx9ImmConst; - uint32_t aui32Dx9ImmConstArrayRemap[MAX_DX9_IMMCONST]; - - ShaderVarType sGroupSharedVarType[MAX_GROUPSHARED]; - - TextureSamplerInfo textureSamplerInfo; -} ShaderData; - -// CONFETTI NOTE: DAVID SROUR -// The following is super sketchy, but at the moment, -// there is no way to figure out the type of a resource -// since HLSL has only register sets for the following: -// bool, int4, float4, sampler. -enum -{ - GMEM_FLOAT4_START_SLOT = 120 -}; -enum -{ - GMEM_FLOAT3_START_SLOT = 112 -}; -enum -{ - GMEM_FLOAT2_START_SLOT = 104 -}; -enum -{ - GMEM_FLOAT_START_SLOT = 96 -}; - -// CONFETTI NOTE -// Set the starting binding point for UAV_Buffer. -// All the binding points after the starting point is reserved for UAV -// only. This apply for both [[texture]] and [[buffer]] -enum -{ - UAV_BUFFER_START_SLOT = 25 -}; - -typedef struct HLSLCrossCompilerContext_TAG -{ - bstring mainShader; - bstring stagedInputDeclarations; // Metal only - bstring parameterDeclarations; // Metal only - bstring declaredOutputs; // Metal only - bstring earlyMain;//Code to be inserted at the start of main() - bstring postShaderCode[NUM_PHASES];//End of main or before emit() - - bstring* currentShaderString;//either mainShader or earlyMain - - int needsFragmentTestHint; // METAL only - - int havePostShaderCode[NUM_PHASES]; - uint32_t currentPhase; - - // GMEM INPUT AND OUTPUT TYPES MUST MATCH! - // THIS TABLE KEEPS TRACK OF WHAT THE OUTPUT TYPE SHOULD - // BE IF GMEM INPUT WAS DECLARED TO THE SAME SLOT # - uint32_t gmemOutputNumElements[MAX_COLOR_MRT]; // Metal only - - int indent; - unsigned int flags; - ShaderData* psShader; -} HLSLCrossCompilerContext; - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c deleted file mode 100644 index d380100d83..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c +++ /dev/null @@ -1,15 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#include "structsMetal.h" - -int IsAtomicVar(const ShaderVarType* const var, AtomicVarList* const list) -{ - for (uint32_t i = 0; i < list->Filled; i++) - { - if (var == list->AtomicVars[i]) - { - return 1; - } - } - return 0; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h deleted file mode 100644 index cd63921310..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h +++ /dev/null @@ -1,19 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates - -#ifndef STRUCTSS_METAL_H -#define STRUCTSS_METAL_H - -#include "hlslcc.h" -#include <stdint.h> - -typedef struct AtomicVarList_s -{ - const ShaderVarType** AtomicVars; - uint32_t Filled; - uint32_t Size; -} AtomicVarList; - -int IsAtomicVar(const ShaderVarType* const var, AtomicVarList* const list); - - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h deleted file mode 100644 index d18ee2c243..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h +++ /dev/null @@ -1,19 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_DECLARATION_H -#define TO_GLSL_DECLARATION_H - -#include "internal_includes/structs.h" - -void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); - -const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); -const char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand, int* stream); - -//Hull shaders have multiple phases. -//Each phase has its own temps. -//Convert to global temps for GLSL. -void ConsolidateHullTempVars(ShaderData* psShader); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h deleted file mode 100644 index 34f67cfe46..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h +++ /dev/null @@ -1,18 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_INSTRUCTION_H -#define TO_GLSL_INSTRUCTION_H - -#include "internal_includes/structs.h" - -void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst); - -//For each MOV temp, immediate; check to see if the next instruction -//using that temp has an integer opcode. If so then the immediate value -//is flaged as having an integer encoding. -void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext); - -void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h deleted file mode 100644 index 1d7430504c..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h +++ /dev/null @@ -1,72 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_GLSL_OPERAND_H -#define TO_GLSL_OPERAND_H - -#include "internal_includes/structs.h" - -#define TO_FLAG_NONE 0x0 -#define TO_FLAG_INTEGER 0x1 -#define TO_FLAG_NAME_ONLY 0x2 -#define TO_FLAG_DECLARATION_NAME 0x4 -#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. -#define TO_FLAG_UNSIGNED_INTEGER 0x10 -#define TO_FLAG_DOUBLE 0x20 -#define TO_FLAG_FLOAT16 0x40 -// --- TO_AUTO_BITCAST_TO_FLOAT --- -//If the operand is an integer temp variable then this flag -//indicates that the temp has a valid floating point encoding -//and that the current expression expects the operand to be floating point -//and therefore intBitsToFloat must be applied to that variable. -#define TO_AUTO_BITCAST_TO_FLOAT 0x80 -#define TO_AUTO_BITCAST_TO_INT 0x100 -#define TO_AUTO_BITCAST_TO_UINT 0x200 -#define TO_AUTO_BITCAST_TO_FLOAT16 0x400 -// AUTO_EXPAND flags automatically expand the operand to at least (i/u)vecX -// to match HLSL functionality. -#define TO_AUTO_EXPAND_TO_VEC2 0x800 -#define TO_AUTO_EXPAND_TO_VEC3 0x1000 -#define TO_AUTO_EXPAND_TO_VEC4 0x2000 - - -void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); -// Translate operand but add additional component mask -void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask); - -int GetMaxComponentFromComponentMask(const Operand* psOperand); -void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); -void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); -void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask); - -uint32_t GetNumSwizzleElements(const Operand* psOperand); -uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32CompMask); -void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); -int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -uint32_t IsSwizzleReplicated(const Operand* psOperand); - -void ResourceName(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare); - -bstring TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); -void ConcatTextureSamplerName(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); - -//Non-zero means the components overlap -int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB); - -// Returns the write mask for the operand used for destination -uint32_t GetOperandWriteMask(const Operand *psOperand); - -SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates); - -const char * GetConstructorForType(const SHADER_VARIABLE_TYPE eType, - const int components); - -const char * GetConstructorForTypeFlag(const uint32_t ui32Flag, - const int components); - -uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType); -SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h deleted file mode 100644 index fb10d5b691..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h +++ /dev/null @@ -1,15 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_DECLARATION_H -#define TO_METAL_DECLARATION_H - -#include "internal_includes/structs.h" -#include "internal_includes/structsMetal.h" - -void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, AtomicVarList* psAtomicList); - -char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); -char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h deleted file mode 100644 index e5b267cd58..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h +++ /dev/null @@ -1,20 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_INSTRUCTION_H -#define TO_METAL_INSTRUCTION_H - -#include "internal_includes/structs.h" -#include "structsMetal.h" - -void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst); -void DetectAtomicInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst, AtomicVarList* psAtomicList); - -//For each MOV temp, immediate; check to see if the next instruction -//using that temp has an integer opcode. If so then the immediate value -//is flaged as having an integer encoding. -void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext); - -void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h deleted file mode 100644 index 6cebf5bab6..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h +++ /dev/null @@ -1,78 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TO_METAL_OPERAND_H -#define TO_METAL_OPERAND_H - -#include "internal_includes/structs.h" - -#define TO_FLAG_NONE 0x0 -#define TO_FLAG_INTEGER 0x1 -#define TO_FLAG_NAME_ONLY 0x2 -#define TO_FLAG_DECLARATION_NAME 0x4 -#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. -#define TO_FLAG_UNSIGNED_INTEGER 0x10 -#define TO_FLAG_DOUBLE 0x20 -#define TO_FLAG_FLOAT16 0x40 -// --- TO_AUTO_BITCAST_TO_FLOAT --- -//If the operand is an integer temp variable then this flag -//indicates that the temp has a valid floating point encoding -//and that the current expression expects the operand to be floating point -//and therefore intBitsToFloat must be applied to that variable. -#define TO_AUTO_BITCAST_TO_FLOAT 0x80 -#define TO_AUTO_BITCAST_TO_INT 0x100 -#define TO_AUTO_BITCAST_TO_UINT 0x200 -#define TO_AUTO_BITCAST_TO_FLOAT16 0x400 -// AUTO_EXPAND flags automatically expand the operand to at least (i/u)vecX -// to match HLSL functionality. -#define TO_AUTO_EXPAND_TO_VEC2 0x800 -#define TO_AUTO_EXPAND_TO_VEC3 0x1000 -#define TO_AUTO_EXPAND_TO_VEC4 0x2000 - -void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); -// Translate operand but add additional component mask -void TranslateOperandWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask); - -int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand); -void TranslateOperandIndexMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); -void TranslateOperandIndexMADMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); -void TranslateOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -void TranslateOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask); - -void TranslateGmemOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements); - -uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand); -uint32_t GetNumSwizzleElementsWithMaskMETAL(const Operand *psOperand, uint32_t ui32CompMask); -void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count); -int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -uint32_t IsSwizzleReplicatedMETAL(const Operand* psOperand); - -void ResourceNameMETAL(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare); - -bstring TextureSamplerNameMETAL(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); -void ConcatTextureSamplerNameMETAL(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); - -//Non-zero means the components overlap -int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB); - -// Returns the write mask for the operand used for destination -uint32_t GetOperandWriteMaskMETAL(const Operand *psOperand); - -SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); -SHADER_VARIABLE_TYPE GetOperandDataTypeExMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates); - -const char * GetConstructorForTypeMETAL(const SHADER_VARIABLE_TYPE eType, - const int components); - -const char * GetConstructorForTypeFlagMETAL(const uint32_t ui32Flag, - const int components); - -uint32_t SVTTypeToFlagMETAL(const SHADER_VARIABLE_TYPE eType); -SHADER_VARIABLE_TYPE TypeFlagsToSVTTypeMETAL(const uint32_t typeflags); - - -uint32_t GetGmemInputResourceSlotMETAL(uint32_t const slotIn); - -uint32_t GetGmemInputResourceNumElementsMETAL(uint32_t const slotIn); - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h deleted file mode 100644 index ddf17058cd..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h +++ /dev/null @@ -1,819 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#ifndef TOKENS_H -#define TOKENS_H - -#include "hlslcc.h" - -typedef enum -{ - INVALID_SHADER = -1, - PIXEL_SHADER, - VERTEX_SHADER, - GEOMETRY_SHADER, - HULL_SHADER, - DOMAIN_SHADER, - COMPUTE_SHADER, -} SHADER_TYPE; - -static SHADER_TYPE DecodeShaderType(uint32_t ui32Token) -{ - return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16); -} - -static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token) -{ - return (ui32Token & 0x000000f0) >> 4; -} - -static uint32_t DecodeProgramMinorVersion(uint32_t ui32Token) -{ - return (ui32Token & 0x0000000f); -} - -static uint32_t DecodeInstructionLength(uint32_t ui32Token) -{ - return (ui32Token & 0x7f000000) >> 24; -} - -static uint32_t DecodeIsOpcodeExtended(uint32_t ui32Token) -{ - return (ui32Token & 0x80000000) >> 31; -} - -typedef enum EXTENDED_OPCODE_TYPE -{ - EXTENDED_OPCODE_EMPTY = 0, - EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, - EXTENDED_OPCODE_RESOURCE_DIM = 2, - EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, -} EXTENDED_OPCODE_TYPE; - -static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token) -{ - return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f); -} - -typedef enum RESOURCE_RETURN_TYPE -{ - RETURN_TYPE_UNORM = 1, - RETURN_TYPE_SNORM = 2, - RETURN_TYPE_SINT = 3, - RETURN_TYPE_UINT = 4, - RETURN_TYPE_FLOAT = 5, - RETURN_TYPE_MIXED = 6, - RETURN_TYPE_DOUBLE = 7, - RETURN_TYPE_CONTINUED = 8, - RETURN_TYPE_UNUSED = 9, -} RESOURCE_RETURN_TYPE; - -static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) -{ - return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF); -} - -static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) -{ - return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF); -} - -typedef enum -{ - //For DX9 - OPCODE_POW = -6, - OPCODE_DP2ADD = -5, - OPCODE_LRP = -4, - OPCODE_ENDREP = -3, - OPCODE_REP = -2, - OPCODE_SPECIAL_DCL_IMMCONST = -1, - - OPCODE_ADD, - OPCODE_AND, - OPCODE_BREAK, - OPCODE_BREAKC, - OPCODE_CALL, - OPCODE_CALLC, - OPCODE_CASE, - OPCODE_CONTINUE, - OPCODE_CONTINUEC, - OPCODE_CUT, - OPCODE_DEFAULT, - OPCODE_DERIV_RTX, - OPCODE_DERIV_RTY, - OPCODE_DISCARD, - OPCODE_DIV, - OPCODE_DP2, - OPCODE_DP3, - OPCODE_DP4, - OPCODE_ELSE, - OPCODE_EMIT, - OPCODE_EMITTHENCUT, - OPCODE_ENDIF, - OPCODE_ENDLOOP, - OPCODE_ENDSWITCH, - OPCODE_EQ, - OPCODE_EXP, - OPCODE_FRC, - OPCODE_FTOI, - OPCODE_FTOU, - OPCODE_GE, - OPCODE_IADD, - OPCODE_IF, - OPCODE_IEQ, - OPCODE_IGE, - OPCODE_ILT, - OPCODE_IMAD, - OPCODE_IMAX, - OPCODE_IMIN, - OPCODE_IMUL, - OPCODE_INE, - OPCODE_INEG, - OPCODE_ISHL, - OPCODE_ISHR, - OPCODE_ITOF, - OPCODE_LABEL, - OPCODE_LD, - OPCODE_LD_MS, - OPCODE_LOG, - OPCODE_LOOP, - OPCODE_LT, - OPCODE_MAD, - OPCODE_MIN, - OPCODE_MAX, - OPCODE_CUSTOMDATA, - OPCODE_MOV, - OPCODE_MOVC, - OPCODE_MUL, - OPCODE_NE, - OPCODE_NOP, - OPCODE_NOT, - OPCODE_OR, - OPCODE_RESINFO, - OPCODE_RET, - OPCODE_RETC, - OPCODE_ROUND_NE, - OPCODE_ROUND_NI, - OPCODE_ROUND_PI, - OPCODE_ROUND_Z, - OPCODE_RSQ, - OPCODE_SAMPLE, - OPCODE_SAMPLE_C, - OPCODE_SAMPLE_C_LZ, - OPCODE_SAMPLE_L, - OPCODE_SAMPLE_D, - OPCODE_SAMPLE_B, - OPCODE_SQRT, - OPCODE_SWITCH, - OPCODE_SINCOS, - OPCODE_UDIV, - OPCODE_ULT, - OPCODE_UGE, - OPCODE_UMUL, - OPCODE_UMAD, - OPCODE_UMAX, - OPCODE_UMIN, - OPCODE_USHR, - OPCODE_UTOF, - OPCODE_XOR, - OPCODE_DCL_RESOURCE, // DCL* opcodes have - OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats. - OPCODE_DCL_SAMPLER, - OPCODE_DCL_INDEX_RANGE, - OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, - OPCODE_DCL_GS_INPUT_PRIMITIVE, - OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, - OPCODE_DCL_INPUT, - OPCODE_DCL_INPUT_SGV, - OPCODE_DCL_INPUT_SIV, - OPCODE_DCL_INPUT_PS, - OPCODE_DCL_INPUT_PS_SGV, - OPCODE_DCL_INPUT_PS_SIV, - OPCODE_DCL_OUTPUT, - OPCODE_DCL_OUTPUT_SGV, - OPCODE_DCL_OUTPUT_SIV, - OPCODE_DCL_TEMPS, - OPCODE_DCL_INDEXABLE_TEMP, - OPCODE_DCL_GLOBAL_FLAGS, - -// ----------------------------------------------- - - OPCODE_RESERVED_10, - -// ---------- DX 10.1 op codes--------------------- - - OPCODE_LOD, - OPCODE_GATHER4, - OPCODE_SAMPLE_POS, - OPCODE_SAMPLE_INFO, - -// ----------------------------------------------- - - // This should be 10.1's version of NUM_OPCODES - OPCODE_RESERVED_10_1, - -// ---------- DX 11 op codes--------------------- - OPCODE_HS_DECLS, // token marks beginning of HS sub-shader - OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader - OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader - OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader - - OPCODE_EMIT_STREAM, - OPCODE_CUT_STREAM, - OPCODE_EMITTHENCUT_STREAM, - OPCODE_INTERFACE_CALL, - - OPCODE_BUFINFO, - OPCODE_DERIV_RTX_COARSE, - OPCODE_DERIV_RTX_FINE, - OPCODE_DERIV_RTY_COARSE, - OPCODE_DERIV_RTY_FINE, - OPCODE_GATHER4_C, - OPCODE_GATHER4_PO, - OPCODE_GATHER4_PO_C, - OPCODE_RCP, - OPCODE_F32TOF16, - OPCODE_F16TOF32, - OPCODE_UADDC, - OPCODE_USUBB, - OPCODE_COUNTBITS, - OPCODE_FIRSTBIT_HI, - OPCODE_FIRSTBIT_LO, - OPCODE_FIRSTBIT_SHI, - OPCODE_UBFE, - OPCODE_IBFE, - OPCODE_BFI, - OPCODE_BFREV, - OPCODE_SWAPC, - - OPCODE_DCL_STREAM, - OPCODE_DCL_FUNCTION_BODY, - OPCODE_DCL_FUNCTION_TABLE, - OPCODE_DCL_INTERFACE, - - OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, - OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, - OPCODE_DCL_TESS_DOMAIN, - OPCODE_DCL_TESS_PARTITIONING, - OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, - OPCODE_DCL_HS_MAX_TESSFACTOR, - OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, - OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, - - OPCODE_DCL_THREAD_GROUP, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, - OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, - OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, - OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, - OPCODE_DCL_RESOURCE_RAW, - OPCODE_DCL_RESOURCE_STRUCTURED, - OPCODE_LD_UAV_TYPED, - OPCODE_STORE_UAV_TYPED, - OPCODE_LD_RAW, - OPCODE_STORE_RAW, - OPCODE_LD_STRUCTURED, - OPCODE_STORE_STRUCTURED, - OPCODE_ATOMIC_AND, - OPCODE_ATOMIC_OR, - OPCODE_ATOMIC_XOR, - OPCODE_ATOMIC_CMP_STORE, - OPCODE_ATOMIC_IADD, - OPCODE_ATOMIC_IMAX, - OPCODE_ATOMIC_IMIN, - OPCODE_ATOMIC_UMAX, - OPCODE_ATOMIC_UMIN, - OPCODE_IMM_ATOMIC_ALLOC, - OPCODE_IMM_ATOMIC_CONSUME, - OPCODE_IMM_ATOMIC_IADD, - OPCODE_IMM_ATOMIC_AND, - OPCODE_IMM_ATOMIC_OR, - OPCODE_IMM_ATOMIC_XOR, - OPCODE_IMM_ATOMIC_EXCH, - OPCODE_IMM_ATOMIC_CMP_EXCH, - OPCODE_IMM_ATOMIC_IMAX, - OPCODE_IMM_ATOMIC_IMIN, - OPCODE_IMM_ATOMIC_UMAX, - OPCODE_IMM_ATOMIC_UMIN, - OPCODE_SYNC, - - OPCODE_DADD, - OPCODE_DMAX, - OPCODE_DMIN, - OPCODE_DMUL, - OPCODE_DEQ, - OPCODE_DGE, - OPCODE_DLT, - OPCODE_DNE, - OPCODE_DMOV, - OPCODE_DMOVC, - OPCODE_DTOF, - OPCODE_FTOD, - - OPCODE_EVAL_SNAPPED, - OPCODE_EVAL_SAMPLE_INDEX, - OPCODE_EVAL_CENTROID, - - OPCODE_DCL_GS_INSTANCE_COUNT, - - OPCODE_ABORT, - OPCODE_DEBUG_BREAK, - -// ----------------------------------------------- - - // This marks the end of D3D11.0 opcodes - OPCODE_RESERVED_11, - - OPCODE_DDIV, - OPCODE_DFMA, - OPCODE_DRCP, - - OPCODE_MSAD, - - OPCODE_DTOI, - OPCODE_DTOU, - OPCODE_ITOD, - OPCODE_UTOD, - -// ----------------------------------------------- - - // This marks the end of D3D11.1 opcodes - OPCODE_RESERVED_11_1, - - NUM_OPCODES, - OPCODE_INVAILD = NUM_OPCODES, -} OPCODE_TYPE; - -static OPCODE_TYPE DecodeOpcodeType(uint32_t ui32Token) -{ - return (OPCODE_TYPE)(ui32Token & 0x00007ff); -} - -typedef enum -{ - INDEX_0D, - INDEX_1D, - INDEX_2D, - INDEX_3D, -} OPERAND_INDEX_DIMENSION; - -static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token) -{ - return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20); -} - -typedef enum OPERAND_TYPE -{ - OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10, - OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9, - OPERAND_TYPE_SPECIAL_TEXCOORD = -8, - OPERAND_TYPE_SPECIAL_POSITION = -7, - OPERAND_TYPE_SPECIAL_FOG = -6, - OPERAND_TYPE_SPECIAL_POINTSIZE = -5, - OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR = -4, - OPERAND_TYPE_SPECIAL_OUTBASECOLOUR = -3, - OPERAND_TYPE_SPECIAL_ADDRESS = -2, - OPERAND_TYPE_SPECIAL_IMMCONST = -1, - OPERAND_TYPE_TEMP = 0, // Temporary Register File - OPERAND_TYPE_INPUT = 1, // General Input Register File - OPERAND_TYPE_OUTPUT = 2, // General Output Register File - OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable) - OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s) - // If for example, operand token bits - // [01:00]==OPERAND_4_COMPONENT, - // this means that the operand type: - // OPERAND_TYPE_IMMEDIATE32 - // results in 4 additional 32bit - // DWORDS present for the operand. - OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO - OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state - OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture) - OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer - OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer - OPERAND_TYPE_LABEL = 10, // Label - OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID - OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth - OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations - // Below Are operands new in DX 10.1 - OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources - OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar) - // Below Are operands new in DX 11 - OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource - OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition - OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class - OPERAND_TYPE_INTERFACE = 19, // Reference to an interface - OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function - OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function - OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is - OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID - OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID - OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them) - OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them) - OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them) - OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point - OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer - OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u# - OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g# - OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID - OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID - OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group - OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input - OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value. - OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID - OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth - OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth - OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter -} OPERAND_TYPE; - -static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token) -{ - return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12); -} - -static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token) -{ - return (SPECIAL_NAME)(ui32Token & 0x0000ffff); -} - -typedef enum OPERAND_INDEX_REPRESENTATION -{ - OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD - OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs - // (HI32:LO32) - OPERAND_INDEX_RELATIVE = 2, // Extra operand - OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by - // extra operand - OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS - // (HI32:LO32) followed - // by extra operand -} OPERAND_INDEX_REPRESENTATION; - -static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token) -{ - return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3))); -} - -typedef enum OPERAND_NUM_COMPONENTS -{ - OPERAND_0_COMPONENT = 0, - OPERAND_1_COMPONENT = 1, - OPERAND_4_COMPONENT = 2, - OPERAND_N_COMPONENT = 3 // unused for now -} OPERAND_NUM_COMPONENTS; - -static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token) -{ - return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003); -} - -typedef enum OPERAND_4_COMPONENT_SELECTION_MODE -{ - OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components - OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components - OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components -} OPERAND_4_COMPONENT_SELECTION_MODE; - -static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token) -{ - return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2); -} - -#define OPERAND_4_COMPONENT_MASK_X 0x00000001 -#define OPERAND_4_COMPONENT_MASK_Y 0x00000002 -#define OPERAND_4_COMPONENT_MASK_Z 0x00000004 -#define OPERAND_4_COMPONENT_MASK_W 0x00000008 -#define OPERAND_4_COMPONENT_MASK_R OPERAND_4_COMPONENT_MASK_X -#define OPERAND_4_COMPONENT_MASK_G OPERAND_4_COMPONENT_MASK_Y -#define OPERAND_4_COMPONENT_MASK_B OPERAND_4_COMPONENT_MASK_Z -#define OPERAND_4_COMPONENT_MASK_A OPERAND_4_COMPONENT_MASK_W -#define OPERAND_4_COMPONENT_MASK_ALL 0x0000000f - -static uint32_t DecodeOperand4CompMask(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x000000f0) >> 4); -} - -static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x00000ff0) >> 4); -} - -static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x00000030) >> 4); -} - -#define OPERAND_4_COMPONENT_X 0 -#define OPERAND_4_COMPONENT_Y 1 -#define OPERAND_4_COMPONENT_Z 2 -#define OPERAND_4_COMPONENT_W 3 - -static uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/); - -static uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X<<2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6))); -static uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6))); -static uint32_t ZZZZ_SWIZZLE = (((OPERAND_4_COMPONENT_Z) | (OPERAND_4_COMPONENT_Z<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_Z << 6))); -static uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMPONENT_W<<2) | (OPERAND_4_COMPONENT_W << 4) | (OPERAND_4_COMPONENT_W << 6))); - -static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp) -{ - return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3); -} - -typedef enum RESOURCE_DIMENSION -{ - RESOURCE_DIMENSION_UNKNOWN = 0, - RESOURCE_DIMENSION_BUFFER = 1, - RESOURCE_DIMENSION_TEXTURE1D = 2, - RESOURCE_DIMENSION_TEXTURE2D = 3, - RESOURCE_DIMENSION_TEXTURE2DMS = 4, - RESOURCE_DIMENSION_TEXTURE3D = 5, - RESOURCE_DIMENSION_TEXTURECUBE = 6, - RESOURCE_DIMENSION_TEXTURE1DARRAY = 7, - RESOURCE_DIMENSION_TEXTURE2DARRAY = 8, - RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 9, - RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, - RESOURCE_DIMENSION_RAW_BUFFER = 11, - RESOURCE_DIMENSION_STRUCTURED_BUFFER = 12, -} RESOURCE_DIMENSION; - -static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token) -{ - return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11); -} - -static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token) -{ - return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6); -} - -static const uint32_t SHADER_INPUT_FLAG_COMPARISON_SAMPLER = (1 << 1); - -static uint32_t DecodeShaderInputFlags(uint32_t ui32Token) -{ - return (uint32_t)(ui32Token & 0x00000002); -} - -typedef enum CONSTANT_BUFFER_ACCESS_PATTERN -{ - CONSTANT_BUFFER_ACCESS_PATTERN_IMMEDIATEINDEXED = 0, - CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED = 1 -} CONSTANT_BUFFER_ACCESS_PATTERN; - -static CONSTANT_BUFFER_ACCESS_PATTERN DecodeConstantBufferAccessPattern(uint32_t ui32Token) -{ - return (CONSTANT_BUFFER_ACCESS_PATTERN)((ui32Token & 0x00000800) >> 11); -} - -typedef enum INSTRUCTION_TEST_BOOLEAN -{ - INSTRUCTION_TEST_ZERO = 0, - INSTRUCTION_TEST_NONZERO = 1 -} INSTRUCTION_TEST_BOOLEAN; - -static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token) -{ - return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18); -} - -static uint32_t DecodeIsOperandExtended(uint32_t ui32Token) -{ - return (ui32Token & 0x80000000) >> 31; -} - -typedef enum EXTENDED_OPERAND_TYPE -{ - EXTENDED_OPERAND_EMPTY = 0, - EXTENDED_OPERAND_MODIFIER = 1, -} EXTENDED_OPERAND_TYPE; - -static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token) -{ - return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f); -} - -typedef enum OPERAND_MODIFIER -{ - OPERAND_MODIFIER_NONE = 0, - OPERAND_MODIFIER_NEG = 1, - OPERAND_MODIFIER_ABS = 2, - OPERAND_MODIFIER_ABSNEG = 3, -} OPERAND_MODIFIER; - -static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token) -{ - return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6); -} - -static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11); -static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12); -static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13); -static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14); -static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15); -static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16); -static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17); -static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18); - -static uint32_t DecodeGlobalFlags(uint32_t ui32Token) -{ - return (uint32_t)(ui32Token & 0x00fff800); -} - -static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token) -{ - return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11); -} - - -typedef enum PRIMITIVE_TOPOLOGY -{ - PRIMITIVE_TOPOLOGY_UNDEFINED = 0, - PRIMITIVE_TOPOLOGY_POINTLIST = 1, - PRIMITIVE_TOPOLOGY_LINELIST = 2, - PRIMITIVE_TOPOLOGY_LINESTRIP = 3, - PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4, - PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5, - // 6 is reserved for legacy triangle fans - // Adjacency values should be equal to (0x8 & non-adjacency): - PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10, - PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11, - PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12, - PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13, -} PRIMITIVE_TOPOLOGY; - -static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token) -{ - return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11); -} - -typedef enum PRIMITIVE -{ - PRIMITIVE_UNDEFINED = 0, - PRIMITIVE_POINT = 1, - PRIMITIVE_LINE = 2, - PRIMITIVE_TRIANGLE = 3, - // Adjacency values should be equal to (0x4 & non-adjacency): - PRIMITIVE_LINE_ADJ = 6, - PRIMITIVE_TRIANGLE_ADJ = 7, - PRIMITIVE_1_CONTROL_POINT_PATCH = 8, - PRIMITIVE_2_CONTROL_POINT_PATCH = 9, - PRIMITIVE_3_CONTROL_POINT_PATCH = 10, - PRIMITIVE_4_CONTROL_POINT_PATCH = 11, - PRIMITIVE_5_CONTROL_POINT_PATCH = 12, - PRIMITIVE_6_CONTROL_POINT_PATCH = 13, - PRIMITIVE_7_CONTROL_POINT_PATCH = 14, - PRIMITIVE_8_CONTROL_POINT_PATCH = 15, - PRIMITIVE_9_CONTROL_POINT_PATCH = 16, - PRIMITIVE_10_CONTROL_POINT_PATCH = 17, - PRIMITIVE_11_CONTROL_POINT_PATCH = 18, - PRIMITIVE_12_CONTROL_POINT_PATCH = 19, - PRIMITIVE_13_CONTROL_POINT_PATCH = 20, - PRIMITIVE_14_CONTROL_POINT_PATCH = 21, - PRIMITIVE_15_CONTROL_POINT_PATCH = 22, - PRIMITIVE_16_CONTROL_POINT_PATCH = 23, - PRIMITIVE_17_CONTROL_POINT_PATCH = 24, - PRIMITIVE_18_CONTROL_POINT_PATCH = 25, - PRIMITIVE_19_CONTROL_POINT_PATCH = 26, - PRIMITIVE_20_CONTROL_POINT_PATCH = 27, - PRIMITIVE_21_CONTROL_POINT_PATCH = 28, - PRIMITIVE_22_CONTROL_POINT_PATCH = 29, - PRIMITIVE_23_CONTROL_POINT_PATCH = 30, - PRIMITIVE_24_CONTROL_POINT_PATCH = 31, - PRIMITIVE_25_CONTROL_POINT_PATCH = 32, - PRIMITIVE_26_CONTROL_POINT_PATCH = 33, - PRIMITIVE_27_CONTROL_POINT_PATCH = 34, - PRIMITIVE_28_CONTROL_POINT_PATCH = 35, - PRIMITIVE_29_CONTROL_POINT_PATCH = 36, - PRIMITIVE_30_CONTROL_POINT_PATCH = 37, - PRIMITIVE_31_CONTROL_POINT_PATCH = 38, - PRIMITIVE_32_CONTROL_POINT_PATCH = 39, -} PRIMITIVE; - -static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token) -{ - return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11); -} - -static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token) -{ - return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11); -} - -typedef enum TESSELLATOR_DOMAIN -{ - TESSELLATOR_DOMAIN_UNDEFINED = 0, - TESSELLATOR_DOMAIN_ISOLINE = 1, - TESSELLATOR_DOMAIN_TRI = 2, - TESSELLATOR_DOMAIN_QUAD = 3 -} TESSELLATOR_DOMAIN; - -static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token) -{ - return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11); -} - -static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token) -{ - return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11); -} - -static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800; -static const uint32_t SYNC_THREAD_GROUP_SHARED_MEMORY = 0x00001000; -static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP = 0x00002000; -static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000; - -static uint32_t DecodeSyncFlags(uint32_t ui32Token) -{ - return ui32Token & 0x00007800; -} - -// The number of types that implement this interface -static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0x0000ffff) >> 0); -} - -// The number of interfaces that are defined in this array. -static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token) -{ - return (uint32_t)((ui32Token & 0xffff0000) >> 16); -} - -typedef enum CUSTOMDATA_CLASS -{ - CUSTOMDATA_COMMENT = 0, - CUSTOMDATA_DEBUGINFO, - CUSTOMDATA_OPAQUE, - CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, - CUSTOMDATA_SHADER_MESSAGE, -} CUSTOMDATA_CLASS; - -static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token) -{ - return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11); -} - -static uint32_t DecodeInstructionSaturate(uint32_t ui32Token) -{ - return (ui32Token & 0x00002000) ? 1 : 0; -} - -typedef enum OPERAND_MIN_PRECISION -{ - OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision - // for the shader model - OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float - OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float - OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer - OPERAND_MIN_PRECISION_UINT_16 = 5, // Min 16 bit/comp. unsigned integer -} OPERAND_MIN_PRECISION; - -static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token) -{ - return (ui32Token & 0x0001C000) >> 14; -} - -static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token) -{ - return ((ui32Token & 0x0001f800) >> 11); -} - -typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD -{ - IMMEDIATE_ADDRESS_OFFSET_U = 0, - IMMEDIATE_ADDRESS_OFFSET_V = 1, - IMMEDIATE_ADDRESS_OFFSET_W = 2, -} IMMEDIATE_ADDRESS_OFFSET_COORD; - - -#define IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&3)) -#define IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<<IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord)) - -static uint32_t DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_COORD eCoord, uint32_t ui32Token) -{ - return ((((ui32Token)&IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord))>>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord)))); -} - -// UAV access scope flags -static const uint32_t GLOBALLY_COHERENT_ACCESS = 0x00010000; -static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token) -{ - return ui32Token & 0x00010000; -} - - -typedef enum RESINFO_RETURN_TYPE -{ - RESINFO_INSTRUCTION_RETURN_FLOAT = 0, - RESINFO_INSTRUCTION_RETURN_RCPFLOAT = 1, - RESINFO_INSTRUCTION_RETURN_UINT = 2 -} RESINFO_RETURN_TYPE; - -static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token) -{ - return (RESINFO_RETURN_TYPE)((ui32Token & 0x00001800) >> 11); -} - -#include "tokensDX9.h" - -#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h deleted file mode 100644 index 1284419ca2..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h +++ /dev/null @@ -1,304 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "debug.h" - -static const uint32_t D3D9SHADER_TYPE_VERTEX = 0xFFFE0000; -static const uint32_t D3D9SHADER_TYPE_PIXEL = 0xFFFF0000; - -static SHADER_TYPE DecodeShaderTypeDX9(const uint32_t ui32Token) -{ - uint32_t ui32Type = ui32Token & 0xFFFF0000; - if(ui32Type == D3D9SHADER_TYPE_VERTEX) - return VERTEX_SHADER; - - if(ui32Type == D3D9SHADER_TYPE_PIXEL) - return PIXEL_SHADER; - - return INVALID_SHADER; -} - -static uint32_t DecodeProgramMajorVersionDX9(const uint32_t ui32Token) -{ - return ((ui32Token)>>8)&0xFF; -} - -static uint32_t DecodeProgramMinorVersionDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xFF; -} - -typedef enum -{ - OPCODE_DX9_NOP = 0, - OPCODE_DX9_MOV , - OPCODE_DX9_ADD , - OPCODE_DX9_SUB , - OPCODE_DX9_MAD , - OPCODE_DX9_MUL , - OPCODE_DX9_RCP , - OPCODE_DX9_RSQ , - OPCODE_DX9_DP3 , - OPCODE_DX9_DP4 , - OPCODE_DX9_MIN , - OPCODE_DX9_MAX , - OPCODE_DX9_SLT , - OPCODE_DX9_SGE , - OPCODE_DX9_EXP , - OPCODE_DX9_LOG , - OPCODE_DX9_LIT , - OPCODE_DX9_DST , - OPCODE_DX9_LRP , - OPCODE_DX9_FRC , - OPCODE_DX9_M4x4 , - OPCODE_DX9_M4x3 , - OPCODE_DX9_M3x4 , - OPCODE_DX9_M3x3 , - OPCODE_DX9_M3x2 , - OPCODE_DX9_CALL , - OPCODE_DX9_CALLNZ , - OPCODE_DX9_LOOP , - OPCODE_DX9_RET , - OPCODE_DX9_ENDLOOP , - OPCODE_DX9_LABEL , - OPCODE_DX9_DCL , - OPCODE_DX9_POW , - OPCODE_DX9_CRS , - OPCODE_DX9_SGN , - OPCODE_DX9_ABS , - OPCODE_DX9_NRM , - OPCODE_DX9_SINCOS , - OPCODE_DX9_REP , - OPCODE_DX9_ENDREP , - OPCODE_DX9_IF , - OPCODE_DX9_IFC , - OPCODE_DX9_ELSE , - OPCODE_DX9_ENDIF , - OPCODE_DX9_BREAK , - OPCODE_DX9_BREAKC , - OPCODE_DX9_MOVA , - OPCODE_DX9_DEFB , - OPCODE_DX9_DEFI , - - OPCODE_DX9_TEXCOORD = 64, - OPCODE_DX9_TEXKILL , - OPCODE_DX9_TEX , - OPCODE_DX9_TEXBEM , - OPCODE_DX9_TEXBEML , - OPCODE_DX9_TEXREG2AR , - OPCODE_DX9_TEXREG2GB , - OPCODE_DX9_TEXM3x2PAD , - OPCODE_DX9_TEXM3x2TEX , - OPCODE_DX9_TEXM3x3PAD , - OPCODE_DX9_TEXM3x3TEX , - OPCODE_DX9_RESERVED0 , - OPCODE_DX9_TEXM3x3SPEC , - OPCODE_DX9_TEXM3x3VSPEC , - OPCODE_DX9_EXPP , - OPCODE_DX9_LOGP , - OPCODE_DX9_CND , - OPCODE_DX9_DEF , - OPCODE_DX9_TEXREG2RGB , - OPCODE_DX9_TEXDP3TEX , - OPCODE_DX9_TEXM3x2DEPTH , - OPCODE_DX9_TEXDP3 , - OPCODE_DX9_TEXM3x3 , - OPCODE_DX9_TEXDEPTH , - OPCODE_DX9_CMP , - OPCODE_DX9_BEM , - OPCODE_DX9_DP2ADD , - OPCODE_DX9_DSX , - OPCODE_DX9_DSY , - OPCODE_DX9_TEXLDD , - OPCODE_DX9_SETP , - OPCODE_DX9_TEXLDL , - OPCODE_DX9_BREAKP , - - OPCODE_DX9_PHASE = 0xFFFD, - OPCODE_DX9_COMMENT = 0xFFFE, - OPCODE_DX9_END = 0xFFFF, - - OPCODE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum -} OPCODE_TYPE_DX9; - -static OPCODE_TYPE_DX9 DecodeOpcodeTypeDX9(const uint32_t ui32Token) -{ - return (OPCODE_TYPE_DX9)(ui32Token & 0x0000FFFF); -} - -static uint32_t DecodeInstructionLengthDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x0F000000)>>24; -} - -static uint32_t DecodeCommentLengthDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x7FFF0000)>>16; -} - -static uint32_t DecodeOperandRegisterNumberDX9(const uint32_t ui32Token) -{ - return ui32Token & 0x000007FF; -} - -typedef enum -{ - OPERAND_TYPE_DX9_TEMP = 0, // Temporary Register File - OPERAND_TYPE_DX9_INPUT = 1, // Input Register File - OPERAND_TYPE_DX9_CONST = 2, // Constant Register File - OPERAND_TYPE_DX9_ADDR = 3, // Address Register (VS) - OPERAND_TYPE_DX9_TEXTURE = 3, // Texture Register File (PS) - OPERAND_TYPE_DX9_RASTOUT = 4, // Rasterizer Register File - OPERAND_TYPE_DX9_ATTROUT = 5, // Attribute Output Register File - OPERAND_TYPE_DX9_TEXCRDOUT = 6, // Texture Coordinate Output Register File - OPERAND_TYPE_DX9_OUTPUT = 6, // Output register file for VS3.0+ - OPERAND_TYPE_DX9_CONSTINT = 7, // Constant Integer Vector Register File - OPERAND_TYPE_DX9_COLOROUT = 8, // Color Output Register File - OPERAND_TYPE_DX9_DEPTHOUT = 9, // Depth Output Register File - OPERAND_TYPE_DX9_SAMPLER = 10, // Sampler State Register File - OPERAND_TYPE_DX9_CONST2 = 11, // Constant Register File 2048 - 4095 - OPERAND_TYPE_DX9_CONST3 = 12, // Constant Register File 4096 - 6143 - OPERAND_TYPE_DX9_CONST4 = 13, // Constant Register File 6144 - 8191 - OPERAND_TYPE_DX9_CONSTBOOL = 14, // Constant Boolean register file - OPERAND_TYPE_DX9_LOOP = 15, // Loop counter register file - OPERAND_TYPE_DX9_TEMPFLOAT16 = 16, // 16-bit float temp register file - OPERAND_TYPE_DX9_MISCTYPE = 17, // Miscellaneous (single) registers. - OPERAND_TYPE_DX9_LABEL = 18, // Label - OPERAND_TYPE_DX9_PREDICATE = 19, // Predicate register - OPERAND_TYPE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum -} OPERAND_TYPE_DX9; - -static OPERAND_TYPE_DX9 DecodeOperandTypeDX9(const uint32_t ui32Token) -{ - return (OPERAND_TYPE_DX9)(((ui32Token & 0x70000000) >> 28) | - ((ui32Token & 0x00001800) >> 8)); -} - -static uint32_t CreateOperandTokenDX9(const uint32_t ui32RegNum, const OPERAND_TYPE_DX9 eType) -{ - uint32_t ui32Token = ui32RegNum; - ASSERT(ui32RegNum <2048); - ui32Token |= (eType <<28) & 0x70000000; - ui32Token |= (eType <<8) & 0x00001800; - return ui32Token; -} - -typedef enum { - DECLUSAGE_POSITION = 0, - DECLUSAGE_BLENDWEIGHT = 1, - DECLUSAGE_BLENDINDICES = 2, - DECLUSAGE_NORMAL = 3, - DECLUSAGE_PSIZE = 4, - DECLUSAGE_TEXCOORD = 5, - DECLUSAGE_TANGENT = 6, - DECLUSAGE_BINORMAL = 7, - DECLUSAGE_TESSFACTOR = 8, - DECLUSAGE_POSITIONT = 9, - DECLUSAGE_COLOR = 10, - DECLUSAGE_FOG = 11, - DECLUSAGE_DEPTH = 12, - DECLUSAGE_SAMPLE = 13 -} DECLUSAGE_DX9; - -static DECLUSAGE_DX9 DecodeUsageDX9(const uint32_t ui32Token) -{ - return (DECLUSAGE_DX9) (ui32Token & 0x0000000f); -} - -static uint32_t DecodeUsageIndexDX9(const uint32_t ui32Token) -{ - return (ui32Token & 0x000f0000)>>16; -} - -static uint32_t DecodeOperandIsRelativeAddressModeDX9(const uint32_t ui32Token) -{ - return ui32Token & (1<<13); -} - -static const uint32_t DX9_SWIZZLE_SHIFT = 16; -#define NO_SWIZZLE_DX9 ((0<<DX9_SWIZZLE_SHIFT)|(1<<DX9_SWIZZLE_SHIFT)|(2<<DX9_SWIZZLE_SHIFT)|(3<<DX9_SWIZZLE_SHIFT)) - -#define REPLICATE_SWIZZLE_DX9(CHANNEL) ((CHANNEL<<DX9_SWIZZLE_SHIFT)|(CHANNEL<<(DX9_SWIZZLE_SHIFT+2))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+4))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+6))) - -static uint32_t DecodeOperandSwizzleDX9(const uint32_t ui32Token) -{ - return ui32Token & 0x00FF0000; -} - -static const uint32_t DX9_WRITEMASK_0 = 0x00010000; // Component 0 (X;Red) -static const uint32_t DX9_WRITEMASK_1 = 0x00020000; // Component 1 (Y;Green) -static const uint32_t DX9_WRITEMASK_2 = 0x00040000; // Component 2 (Z;Blue) -static const uint32_t DX9_WRITEMASK_3 = 0x00080000; // Component 3 (W;Alpha) -static const uint32_t DX9_WRITEMASK_ALL = 0x000F0000; // All Components - -static uint32_t DecodeDestWriteMaskDX9(const uint32_t ui32Token) -{ - return ui32Token & DX9_WRITEMASK_ALL; -} - -static RESOURCE_DIMENSION DecodeTextureTypeMaskDX9(const uint32_t ui32Token) -{ - - switch(ui32Token & 0x78000000) - { - case 2 << 27: - return RESOURCE_DIMENSION_TEXTURE2D; - case 3 << 27: - return RESOURCE_DIMENSION_TEXTURECUBE; - case 4 << 27: - return RESOURCE_DIMENSION_TEXTURE3D; - default: - return RESOURCE_DIMENSION_UNKNOWN; - } -} - - - -static const uint32_t DESTMOD_DX9_NONE = 0; -static const uint32_t DESTMOD_DX9_SATURATE = (1 << 20); -static const uint32_t DESTMOD_DX9_PARTIALPRECISION = (2 << 20); -static const uint32_t DESTMOD_DX9_MSAMPCENTROID = (4 << 20); -static uint32_t DecodeDestModifierDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xf00000; -} - -typedef enum -{ - SRCMOD_DX9_NONE = 0 << 24, - SRCMOD_DX9_NEG = 1 << 24, - SRCMOD_DX9_BIAS = 2 << 24, - SRCMOD_DX9_BIASNEG = 3 << 24, - SRCMOD_DX9_SIGN = 4 << 24, - SRCMOD_DX9_SIGNNEG = 5 << 24, - SRCMOD_DX9_COMP = 6 << 24, - SRCMOD_DX9_X2 = 7 << 24, - SRCMOD_DX9_X2NEG = 8 << 24, - SRCMOD_DX9_DZ = 9 << 24, - SRCMOD_DX9_DW = 10 << 24, - SRCMOD_DX9_ABS = 11 << 24, - SRCMOD_DX9_ABSNEG = 12 << 24, - SRCMOD_DX9_NOT = 13 << 24, - SRCMOD_DX9_FORCE_DWORD = 0xffffffff -} SRCMOD_DX9; -static uint32_t DecodeSrcModifierDX9(const uint32_t ui32Token) -{ - return ui32Token & 0xf000000; -} - -typedef enum -{ - D3DSPC_RESERVED0 = 0, - D3DSPC_GT = 1, - D3DSPC_EQ = 2, - D3DSPC_GE = 3, - D3DSPC_LT = 4, - D3DSPC_NE = 5, - D3DSPC_LE = 6, - D3DSPC_BOOLEAN = 7, //Make use of the RESERVED1 bit to indicate if-bool opcode. -} COMPARISON_DX9; - -static COMPARISON_DX9 DecodeComparisonDX9(const uint32_t ui32Token) -{ - return (COMPARISON_DX9)((ui32Token & (0x07<<16))>>16); -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c b/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c deleted file mode 100644 index 03f3388a93..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c +++ /dev/null @@ -1,1213 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/reflect.h" -#include "internal_includes/debug.h" -#include "internal_includes/decode.h" -#include "internal_includes/hlslcc_malloc.h" -#include "bstrlib.h" -#include <stdlib.h> -#include <stdio.h> - -static void FormatVariableName(char* Name) -{ - /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx - The uniform function parameters appear in the - constant table prepended with a dollar sign ($), - unlike the global variables. The dollar sign is - required to avoid name collisions between local - uniform inputs and global variables of the same name.*/ - - /* Leave $ThisPointer, $Element and $Globals as-is. - Otherwise remove $ character ($ is not a valid character for GLSL variable names). */ - if (Name[0] == '$') - { - if (strcmp(Name, "$Element") != 0 && - strcmp(Name, "$Globals") != 0 && - strcmp(Name, "$ThisPointer") != 0) - { - Name[0] = '_'; - } - } -} - -static void ReadStringFromTokenStream(const uint32_t* tokens, char* str) -{ - char* charTokens = (char*) tokens; - char nextCharacter = *charTokens++; - int length = 0; - - //Add each individual character until - //a terminator is found. - while (nextCharacter != 0) - { - str[length++] = nextCharacter; - - if (length > MAX_REFLECT_STRING_LENGTH) - { - str[length - 1] = '\0'; - return; - } - - nextCharacter = *charTokens++; - } - - str[length] = '\0'; -} - -static void ReadInputSignatures(const uint32_t* pui32Tokens, - ShaderInfo* psShaderInfo, - const int extended) -{ - uint32_t i; - - InOutSignature* psSignatures; - const uint32_t* pui32FirstSignatureToken = pui32Tokens; - const uint32_t ui32ElementCount = *pui32Tokens++; - /*const uint32_t ui32Key =*/ *pui32Tokens++; - - psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); - psShaderInfo->psInputSignatures = psSignatures; - psShaderInfo->ui32NumInputSignatures = ui32ElementCount; - - for (i = 0; i < ui32ElementCount; ++i) - { - uint32_t ui32ComponentMasks; - InOutSignature* psCurrentSignature = psSignatures + i; - uint32_t ui32SemanticNameOffset; - - psCurrentSignature->ui32Stream = 0; - psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; - - if (extended) - { - psCurrentSignature->ui32Stream = *pui32Tokens++; - } - - ui32SemanticNameOffset = *pui32Tokens++; - psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; - psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++; - psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; - psCurrentSignature->ui32Register = *pui32Tokens++; - - ui32ComponentMasks = *pui32Tokens++; - psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; - //Shows which components are read - psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; - - if (extended) - { - psCurrentSignature->eMinPrec = *pui32Tokens++; - } - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); - } -} - -static void ReadOutputSignatures(const uint32_t* pui32Tokens, - ShaderInfo* psShaderInfo, - const int minPrec, - const int streams) -{ - uint32_t i; - - InOutSignature* psSignatures; - const uint32_t* pui32FirstSignatureToken = pui32Tokens; - const uint32_t ui32ElementCount = *pui32Tokens++; - /*const uint32_t ui32Key =*/ *pui32Tokens++; - - psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); - psShaderInfo->psOutputSignatures = psSignatures; - psShaderInfo->ui32NumOutputSignatures = ui32ElementCount; - - for (i = 0; i < ui32ElementCount; ++i) - { - uint32_t ui32ComponentMasks; - InOutSignature* psCurrentSignature = psSignatures + i; - uint32_t ui32SemanticNameOffset; - - psCurrentSignature->ui32Stream = 0; - psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; - - if (streams) - { - psCurrentSignature->ui32Stream = *pui32Tokens++; - } - - ui32SemanticNameOffset = *pui32Tokens++; - psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; - psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; - psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; - psCurrentSignature->ui32Register = *pui32Tokens++; - - // Massage some special inputs/outputs to match the types of GLSL counterparts - if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX) - { - psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32; - } - - ui32ComponentMasks = *pui32Tokens++; - psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; - //Shows which components are NEVER written. - psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; - - if (minPrec) - { - psCurrentSignature->eMinPrec = *pui32Tokens++; - } - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); - } -} - -static void ReadPatchConstantSignatures(const uint32_t* pui32Tokens, - ShaderInfo* psShaderInfo, - const int minPrec, - const int streams) -{ - uint32_t i; - - InOutSignature* psSignatures; - const uint32_t* pui32FirstSignatureToken = pui32Tokens; - const uint32_t ui32ElementCount = *pui32Tokens++; - /*const uint32_t ui32Key =*/ *pui32Tokens++; - - psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); - psShaderInfo->psPatchConstantSignatures = psSignatures; - psShaderInfo->ui32NumPatchConstantSignatures = ui32ElementCount; - - for (i = 0; i < ui32ElementCount; ++i) - { - uint32_t ui32ComponentMasks; - InOutSignature* psCurrentSignature = psSignatures + i; - uint32_t ui32SemanticNameOffset; - - psCurrentSignature->ui32Stream = 0; - psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; - - if (streams) - { - psCurrentSignature->ui32Stream = *pui32Tokens++; - } - - ui32SemanticNameOffset = *pui32Tokens++; - psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; - psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; - psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; - psCurrentSignature->ui32Register = *pui32Tokens++; - - // Massage some special inputs/outputs to match the types of GLSL counterparts - if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX) - { - psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32; - } - - ui32ComponentMasks = *pui32Tokens++; - psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; - //Shows which components are NEVER written. - psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; - - if (minPrec) - { - psCurrentSignature->eMinPrec = *pui32Tokens++; - } - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); - } -} - -static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding) -{ - uint32_t ui32NameOffset = *pui32Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken + ui32NameOffset), psBinding->Name); - FormatVariableName(psBinding->Name); - - psBinding->eType = *pui32Tokens++; - psBinding->ui32ReturnType = *pui32Tokens++; - psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++; - psBinding->ui32NumSamples = *pui32Tokens++; - psBinding->ui32BindPoint = *pui32Tokens++; - psBinding->ui32BindCount = *pui32Tokens++; - psBinding->ui32Flags = *pui32Tokens++; - psBinding->eBindArea = UAVAREA_INVALID; - - return pui32Tokens; -} - -//Read D3D11_SHADER_TYPE_DESC -static void ReadShaderVariableType(const uint32_t ui32MajorVersion, - const uint32_t* pui32FirstConstBufToken, - const uint32_t* pui32tokens, ShaderVarType* varType) -{ - const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens; - uint16_t ui32MemberCount; - uint32_t ui32MemberOffset; - const uint32_t* pui32MemberTokens; - uint32_t i; - - varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0]; - varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1]; - varType->Rows = pui16Tokens[2]; - varType->Columns = pui16Tokens[3]; - varType->Elements = pui16Tokens[4]; - - varType->MemberCount = ui32MemberCount = pui16Tokens[5]; - varType->Members = 0; - - if (varType->ParentCount) - { - ASSERT((strlen(varType->Parent->FullName) + 1 + strlen(varType->Name) + 1 + 2) < MAX_REFLECT_STRING_LENGTH); - - strcpy(varType->FullName, varType->Parent->FullName); - strcat(varType->FullName, "."); - strcat(varType->FullName, varType->Name); - } - - if (ui32MemberCount) - { - varType->Members = (ShaderVarType*)hlslcc_malloc(sizeof(ShaderVarType) * ui32MemberCount); - - ui32MemberOffset = pui32tokens[3]; - - pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberOffset); - - for (i = 0; i < ui32MemberCount; ++i) - { - uint32_t ui32NameOffset = *pui32MemberTokens++; - uint32_t ui32MemberTypeOffset = *pui32MemberTokens++; - - varType->Members[i].Parent = varType; - varType->Members[i].ParentCount = varType->ParentCount + 1; - - varType->Members[i].Offset = *pui32MemberTokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), varType->Members[i].Name); - - ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken, - (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberTypeOffset), &varType->Members[i]); - } - } -} - -static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo, - const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32Tokens, ConstantBuffer* psBuffer) -{ - uint32_t i; - uint32_t ui32NameOffset = *pui32Tokens++; - uint32_t ui32VarCount = *pui32Tokens++; - uint32_t ui32VarOffset = *pui32Tokens++; - const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32VarOffset); - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), psBuffer->Name); - FormatVariableName(psBuffer->Name); - - psBuffer->ui32NumVars = ui32VarCount; - psBuffer->asVars = hlslcc_malloc(psBuffer->ui32NumVars * sizeof(ShaderVar)); - - for (i = 0; i < ui32VarCount; ++i) - { - //D3D11_SHADER_VARIABLE_DESC - ShaderVar* const psVar = &psBuffer->asVars[i]; - - uint32_t ui32Flags; - uint32_t ui32TypeOffset; - uint32_t ui32DefaultValueOffset; - - ui32NameOffset = *pui32VarToken++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), psVar->Name); - FormatVariableName(psVar->Name); - - psVar->ui32StartOffset = *pui32VarToken++; - psVar->ui32Size = *pui32VarToken++; - ui32Flags = *pui32VarToken++; - ui32TypeOffset = *pui32VarToken++; - - strcpy(psVar->sType.Name, psVar->Name); - strcpy(psVar->sType.FullName, psVar->Name); - psVar->sType.Parent = 0; - psVar->sType.ParentCount = 0; - psVar->sType.Offset = 0; - - ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken, - (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32TypeOffset), &psVar->sType); - - ui32DefaultValueOffset = *pui32VarToken++; - - - if (psShaderInfo->ui32MajorVersion >= 5) - { - /* uint32_t StartTexture = */ *pui32VarToken++; - /* uint32_t TextureSize = */ *pui32VarToken++; - /* uint32_t StartSampler = */ *pui32VarToken++; - /* uint32_t SamplerSize = */ *pui32VarToken++; - } - - psVar->haveDefaultValue = 0; - - if (ui32DefaultValueOffset) - { - const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4; - const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32DefaultValueOffset); - - //Always a sequence of 4-bytes at the moment. - //bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes. - ASSERT(psVar->ui32Size % 4 == 0); - - psVar->haveDefaultValue = 1; - - psVar->pui32DefaultValues = hlslcc_malloc(psVar->ui32Size); - - for (uint32_t ii = 0; ii < ui32NumDefaultValues; ++ii) - { - psVar->pui32DefaultValues[ii] = pui32DefaultValToken[ii]; - } - } - } - - - { - uint32_t ui32Flags; - uint32_t ui32BufferType; - - psBuffer->ui32TotalSizeInBytes = *pui32Tokens++; - psBuffer->blob = 0; - ui32Flags = *pui32Tokens++; - ui32BufferType = *pui32Tokens++; - } - - return pui32Tokens; -} - -static void ReadResources(const uint32_t* pui32Tokens,//in - ShaderInfo* psShaderInfo) //out -{ - ResourceBinding* psResBindings; - ConstantBuffer* psConstantBuffers; - const uint32_t* pui32ConstantBuffers; - const uint32_t* pui32ResourceBindings; - const uint32_t* pui32FirstToken = pui32Tokens; - uint32_t i; - - const uint32_t ui32NumConstantBuffers = *pui32Tokens++; - const uint32_t ui32ConstantBufferOffset = *pui32Tokens++; - - uint32_t ui32NumResourceBindings = *pui32Tokens++; - uint32_t ui32ResourceBindingOffset = *pui32Tokens++; - /*uint32_t ui32ShaderModel =*/ *pui32Tokens++; - /*uint32_t ui32CompileFlags =*/ *pui32Tokens++;//D3DCompile flags? http://msdn.microsoft.com/en-us/library/gg615083(v=vs.85).aspx - - //Resources - pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset); - - psResBindings = hlslcc_malloc(sizeof(ResourceBinding) * ui32NumResourceBindings); - - psShaderInfo->ui32NumResourceBindings = ui32NumResourceBindings; - psShaderInfo->psResourceBindings = psResBindings; - - for (i = 0; i < ui32NumResourceBindings; ++i) - { - pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings + i); - ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS); - } - - //Constant buffers - pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset); - - psConstantBuffers = hlslcc_malloc(sizeof(ConstantBuffer) * ui32NumConstantBuffers); - - psShaderInfo->ui32NumConstantBuffers = ui32NumConstantBuffers; - psShaderInfo->psConstantBuffers = psConstantBuffers; - - for (i = 0; i < ui32NumConstantBuffers; ++i) - { - pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers + i); - } - - - //Map resource bindings to constant buffers - if (psShaderInfo->ui32NumConstantBuffers) - { - for (i = 0; i < ui32NumResourceBindings; ++i) - { - ResourceGroup eRGroup; - uint32_t cbufIndex = 0; - - eRGroup = ResourceTypeToResourceGroup(psResBindings[i].eType); - - //Find the constant buffer whose name matches the resource at the given resource binding point - for (cbufIndex = 0; cbufIndex < psShaderInfo->ui32NumConstantBuffers; cbufIndex++) - { - if (strcmp(psConstantBuffers[cbufIndex].Name, psResBindings[i].Name) == 0) - { - psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex; - } - } - } - } -} - -static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType) -{ - const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens; - uint32_t ui32NameOffset = *pui32Tokens; - pui16Tokens += 2; - - psClassType->ui16ID = *pui16Tokens++; - psClassType->ui16ConstBufStride = *pui16Tokens++; - psClassType->ui16Texture = *pui16Tokens++; - psClassType->ui16Sampler = *pui16Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset), psClassType->Name); - - return pui16Tokens; -} - -static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassInstance* psClassInstance) -{ - uint32_t ui32NameOffset = *pui16Tokens++ << 16; - ui32NameOffset |= *pui16Tokens++; - - psClassInstance->ui16ID = *pui16Tokens++; - psClassInstance->ui16ConstBuf = *pui16Tokens++; - psClassInstance->ui16ConstBufOffset = *pui16Tokens++; - psClassInstance->ui16Texture = *pui16Tokens++; - psClassInstance->ui16Sampler = *pui16Tokens++; - - ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset), psClassInstance->Name); - - return pui16Tokens; -} - - -static void ReadInterfaces(const uint32_t* pui32Tokens, - ShaderInfo* psShaderInfo) -{ - uint32_t i; - uint32_t ui32StartSlot; - const uint32_t* pui32FirstInterfaceToken = pui32Tokens; - const uint32_t ui32ClassInstanceCount = *pui32Tokens++; - const uint32_t ui32ClassTypeCount = *pui32Tokens++; - const uint32_t ui32InterfaceSlotRecordCount = *pui32Tokens++; - /*const uint32_t ui32InterfaceSlotCount =*/ *pui32Tokens++; - const uint32_t ui32ClassInstanceOffset = *pui32Tokens++; - const uint32_t ui32ClassTypeOffset = *pui32Tokens++; - const uint32_t ui32InterfaceSlotOffset = *pui32Tokens++; - - const uint16_t* pui16ClassTypes = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassTypeOffset); - const uint16_t* pui16ClassInstances = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassInstanceOffset); - const uint32_t* pui32InterfaceSlots = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32InterfaceSlotOffset); - - const uint32_t* pui32InterfaceSlotTokens = pui32InterfaceSlots; - - ClassType* psClassTypes; - ClassInstance* psClassInstances; - - psClassTypes = hlslcc_malloc(sizeof(ClassType) * ui32ClassTypeCount); - for (i = 0; i < ui32ClassTypeCount; ++i) - { - pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes + i); - psClassTypes[i].ui16ID = (uint16_t)i; - } - - psClassInstances = hlslcc_malloc(sizeof(ClassInstance) * ui32ClassInstanceCount); - for (i = 0; i < ui32ClassInstanceCount; ++i) - { - pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances + i); - } - - //Slots map function table to $ThisPointer cbuffer variable index - ui32StartSlot = 0; - for (i = 0; i < ui32InterfaceSlotRecordCount; ++i) - { - uint32_t k; - - const uint32_t ui32SlotSpan = *pui32InterfaceSlotTokens++; - const uint32_t ui32Count = *pui32InterfaceSlotTokens++; - const uint32_t ui32TypeIDOffset = *pui32InterfaceSlotTokens++; - const uint32_t ui32TableIDOffset = *pui32InterfaceSlotTokens++; - - const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32TypeIDOffset); - const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32TableIDOffset); - - for (k = 0; k < ui32Count; ++k) - { - psShaderInfo->aui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++; - } - - ui32StartSlot += ui32SlotSpan; - } - - psShaderInfo->ui32NumClassInstances = ui32ClassInstanceCount; - psShaderInfo->psClassInstances = psClassInstances; - - psShaderInfo->ui32NumClassTypes = ui32ClassTypeCount; - psShaderInfo->psClassTypes = psClassTypes; -} - -void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf) -{ - if (psShaderInfo->ui32MajorVersion > 3) - { - *ppsConstBuf = psShaderInfo->psConstantBuffers + psShaderInfo->aui32ResourceMap[eGroup][ui32BindPoint]; - } - else - { - ASSERT(psShaderInfo->ui32NumConstantBuffers == 1); - *ppsConstBuf = psShaderInfo->psConstantBuffers; - } -} - -int GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding) -{ - uint32_t i; - const uint32_t ui32NumBindings = psShaderInfo->ui32NumResourceBindings; - ResourceBinding* psBindings = psShaderInfo->psResourceBindings; - - for (i = 0; i < ui32NumBindings; ++i) - { - if (ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup) - { - if (ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount)) - { - *ppsOutBinding = psBindings + i; - return 1; - } - } - } - - return 0; -} - -int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar) -{ - uint32_t i; - ConstantBuffer* psThisPointerConstBuffer = psShaderInfo->psThisPointerConstBuffer; - - const uint32_t ui32NumVars = psThisPointerConstBuffer->ui32NumVars; - - for (i = 0; i < ui32NumVars; ++i) - { - if (ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset && - ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size)) - { - *ppsShaderVar = &psThisPointerConstBuffer->asVars[i]; - return 1; - } - } - return 0; -} - -int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) -{ - uint32_t i; - const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; - - for (i = 0; i < ui32NumVars; ++i) - { - InOutSignature* psInputSignatures = psShaderInfo->psInputSignatures; - if (ui32Register == psInputSignatures[i].ui32Register) - { - *ppsOut = psInputSignatures + i; - return 1; - } - } - return 0; -} - -int GetOutputSignatureFromRegister(const uint32_t currentPhase, - const uint32_t ui32Register, - const uint32_t ui32CompMask, - const uint32_t ui32Stream, - ShaderInfo* psShaderInfo, - InOutSignature** ppsOut) -{ - uint32_t i; - - if (currentPhase == HS_JOIN_PHASE || currentPhase == HS_FORK_PHASE) - { - const uint32_t ui32NumVars = psShaderInfo->ui32NumPatchConstantSignatures; - - for (i = 0; i < ui32NumVars; ++i) - { - InOutSignature* psOutputSignatures = psShaderInfo->psPatchConstantSignatures; - if (ui32Register == psOutputSignatures[i].ui32Register && - (ui32CompMask & psOutputSignatures[i].ui32Mask) && - ui32Stream == psOutputSignatures[i].ui32Stream) - { - *ppsOut = psOutputSignatures + i; - return 1; - } - } - } - else - { - const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; - - for (i = 0; i < ui32NumVars; ++i) - { - InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; - if (ui32Register == psOutputSignatures[i].ui32Register && - (ui32CompMask & psOutputSignatures[i].ui32Mask) && - ui32Stream == psOutputSignatures[i].ui32Stream) - { - *ppsOut = psOutputSignatures + i; - return 1; - } - } - } - return 0; -} - -int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) -{ - uint32_t i; - const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; - - for (i = 0; i < ui32NumVars; ++i) - { - InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; - if (eSystemValueType == psOutputSignatures[i].eSystemValueType && - ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex) - { - *ppsOut = psOutputSignatures + i; - return 1; - } - } - return 0; -} - -static int IsOffsetInType(ShaderVarType* psType, - uint32_t parentOffset, - uint32_t offsetToFind, - const uint32_t* pui32Swizzle, - int32_t* pi32Index, - int32_t* pi32Rebase) -{ - uint32_t thisOffset = parentOffset + psType->Offset; - uint32_t thisSize = psType->Columns * psType->Rows * 4; - - if (psType->Elements) - { - // Everything smaller than vec4 in an array takes the space of vec4, except for the last one - if (thisSize < 4 * 4) - { - thisSize = (4 * 4 * (psType->Elements - 1)) + thisSize; - } - else - { - thisSize *= psType->Elements; - } - } - - //Swizzle can point to another variable. In the example below - //cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined - //into vectors. psCBuf->ui32NumVars will be 3. - - // cbuffer cbUIUpdates - // { - // - // float g_fLifeSpan; // Offset: 0 Size: 4 - // float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused] - // float g_fRadiusMin; // Offset: 8 Size: 4 [unused] - // float g_fRadiusMax; // Offset: 12 Size: 4 [unused] - // float g_fGrowTime; // Offset: 16 Size: 4 [unused] - // float g_fStepSize; // Offset: 20 Size: 4 - // float g_fTurnRate; // Offset: 24 Size: 4 - // float g_fTurnSpeed; // Offset: 28 Size: 4 [unused] - // float g_fLeafRate; // Offset: 32 Size: 4 - // float g_fShrinkTime; // Offset: 36 Size: 4 [unused] - // uint g_uMaxFaces; // Offset: 40 Size: 4 - // - // } - - // Name Type Format Dim Slot Elements - // ------------------------------ ---------- ------- ----------- ---- -------- - // cbUIUpdates cbuffer NA NA 1 1 - - if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - offsetToFind += 4; - } - else - if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - offsetToFind += 8; - } - else - if (pui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - offsetToFind += 12; - } - - if ((offsetToFind >= thisOffset) && - offsetToFind < (thisOffset + thisSize)) - { - if (psType->Class == SVC_MATRIX_ROWS || - psType->Class == SVC_MATRIX_COLUMNS) - { - //Matrices are treated as arrays of vectors. - pi32Index[0] = (offsetToFind - thisOffset) / 16; - } - //Check for array of scalars or vectors (both take up 16 bytes per element) - else if ((psType->Class == SVC_SCALAR || psType->Class == SVC_VECTOR) && psType->Elements > 1) - { - pi32Index[0] = (offsetToFind - thisOffset) / 16; - } - else if (psType->Class == SVC_VECTOR && psType->Columns > 1) - { - //Check for vector starting at a non-vec4 offset. - - // cbuffer $Globals - // { - // - // float angle; // Offset: 0 Size: 4 - // float2 angle2; // Offset: 4 Size: 8 - // - // } - - //cb0[0].x = angle - //cb0[0].yzyy = angle2.xyxx - - //Rebase angle2 so that .y maps to .x, .z maps to .y - - pi32Rebase[0] = thisOffset % 16; - } - - return 1; - } - return 0; -} - -int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, - const uint32_t* pui32Swizzle, - ConstantBuffer* psCBuf, - ShaderVarType** ppsShaderVar, - int32_t* pi32Index, - int32_t* pi32Rebase) -{ - uint32_t i; - - uint32_t ui32ByteOffset = ui32Vec4Offset * 16; - - const uint32_t ui32NumVars = psCBuf->ui32NumVars; - - for (i = 0; i < ui32NumVars; ++i) - { - if (psCBuf->asVars[i].sType.Class == SVC_STRUCT) - { - uint32_t m = 0; - - for (m = 0; m < psCBuf->asVars[i].sType.MemberCount; ++m) - { - ShaderVarType* psMember = psCBuf->asVars[i].sType.Members + m; - - ASSERT(psMember->Class != SVC_STRUCT); - - if (IsOffsetInType(psMember, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) - { - ppsShaderVar[0] = psMember; - return 1; - } - } - } - else - { - if (IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) - { - ppsShaderVar[0] = &psCBuf->asVars[i].sType; - return 1; - } - } - } - return 0; -} - -ResourceGroup ResourceTypeToResourceGroup(ResourceType eType) -{ - switch (eType) - { - case RTYPE_CBUFFER: - return RGROUP_CBUFFER; - - case RTYPE_SAMPLER: - return RGROUP_SAMPLER; - - case RTYPE_TEXTURE: - case RTYPE_BYTEADDRESS: - case RTYPE_STRUCTURED: - return RGROUP_TEXTURE; - - case RTYPE_UAV_RWTYPED: - case RTYPE_UAV_RWSTRUCTURED: - case RTYPE_UAV_RWBYTEADDRESS: - case RTYPE_UAV_APPEND_STRUCTURED: - case RTYPE_UAV_CONSUME_STRUCTURED: - case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: - return RGROUP_UAV; - - case RTYPE_TBUFFER: - ASSERT(0); // Need to find out which group this belongs to - return RGROUP_TEXTURE; - } - - ASSERT(0); - return RGROUP_CBUFFER; -} - -void LoadShaderInfo(const uint32_t ui32MajorVersion, - const uint32_t ui32MinorVersion, - const ReflectionChunks* psChunks, - ShaderInfo* psInfo) -{ - const uint32_t* pui32Inputs = psChunks->pui32Inputs; - const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11; - const uint32_t* pui32Resources = psChunks->pui32Resources; - const uint32_t* pui32Interfaces = psChunks->pui32Interfaces; - const uint32_t* pui32Outputs = psChunks->pui32Outputs; - const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11; - const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams; - const uint32_t* pui32PatchConstants = psChunks->pui32PatchConstants; - - psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED; - psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED; - - psInfo->ui32MajorVersion = ui32MajorVersion; - psInfo->ui32MinorVersion = ui32MinorVersion; - - - if (pui32Inputs) - { - ReadInputSignatures(pui32Inputs, psInfo, 0); - } - if (pui32Inputs11) - { - ReadInputSignatures(pui32Inputs11, psInfo, 1); - } - if (pui32Resources) - { - ReadResources(pui32Resources, psInfo); - } - if (pui32Interfaces) - { - ReadInterfaces(pui32Interfaces, psInfo); - } - if (pui32Outputs) - { - ReadOutputSignatures(pui32Outputs, psInfo, 0, 0); - } - if (pui32Outputs11) - { - ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1); - } - if (pui32OutputsWithStreams) - { - ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1); - } - if (pui32PatchConstants) - { - ReadPatchConstantSignatures(pui32PatchConstants, psInfo, 0, 0); - } - // if(pui32Effects10Data) - // ReadEffectsData(pui32Effects10Data, psInfo); NOT IMPLEMENTED - - uint32_t i; - for (i = 0; i < psInfo->ui32NumConstantBuffers; ++i) - { - bstring cbufName = bfromcstr(&psInfo->psConstantBuffers[i].Name[0]); - bstring cbufThisPointer = bfromcstr("$ThisPointer"); - if (bstrcmp(cbufName, cbufThisPointer) == 0) - { - psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i]; - } - } - - for (i = 0; i < MAX_RESOURCE_BINDINGS; ++i) - { - psInfo->aui32SamplerMap[i] = MAX_RESOURCE_BINDINGS; - } -} - -void FreeShaderInfo(ShaderInfo* psShaderInfo) -{ - //Free any default values for constants. - uint32_t cbuf; - for (cbuf = 0; cbuf < psShaderInfo->ui32NumConstantBuffers; ++cbuf) - { - ConstantBuffer* psCBuf = &psShaderInfo->psConstantBuffers[cbuf]; - uint32_t var; - if (psCBuf->ui32NumVars) - { - for (var = 0; var < psCBuf->ui32NumVars; ++var) - { - ShaderVar* psVar = &psCBuf->asVars[var]; - if (psVar->haveDefaultValue) - { - hlslcc_free(psVar->pui32DefaultValues); - } - } - hlslcc_free(psCBuf->asVars); - } - } - hlslcc_free(psShaderInfo->psInputSignatures); - hlslcc_free(psShaderInfo->psResourceBindings); - hlslcc_free(psShaderInfo->psConstantBuffers); - hlslcc_free(psShaderInfo->psClassTypes); - hlslcc_free(psShaderInfo->psClassInstances); - hlslcc_free(psShaderInfo->psOutputSignatures); - hlslcc_free(psShaderInfo->psPatchConstantSignatures); - - psShaderInfo->ui32NumInputSignatures = 0; - psShaderInfo->ui32NumResourceBindings = 0; - psShaderInfo->ui32NumConstantBuffers = 0; - psShaderInfo->ui32NumClassTypes = 0; - psShaderInfo->ui32NumClassInstances = 0; - psShaderInfo->ui32NumOutputSignatures = 0; - psShaderInfo->ui32NumPatchConstantSignatures = 0; -} - -typedef struct ConstantTableD3D9_TAG -{ - uint32_t size; - uint32_t creator; - uint32_t version; - uint32_t constants; - uint32_t constantInfos; - uint32_t flags; - uint32_t target; -} ConstantTableD3D9; - -// These enums match those in d3dx9shader.h. -enum RegisterSet -{ - RS_BOOL, - RS_INT4, - RS_FLOAT4, - RS_SAMPLER, -}; - -enum TypeClass -{ - CLASS_SCALAR, - CLASS_VECTOR, - CLASS_MATRIX_ROWS, - CLASS_MATRIX_COLUMNS, - CLASS_OBJECT, - CLASS_STRUCT, -}; - -enum Type -{ - PT_VOID, - PT_BOOL, - PT_INT, - PT_FLOAT, - PT_STRING, - PT_TEXTURE, - PT_TEXTURE1D, - PT_TEXTURE2D, - PT_TEXTURE3D, - PT_TEXTURECUBE, - PT_SAMPLER, - PT_SAMPLER1D, - PT_SAMPLER2D, - PT_SAMPLER3D, - PT_SAMPLERCUBE, - PT_PIXELSHADER, - PT_VERTEXSHADER, - PT_PIXELFRAGMENT, - PT_VERTEXFRAGMENT, - PT_UNSUPPORTED, -}; -typedef struct ConstantInfoD3D9_TAG -{ - uint32_t name; - uint16_t registerSet; - uint16_t registerIndex; - uint16_t registerCount; - uint16_t reserved; - uint32_t typeInfo; - uint32_t defaultValue; -} ConstantInfoD3D9; - -typedef struct TypeInfoD3D9_TAG -{ - uint16_t typeClass; - uint16_t type; - uint16_t rows; - uint16_t columns; - uint16_t elements; - uint16_t structMembers; - uint32_t structMemberInfos; -} TypeInfoD3D9; - -typedef struct StructMemberInfoD3D9_TAG -{ - uint32_t name; - uint32_t typeInfo; -} StructMemberInfoD3D9; - -void LoadD3D9ConstantTable(const char* data, - ShaderInfo* psInfo) -{ - ConstantTableD3D9* ctab; - uint32_t constNum; - ConstantInfoD3D9* cinfos; - ConstantBuffer* psConstantBuffer; - uint32_t ui32ConstantBufferSize = 0; - uint32_t numResourceBindingsNeeded = 0; - ShaderVar* var; - - ctab = (ConstantTableD3D9*)data; - - cinfos = (ConstantInfoD3D9*) (data + ctab->constantInfos); - - psInfo->ui32NumConstantBuffers++; - - //Only 1 Constant Table in d3d9 - ASSERT(psInfo->ui32NumConstantBuffers == 1); - - psConstantBuffer = hlslcc_malloc(sizeof(ConstantBuffer)); - - psInfo->psConstantBuffers = psConstantBuffer; - - psConstantBuffer->ui32NumVars = 0; - strcpy(psConstantBuffer->Name, "$Globals"); - - //Determine how many resource bindings to create - for (constNum = 0; constNum < ctab->constants; ++constNum) - { - if (cinfos[constNum].registerSet == RS_SAMPLER) - { - ++numResourceBindingsNeeded; - } - } - - psInfo->psResourceBindings = hlslcc_malloc(numResourceBindingsNeeded * sizeof(ResourceBinding)); - - psConstantBuffer->asVars = hlslcc_malloc((ctab->constants - numResourceBindingsNeeded) * sizeof(ShaderVar)); - - var = &psConstantBuffer->asVars[0]; - - for (constNum = 0; constNum < ctab->constants; ++constNum) - { - TypeInfoD3D9* typeInfo = (TypeInfoD3D9*) (data + cinfos[constNum].typeInfo); - - if (cinfos[constNum].registerSet != RS_SAMPLER) - { - strcpy(var->Name, data + cinfos[constNum].name); - FormatVariableName(var->Name); - var->ui32Size = cinfos[constNum].registerCount * 16; - var->ui32StartOffset = cinfos[constNum].registerIndex * 16; - var->haveDefaultValue = 0; - - if (ui32ConstantBufferSize < (var->ui32Size + var->ui32StartOffset)) - { - ui32ConstantBufferSize = var->ui32Size + var->ui32StartOffset; - } - - var->sType.Rows = typeInfo->rows; - var->sType.Columns = typeInfo->columns; - var->sType.Elements = typeInfo->elements; - var->sType.MemberCount = typeInfo->structMembers; - var->sType.Members = 0; - var->sType.Offset = 0; - strcpy(var->sType.FullName, var->Name); - var->sType.Parent = 0; - var->sType.ParentCount = 0; - - switch (typeInfo->typeClass) - { - case CLASS_SCALAR: - { - var->sType.Class = SVC_SCALAR; - break; - } - case CLASS_VECTOR: - { - var->sType.Class = SVC_VECTOR; - break; - } - case CLASS_MATRIX_ROWS: - { - var->sType.Class = SVC_MATRIX_ROWS; - break; - } - case CLASS_MATRIX_COLUMNS: - { - var->sType.Class = SVC_MATRIX_COLUMNS; - break; - } - case CLASS_OBJECT: - { - var->sType.Class = SVC_OBJECT; - break; - } - case CLASS_STRUCT: - { - var->sType.Class = SVC_STRUCT; - break; - } - } - - switch (cinfos[constNum].registerSet) - { - case RS_BOOL: - { - var->sType.Type = SVT_BOOL; - break; - } - case RS_INT4: - { - var->sType.Type = SVT_INT; - break; - } - case RS_FLOAT4: - { - var->sType.Type = SVT_FLOAT; - break; - } - } - - var++; - psConstantBuffer->ui32NumVars++; - } - else - { - //Create a resource if it is sampler in order to replicate the d3d10+ - //method of separating samplers from general constants. - uint32_t ui32ResourceIndex = psInfo->ui32NumResourceBindings++; - ResourceBinding* res = &psInfo->psResourceBindings[ui32ResourceIndex]; - - strcpy(res->Name, data + cinfos[constNum].name); - FormatVariableName(res->Name); - - res->ui32BindPoint = cinfos[constNum].registerIndex; - res->ui32BindCount = cinfos[constNum].registerCount; - res->ui32Flags = 0; - res->ui32NumSamples = 1; - res->ui32ReturnType = 0; - - res->eType = RTYPE_TEXTURE; - - switch (typeInfo->type) - { - case PT_SAMPLER: - case PT_SAMPLER1D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE1D; - break; - case PT_SAMPLER2D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; - break; - case PT_SAMPLER3D: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE3D; - break; - case PT_SAMPLERCUBE: - res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURECUBE; - break; - } - } - } - psConstantBuffer->ui32TotalSizeInBytes = ui32ConstantBufferSize; -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c deleted file mode 100644 index 6c9d02015e..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c +++ /dev/null @@ -1,851 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/tokens.h" -#include "internal_includes/structs.h" -#include "internal_includes/decode.h" -#include "stdlib.h" -#include "stdio.h" -#include "bstrlib.h" -#include "internal_includes/toGLSLInstruction.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/toGLSLDeclaration.h" -#include "internal_includes/languages.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" - -#ifndef GL_VERTEX_SHADER_ARB -#define GL_VERTEX_SHADER_ARB 0x8B31 -#endif -#ifndef GL_FRAGMENT_SHADER_ARB -#define GL_FRAGMENT_SHADER_ARB 0x8B30 -#endif -#ifndef GL_GEOMETRY_SHADER -#define GL_GEOMETRY_SHADER 0x8DD9 -#endif -#ifndef GL_TESS_EVALUATION_SHADER -#define GL_TESS_EVALUATION_SHADER 0x8E87 -#endif -#ifndef GL_TESS_CONTROL_SHADER -#define GL_TESS_CONTROL_SHADER 0x8E88 -#endif -#ifndef GL_COMPUTE_SHADER -#define GL_COMPUTE_SHADER 0x91B9 -#endif - - -HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t),void* (*calloc_override)(size_t,size_t),void (*free_override)(void *),void* (*realloc_override)(void*,size_t)) -{ - hlslcc_malloc = malloc_override; - hlslcc_calloc = calloc_override; - hlslcc_free = free_override; - hlslcc_realloc = realloc_override; -} - -void AddIndentation(HLSLCrossCompilerContext* psContext) -{ - int i; - int indent = psContext->indent; - bstring glsl = *psContext->currentShaderString; - for(i=0; i < indent; ++i) - { - bcatcstr(glsl, " "); - } -} - -void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) -{ - bstring glsl = *psContext->currentShaderString; - - if(psContext->psShader->ui32MajorVersion > 3 && psContext->psShader->eTargetLanguage != LANG_ES_300 && psContext->psShader->eTargetLanguage != LANG_ES_310 && !(psContext->psShader->eTargetLanguage >= LANG_330)) - { - //DX10+ bycode format requires the ability to treat registers - //as raw bits. ES3.0+ has that built-in, also 330 onwards - bcatcstr(glsl,"#extension GL_ARB_shader_bit_encoding : require\n"); - } - - if(!HaveCompute(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->eShaderType == COMPUTE_SHADER) - { - bcatcstr(glsl,"#extension GL_ARB_compute_shader : enable\n"); - bcatcstr(glsl,"#extension GL_ARB_shader_storage_buffer_object : enable\n"); - } - } - - if (!HaveAtomicMem(psContext->psShader->eTargetLanguage) || - !HaveAtomicCounter(psContext->psShader->eTargetLanguage)) - { - if( psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_ALLOC] || - psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_CONSUME] || - psContext->psShader->aiOpcodeUsed[OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED]) - { - bcatcstr(glsl,"#extension GL_ARB_shader_atomic_counters : enable\n"); - - bcatcstr(glsl,"#extension GL_ARB_shader_storage_buffer_object : enable\n"); - } - } - - if(!HaveGather(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_C]) - { - bcatcstr(glsl,"#extension GL_ARB_texture_gather : enable\n"); - } - } - - if(!HaveGatherNonConstOffset(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || - psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO]) - { - bcatcstr(glsl,"#extension GL_ARB_gpu_shader5 : enable\n"); - } - } - - if(!HaveQueryLod(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->aiOpcodeUsed[OPCODE_LOD]) - { - bcatcstr(glsl,"#extension GL_ARB_texture_query_lod : enable\n"); - } - } - - if(!HaveQueryLevels(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->aiOpcodeUsed[OPCODE_RESINFO]) - { - bcatcstr(glsl,"#extension GL_ARB_texture_query_levels : enable\n"); - } - } - - if(!HaveImageLoadStore(psContext->psShader->eTargetLanguage)) - { - if(psContext->psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] || - psContext->psShader->aiOpcodeUsed[OPCODE_STORE_RAW] || - psContext->psShader->aiOpcodeUsed[OPCODE_STORE_STRUCTURED]) - { - bcatcstr(glsl,"#extension GL_ARB_shader_image_load_store : enable\n"); - bcatcstr(glsl,"#extension GL_ARB_shader_bit_encoding : enable\n"); - } - else - if(psContext->psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] || - psContext->psShader->aiOpcodeUsed[OPCODE_LD_RAW] || - psContext->psShader->aiOpcodeUsed[OPCODE_LD_STRUCTURED]) - { - bcatcstr(glsl,"#extension GL_ARB_shader_image_load_store : enable\n"); - } - } - - //The fragment language has no default precision qualifier for floating point types. - if (psContext->psShader->eShaderType == PIXEL_SHADER && - psContext->psShader->eTargetLanguage == LANG_ES_100 || psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision highp float;\n"); - } - - /* There is no default precision qualifier for the following sampler types in either the vertex or fragment language: */ - if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision lowp sampler3D;\n"); - bcatcstr(glsl, "precision lowp samplerCubeShadow;\n"); - bcatcstr(glsl, "precision lowp sampler2DShadow;\n"); - bcatcstr(glsl, "precision lowp sampler2DArray;\n"); - bcatcstr(glsl, "precision lowp sampler2DArrayShadow;\n"); - bcatcstr(glsl, "precision lowp isampler2D;\n"); - bcatcstr(glsl, "precision lowp isampler3D;\n"); - bcatcstr(glsl, "precision lowp isamplerCube;\n"); - bcatcstr(glsl, "precision lowp isampler2DArray;\n"); - bcatcstr(glsl, "precision lowp usampler2D;\n"); - bcatcstr(glsl, "precision lowp usampler3D;\n"); - bcatcstr(glsl, "precision lowp usamplerCube;\n"); - bcatcstr(glsl, "precision lowp usampler2DArray;\n"); - - if (psContext->psShader->eTargetLanguage == LANG_ES_310) - { - bcatcstr(glsl, "precision lowp isampler2DMS;\n"); - bcatcstr(glsl, "precision lowp usampler2D;\n"); - bcatcstr(glsl, "precision lowp usampler3D;\n"); - bcatcstr(glsl, "precision lowp usamplerCube;\n"); - bcatcstr(glsl, "precision lowp usampler2DArray;\n"); - bcatcstr(glsl, "precision lowp usampler2DMS;\n"); - bcatcstr(glsl, "precision lowp image2D;\n"); - bcatcstr(glsl, "precision lowp image3D;\n"); - bcatcstr(glsl, "precision lowp imageCube;\n"); - bcatcstr(glsl, "precision lowp image2DArray;\n"); - bcatcstr(glsl, "precision lowp iimage2D;\n"); - bcatcstr(glsl, "precision lowp iimage3D;\n"); - bcatcstr(glsl, "precision lowp iimageCube;\n"); - bcatcstr(glsl, "precision lowp uimage2DArray;\n"); - } - bcatcstr(glsl, "\n"); - } - - if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "subroutine void SubroutineType();\n"); - } - - if (psContext->psShader->ui32MajorVersion <= 3) - { - bcatcstr(glsl, "int RepCounter;\n"); - bcatcstr(glsl, "int LoopCounter;\n"); - bcatcstr(glsl, "int ZeroBasedCounter;\n"); - if (psContext->psShader->eShaderType == VERTEX_SHADER) - { - uint32_t texCoord; - bcatcstr(glsl, "ivec4 Address;\n"); - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "out vec4 OffsetColour;\n"); - bcatcstr(glsl, "out vec4 BaseColour;\n"); - - bcatcstr(glsl, "out vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "out vec4 TexCoord%d;\n", texCoord); - } - } - else - { - bcatcstr(glsl, "varying vec4 OffsetColour;\n"); - bcatcstr(glsl, "varying vec4 BaseColour;\n"); - - bcatcstr(glsl, "varying vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); - } - } - } - else - { - uint32_t renderTargets, texCoord; - - if (InOutSupported(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "in vec4 OffsetColour;\n"); - bcatcstr(glsl, "in vec4 BaseColour;\n"); - - bcatcstr(glsl, "in vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "in vec4 TexCoord%d;\n", texCoord); - } - } - else - { - bcatcstr(glsl, "varying vec4 OffsetColour;\n"); - bcatcstr(glsl, "varying vec4 BaseColour;\n"); - - bcatcstr(glsl, "varying vec4 Fog;\n"); - - for (texCoord = 0; texCoord < 8; ++texCoord) - { - bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); - } - } - - if (psContext->psShader->eTargetLanguage > LANG_120) - { - bcatcstr(glsl, "out vec4 outFragData[8];\n"); - for (renderTargets = 0; renderTargets < 8; ++renderTargets) - { - bformata(glsl, "#define Output%d outFragData[%d]\n", renderTargets, renderTargets); - } - } - else if (psContext->psShader->eTargetLanguage >= LANG_ES_300 && psContext->psShader->eTargetLanguage < LANG_120) - { - // ES 3 supports min 4 rendertargets, I guess this is reasonable lower limit for DX9 shaders - bcatcstr(glsl, "out vec4 outFragData[4];\n"); - for (renderTargets = 0; renderTargets < 4; ++renderTargets) - { - bformata(glsl, "#define Output%d outFragData[%d]\n", renderTargets, renderTargets); - } - } - else if (psContext->psShader->eTargetLanguage == LANG_ES_100) - { - bcatcstr(glsl, "#define Output0 gl_FragColor;\n"); - } - else - { - for (renderTargets = 0; renderTargets < 8; ++renderTargets) - { - bformata(glsl, "#define Output%d gl_FragData[%d]\n", renderTargets, renderTargets); - } - } - } - } - - if((psContext->flags & HLSLCC_FLAG_ORIGIN_UPPER_LEFT) - && (psContext->psShader->eTargetLanguage >= LANG_150)) - { - bcatcstr(glsl,"layout(origin_upper_left) in vec4 gl_FragCoord;\n"); - } - - if((psContext->flags & HLSLCC_FLAG_PIXEL_CENTER_INTEGER) - && (psContext->psShader->eTargetLanguage >= LANG_150)) - { - bcatcstr(glsl,"layout(pixel_center_integer) in vec4 gl_FragCoord;\n"); - } - - /* For versions which do not support a vec1 (currently all versions) */ - bcatcstr(glsl,"struct vec1 {\n"); - bcatcstr(glsl,"\tfloat x;\n"); - bcatcstr(glsl,"};\n"); - - if(HaveUVec(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl,"struct uvec1 {\n"); - bcatcstr(glsl,"\tuint x;\n"); - bcatcstr(glsl,"};\n"); - } - - bcatcstr(glsl,"struct ivec1 {\n"); - bcatcstr(glsl,"\tint x;\n"); - bcatcstr(glsl,"};\n"); - - /* - OpenGL 4.1 API spec: - To use any built-in input or output in the gl_PerVertex block in separable - program objects, shader code must redeclare that block prior to use. - */ - if(psContext->psShader->eShaderType == VERTEX_SHADER && psContext->psShader->eTargetLanguage >= LANG_410) - { - bcatcstr(glsl, "out gl_PerVertex {\n"); - bcatcstr(glsl, "vec4 gl_Position;\n"); - bcatcstr(glsl, "float gl_PointSize;\n"); - bcatcstr(glsl, "float gl_ClipDistance[];"); - bcatcstr(glsl, "};\n"); - } -} - -ShaderLang ChooseLanguage(ShaderData* psShader) -{ - // Depends on the HLSL shader model extracted from bytecode. - switch(psShader->ui32MajorVersion) - { - case 5: - { - return LANG_430; - } - case 4: - { - return LANG_330; - } - default: - { - return LANG_120; - } - } -} - -const char* GetVersionString(ShaderLang language) -{ - switch(language) - { - case LANG_ES_100: - { - return "#version 100\n"; - break; - } - case LANG_ES_300: - { - return "#version 300 es\n"; - break; - } - case LANG_ES_310: - { - return "#version 310 es\n"; - break; - } - case LANG_120: - { - return "#version 120\n"; - break; - } - case LANG_130: - { - return "#version 130\n"; - break; - } - case LANG_140: - { - return "#version 140\n"; - break; - } - case LANG_150: - { - return "#version 150\n"; - break; - } - case LANG_330: - { - return "#version 330\n"; - break; - } - case LANG_400: - { - return "#version 400\n"; - break; - } - case LANG_410: - { - return "#version 410\n"; - break; - } - case LANG_420: - { - return "#version 420\n"; - break; - } - case LANG_430: - { - return "#version 430\n"; - break; - } - case LANG_440: - { - return "#version 440\n"; - break; - } - default: - { - return ""; - break; - } - } -} - -void TranslateToGLSL(HLSLCrossCompilerContext* psContext, ShaderLang* planguage,const GlExtensions *extensions) -{ - bstring glsl; - uint32_t i; - ShaderData* psShader = psContext->psShader; - ShaderLang language = *planguage; - uint32_t ui32InstCount = 0; - uint32_t ui32DeclCount = 0; - - psContext->indent = 0; - - /*psShader->sPhase[MAIN_PHASE].ui32InstanceCount = 1; - psShader->sPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); - psShader->sPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); - psShader->sPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->sPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t));*/ - - if(language == LANG_DEFAULT) - { - language = ChooseLanguage(psShader); - *planguage = language; - } - - glsl = bfromcstralloc (1024, GetVersionString(language)); - - psContext->mainShader = glsl; - psContext->earlyMain = bfromcstralloc (1024, ""); - for(i=0; i<NUM_PHASES;++i) - { - psContext->postShaderCode[i] = bfromcstralloc (1024, ""); - } - psContext->currentShaderString = &glsl; - psShader->eTargetLanguage = language; - psShader->extensions = (const struct GlExtensions*)extensions; - psContext->currentPhase = MAIN_PHASE; - - if(extensions) - { - if(extensions->ARB_explicit_attrib_location) - bcatcstr(glsl,"#extension GL_ARB_explicit_attrib_location : require\n"); - if(extensions->ARB_explicit_uniform_location) - bcatcstr(glsl,"#extension GL_ARB_explicit_uniform_location : require\n"); - if(extensions->ARB_shading_language_420pack) - bcatcstr(glsl,"#extension GL_ARB_shading_language_420pack : require\n"); - } - - AddVersionDependentCode(psContext); - - if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) - { - bcatcstr(glsl, "layout(std140) uniform;\n"); - } - - //Special case. Can have multiple phases. - if(psShader->eShaderType == HULL_SHADER) - { - int haveInstancedForkPhase = 0; // Do we have an instanced fork phase? - int isCurrentForkPhasedInstanced = 0; // Is the current fork phase instanced? - const char* asPhaseFuncNames[NUM_PHASES]; - uint32_t ui32PhaseFuncCallOrder[3]; - uint32_t ui32PhaseCallIndex; - - uint32_t ui32Phase; - uint32_t ui32Instance; - - asPhaseFuncNames[MAIN_PHASE] = ""; - asPhaseFuncNames[HS_GLOBAL_DECL] = ""; - asPhaseFuncNames[HS_FORK_PHASE] = "fork_phase"; - asPhaseFuncNames[HS_CTRL_POINT_PHASE] = "control_point_phase"; - asPhaseFuncNames[HS_JOIN_PHASE] = "join_phase"; - - ConsolidateHullTempVars(psShader); - - for(i=0; i < psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]; ++i) - { - TranslateDeclaration(psContext, psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0]+i); - } - - for(ui32Phase=HS_CTRL_POINT_PHASE; ui32Phase<NUM_PHASES; ui32Phase++) - { - psContext->currentPhase = ui32Phase; - for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) - { - isCurrentForkPhasedInstanced = 0; //reset for each fork phase for cases we don't have a fork phase instance count opcode. - bformata(glsl, "//%s declarations\n", asPhaseFuncNames[ui32Phase]); - for(i=0; i < psShader->asPhase[ui32Phase].pui32DeclCount[ui32Instance]; ++i) - { - TranslateDeclaration(psContext, psShader->asPhase[ui32Phase].ppsDecl[ui32Instance]+i); - if(psShader->asPhase[ui32Phase].ppsDecl[ui32Instance][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) - { - haveInstancedForkPhase = 1; - isCurrentForkPhasedInstanced = 1; - } - } - - bformata(glsl, "void %s%d()\n{\n", asPhaseFuncNames[ui32Phase], ui32Instance); - psContext->indent++; - - SetDataTypes(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance], psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1); - - if(isCurrentForkPhasedInstanced) - { - AddIndentation(psContext); - bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", ui32Instance); - psContext->indent++; - } - - //The minus one here is remove the return statement at end of phases. - //This is needed otherwise the for loop will only run once. - ASSERT(psShader->asPhase[ui32Phase].ppsInst[ui32Instance] [psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1].eOpcode == OPCODE_RET); - for(i=0; i < psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1; ++i) - { - TranslateInstruction(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance]+i, NULL); - } - - if(haveInstancedForkPhase) - { - psContext->indent--; - AddIndentation(psContext); - - if(isCurrentForkPhasedInstanced) - { - bcatcstr(glsl, "}\n"); - } - - if(psContext->havePostShaderCode[psContext->currentPhase]) - { - #ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); - #endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); - #ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); - #endif - } - } - - psContext->indent--; - bcatcstr(glsl, "}\n"); - } - } - - bcatcstr(glsl, "void main()\n{\n"); - - psContext->indent++; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Start Early Main ---\n"); -#endif - bconcat(glsl, psContext->earlyMain); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End Early Main ---\n"); -#endif - - ui32PhaseFuncCallOrder[0] = HS_CTRL_POINT_PHASE; - ui32PhaseFuncCallOrder[1] = HS_FORK_PHASE; - ui32PhaseFuncCallOrder[2] = HS_JOIN_PHASE; - - for(ui32PhaseCallIndex=0; ui32PhaseCallIndex<3; ui32PhaseCallIndex++) - { - ui32Phase = ui32PhaseFuncCallOrder[ui32PhaseCallIndex]; - for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) - { - AddIndentation(psContext); - bformata(glsl, "%s%d();\n", asPhaseFuncNames[ui32Phase], ui32Instance); - - if(ui32Phase == HS_FORK_PHASE) - { - if(psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount || - (ui32Instance+1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) - { - AddIndentation(psContext); - bcatcstr(glsl, "barrier();\n"); - } - } - } - } - - psContext->indent--; - - bcatcstr(glsl, "}\n"); - - return; - } - - - ui32InstCount = psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; - ui32DeclCount = psShader->asPhase[MAIN_PHASE].pui32DeclCount[0]; - - for(i=0; i < ui32DeclCount; ++i) - { - TranslateDeclaration(psContext, psShader->asPhase[MAIN_PHASE].ppsDecl[0]+i); - } - - if(psContext->psShader->ui32NumDx9ImmConst) - { - bformata(psContext->mainShader, "vec4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); - } - - bcatcstr(glsl, "void main()\n{\n"); - - psContext->indent++; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Start Early Main ---\n"); -#endif - bconcat(glsl, psContext->earlyMain); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End Early Main ---\n"); -#endif - - MarkIntegerImmediates(psContext); - - SetDataTypes(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0], ui32InstCount); - - for(i=0; i < ui32InstCount; ++i) - { - TranslateInstruction(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0]+i, i+1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0]+i+1 : 0); - } - - psContext->indent--; - - bcatcstr(glsl, "}\n"); -} - -static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) -{ - uint32_t ui32Inst; - for(ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) - { - Instruction* psCurrentInst = &psInst[ui32Inst]; - const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; - uint32_t ui32Operand; - - for(ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) - { - uint32_t ui32SubOperand; - for(ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) - { - if(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) - { - hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); - psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; - } - } - } - } -} - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToGLSL(const char* shader, - unsigned int flags, - ShaderLang language, - const GlExtensions *extensions, - Shader* result) -{ - uint32_t* tokens; - ShaderData* psShader; - char* glslcstr = NULL; - int GLSLShaderType = GL_FRAGMENT_SHADER_ARB; - int success = 0; - uint32_t i; - - tokens = (uint32_t*)shader; - - psShader = DecodeDXBC(tokens); - - if(psShader) - { - HLSLCrossCompilerContext sContext; - - if(psShader->ui32MajorVersion <= 3) - { - flags &= ~HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS; - } - - sContext.psShader = psShader; - sContext.flags = flags; - - for(i=0; i<NUM_PHASES;++i) - { - sContext.havePostShaderCode[i] = 0; - } - - TranslateToGLSL(&sContext, &language,extensions); - - switch(psShader->eShaderType) - { - case VERTEX_SHADER: - { - GLSLShaderType = GL_VERTEX_SHADER_ARB; - break; - } - case GEOMETRY_SHADER: - { - GLSLShaderType = GL_GEOMETRY_SHADER; - break; - } - case DOMAIN_SHADER: - { - GLSLShaderType = GL_TESS_EVALUATION_SHADER; - break; - } - case HULL_SHADER: - { - GLSLShaderType = GL_TESS_CONTROL_SHADER; - break; - } - case COMPUTE_SHADER: - { - GLSLShaderType = GL_COMPUTE_SHADER; - break; - } - default: - { - break; - } - } - - glslcstr = bstr2cstr(sContext.mainShader, '\0'); - - bdestroy(sContext.mainShader); - bdestroy(sContext.earlyMain); - for(i=0; i<NUM_PHASES; ++i) - { - bdestroy(sContext.postShaderCode[i]); - } - - for(i=0; i<NUM_PHASES;++i) - { - if(psShader->asPhase[i].ppsDecl != 0) - { - uint32_t k; - for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) - { - hlslcc_free(psShader->asPhase[i].ppsDecl[k]); - } - hlslcc_free(psShader->asPhase[i].ppsDecl); - } - if(psShader->asPhase[i].ppsInst != 0) - { - uint32_t k; - for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) - { - FreeSubOperands(psShader->asPhase[i].ppsInst[k], psShader->asPhase[i].pui32InstCount[k]); - hlslcc_free(psShader->asPhase[i].ppsInst[k]); - } - hlslcc_free(psShader->asPhase[i].ppsInst); - } - } - - memcpy(&result->reflection,&psShader->sInfo,sizeof(psShader->sInfo)); - - result->textureSamplerInfo.ui32NumTextureSamplerPairs = psShader->textureSamplerInfo.ui32NumTextureSamplerPairs; - for (i=0; i<result->textureSamplerInfo.ui32NumTextureSamplerPairs; i++) - strcpy(result->textureSamplerInfo.aTextureSamplerPair[i].Name, psShader->textureSamplerInfo.aTextureSamplerPair[i].Name); - - hlslcc_free(psShader); - - success = 1; - } - - shader = 0; - tokens = 0; - - /* Fill in the result struct */ - - result->shaderType = GLSLShaderType; - result->sourceCode = glslcstr; - result->GLSLLanguage = language; - - return success; -} - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToGLSL(const char* filename, - unsigned int flags, - ShaderLang language, - const GlExtensions *extensions, - Shader* result) -{ - FILE* shaderFile; - int length; - size_t readLength; - char* shader; - int success = 0; - - shaderFile = fopen(filename, "rb"); - - if(!shaderFile) - { - return 0; - } - - fseek(shaderFile, 0, SEEK_END); - length = ftell(shaderFile); - fseek(shaderFile, 0, SEEK_SET); - - shader = (char*)hlslcc_malloc(length+1); - - readLength = fread(shader, 1, length, shaderFile); - - fclose(shaderFile); - shaderFile = 0; - - shader[readLength] = '\0'; - - success = TranslateHLSLFromMemToGLSL(shader, flags, language, extensions, result); - - hlslcc_free(shader); - - return success; -} - -HLSLCC_API void HLSLCC_APIENTRY FreeShader(Shader* s) -{ - bcstrfree(s->sourceCode); - s->sourceCode = NULL; - FreeShaderInfo(&s->reflection); -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c deleted file mode 100644 index 4d9195339f..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c +++ /dev/null @@ -1,2678 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "hlslcc.h" -#include "internal_includes/toGLSLDeclaration.h" -#include "internal_includes/toGLSLOperand.h" -#include "internal_includes/languages.h" -#include "bstrlib.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include <math.h> -#include <float.h> - -#ifdef _MSC_VER - #ifndef isnan - #define isnan(x) _isnan(x) - #endif - - #ifndef isinf - #define isinf(x) (!_finite(x)) - #endif -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) - -typedef enum { - GLVARTYPE_FLOAT, - GLVARTYPE_INT, - GLVARTYPE_FLOAT4, -} GLVARTYPE; - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -const char* GetTypeString(GLVARTYPE eType) -{ - switch(eType) - { - case GLVARTYPE_FLOAT: - { - return "float"; - } - case GLVARTYPE_INT: - { - return "int"; - } - case GLVARTYPE_FLOAT4: - { - return "vec4"; - } - default: - { - return ""; - } - } -} -const uint32_t GetTypeElementCount(GLVARTYPE eType) -{ - switch(eType) - { - case GLVARTYPE_FLOAT: - case GLVARTYPE_INT: - { - return 1; - } - case GLVARTYPE_FLOAT4: - { - return 4; - } - default: - { - return 0; - } - } -} - -void AddToDx9ImmConstIndexableArray(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - bstring* savedStringPtr = psContext->currentShaderString; - - psContext->currentShaderString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; - bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); - TranslateOperand(psContext, psOperand, TO_FLAG_NONE); - bcatcstr(psContext->earlyMain, ";\n"); - psContext->indent--; - psContext->psShader->ui32NumDx9ImmConst++; - - psContext->currentShaderString = savedStringPtr; -} - -void DeclareConstBufferShaderVariable(bstring glsl, const char* Name, const struct ShaderVarType_TAG* psType, int unsizedArray) - //const SHADER_VARIABLE_CLASS eClass, const SHADER_VARIABLE_TYPE eType, - //const char* pszName) -{ - if(psType->Class == SVC_STRUCT) - { - bformata(glsl, "\t%s_Type %s", Name, Name); - } - else if(psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) - { - switch(psType->Type) - { - case SVT_FLOAT: - { - bformata(glsl, "\tmat4 %s", Name); - break; - } - default: - { - ASSERT(0); - break; - } - } - if(psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - else - if(psType->Class == SVC_VECTOR) - { - switch(psType->Type) - { - case SVT_FLOAT: - { - bformata(glsl, "\tvec%d %s", psType->Columns, Name); - break; - } - case SVT_UINT: - { - bformata(glsl, "\tuvec%d %s", psType->Columns, Name); - break; - } - case SVT_INT: - { - bformata(glsl, "\tivec%d %s", psType->Columns, Name); - break; - } - case SVT_DOUBLE: - { - bformata(glsl, "\tdvec%d %s", psType->Columns, Name); - break; - } - case SVT_BOOL: - { - bformata(glsl, "\tbvec%d %s", psType->Columns, Name); - break; - } - default: - { - ASSERT(0); - break; - } - } - - if(psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - else - if(psType->Class == SVC_SCALAR) - { - switch(psType->Type) - { - case SVT_FLOAT: - { - bformata(glsl, "\tfloat %s", Name); - break; - } - case SVT_UINT: - { - bformata(glsl, "\tuint %s", Name); - break; - } - case SVT_INT: - { - bformata(glsl, "\tint %s", Name); - break; - } - case SVT_DOUBLE: - { - bformata(glsl, "\tdouble %s", Name); - break; - } - case SVT_BOOL: - { - //Use int instead of bool. - //Allows implicit conversions to integer and - //bool consumes 4-bytes in HLSL and GLSL anyway. - bformata(glsl, "\tint %s", Name); - // Also change the definition in the type tree. - ((ShaderVarType *)psType)->Type = SVT_INT; - break; - } - default: - { - ASSERT(0); - break; - } - } - - if(psType->Elements > 1) - { - bformata(glsl, "[%d]", psType->Elements); - } - } - if(unsizedArray) - bformata(glsl, "[]"); - bformata(glsl, ";\n"); -} - -//In GLSL embedded structure definitions are not supported. -void PreDeclareStructType(bstring glsl, const char* Name, const struct ShaderVarType_TAG* psType) -{ - uint32_t i; - - for(i=0; i<psType->MemberCount; ++i) - { - if(psType->Members[i].Class == SVC_STRUCT) - { - PreDeclareStructType(glsl, psType->Members[i].Name, &psType->Members[i]); - } - } - - if(psType->Class == SVC_STRUCT) - { -#if defined(_DEBUG) - uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; -#endif - //Not supported at the moment - ASSERT(!unnamed_struct); - - bformata(glsl, "struct %s_Type {\n", Name); - - for(i=0; i<psType->MemberCount; ++i) - { - ASSERT(psType->Members != 0); - - DeclareConstBufferShaderVariable(glsl, psType->Members[i].Name, &psType->Members[i], 0); - } - - bformata(glsl, "};\n"); - } -} - -const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) -{ - bstring inputName; - char* cstr; - InOutSignature* psIn; - int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn); - - if((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && found) - { - if (eShaderType == VERTEX_SHADER) /* We cannot have input and output names conflict, but vs output must match ps input. Prefix vs input. */ - inputName = bformat("in_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); - else - inputName = bformat("%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); - } - else if(eShaderType == GEOMETRY_SHADER) - { - inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else if(eShaderType == HULL_SHADER) - { - inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - else if(eShaderType == DOMAIN_SHADER) - { - inputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); - } - else if(eShaderType == PIXEL_SHADER) - { - if(psContext->flags & HLSLCC_FLAG_TESS_ENABLED) - { - inputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); - } - else - { - inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - } - else - { - ASSERT(eShaderType == VERTEX_SHADER); - inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); - } - if((psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) && found) - { - bformata(inputName,"_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); - } - - cstr = bstr2cstr(inputName, '\0'); - bdestroy(inputName); - return cstr; -} - -const char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, - const SHADER_TYPE eShaderType, - const Operand* psOperand, - int* piStream) -{ - bstring outputName; - char* cstr; - InOutSignature* psOut; - -#if defined(_DEBUG) - int foundOutput = -#endif - GetOutputSignatureFromRegister( - psContext->currentPhase, - psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - psContext->psShader->ui32CurrentVertexOutputStream, - &psContext->psShader->sInfo, - &psOut); - - ASSERT(foundOutput); - - if(psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) - { - outputName = bformat("%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); - } - else if(eShaderType == GEOMETRY_SHADER) - { - if(psOut->ui32Stream != 0) - { - outputName = bformat("VtxGeoOutput%d_S%d", psOperand->ui32RegisterNumber, psOut->ui32Stream); - piStream[0] = psOut->ui32Stream; - } - else - { - outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - - } - else if(eShaderType == DOMAIN_SHADER) - { - outputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); - } - else if(eShaderType == VERTEX_SHADER) - { - if(psContext->flags & HLSLCC_FLAG_GS_ENABLED) - { - outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else - { - outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); - } - } - else if(eShaderType == PIXEL_SHADER) - { - outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); - } - else - { - ASSERT(eShaderType == HULL_SHADER); - outputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); - } - if(psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) - { - bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); - } - - cstr = bstr2cstr(outputName, '\0'); - bdestroy(outputName); - return cstr; -} - -const char* GetInterpolationString(INTERPOLATION_MODE eMode) -{ - switch(eMode) - { - case INTERPOLATION_CONSTANT: - { - return "flat"; - } - case INTERPOLATION_LINEAR: - { - return ""; - } - case INTERPOLATION_LINEAR_CENTROID: - { - return "centroid"; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE: - { - return "noperspective"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: - { - return "noperspective centroid"; - } - case INTERPOLATION_LINEAR_SAMPLE: - { - return "sample"; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: - { - return "noperspective sample"; - } - default: - { - return ""; - } - } -} - -static void DeclareInput( - HLSLCrossCompilerContext* psContext, - const Declaration* psDecl, - const char* Interpolation, const char* StorageQualifier, const char* Precision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) -{ - ShaderData* psShader = psContext->psShader; - bstring glsl = *psContext->currentShaderString; - - // This falls within the specified index ranges. The default is 0 if no input range is specified - if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - return; - - if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - const char* vecType = "vec"; - const char* scalarType = "float"; - InOutSignature* psSignature = NULL; - - if( GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature) ) - { - switch(psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - vecType = "uvec"; - scalarType = "uint"; - break; - } - case INOUT_COMPONENT_SINT32: - { - vecType = "ivec"; - scalarType = "int"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - } - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || - (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) - { - // Skip location if requested by the flags. - if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - switch(eIndexDim) - { - case INDEX_2D: - { - if(iNumComponents == 1) - { - const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; - - bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, - arraySize); - - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; - } - else - { - bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, - psDecl->asOperands[0].aui32ArraySizes[0]); - - bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].aui32ArraySizes[0]); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; - } - break; - } - default: - { - - if(psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) - { - InputName = "TexCoord"; - } - - if(iNumComponents == 1) - { - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; - - bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); - bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - else - { - if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) - { - bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; - } - else - { - bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); - bformata(glsl, "%s%d Input%d;\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - } - break; - } - } - } - - if(psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) - { - psContext->currentShaderString = &psContext->earlyMain; - psContext->indent++; - - if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array - { - AddIndentation(psContext); - bformata(psContext->earlyMain, "Input%d = %s;\n", psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else - { - int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; - - while(arrayIndex) - { - AddIndentation(psContext); - bformata(psContext->earlyMain, "Input%d[%d] = %s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex-1, - InputName, arrayIndex-1); - - arrayIndex--; - } - } - psContext->indent--; - psContext->currentShaderString = &psContext->mainShader; - } -} - -void AddBuiltinInput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName) -{ - bstring glsl = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, &psDecl->asOperands[0]); - switch(eType) - { - case SVT_INT: - bformata(glsl, "ivec4 "); - break; - case SVT_UINT: - bformata(glsl, "uvec4 "); - break; - case SVT_BOOL: - bformata(glsl, "bvec4 "); - break; - default: - bformata(glsl, "vec4 "); - break; - } - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, ";\n"); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; - } - else - { - //This register has already been declared. The HLSL bytecode likely looks - //something like this then: - // dcl_input_ps constant v3.x - // dcl_input_ps_sgv v3.y, primitive_id - - //GLSL does not allow assignment to a varying! - } - - psContext->currentShaderString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_DESTINATION); - - bformata(psContext->earlyMain, " = %s", builtinName); - - switch(psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); - break; - default: - //Scalar built-in. Don't apply swizzle. - break; - } - bcatcstr(psContext->earlyMain, ";\n"); - - psContext->indent--; - psContext->currentShaderString = &psContext->mainShader; -} - -int OutputNeedsDeclaring(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) -{ - ShaderData* psShader = psContext->psShader; - const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; - if(psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) - { - int offset; - - for(offset = 0; offset < count; offset++) - { - psShader->aiOutputDeclared[psOperand->ui32RegisterNumber+offset] = declared; - } - return 1; - } - - if(psShader->eShaderType == PIXEL_SHADER) - { - if(psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL) - { - return 1; - } - } - - return 0; -} - -void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) -{ - bstring glsl = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) - { - InOutSignature* psSignature = NULL; - - GetOutputSignatureFromRegister( - psContext->currentPhase, - psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].ui32CompMask, - 0, - &psShader->sInfo, &psSignature); - - bcatcstr(glsl, "#undef "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "\n"); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, " phase%d_", psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "\n"); - - switch (type) - { - case GLVARTYPE_INT: - bcatcstr(glsl, "ivec4 "); - break; - default: - bcatcstr(glsl, "vec4 "); - } - - bformata(glsl, "phase%d_", psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - if(arrayElements) - bformata(glsl, "[%d];\n", arrayElements); - else - bcatcstr(glsl, ";\n"); - - psContext->currentShaderString = &psContext->postShaderCode[psContext->currentPhase]; - glsl = *psContext->currentShaderString; - psContext->indent++; - if(arrayElements) - { - int elem; - for(elem = 0; elem < arrayElements; elem++) - { - AddIndentation(psContext); - bformata(glsl, "%s[%d] = %s(phase%d_", builtinName, elem, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); - bformata(glsl, "[%d]", elem); - TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); - bformata(glsl, ");\n"); - } - } - else - { - - if(psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) - { - int max = GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); - - int applySiwzzle = GetNumSwizzleElements(&psDecl->asOperands[0]) > 1 ? 1 : 0; - int index; - int i; - int multiplier = 1; - char* swizzle[] = {".x", ".y", ".z", ".w"}; - - ASSERT(psSignature!=NULL); - - index = psSignature->ui32SemanticIndex; - - //Clip distance can be spread across 1 or 2 outputs (each no more than a vec4). - //Some examples: - //float4 clip[2] : SV_ClipDistance; //8 clip distances - //float3 clip[2] : SV_ClipDistance; //6 clip distances - //float4 clip : SV_ClipDistance; //4 clip distances - //float clip : SV_ClipDistance; //1 clip distance. - - //In GLSL the clip distance built-in is an array of up to 8 floats. - //So vector to array conversion needs to be done here. - if(index == 1) - { - InOutSignature* psFirstClipSignature; - if(GetOutputSignatureFromSystemValue(NAME_CLIP_DISTANCE, 1, &psShader->sInfo, &psFirstClipSignature)) - { - if(psFirstClipSignature->ui32Mask & (1 << 3)) - { - multiplier = 4; - } - else - if(psFirstClipSignature->ui32Mask & (1 << 2)) - { - multiplier = 3; - } - else - if(psFirstClipSignature->ui32Mask & (1 << 1)) - { - multiplier = 2; - } - } - } - - for(i=0; i<max; ++i) - { - AddIndentation(psContext); - bformata(glsl, "%s[%d] = (phase%d_", builtinName, i + multiplier*index, psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - if(applySiwzzle) - { - bformata(glsl, ")%s;\n", swizzle[i]); - } - else - { - bformata(glsl, ");\n"); - } - } - } - else - { - uint32_t elements = GetNumSwizzleElements(&psDecl->asOperands[0]); - - if(elements != GetTypeElementCount(type)) - { - //This is to handle float3 position seen in control point phases - //struct HS_OUTPUT - //{ - // float3 vPosition : POSITION; - //}; -> dcl_output o0.xyz - //gl_Position is vec4. - AddIndentation(psContext); - bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, ", 1);\n"); - } - else - { - AddIndentation(psContext); - bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); - TranslateOperand(psContext, &psDecl->asOperands[0], type == GLVARTYPE_INT ? TO_FLAG_INTEGER : TO_FLAG_NONE); - bformata(glsl, ");\n"); - } - } - } - psContext->indent--; - psContext->currentShaderString = &psContext->mainShader; - } -} - -void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) -{ - bstring glsl = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - const char* Precision = ""; - const char* type = "vec"; - - InOutSignature* psSignature = NULL; - - GetOutputSignatureFromRegister( - psContext->currentPhase, - psDecl->asOperands[0].ui32RegisterNumber, - psDecl->asOperands[0].ui32CompMask, - psShader->ui32CurrentVertexOutputStream, - &psShader->sInfo, - &psSignature); - - switch(psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uvec"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "ivec"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - - if(HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch(psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - //type = "ivec"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - //type = "uvec"; - break; - } - } - } - - switch(psShader->eShaderType) - { - case PIXEL_SHADER: - { - switch(psDecl->asOperands[0].eType) - { - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - case OPERAND_TYPE_OUTPUT_DEPTH: - { - - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - { - bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); - bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); - bcatcstr(glsl, "layout (depth_greater) out float gl_FragDepth;\n"); - bcatcstr(glsl, "#endif\n"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); - bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); - bcatcstr(glsl, "layout (depth_less) out float gl_FragDepth;\n"); - bcatcstr(glsl, "#endif\n"); - break; - } - default: - { - if(WriteToFragData(psContext->psShader->eTargetLanguage)) - { - bformata(glsl, "#define Output%d gl_FragData[%d]\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); - } - else - { - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, PIXEL_SHADER, psOperand, &stream); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags)) - { - uint32_t index = 0; - uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; - - if((psContext->flags & HLSLCC_FLAG_DUAL_SOURCE_BLENDING) && DualSourceBlendSupported(psContext->psShader->eTargetLanguage)) - { - if(renderTarget > 0) - { - renderTarget = 0; - index = 1; - } - bformata(glsl, "layout(location = %d, index = %d) ", renderTarget, index); - } - else - { - bformata(glsl, "layout(location = %d) ", renderTarget); - } - } - - bformata(glsl, "out %s %s4 %s;\n", Precision, type, OutputName); - if(stream) - { - bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); - } - else - { - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - } - } - break; - } - } - break; - } - case VERTEX_SHADER: - { - int iNumComponents = 4;//GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); - const char* Interpolation = ""; - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - if(InOutSupported(psContext->psShader->eTargetLanguage)) - { - bformata(glsl, "%s out %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); - } - else - { - bformata(glsl, "%s varying %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); - } - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - - break; - } - case GEOMETRY_SHADER: - { - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, GEOMETRY_SHADER, psOperand, &stream); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - bformata(glsl, "out %s4 %s;\n", type, OutputName); - if(stream) - { - bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); - } - else - { - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - } - break; - } - case HULL_SHADER: - { - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, HULL_SHADER, psOperand, &stream); - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber!=0);//Reg 0 should be gl_out[gl_InvocationID].gl_Position. - - if(psContext->currentPhase == HS_JOIN_PHASE) - { - bformata(glsl, "out patch %s4 %s[];\n", type, OutputName); - } - else - { - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - bformata(glsl, "out %s4 %s[];\n", type, OutputName); - } - bformata(glsl, "#define Output%d %s[gl_InvocationID]\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - break; - } - case DOMAIN_SHADER: - { - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, DOMAIN_SHADER, psOperand, &stream); - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - bformata(glsl, "out %s4 %s;\n", type, OutputName); - bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - break; - } - } - } - else - { - /* - Multiple outputs can be packed into one register. e.g. - // Name Index Mask Register SysValue Format Used - // -------------------- ----- ------ -------- -------- ------- ------ - // FACTOR 0 x 3 NONE int x - // MAX 0 y 3 NONE int y - - We want unique outputs to make it easier to use transform feedback. - - out ivec4 FACTOR0; - #define Output3 FACTOR0 - out ivec4 MAX0; - - MAIN SHADER CODE. Writes factor and max to Output3 which aliases FACTOR0. - - MAX0.x = FACTOR0.y; - - This unpacking of outputs is only done when using HLSLCC_FLAG_INOUT_SEMANTIC_NAMES/HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES. - When not set the application will be using HLSL reflection information to discover - what the input and outputs mean if need be. - */ - - // - - if((psContext->flags & (HLSLCC_FLAG_INOUT_SEMANTIC_NAMES|HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES)) && (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - InOutSignature* psSignature = NULL; - const char* type = "vec"; - int stream = 0; - const char* OutputName = GetDeclaredOutputName(psContext, psShader->eShaderType, psOperand, &stream); - - GetOutputSignatureFromRegister( - psContext->currentPhase, - psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - 0, - &psShader->sInfo, - &psSignature); - - if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - if (!((psShader->eShaderType == VERTEX_SHADER) && (psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS))) - bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); - } - - switch(psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uvec"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "ivec"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - bformata(glsl, "out %s4 %s;\n", type, OutputName); - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - psContext->currentShaderString = &psContext->postShaderCode[psContext->currentPhase]; - glsl = *psContext->currentShaderString; - - bcatcstr(glsl, OutputName); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); - bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); - TranslateOperandSwizzle(psContext, psOperand); - bcatcstr(glsl, ";\n"); - - psContext->currentShaderString = &psContext->mainShader; - glsl = *psContext->currentShaderString; - } - } -} - -void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, - bstring glsl) -{ - uint32_t i; - const char* Name = psCBuf->Name; - if(psCBuf->Name[0] == '$') //For $Globals - { - Name++; - } - - for(i=0; i < psCBuf->ui32NumVars; ++i) - { - PreDeclareStructType(glsl, - psCBuf->asVars[i].Name, - &psCBuf->asVars[i].sType); - } - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); - - bformata(glsl, "uniform %s {\n ", Name); - - for(i=0; i < psCBuf->ui32NumVars; ++i) - { - DeclareConstBufferShaderVariable(glsl, - psCBuf->asVars[i].Name, - &psCBuf->asVars[i].sType, 0); - } - - bcatcstr(glsl, "};\n"); -} - -void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, const Operand* psOperand, - const uint32_t ui32GloballyCoherentAccess, - const ResourceType eResourceType, - bstring glsl) -{ - bstring StructName; -#if defined(_DEBUG) - uint32_t unnamed_struct = -#endif - strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; - - ASSERT(psCBuf->ui32NumVars == 1); - ASSERT(unnamed_struct); - - StructName = bfromcstr(""); - - //TranslateOperand(psContext, psOperand, TO_FLAG_NAME_ONLY); - if(psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) - { - bformata(StructName, "StructuredRes%d", psOperand->ui32RegisterNumber); - } - else if(psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) - { - bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); - } - else - { - ResourceName(StructName, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); - } - - PreDeclareStructType(glsl, - bstr2cstr(StructName, '\0'), - &psCBuf->asVars[0].sType); - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); - - if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) - { - bcatcstr(glsl, "coherent "); - } - - if(eResourceType == RTYPE_STRUCTURED) - { - bcatcstr(glsl, "readonly "); - } - - bformata(glsl, "buffer Block%d {\n", psOperand->ui32RegisterNumber); - - DeclareConstBufferShaderVariable(glsl, - bstr2cstr(StructName, '\0'), - &psCBuf->asVars[0].sType, - 1); - - bcatcstr(glsl, "};\n"); - - bdestroy(StructName); -} - - -void DeclareStructConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, const Operand* psOperand, - bstring glsl) -{ - uint32_t i; - int useGlobalsStruct = 1; - - if(psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT && psCBuf->Name[0] == '$') - useGlobalsStruct = 0; - - if(useGlobalsStruct) - { - for(i=0; i < psCBuf->ui32NumVars; ++i) - { - PreDeclareStructType(glsl, - psCBuf->asVars[i].Name, - &psCBuf->asVars[i].sType); - } - } - - /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(location = %d) ", ui32BindingPoint); - if(useGlobalsStruct) - { - bcatcstr(glsl, "uniform struct "); - TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); - - bcatcstr(glsl, "_Type {\n"); - } - - for(i=0; i < psCBuf->ui32NumVars; ++i) - { - if(!useGlobalsStruct) - bcatcstr(glsl, "uniform "); - - DeclareConstBufferShaderVariable(glsl, - psCBuf->asVars[i].Name, - &psCBuf->asVars[i].sType, 0); - } - - if(useGlobalsStruct) - { - bcatcstr(glsl, "} "); - - TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); - - bcatcstr(glsl, ";\n"); -} -} - -char* GetSamplerType(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eDimension, - const uint32_t ui32RegisterNumber) -{ - ResourceBinding* psBinding = 0; - RESOURCE_RETURN_TYPE eType = RETURN_TYPE_UNORM; - int found; - found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - if(found) - { - eType = (RESOURCE_RETURN_TYPE)psBinding->ui32ReturnType; - } - switch(eDimension) - { - case RESOURCE_DIMENSION_BUFFER: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isamplerBuffer"; - case RETURN_TYPE_UINT: - return "usamplerBuffer"; - default: - return "samplerBuffer"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE1D: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler1D"; - case RETURN_TYPE_UINT: - return "usampler1D"; - default: - return "sampler1D"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2D: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler2D"; - case RETURN_TYPE_UINT: - return "usampler2D"; - default: - return "sampler2D"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler2DMS"; - case RETURN_TYPE_UINT: - return "usampler2DMS"; - default: - return "sampler2DMS"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE3D: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler3D"; - case RETURN_TYPE_UINT: - return "usampler3D"; - default: - return "sampler3D"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURECUBE: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isamplerCube"; - case RETURN_TYPE_UINT: - return "usamplerCube"; - default: - return "samplerCube"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler1DArray"; - case RETURN_TYPE_UINT: - return "usampler1DArray"; - default: - return "sampler1DArray"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler2DArray"; - case RETURN_TYPE_UINT: - return "usampler2DArray"; - default: - return "sampler2DArray"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isampler2DMSArray"; - case RETURN_TYPE_UINT: - return "usampler2DMSArray"; - default: - return "sampler2DMSArray"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - switch(eType) - { - case RETURN_TYPE_SINT: - return "isamplerCubeArray"; - case RETURN_TYPE_UINT: - return "usamplerCubeArray"; - default: - return "samplerCubeArray"; - } - break; - } - } - - return "sampler2D"; -} - -static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, uint32_t samplerCanDoShadowCmp) -{ - bstring glsl = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - uint32_t i; - - const char* samplerTypeName = GetSamplerType(psContext, - psDecl->value.eResourceDimension, - psDecl->asOperands[0].ui32RegisterNumber); - - if (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) - { - if(samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) - { - for (i = 0; i < psDecl->ui32SamplerUsedCount; i++) - { - bcatcstr(glsl, "uniform "); - bcatcstr(glsl, samplerTypeName); - bcatcstr(glsl, "Shadow "); - ConcatTextureSamplerName(glsl, &psShader->sInfo, psDecl->asOperands[0].ui32RegisterNumber, psDecl->ui32SamplerUsed[i], 1); - bcatcstr(glsl, ";\n"); - } - } - for (i = 0; i < psDecl->ui32SamplerUsedCount; i++) - { - bcatcstr(glsl, "uniform "); - bcatcstr(glsl, samplerTypeName); - bcatcstr(glsl, " "); - ConcatTextureSamplerName(glsl, &psShader->sInfo, psDecl->asOperands[0].ui32RegisterNumber, psDecl->ui32SamplerUsed[i], 0); - bcatcstr(glsl, ";\n"); - } - } - - if(samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) - { - //Create shadow and non-shadow sampler. - //HLSL does not have separate types for depth compare, just different functions. - - bcatcstr(glsl, "uniform "); - bcatcstr(glsl, samplerTypeName); - bcatcstr(glsl, "Shadow "); - ResourceName(glsl, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 1); - bcatcstr(glsl, ";\n"); - } - - bcatcstr(glsl, "uniform "); - bcatcstr(glsl, samplerTypeName); - bcatcstr(glsl, " "); - ResourceName(glsl, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 0); - bcatcstr(glsl, ";\n"); -} - -void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) -{ - bstring glsl = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - switch(psDecl->eOpcode) - { - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_PS_SGV: - { - const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; - switch(eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinInput(psContext, psDecl, "gl_Position"); - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_Layer"); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinInput(psContext, psDecl, "gl_ClipDistance"); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_ViewportIndex"); - break; - } - case NAME_INSTANCE_ID: - { - AddBuiltinInput(psContext, psDecl, "gl_InstanceID"); - break; - } - case NAME_IS_FRONT_FACE: - { - /* - Cast to int used because - if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. - Suggests no implicit conversion for bool<->int. - */ - - AddBuiltinInput(psContext, psDecl, "int(gl_FrontFacing)"); - break; - } - case NAME_SAMPLE_INDEX: - { - AddBuiltinInput(psContext, psDecl, "gl_SampleID"); - break; - } - case NAME_VERTEX_ID: - { - AddBuiltinInput(psContext, psDecl, "gl_VertexID"); - break; - } - case NAME_PRIMITIVE_ID: - { - AddBuiltinInput(psContext, psDecl, "gl_PrimitiveID"); - break; - } - default: - { - bformata(glsl, "in vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); - break; - } - } - break; - } - - case OPCODE_DCL_OUTPUT_SIV: - { - switch(psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_Position"); - break; - } - case NAME_RENDER_TARGET_ARRAY_INDEX: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_Layer"); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_ClipDistance"); - break; - } - case NAME_VIEWPORT_ARRAY_INDEX: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_ViewportIndex"); - break; - } - case NAME_VERTEX_ID: - { - ASSERT(0); //VertexID is not an output - break; - } - case NAME_PRIMITIVE_ID: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_PrimitiveID"); - break; - } - case NAME_INSTANCE_ID: - { - ASSERT(0); //InstanceID is not an output - break; - } - case NAME_IS_FRONT_FACE: - { - ASSERT(0); //FrontFacing is not an output - break; - } - case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: - { - if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 4, "gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); - break; - } - case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[3]"); - break; - } - case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: - { - if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 3,"gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); - break; - } - case NAME_FINAL_LINE_DENSITY_TESSFACTOR: - { - if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelOuter"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); - } - break; - } - case NAME_FINAL_LINE_DETAIL_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); - break; - } - case NAME_FINAL_TRI_INSIDE_TESSFACTOR: - case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: - { - if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelInner"); - } - else - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[0]"); - } - break; - } - case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[1]"); - break; - } - default: - { - bformata(glsl, "out vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); - - bcatcstr(glsl, "#define "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); - break; - } - } - break; - } - case OPCODE_DCL_INPUT: - { - const Operand* psOperand = &psDecl->asOperands[0]; - //Force the number of components to be 4. -/*dcl_output o3.xy - dcl_output o3.z - -Would generate a vec2 and a vec3. We discard the second one making .z invalid! - -*/ - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); - const char* StorageQualifier = "attribute"; - const char* InputName; - const char* Precision = ""; - - if((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT)|| - (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID)|| - (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK)|| - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID)|| - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID)|| - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP)|| - (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED) || - (psOperand->eType == OPERAND_TYPE_INPUT_FORK_INSTANCE_ID)) - { - break; - } - - //Already declared as part of an array. - if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - break; - } - - InputName = GetDeclaredInputName(psContext, psShader->eShaderType, psOperand); - - if(InOutSupported(psContext->psShader->eTargetLanguage)) - { - StorageQualifier = "in"; - } - - if(HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch(psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - break; - } - } - } - - DeclareInput(psContext, psDecl, - "", StorageQualifier, Precision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); - - break; - } - case OPCODE_DCL_INPUT_PS_SIV: - { - switch(psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinInput(psContext, psDecl, "gl_FragCoord"); - break; - } - } - break; - } - case OPCODE_DCL_INPUT_SIV: - { - break; - } - case OPCODE_DCL_INPUT_PS: - { - const Operand* psOperand = &psDecl->asOperands[0]; - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); - const char* StorageQualifier = "varying"; - const char* Precision = ""; - const char* InputName = GetDeclaredInputName(psContext, PIXEL_SHADER, psOperand); - const char* Interpolation = ""; - - if(InOutSupported(psContext->psShader->eTargetLanguage)) - { - StorageQualifier = "in"; - } - - switch(psDecl->value.eInterpolation) - { - case INTERPOLATION_CONSTANT: - { - Interpolation = "flat"; - break; - } - case INTERPOLATION_LINEAR: - { - break; - } - case INTERPOLATION_LINEAR_CENTROID: - { - Interpolation = "centroid"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE: - { - Interpolation = "noperspective"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: - { - Interpolation = "noperspective centroid"; - break; - } - case INTERPOLATION_LINEAR_SAMPLE: - { - Interpolation = "sample"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: - { - Interpolation = "noperspective sample"; - break; - } - } - - if(HavePrecisionQualifers(psShader->eTargetLanguage)) - { - switch(psOperand->eMinPrecision) - { - case OPERAND_MIN_PRECISION_DEFAULT: - { - Precision = "highp"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_FLOAT_2_8: - { - Precision = "lowp"; - break; - } - case OPERAND_MIN_PRECISION_SINT_16: - { - Precision = "mediump"; - break; - } - case OPERAND_MIN_PRECISION_UINT_16: - { - Precision = "mediump"; - break; - } - } - } - - DeclareInput(psContext, psDecl, - Interpolation, StorageQualifier, Precision, iNumComponents, INDEX_1D, InputName); - - break; - } - case OPCODE_DCL_TEMPS: - { - const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; - - if(ui32NumTemps > 0) - { - bformata(glsl, "vec4 Temp[%d];\n", ui32NumTemps); - - bformata(glsl, "ivec4 Temp_int[%d];\n", ui32NumTemps); - if(HaveUVec(psShader->eTargetLanguage)) - { - bformata(glsl, "uvec4 Temp_uint[%d];\n", ui32NumTemps); - } - if(psShader->fp64) - { - bformata(glsl, "dvec4 Temp_double[%d];\n", ui32NumTemps); - } - } - - break; - } - case OPCODE_SPECIAL_DCL_IMMCONST: - { - const Operand* psDest = &psDecl->asOperands[0]; - const Operand* psSrc = &psDecl->asOperands[1]; - - ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); - if(psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) - { - bformata(glsl, "const ivec4 IntImmConst%d = ", psDest->ui32RegisterNumber); - } - else - { - bformata(glsl, "const vec4 ImmConst%d = ", psDest->ui32RegisterNumber); - AddToDx9ImmConstIndexableArray(psContext, psDest); - } - TranslateOperand(psContext, psSrc, psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT ? TO_FLAG_INTEGER : TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(glsl, ";\n"); - - break; - } - case OPCODE_DCL_CONSTANT_BUFFER: - { - const Operand* psOperand = &psDecl->asOperands[0]; - const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; - - const char* StageName = "VS"; - - switch(psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - StageName = "PS"; - break; - } - case HULL_SHADER: - { - StageName = "HS"; - break; - } - case DOMAIN_SHADER: - { - StageName = "DS"; - break; - } - case GEOMETRY_SHADER: - { - StageName = "GS"; - break; - } - case COMPUTE_SHADER: - { - StageName = "CS"; - break; - } - default: - { - break; - } - } - - ConstantBuffer* psCBuf = NULL; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - if (psCBuf) - { - // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. - // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads - // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. - psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; - } - - // We don't have a original resource name, maybe generate one??? - if(!psCBuf) - { - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - bformata(glsl, "layout(location = %d) ",ui32BindingPoint); - - bformata(glsl, "layout(std140) uniform ConstantBuffer%d {\n\tvec4 data[%d];\n} cb%d;\n", ui32BindingPoint,psOperand->aui32ArraySizes[1],ui32BindingPoint); - break; - } - else if (psCBuf->blob) - { - bformata(glsl, "layout(std140) uniform %s%s {\n\tvec4 %s%s_data[%d];\n};\n", psCBuf->Name, StageName, psCBuf->Name, StageName, psOperand->aui32ArraySizes[1]); - break; - } - - if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) - { - if(psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO && psCBuf->Name[0] == '$') - { - DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand, glsl); - } - else - { - DeclareUBOConstants(psContext, ui32BindingPoint, psCBuf, glsl); - } - } - else - { - DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand, glsl); - } - break; - } - case OPCODE_DCL_RESOURCE: - { - if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) - { - // Explicit layout bindings are not currently compatible with combined texture samplers. The layout below assumes there is exactly one GLSL sampler - // for each HLSL texture declaration, but when combining textures+samplers, there can be multiple OGL samplers for each HLSL texture declaration. - if((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) - { - //Constant buffer locations start at 0. Resource locations start at ui32NumConstantBuffers. - bformata(glsl, "layout(location = %d) ", - psContext->psShader->sInfo.ui32NumConstantBuffers + psDecl->asOperands[0].ui32RegisterNumber); - } - } - - switch(psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_BUFFER: - { - bformata(glsl, "uniform %s ", GetSamplerType(psContext, - RESOURCE_DIMENSION_BUFFER, - psDecl->asOperands[0].ui32RegisterNumber)); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); - break; - } - case RESOURCE_DIMENSION_TEXTURE1D: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - TranslateResourceTexture(psContext, psDecl, 0); - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - TranslateResourceTexture(psContext, psDecl, 0); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - TranslateResourceTexture(psContext, psDecl, 0); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - } - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); - psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; - break; - } - case OPCODE_DCL_OUTPUT: - { - if(psShader->eShaderType == HULL_SHADER && psDecl->asOperands[0].ui32RegisterNumber==0) - { - AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_out[gl_InvocationID].gl_Position"); - } - else - { - AddUserOutput(psContext, psDecl); - } - break; - } - case OPCODE_DCL_GLOBAL_FLAGS: - { - uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; - - if(ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL) - { - bcatcstr(glsl, "layout(early_fragment_tests) in;\n"); - } - if(!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) - { - //TODO add precise - //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx - } - if(ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) - { - bcatcstr(glsl, "#extension GL_ARB_gpu_shader_fp64 : enable\n"); - psShader->fp64 = 1; - } - break; - } - - case OPCODE_DCL_THREAD_GROUP: - { - bformata(glsl, "layout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\n", - psDecl->value.aui32WorkGroupSize[0], - psDecl->value.aui32WorkGroupSize[1], - psDecl->value.aui32WorkGroupSize[2]); - break; - } - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - { - if(psContext->psShader->eShaderType == HULL_SHADER) - { - psContext->psShader->sInfo.eTessOutPrim = psDecl->value.eTessOutPrim; - } - break; - } - case OPCODE_DCL_TESS_DOMAIN: - { - if(psContext->psShader->eShaderType == DOMAIN_SHADER) - { - switch(psDecl->value.eTessDomain) - { - case TESSELLATOR_DOMAIN_ISOLINE: - { - bcatcstr(glsl, "layout(isolines) in;\n"); - break; - } - case TESSELLATOR_DOMAIN_TRI: - { - bcatcstr(glsl, "layout(triangles) in;\n"); - break; - } - case TESSELLATOR_DOMAIN_QUAD: - { - bcatcstr(glsl, "layout(quads) in;\n"); - break; - } - default: - { - break; - } - } - } - break; - } - case OPCODE_DCL_TESS_PARTITIONING: - { - if(psContext->psShader->eShaderType == HULL_SHADER) - { - psContext->psShader->sInfo.eTessPartitioning = psDecl->value.eTessPartitioning; - } - break; - } - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - { - switch(psDecl->value.eOutputPrimitiveTopology) - { - case PRIMITIVE_TOPOLOGY_POINTLIST: - { - bcatcstr(glsl, "layout(points) out;\n"); - break; - } - case PRIMITIVE_TOPOLOGY_LINELIST_ADJ: - case PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: - case PRIMITIVE_TOPOLOGY_LINELIST: - case PRIMITIVE_TOPOLOGY_LINESTRIP: - { - bcatcstr(glsl, "layout(line_strip) out;\n"); - break; - } - - case PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: - case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: - case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: - case PRIMITIVE_TOPOLOGY_TRIANGLELIST: - { - bcatcstr(glsl, "layout(triangle_strip) out;\n"); - break; - } - default: - { - break; - } - } - break; - } - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - { - bformata(glsl, "layout(max_vertices = %d) out;\n", psDecl->value.ui32MaxOutputVertexCount); - break; - } - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - { - switch(psDecl->value.eInputPrimitive) - { - case PRIMITIVE_POINT: - { - bcatcstr(glsl, "layout(points) in;\n"); - break; - } - case PRIMITIVE_LINE: - { - bcatcstr(glsl, "layout(lines) in;\n"); - break; - } - case PRIMITIVE_LINE_ADJ: - { - bcatcstr(glsl, "layout(lines_adjacency) in;\n"); - break; - } - case PRIMITIVE_TRIANGLE: - { - bcatcstr(glsl, "layout(triangles) in;\n"); - break; - } - case PRIMITIVE_TRIANGLE_ADJ: - { - bcatcstr(glsl, "layout(triangles_adjacency) in;\n"); - break; - } - default: - { - break; - } - } - break; - } - case OPCODE_DCL_INTERFACE: - { - const uint32_t interfaceID = psDecl->value.interface.ui32InterfaceID; - const uint32_t numUniforms = psDecl->value.interface.ui32ArraySize; - const uint32_t ui32NumBodiesPerTable = psContext->psShader->funcPointer[interfaceID].ui32NumBodiesPerTable; - ShaderVar* psVar; - uint32_t varFound; - - const char* uniformName; - - varFound = GetInterfaceVarFromOffset(interfaceID, &psContext->psShader->sInfo, &psVar); - ASSERT(varFound); - uniformName = &psVar->Name[0]; - - bformata(glsl, "subroutine uniform SubroutineType %s[%d*%d];\n", uniformName, numUniforms, ui32NumBodiesPerTable); - break; - } - case OPCODE_DCL_FUNCTION_BODY: - { - //bformata(glsl, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); - break; - } - case OPCODE_DCL_FUNCTION_TABLE: - { - break; - } - case OPCODE_CUSTOMDATA: - { - const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; - const uint32_t ui32NumVec4Minus1 = (ui32NumVec4-1); - uint32_t ui32ConstIndex = 0; - float x, y, z, w; - - //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. - //else 2 buffers - one integer and one float. - More data - - if(ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) - { - bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(glsl, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); - - bformata(glsl, "vec4 immediateConstBuffer[%d] = vec4[%d] (\n", ui32NumVec4, ui32NumVec4); - for(;ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) - { - float loopLocalX, loopLocalY, loopLocalZ, loopLocalW; - loopLocalX = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - loopLocalY = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - loopLocalZ = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - loopLocalW = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - - //A single vec4 can mix integer and float types. - //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. - if(fpcheck(loopLocalX)) - { - loopLocalX = 0; - } - if(fpcheck(loopLocalY)) - { - loopLocalY = 0; - } - if(fpcheck(loopLocalZ)) - { - loopLocalZ = 0; - } - if(fpcheck(loopLocalW)) - { - loopLocalW = 0; - } - - bformata(glsl, "\tvec4(%f, %f, %f, %f), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); - } - //No trailing comma on this one - x = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - y = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - z = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - w = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - if(fpcheck(x)) - { - x = 0; - } - if(fpcheck(y)) - { - y = 0; - } - if(fpcheck(z)) - { - z = 0; - } - if(fpcheck(w)) - { - w = 0; - } - bformata(glsl, "\tvec4(%f, %f, %f, %f)\n", x, y, z, w); - bcatcstr(glsl, ");\n"); - } - else - { - bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(glsl, "#define immediateConstBufferF(idx) intBitsToFloat(immediateConstBufferInt[idx])\n"); - } - - { - uint32_t ui32ConstIndex2 = 0; - int x2, y2, z2, w2; - - bformata(glsl, "ivec4 immediateConstBufferInt[%d] = ivec4[%d] (\n", ui32NumVec4, ui32NumVec4); - for (; ui32ConstIndex2 < ui32NumVec4Minus1; ui32ConstIndex2++) - { - int loopLocalX, loopLocalY, loopLocalZ, loopLocalW; - loopLocalX = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; - loopLocalY = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; - loopLocalZ = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; - loopLocalW = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; - - bformata(glsl, "\tivec4(%d, %d, %d, %d), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); - } - //No trailing comma on this one - x2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; - y2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; - z2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; - w2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; - - bformata(glsl, "\tivec4(%d, %d, %d, %d)\n", x2, y2, z2, w2); - bcatcstr(glsl, ");\n"); - } - - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - const uint32_t forkPhaseNum = psDecl->value.aui32HullPhaseInstanceInfo[0]; - const uint32_t instanceCount = psDecl->value.aui32HullPhaseInstanceInfo[1]; - bformata(glsl, "const int HullPhase%dInstanceCount = %d;\n", forkPhaseNum, instanceCount); - break; - } - case OPCODE_DCL_INDEXABLE_TEMP: - { - const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; - const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; - const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; - bformata(glsl, "vec%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - bformata(glsl, "ivec%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - if(HaveUVec(psShader->eTargetLanguage)) - { - bformata(glsl, "uvec%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - } - if(psShader->fp64) - { - bformata(glsl, "dvec%d TempArray%d_double[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - } - break; - } - case OPCODE_DCL_INDEX_RANGE: - { - break; - } - case OPCODE_HS_DECLS: - { - break; - } - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - { - if(psContext->psShader->eShaderType == HULL_SHADER) - { - bformata(glsl, "layout(vertices=%d) out;\n", psDecl->value.ui32MaxOutputVertexCount); - } - break; - } - case OPCODE_HS_FORK_PHASE: - { - break; - } - case OPCODE_HS_JOIN_PHASE: - { - break; - } - case OPCODE_DCL_SAMPLER: - { - break; - } - case OPCODE_DCL_HS_MAX_TESSFACTOR: - { - //For GLSL the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - { - // non-float images need either 'i' or 'u' prefix. - char imageTypePrefix[2] = { 0, 0 }; - if(psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) - { - bcatcstr(glsl, "coherent "); - } - - if(psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] == 0) - { - bcatcstr(glsl, "writeonly "); - } - else - { - if(psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) - { - bcatcstr(glsl, "readonly "); - } - - switch(psDecl->sUAV.Type) - { - case RETURN_TYPE_FLOAT: - bcatcstr(glsl, "layout(rgba32f) "); - break; - case RETURN_TYPE_UNORM: - bcatcstr(glsl, "layout(rgba8) "); - break; - case RETURN_TYPE_SNORM: - bcatcstr(glsl, "layout(rgba8_snorm) "); - break; - case RETURN_TYPE_UINT: - bcatcstr(glsl, "layout(rgba32ui) "); - imageTypePrefix[0] = 'u'; - break; - case RETURN_TYPE_SINT: - bcatcstr(glsl, "layout(rgba32i) "); - imageTypePrefix[0] = 'i'; - break; - default: - ASSERT(0); - } - } - - switch(psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_BUFFER: - { - bformata(glsl, "uniform %simageBuffer ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE1D: - { - bformata(glsl, "uniform %simage1D ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - bformata(glsl, "uniform %simage2D ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - bformata(glsl, "uniform %simage2DMS ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - bformata(glsl, "uniform %simage3D ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - bformata(glsl, "uniform %simageCube ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - bformata(glsl, "uniform %simage1DArray ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - bformata(glsl, "uniform %simage2DArray ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - bformata(glsl, "uniform %simage3DArray ", imageTypePrefix); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - bformata(glsl, "uniform %simageCubeArray ", imageTypePrefix); - break; - } - } - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - { - const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; - ConstantBuffer* psCBuf = NULL; - - if(psDecl->sUAV.bCounter) - { - bformata(glsl, "layout (binding = 1) uniform atomic_uint "); - ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(glsl, "_counter; \n"); - } - - GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], - psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED, glsl); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - { - if(psDecl->sUAV.bCounter) - { - bformata(glsl, "layout (binding = 1) uniform atomic_uint "); - ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(glsl, "_counter; \n"); - } - - bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); - ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bcatcstr(glsl, "[];\n};\n"); - - break; - } - case OPCODE_DCL_RESOURCE_STRUCTURED: - { - ConstantBuffer* psCBuf = NULL; - - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], - 0, RTYPE_STRUCTURED, glsl); - break; - } - case OPCODE_DCL_RESOURCE_RAW: - { - bformata(glsl, "buffer Block%d {\n\tuint RawRes%d[];\n};\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - { - ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); - - bcatcstr(glsl, "shared struct {\n"); - bformata(glsl, "uint value[%d];\n", psDecl->sTGSM.ui32Stride/4); - bcatcstr(glsl, "} "); - TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(glsl, "[%d];\n", - psDecl->sTGSM.ui32Count); - - memset(psVarType, 0, sizeof(ShaderVarType)); - strcpy(psVarType->Name, "$Element"); - - psVarType->Columns = psDecl->sTGSM.ui32Stride/4; - psVarType->Elements = psDecl->sTGSM.ui32Count; - break; - } - case OPCODE_DCL_STREAM: - { - ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_STREAM); - - psShader->ui32CurrentVertexOutputStream = psDecl->asOperands[0].ui32RegisterNumber; - - bformata(glsl, "layout(stream = %d) out;\n", psShader->ui32CurrentVertexOutputStream); - - break; - } - case OPCODE_DCL_GS_INSTANCE_COUNT: - { - bformata(glsl, "layout(invocations = %d) in;\n", psDecl->value.ui32GSInstanceCount); - break; - } - default: - { - ASSERT(0); - break; - } - } -} - -//Convert from per-phase temps to global temps for GLSL. -void ConsolidateHullTempVars(ShaderData* psShader) -{ - uint32_t i, k; - uint32_t ui32Phase, ui32Instance; - const uint32_t ui32NumDeclLists = psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount + - psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount + - psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount + - psShader->asPhase[HS_GLOBAL_DECL].ui32InstanceCount; - - Declaration** pasDeclArray = hlslcc_malloc(sizeof(Declaration*) * ui32NumDeclLists); - - uint32_t* pui32DeclCounts = hlslcc_malloc(sizeof(uint32_t) * ui32NumDeclLists); - uint32_t ui32NumTemps = 0; - - i=0; - for(ui32Phase = HS_GLOBAL_DECL; ui32Phase < NUM_PHASES; ui32Phase++) - { - for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) - { - pasDeclArray[i] = psShader->asPhase[ui32Phase].ppsDecl[ui32Instance]; - pui32DeclCounts[i++] = psShader->asPhase[ui32Phase].pui32DeclCount[ui32Instance]; - } - } - - for(k = 0; k < ui32NumDeclLists; ++k) - { - for(i=0; i < pui32DeclCounts[k]; ++i) - { - Declaration* psDecl = pasDeclArray[k]+i; - - if(psDecl->eOpcode == OPCODE_DCL_TEMPS) - { - if(ui32NumTemps < psDecl->value.ui32NumTemps) - { - //Find the total max number of temps needed by the entire - //shader. - ui32NumTemps = psDecl->value.ui32NumTemps; - } - //Only want one global temp declaration. - psDecl->value.ui32NumTemps = 0; - } - } - } - - //Find the first temp declaration and make it - //declare the max needed amount of temps. - for(k = 0; k < ui32NumDeclLists; ++k) - { - for(i=0; i < pui32DeclCounts[k]; ++i) - { - Declaration* psDecl = pasDeclArray[k]+i; - - if(psDecl->eOpcode == OPCODE_DCL_TEMPS) - { - psDecl->value.ui32NumTemps = ui32NumTemps; - return; - } - } - } - - hlslcc_free(pasDeclArray); - hlslcc_free(pui32DeclCounts); -} - diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c deleted file mode 100644 index cb72838092..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c +++ /dev/null @@ -1,4576 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toGLSLInstruction.h" -#include <stdlib.h> -#include "bstrlib.h" -#include "hlslcc.h" -#include "internal_includes/debug.h" -#include "internal_includes/languages.h" -#include "internal_includes/toGLSLOperand.h" -#include "stdio.h" - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); -static int GLSLIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode); - -// Calculate the bits set in mask -static int GLSLWriteMaskToComponentCount(uint32_t writeMask) -{ - uint32_t count; - // In HLSL bytecode writemask 0 also means everything - if (writeMask == 0) - return 4; - - // Count bits set - // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 - count = (writeMask * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; - - return (int)count; -} - -static uint32_t GLSLBuildComponentMaskFromElementCount(int count) -{ - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - return (1 << count) - 1; -} - -// This function prints out the destination name, possible destination writemask, assignment operator -// and any possible conversions needed based on the eSrcType+ui32SrcElementCount (type and size of data expected to be coming in) -// As an output, pNeedsParenthesis will be filled with the amount of closing parenthesis needed -// and pSrcCount will be filled with the number of components expected -// ui32CompMask can be used to only write to 1 or more components (used by MOVC) -static void GLSLAddOpAssignToDestWithMask(HLSLCrossCompilerContext* psContext, - const Operand* psDest, - SHADER_VARIABLE_TYPE eSrcType, - uint32_t ui32SrcElementCount, - const char* szAssignmentOp, - int* pNeedsParenthesis, - uint32_t ui32CompMask) -{ - uint32_t ui32DestElementCount = GetNumSwizzleElementsWithMask(psDest, ui32CompMask); - bstring glsl = *psContext->currentShaderString; - SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataType(psContext, psDest); - ASSERT(pNeedsParenthesis != NULL); - - *pNeedsParenthesis = 0; - - TranslateOperandWithMask(psContext, psDest, TO_FLAG_DESTINATION, ui32CompMask); - - // Simple path: types match. - if (eDestDataType == eSrcType) - { - // Cover cases where the HLSL language expects the rest of the components to be default-filled - // eg. MOV r0, c0.x => Temp[0] = vec4(c0.x); - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); - *pNeedsParenthesis = 1; - } - else - bformata(glsl, " %s ", szAssignmentOp); - return; - } - - switch (eDestDataType) - { - case SVT_INT: - if (eSrcType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) - { - bformata(glsl, " %s floatBitsToInt(", szAssignmentOp); - // Cover cases where the HLSL language expects the rest of the components to be default-filled - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); - (*pNeedsParenthesis)++; - } - } - else - bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); - break; - case SVT_UINT: - if (eSrcType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) - { - bformata(glsl, " %s floatBitsToUint(", szAssignmentOp); - // Cover cases where the HLSL language expects the rest of the components to be default-filled - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); - (*pNeedsParenthesis)++; - } - } - else - bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); - break; - - case SVT_FLOAT: - if (psContext->psShader->ui32MajorVersion > 3) - { - if (eSrcType == SVT_INT) - bformata(glsl, " %s intBitsToFloat(", szAssignmentOp); - else - bformata(glsl, " %s uintBitsToFloat(", szAssignmentOp); - // Cover cases where the HLSL language expects the rest of the components to be default-filled - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); - (*pNeedsParenthesis)++; - } - } - else - bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); - break; - default: - // TODO: Handle bools? - break; - } - (*pNeedsParenthesis)++; - return; -} - -static void GLSLMETALAddAssignToDest(HLSLCrossCompilerContext* psContext, - const Operand* psDest, - SHADER_VARIABLE_TYPE eSrcType, - uint32_t ui32SrcElementCount, - int* pNeedsParenthesis) -{ - GLSLAddOpAssignToDestWithMask(psContext, psDest, eSrcType, ui32SrcElementCount, "=", pNeedsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); -} - -static void GLSLAddAssignPrologue(HLSLCrossCompilerContext* psContext, int numParenthesis) -{ - bstring glsl = *psContext->currentShaderString; - while (numParenthesis != 0) - { - bcatcstr(glsl, ")"); - numParenthesis--; - } - bcatcstr(glsl, ";\n"); -} -static uint32_t GLSLResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType) -{ - if (eType == RETURN_TYPE_SINT) - { - return TO_FLAG_INTEGER; - } - else if (eType == RETURN_TYPE_UINT) - { - return TO_FLAG_UNSIGNED_INTEGER; - } - else - { - return TO_FLAG_NONE; - } -} - -typedef enum -{ - GLSL_CMP_EQ, - GLSL_CMP_LT, - GLSL_CMP_GE, - GLSL_CMP_NE, -} GLSLComparisonType; - -static void GLSLAddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, GLSLComparisonType eType, uint32_t typeFlag, Instruction* psNextInst) -{ - // Multiple cases to consider here: - // For shader model <=3: all comparisons are floats - // otherwise: - // OPCODE_LT, _GT, _NE etc: inputs are floats, outputs UINT 0xffffffff or 0. typeflag: TO_FLAG_NONE - // OPCODE_ILT, _IGT etc: comparisons are signed ints, outputs UINT 0xffffffff or 0 typeflag TO_FLAG_INTEGER - // _ULT, UGT etc: inputs unsigned ints, outputs UINTs typeflag TO_FLAG_UNSIGNED_INTEGER - // - // Additional complexity: if dest swizzle element count is 1, we can use normal comparison operators, otherwise glsl intrinsics. - - bstring glsl = *psContext->currentShaderString; - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - const uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); - - int floatResult = 0; - int needsParenthesis = 0; - - ASSERT(s0ElemCount == s1ElemCount || s1ElemCount == 1 || s0ElemCount == 1); - if (s0ElemCount != s1ElemCount) - { - // Set the proper auto-expand flag is either argument is scalar - typeFlag |= (TO_AUTO_EXPAND_TO_VEC2 << (max(s0ElemCount, s1ElemCount) - 2)); - } - - if (psContext->psShader->ui32MajorVersion < 4) - { - floatResult = 1; - } - - if (destElemCount > 1) - { - const char* glslOpcode[] = { - "equal", - "lessThan", - "greaterThanEqual", - "notEqual", - }; - - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], floatResult ? SVT_FLOAT : SVT_UINT, destElemCount, &needsParenthesis); - - bcatcstr(glsl, GetConstructorForType(floatResult ? SVT_FLOAT : SVT_UINT, destElemCount)); - bformata(glsl, "(%s(", glslOpcode[eType]); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, "))"); - if (!floatResult) - { - bcatcstr(glsl, " * 0xFFFFFFFFu"); - } - - GLSLAddAssignPrologue(psContext, needsParenthesis); - } - else - { - const char* glslOpcode[] = { - "==", - "<", - ">=", - "!=", - }; - - // Scalar compare - - // Optimization shortcut for the IGE+BREAKC_NZ combo: - // First print out the if(cond)->break directly, and then - // to guarantee correctness with side-effects, re-run - // the actual comparison. In most cases, the second run will - // be removed by the shader compiler optimizer pass (dead code elimination) - // This also makes it easier for some GLSL optimizers to recognize the for loop. - - if (psInst->eOpcode == OPCODE_IGE && psNextInst && psNextInst->eOpcode == OPCODE_BREAKC && - (psInst->asOperands[0].ui32RegisterNumber == psNextInst->asOperands[0].ui32RegisterNumber)) - { - AddIndentation(psContext); - bcatcstr(glsl, "// IGE+BREAKC opt\n"); - AddIndentation(psContext); - - if (psNextInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO) - bcatcstr(glsl, "if (("); - else - bcatcstr(glsl, "if (!("); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bformata(glsl, "%s ", glslOpcode[eType]); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(glsl, ")) { break; }\n"); - - // Mark the BREAKC instruction as already handled - psNextInst->eOpcode = OPCODE_NOP; - - // Continue as usual - } - - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], floatResult ? SVT_FLOAT : SVT_UINT, destElemCount, &needsParenthesis); - - bcatcstr(glsl, "("); - TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - bformata(glsl, "%s", glslOpcode[eType]); - TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - if (floatResult) - { - bcatcstr(glsl, ") ? 1.0 : 0.0"); - } - else - { - bcatcstr(glsl, ") ? 0xFFFFFFFFu : 0u"); - } - GLSLAddAssignPrologue(psContext, needsParenthesis); - } -} - -static void GLSLAddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, Operand* pSrc) -{ - int numParenthesis = 0; - int srcSwizzleCount = GetNumSwizzleElements(pSrc); - uint32_t writeMask = GetOperandWriteMask(pDest); - - const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataTypeEx(psContext, pSrc, GetOperandDataType(psContext, pDest)); - uint32_t flags = SVTTypeToFlag(eSrcType); - - GLSLMETALAddAssignToDest(psContext, pDest, eSrcType, srcSwizzleCount, &numParenthesis); - TranslateOperandWithMask(psContext, pSrc, flags, writeMask); - - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static uint32_t GLSLElemCountToAutoExpandFlag(uint32_t elemCount) -{ - return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2); -} - -static void GLSLAddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, const Operand* src0, Operand* src1, Operand* src2) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t destElemCount = GetNumSwizzleElements(pDest); - uint32_t s0ElemCount = GetNumSwizzleElements(src0); - uint32_t s1ElemCount = GetNumSwizzleElements(src1); - uint32_t s2ElemCount = GetNumSwizzleElements(src2); - uint32_t destWriteMask = GetOperandWriteMask(pDest); - uint32_t destElem; - - const SHADER_VARIABLE_TYPE eDestType = GetOperandDataType(psContext, pDest); - /* - for each component in dest[.mask] - if the corresponding component in src0 (POS-swizzle) - has any bit set - { - copy this component (POS-swizzle) from src1 into dest - } - else - { - copy this component (POS-swizzle) from src2 into dest - } - endfor - */ - - /* Single-component conditional variable (src0) */ - if (s0ElemCount == 1 || IsSwizzleReplicated(src0)) - { - int numParenthesis = 0; - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); - bcatcstr(glsl, "("); - TranslateOperand(psContext, src0, TO_AUTO_BITCAST_TO_INT); - if (s0ElemCount > 1) - bcatcstr(glsl, ".x"); - if (psContext->psShader->ui32MajorVersion < 4) - { - // cmp opcode uses >= 0 - bcatcstr(glsl, " >= 0) ? "); - } - else - { - bcatcstr(glsl, " != 0) ? "); - } - - if (s1ElemCount == 1 && destElemCount > 1) - TranslateOperand(psContext, src1, SVTTypeToFlag(eDestType) | GLSLElemCountToAutoExpandFlag(destElemCount)); - else - TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), destWriteMask); - - bcatcstr(glsl, " : "); - if (s2ElemCount == 1 && destElemCount > 1) - TranslateOperand(psContext, src2, SVTTypeToFlag(eDestType) | GLSLElemCountToAutoExpandFlag(destElemCount)); - else - TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), destWriteMask); - - GLSLAddAssignPrologue(psContext, numParenthesis); - } - else - { - // TODO: We can actually do this in one op using mix(). - int srcElem = 0; - for (destElem = 0; destElem < 4; ++destElem) - { - int numParenthesis = 0; - if (pDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && pDest->ui32CompMask != 0 && !(pDest->ui32CompMask & (1 << destElem))) - continue; - - AddIndentation(psContext); - GLSLAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); - bcatcstr(glsl, "("); - TranslateOperandWithMask(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << srcElem); - if (psContext->psShader->ui32MajorVersion < 4) - { - // cmp opcode uses >= 0 - bcatcstr(glsl, " >= 0) ? "); - } - else - { - bcatcstr(glsl, " != 0) ? "); - } - - TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), 1 << srcElem); - bcatcstr(glsl, " : "); - TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), 1 << srcElem); - - GLSLAddAssignPrologue(psContext, numParenthesis); - - srcElem++; - } - } -} - -// Returns nonzero if operands are identical, only cares about temp registers currently. -static int GLSLAreTempOperandsIdentical(const Operand* psA, const Operand* psB) -{ - if (!psA || !psB) - return 0; - - if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP) - return 0; - - if (psA->eModifier != psB->eModifier) - return 0; - - if (psA->iNumComponents != psB->iNumComponents) - return 0; - - if (psA->ui32RegisterNumber != psB->ui32RegisterNumber) - return 0; - - if (psA->eSelMode != psB->eSelMode) - return 0; - - if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask) - return 0; - - if (psA->eSelMode != OPERAND_4_COMPONENT_MASK_MODE && psA->ui32Swizzle != psB->ui32Swizzle) - return 0; - - return 1; -} - -// Returns nonzero if the operation is commutative -static int GLSLIsOperationCommutative(OPCODE_TYPE eOpCode) -{ - switch (eOpCode) - { - case OPCODE_DADD: - case OPCODE_IADD: - case OPCODE_ADD: - case OPCODE_MUL: - case OPCODE_IMUL: - case OPCODE_OR: - case OPCODE_AND: - return 1; - default: - return 0; - }; -} - -static void -GLSLCallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); - uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = GetOperandWriteMask(&psInst->asOperands[dest]); - int needsParenthesis = 0; - - AddIndentation(psContext); - - if (src1SwizCount == src0SwizCount == dstSwizCount) - { - // Optimization for readability (and to make for loops in WebGL happy): detect cases where either src == dest and emit +=, -= etc. instead. - if (GLSLAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src0]) != 0) - { - GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); - TranslateOperand(psContext, &psInst->asOperands[src1], SVTTypeToFlag(eDataType)); - GLSLAddAssignPrologue(psContext, needsParenthesis); - return; - } - else if (GLSLAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src1]) != 0 && (GLSLIsOperationCommutative(psInst->eOpcode) != 0)) - { - GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); - TranslateOperand(psContext, &psInst->asOperands[src0], SVTTypeToFlag(eDataType)); - GLSLAddAssignPrologue(psContext, needsParenthesis); - return; - } - } - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, &needsParenthesis); - - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], SVTTypeToFlag(eDataType), destMask); - bformata(glsl, " %s ", name); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], SVTTypeToFlag(eDataType), destMask); - GLSLAddAssignPrologue(psContext, needsParenthesis); -} - -static void GLSLCallTernaryOp(HLSLCrossCompilerContext* psContext, - const char* op1, - const char* op2, - Instruction* psInst, - int dest, - int src0, - int src1, - int src2, - uint32_t dataType) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = GetOperandWriteMask(&psInst->asOperands[dest]); - - uint32_t ui32Flags = dataType; - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], TypeFlagsToSVTType(dataType), dstSwizCount, &numParenthesis); - - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bformata(glsl, " %s ", op1); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - bformata(glsl, " %s ", op2); - TranslateOperandWithMask(psContext, &psInst->asOperands[src2], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void GLSLCallHelper3(HLSLCrossCompilerContext* psContext, - const char* name, - Instruction* psInst, - int dest, - int src0, - int src1, - int src2, - int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; - bstring glsl = *psContext->currentShaderString; - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[src2], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void -GLSLCallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; - bstring glsl = *psContext->currentShaderString; - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - - int isDotProduct = (strncmp(name, "dot", 3) == 0) ? 1 : 0; - int numParenthesis = 0; - - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, isDotProduct ? 1 : dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void -GLSLCallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void -GLSLCallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_UINT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_UINT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void GLSLCallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -// Result is an int. -static void GLSLCallHelper1Int(HLSLCrossCompilerContext* psContext, - const char* name, - Instruction* psInst, - const int dest, - const int src0, - int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void GLSLTranslateTexelFetch(HLSLCrossCompilerContext* psContext, Instruction* psInst, ResourceBinding* psBinding, bstring glsl) -{ - int numParenthesis = 0; - uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(GLSLResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, - &numParenthesis); - bcatcstr(glsl, "texelFetch("); - - switch (psBinding->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - case REFLECT_RESOURCE_DIMENSION_BUFFER: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - if (psBinding->eDimension != REFLECT_RESOURCE_DIMENSION_BUFFER) - bcatcstr(glsl, ", 0"); // Buffers don't have LOD - bcatcstr(glsl, ")"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); - bcatcstr(glsl, ", 0)"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); - bcatcstr(glsl, ", 0)"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: // TODO does this make any sense at all? - { - ASSERT(psInst->eOpcode == OPCODE_LD_MS); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(glsl, ")"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - ASSERT(psInst->eOpcode == OPCODE_LD_MS); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(glsl, ")"); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - case REFLECT_RESOURCE_DIMENSION_BUFFEREX: - default: - { - ASSERT(0); - break; - } - } - - AddSwizzleUsingElementCount(psContext, destCount); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static void GLSLTranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, Instruction* psInst, ResourceBinding* psBinding, bstring glsl) -{ - int numParenthesis = 0; - uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(GLSLResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, - &numParenthesis); - - bcatcstr(glsl, "texelFetchOffset("); - - switch (psBinding->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bformata(glsl, ", 0, %d)", psInst->iUAddrOffset); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); - bformata(glsl, ", 0, ivec2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); - bformata(glsl, ", 0, ivec3(%d, %d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset, psInst->iWAddrOffset); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); - bformata(glsl, ", 0, ivec2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); - bformata(glsl, ", 0, int(%d))", psInst->iUAddrOffset); - break; - } - case REFLECT_RESOURCE_DIMENSION_BUFFER: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - case REFLECT_RESOURCE_DIMENSION_BUFFEREX: - default: - { - ASSERT(0); - break; - } - } - - AddSwizzleUsingElementCount(psContext, destCount); - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -// Makes sure the texture coordinate swizzle is appropriate for the texture type. -// i.e. vecX for X-dimension texture. -// Currently supports floating point coord only, so not used for texelFetch. -static void GLSLTranslateTexCoord(HLSLCrossCompilerContext* psContext, const RESOURCE_DIMENSION eResDim, Operand* psTexCoordOperand) -{ - uint32_t flags = TO_AUTO_BITCAST_TO_FLOAT; - uint32_t opMask = OPERAND_4_COMPONENT_MASK_ALL; - - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - // Vec1 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X; - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - // Vec2 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; - flags |= TO_AUTO_EXPAND_TO_VEC2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - // Vec3 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z; - flags |= TO_AUTO_EXPAND_TO_VEC3; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - flags |= TO_AUTO_EXPAND_TO_VEC4; - break; - } - default: - { - ASSERT(0); - break; - } - } - - // FIXME detect when integer coords are needed. - TranslateOperandWithMask(psContext, psTexCoordOperand, flags, opMask); -} - -static int GLSLGetNumTextureDimensions(HLSLCrossCompilerContext* psContext, const RESOURCE_DIMENSION eResDim) -{ - (void)psContext; - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - return 1; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBE: - { - return 2; - } - - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - return 3; - } - default: - { - ASSERT(0); - break; - } - } - return 0; -} - -void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index, int destElem) -{ - bstring glsl = *psContext->currentShaderString; - int numParenthesis = 0; - const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - AddIndentation(psContext); - GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", - &numParenthesis, 1 << destElem); - - //[width, height, depth or array size, total-mip-count] - if (index < 3) - { - int dim = GLSLGetNumTextureDimensions(psContext, eResDim); - bcatcstr(glsl, "("); - if (dim < (index + 1)) - { - bcatcstr(glsl, eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? "0u" : "0.0"); - } - else - { - if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - { - bformata(glsl, "uvec%d(textureSize(", dim); - } - else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) - { - bformata(glsl, "vec%d(1.0) / vec%d(textureSize(", dim, dim); - } - else - { - bformata(glsl, "vec%d(textureSize(", dim); - } - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, "))"); - - switch (index) - { - case 0: - bcatcstr(glsl, ".x"); - break; - case 1: - bcatcstr(glsl, ".y"); - break; - case 2: - bcatcstr(glsl, ".z"); - break; - } - } - - bcatcstr(glsl, ")"); - } - else - { - if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - bcatcstr(glsl, "uint("); - else - bcatcstr(glsl, "float("); - bcatcstr(glsl, "textureQueryLevels("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - } - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -#define TEXSMP_FLAG_NONE 0x0 -#define TEXSMP_FLAG_LOD 0x1 // LOD comes from operand -#define TEXSMP_FLAG_DEPTHCOMPARE 0x2 -#define TEXSMP_FLAG_FIRSTLOD 0x4 // LOD is 0 -#define TEXSMP_FLAG_BIAS 0x8 -#define TEXSMP_FLAGS_GRAD 0x10 - -// TODO FIXME: non-float samplers! -static void GLSLTranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, uint32_t ui32Flags) -{ - bstring glsl = *psContext->currentShaderString; - int numParenthesis = 0; - - const char* funcName = "texture"; - const char* offset = ""; - const char* depthCmpCoordType = ""; - const char* gradSwizzle = ""; - - uint32_t ui32NumOffsets = 0; - - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); - - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; - - ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); - - if (psInst->bAddressOffset) - { - offset = "Offset"; - } - - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - depthCmpCoordType = "vec2"; - gradSwizzle = ".x"; - ui32NumOffsets = 1; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture1D"; - if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) - { - funcName = "shadow1D"; - } - } - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture2D"; - if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) - { - funcName = "shadow2D"; - } - } - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (!iHaveOverloadedTexFuncs) - { - funcName = "textureCube"; - } - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - depthCmpCoordType = "vec4"; - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (!iHaveOverloadedTexFuncs) - { - funcName = "texture3D"; - } - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - depthCmpCoordType = "vec3"; - gradSwizzle = ".x"; - ui32NumOffsets = 1; - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - depthCmpCoordType = "vec4"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) - { - SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! - // Special. Reference is a separate argument. - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, 1, &numParenthesis); - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bcatcstr(glsl, "textureLod("); - } - else - { - bcatcstr(glsl, "texture("); - } - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0); - else - bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, - psInst->asOperands[3].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0)); - bcatcstr(glsl, ","); - GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ","); - //.z = reference. - TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - - bcatcstr(glsl, ")"); - // Doesn't make any sense to do swizzles here, depth comparison returns a scalar. - GLSLAddAssignPrologue(psContext, numParenthesis); - return; - } - - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) - { - // For non-cubeMap Arrays the reference value comes from the - // texture coord vector in GLSL. For cubmap arrays there is a - // separate parameter. - // It is always separate paramter in HLSL. - SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bformata(glsl, "%sLod%s(", funcName, offset); - } - else - { - bformata(glsl, "%s%s(", funcName, offset); - } - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - bformata(glsl, ", %s(", depthCmpCoordType); - GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ","); - //.z = reference. - TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(glsl, ")"); - - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - - bcatcstr(glsl, ")"); - } - else - { - SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - - if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) - { - bformata(glsl, "%sLod%s(", funcName, offset); - } - else if (ui32Flags & TEXSMP_FLAGS_GRAD) - { - bformata(glsl, "%sGrad%s(", funcName, offset); - } - else - { - bformata(glsl, "%s%s(", funcName, offset); - } - if (!useCombinedTextureSamplers) - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); // resource - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); - bcatcstr(glsl, ", "); - GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - if (ui32Flags & (TEXSMP_FLAG_LOD)) - { - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - if (psContext->psShader->ui32MajorVersion < 4) - { - bcatcstr(glsl, ".w"); - } - } - else if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(glsl, ", 0.0"); - } - else if (ui32Flags & TEXSMP_FLAGS_GRAD) - { - bcatcstr(glsl, ", vec4("); - TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); // dx - bcatcstr(glsl, ")"); - bcatcstr(glsl, gradSwizzle); - bcatcstr(glsl, ", vec4("); - TranslateOperand(psContext, &psInst->asOperands[5], TO_AUTO_BITCAST_TO_FLOAT); // dy - bcatcstr(glsl, ")"); - bcatcstr(glsl, gradSwizzle); - } - - if (psInst->bAddressOffset) - { - if (ui32NumOffsets == 1) - { - bformata(glsl, ", %d", psInst->iUAddrOffset); - } - else if (ui32NumOffsets == 2) - { - bformata(glsl, ", ivec2(%d, %d)", psInst->iUAddrOffset, psInst->iVAddrOffset); - } - else if (ui32NumOffsets == 3) - { - bformata(glsl, ", ivec3(%d, %d, %d)", psInst->iUAddrOffset, psInst->iVAddrOffset, psInst->iWAddrOffset); - } - } - - if (ui32Flags & (TEXSMP_FLAG_BIAS)) - { - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - } - - bcatcstr(glsl, ")"); - } - - if (!(ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE)) - { - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[2], GetOperandWriteMask(&psInst->asOperands[0])); - } - GLSLAddAssignPrologue(psContext, numParenthesis); -} - -static ShaderVarType* GLSLLookupStructuredVar(HLSLCrossCompilerContext* psContext, Operand* psResource, Operand* psByteOffset, uint32_t ui32Component) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; - int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; - int vec4Offset = 0; - int32_t index = -1; - int32_t rebase = -1; - int found; - - ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); - // TODO: multi-component stores and vector writes need testing. - - // aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; - - switch (byteOffset % 16) - { - case 0: - aui32Swizzle[0] = 0; - break; - case 4: - aui32Swizzle[0] = 1; - break; - case 8: - aui32Swizzle[0] = 2; - break; - case 12: - aui32Swizzle[0] = 3; - break; - } - - switch (psResource->eType) - { - case OPERAND_TYPE_RESOURCE: - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - // dcl_tgsm_structured defines the amount of memory and a stride. - ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); - return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; - } - default: - ASSERT(0); - break; - } - - found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - ASSERT(found); - - return psVarType; -} - -static void GLSLTranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentShaderString; - ShaderVarType* psVarType = NULL; - int component; - int srcComponent = 0; - - Operand* psDest = 0; - Operand* psDestAddr = 0; - Operand* psDestByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_STORE_STRUCTURED: - psDest = &psInst->asOperands[0]; - psDestAddr = &psInst->asOperands[1]; - psDestByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - - break; - case OPCODE_STORE_RAW: - psDest = &psInst->asOperands[0]; - psDestByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - for (component = 0; component < 4; component++) - { - ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psInst->asOperands[0].ui32CompMask & (1 << component)) - { - - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - psVarType = GLSLLookupStructuredVar(psContext, psDest, psDestByteOff, component); - } - - AddIndentation(psContext); - - if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) - { - bformata(glsl, "StructuredRes%d", psDest->ui32RegisterNumber); - } - else - { - TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - } - bformata(glsl, "["); - if (structured) // Dest address and dest byte offset - { - if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, "].value["); - TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, "/4u "); // bytes to floats - } - else - { - TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - } - else - { - TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - - // RAW: change component using index offset - if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(glsl, " + %d", component); - } - - bformata(glsl, "]"); - - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - if (strcmp(psVarType->Name, "$Element") != 0) - { - bformata(glsl, ".%s", psVarType->Name); - } - } - - if (structured) - { - uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; - if (psVarType) - { - if (psVarType->Type == SVT_INT) - { - flags = TO_FLAG_INTEGER; - } - else if (psVarType->Type == SVT_FLOAT) - { - flags = TO_FLAG_NONE; - } - } - // TGSM always uint - bformata(glsl, " = ("); - if (GetNumSwizzleElements(psSrc) > 1) - TranslateOperandWithMask(psContext, psSrc, flags, 1 << (srcComponent++)); - else - TranslateOperandWithMask(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); - } - else - { - // Dest type is currently always a uint array. - bformata(glsl, " = ("); - if (GetNumSwizzleElements(psSrc) > 1) - TranslateOperandWithMask(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); - else - TranslateOperandWithMask(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); - } - - // Double takes an extra slot. - if (psVarType && psVarType->Type == SVT_DOUBLE) - { - if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - bcatcstr(glsl, ")"); - component++; - } - - bformata(glsl, ");\n"); - } - } -} -static void GLSLTranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentShaderString; - int component; - Operand* psDest = 0; - Operand* psSrcAddr = 0; - Operand* psSrcByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_LD_STRUCTURED: - psDest = &psInst->asOperands[0]; - psSrcAddr = &psInst->asOperands[1]; - psSrcByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - break; - case OPCODE_LD_RAW: - psDest = &psInst->asOperands[0]; - psSrcByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - if (psInst->eOpcode == OPCODE_LD_RAW) - { - int numParenthesis = 0; - int firstItemAdded = 0; - uint32_t destCount = GetNumSwizzleElements(psDest); - uint32_t destMask = GetOperandWriteMask(psDest); - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); - if (destCount > 1) - { - bformata(glsl, "%s(", GetConstructorForType(SVT_UINT, destCount)); - numParenthesis++; - } - for (component = 0; component < 4; component++) - { - if (!(destMask & (1 << component))) - continue; - - if (firstItemAdded) - bcatcstr(glsl, ", "); - else - firstItemAdded = 1; - - bformata(glsl, "RawRes%d[((", psSrc->ui32RegisterNumber); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(glsl, ") >> 2)"); - if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) - { - bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); - } - bcatcstr(glsl, "]"); - } - GLSLAddAssignPrologue(psContext, numParenthesis); - } - else - { - int numParenthesis = 0; - int firstItemAdded = 0; - uint32_t destCount = GetNumSwizzleElements(psDest); - uint32_t destMask = GetOperandWriteMask(psDest); - ASSERT(psInst->eOpcode == OPCODE_LD_STRUCTURED); - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); - if (destCount > 1) - { - bformata(glsl, "%s(", GetConstructorForType(SVT_UINT, destCount)); - numParenthesis++; - } - for (component = 0; component < 4; component++) - { - ShaderVarType* psVar = NULL; - int addedBitcast = 0; - if (!(destMask & (1 << component))) - continue; - - if (firstItemAdded) - bcatcstr(glsl, ", "); - else - firstItemAdded = 1; - - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - // input already in uints - TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "["); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "].value[("); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, " >> 2u) + %d]", psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - } - else - { - ConstantBuffer* psCBuf = NULL; - psVar = GLSLLookupStructuredVar(psContext, psSrc, psSrcByteOff, - psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - if (psVar->Type == SVT_FLOAT) - { - bcatcstr(glsl, "floatBitsToUint("); - addedBitcast = 1; - } - else if (psVar->Type == SVT_DOUBLE) - { - bcatcstr(glsl, "unpackDouble2x32("); - addedBitcast = 1; - } - if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) - { - bformata(glsl, "%s[", psCBuf->Name); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - if (strcmp(psVar->Name, "$Element") != 0) - { - bcatcstr(glsl, "."); - bcatcstr(glsl, psVar->Name); - } - } - else - { - bformata(glsl, "StructuredRes%d[", psSrc->ui32RegisterNumber); - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(glsl, "]."); - - bcatcstr(glsl, psVar->Name); - } - - if (addedBitcast) - bcatcstr(glsl, ")"); - if (psVar->Type == SVT_DOUBLE) - component++; // doubles take up 2 slots - } - } - GLSLAddAssignPrologue(psContext, numParenthesis); - - return; - } - -#if 0 - - //(int)GetNumSwizzleElements(&psInst->asOperands[0]) - for (component = 0; component < 4; component++) - { - const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; - ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psDest->ui32CompMask & (1 << component)) - { - if (structured && psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - psVarType = GLSLLookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); - } - - AddIndentation(psContext); - - aui32Swizzle[0] = psSrc->aui32Swizzle[component]; - - TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION); - if (GetNumSwizzleElements(psDest) > 1) - bformata(glsl, swizzleString[destComponent++]); - - if (psVarType) - { - // TODO completely broken now after GLSLMETALAddAssignToDest refactorings. - GLSLMETALAddAssignToDest(psContext, psDest, SVTTypeToFlag(psVarType->Type), GetNumSwizzleElements(psDest), &numParenthesis); - } - else - { - GLSLMETALAddAssignToDest(psContext, psDest, TO_FLAG_NONE, GetNumSwizzleElements(psDest), &numParenthesis); - } - - if (psSrc->eType == OPERAND_TYPE_RESOURCE) - { - if (structured) - bformata(glsl, "(StructuredRes%d[", psSrc->ui32RegisterNumber); - else - bformata(glsl, "(RawRes%d[", psSrc->ui32RegisterNumber); - } - else - { - bformata(glsl, "("); - TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); - bformata(glsl, "["); - Translate - } - - if (structured) //src address and src byte offset - { - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, "].value["); - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(glsl, "/4u ");//bytes to floats - } - else - { - TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - } - else - { - TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - - //RAW: change component using index offset - if (!structured || (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); - } - - bformata(glsl, "]"); - if (structured && psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - if (strcmp(psVarType->Name, "$Element") != 0) - { - bformata(glsl, ".%s", psVarType->Name); - } - - if (psVarType->Type == SVT_DOUBLE) - { - //Double takes an extra slot. - component++; - } - } - - bformata(glsl, ");\n"); - } - } -#endif -} - -void TranslateAtomicMemOp(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring glsl = *psContext->currentShaderString; - int numParenthesis = 0; - ShaderVarType* psVarType = NULL; - uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; - const char* func = ""; - Operand* dest = 0; - Operand* previousValue = 0; - Operand* destAddr = 0; - Operand* src = 0; - Operand* compare = 0; - - switch (psInst->eOpcode) - { - case OPCODE_IMM_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IADD\n"); -#endif - func = "atomicAdd"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IADD\n"); -#endif - func = "atomicAdd"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_AND\n"); -#endif - func = "atomicAnd"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_AND\n"); -#endif - func = "atomicAnd"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_OR\n"); -#endif - func = "atomicOr"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_OR\n"); -#endif - func = "atomicOr"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_XOR\n"); -#endif - func = "atomicXor"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_XOR\n"); -#endif - func = "atomicXor"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - - case OPCODE_IMM_ATOMIC_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_EXCH\n"); -#endif - func = "atomicExchange"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_CMP_EXC\n"); -#endif - func = "atomicCompSwap"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - compare = &psInst->asOperands[3]; - src = &psInst->asOperands[4]; - break; - } - case OPCODE_ATOMIC_CMP_STORE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_CMP_STORE\n"); -#endif - func = "atomicCompSwap"; - previousValue = 0; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - compare = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_UMIN\n"); -#endif - func = "atomicMin"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_UMIN\n"); -#endif - func = "atomicMin"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IMIN\n"); -#endif - func = "atomicMin"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IMIN\n"); -#endif - func = "atomicMin"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_UMAX\n"); -#endif - func = "atomicMax"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_UMAX\n"); -#endif - func = "atomicMax"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_IMAX\n"); -#endif - func = "atomicMax"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ATOMIC_IMAX\n"); -#endif - func = "atomicMax"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - } - - AddIndentation(psContext); - - psVarType = GLSLLookupStructuredVar(psContext, dest, destAddr, 0); - if (psVarType->Type == SVT_UINT) - { - ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT; - } - else - { - ui32DataTypeFlag = TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT; - } - - if (previousValue) - { - GLSLMETALAddAssignToDest(psContext, previousValue, psVarType->Type, 1, &numParenthesis); - } - bcatcstr(glsl, func); - bformata(glsl, "("); - ResourceName(glsl, psContext, RGROUP_UAV, dest->ui32RegisterNumber, 0); - bformata(glsl, "[0]"); - if (strcmp(psVarType->Name, "$Element") != 0) - { - bformata(glsl, ".%s", psVarType->Name); - } - - bcatcstr(glsl, ", "); - - if (compare) - { - TranslateOperand(psContext, compare, ui32DataTypeFlag); - bcatcstr(glsl, ", "); - } - - TranslateOperand(psContext, src, ui32DataTypeFlag); - bcatcstr(glsl, ")"); - if (previousValue) - { - GLSLAddAssignPrologue(psContext, numParenthesis); - } - else - bcatcstr(glsl, ";\n"); -} - -static void GLSLTranslateConditional(HLSLCrossCompilerContext* psContext, Instruction* psInst, bstring glsl) -{ - const char* statement = ""; - if (psInst->eOpcode == OPCODE_BREAKC) - { - statement = "break"; - } - else if (psInst->eOpcode == OPCODE_CONTINUEC) - { - statement = "continue"; - } - else if (psInst->eOpcode == OPCODE_RETC) - { - statement = "return"; - } - - if (psContext->psShader->ui32MajorVersion < 4) - { - bcatcstr(glsl, "if("); - - TranslateOperand(psContext, &psInst->asOperands[0], SVTTypeToFlag(GetOperandDataType(psContext, &psInst->asOperands[0]))); - switch (psInst->eDX9TestType) - { - case D3DSPC_GT: - { - bcatcstr(glsl, " > "); - break; - } - case D3DSPC_EQ: - { - bcatcstr(glsl, " == "); - break; - } - case D3DSPC_GE: - { - bcatcstr(glsl, " >= "); - break; - } - case D3DSPC_LT: - { - bcatcstr(glsl, " < "); - break; - } - case D3DSPC_NE: - { - bcatcstr(glsl, " != "); - break; - } - case D3DSPC_LE: - { - bcatcstr(glsl, " <= "); - break; - } - case D3DSPC_BOOLEAN: - { - bcatcstr(glsl, " != 0"); - break; - } - default: - { - break; - } - } - - if (psInst->eDX9TestType != D3DSPC_BOOLEAN) - { - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - } - - if (psInst->eOpcode != OPCODE_IF) - { - bformata(glsl, "){ %s; }\n", statement); - } - else - { - bcatcstr(glsl, "){\n"); - } - } - else - { - if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF) - { - bformata(glsl, ")==0u){%s;}\n", statement); - } - else - { - bcatcstr(glsl, ")==0u){\n"); - } - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF) - { - bformata(glsl, ")!=0u){%s;}\n", statement); - } - else - { - bcatcstr(glsl, ")!=0u){\n"); - } - } - } -} - -// Returns the "more important" type of a and b, currently int < uint < float -static SHADER_VARIABLE_TYPE GLSLSelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b) -{ - if (a == SVT_FLOAT || b == SVT_FLOAT) - return SVT_FLOAT; - // Apart from floats, the enum values are fairly well-ordered, use that directly. - return a > b ? a : b; -} - -// Helper function to set the vector type of 1 or more components in a vector -// If the existing values (that we're writing to) are all SVT_VOID, just upgrade the value and we're done -// Otherwise, set all the components in the vector that currently are set to that same value OR are now being written to -// to the "highest" type value (ordering int->uint->float) -static void GLSLSetVectorType(SHADER_VARIABLE_TYPE* aeTempVecType, uint32_t regBaseIndex, uint32_t componentMask, SHADER_VARIABLE_TYPE eType) -{ - int existingTypesFound = 0; - int i = 0; - for (i = 0; i < 4; i++) - { - if (componentMask & (1 << i)) - { - if (aeTempVecType[regBaseIndex + i] != SVT_VOID) - { - existingTypesFound = 1; - break; - } - } - } - - if (existingTypesFound != 0) - { - // Expand the mask to include all components that are used, also upgrade type - for (i = 0; i < 4; i++) - { - if (aeTempVecType[regBaseIndex + i] != SVT_VOID) - { - componentMask |= (1 << i); - eType = GLSLSelectHigherType(eType, aeTempVecType[regBaseIndex + i]); - } - } - } - - // Now componentMask contains the components we actually need to update and eType may have been changed to something else. - // Write the results - for (i = 0; i < 4; i++) - { - if (componentMask & (1 << i)) - { - aeTempVecType[regBaseIndex + i] = eType; - } - } -} - -static void GLSLMarkOperandAs(Operand* psOperand, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) -{ - if (psOperand->eType == OPERAND_TYPE_INDEXABLE_TEMP || psOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - GLSLSetVectorType(aeTempVecType, ui32RegIndex, 1 << psOperand->aui32Swizzle[0], eType); - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - // 0xf == all components, swizzle order doesn't matter. - GLSLSetVectorType(aeTempVecType, ui32RegIndex, 0xf, eType); - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - GLSLSetVectorType(aeTempVecType, ui32RegIndex, ui32CompMask, eType); - } - } -} - -static void GLSLMarkAllOperandsAs(Instruction* psInst, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) -{ - uint32_t i = 0; - for (i = 0; i < psInst->ui32NumOperands; i++) - { - GLSLMarkOperandAs(&psInst->asOperands[i], eType, aeTempVecType); - } -} - -static void GLSLWriteOperandTypes(Operand* psOperand, const SHADER_VARIABLE_TYPE* aeTempVecType) -{ - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eType != OPERAND_TYPE_TEMP) - return; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; - psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex + 1]; - psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex + 2]; - psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex + 3]; - } - else - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - psOperand->aeDataType[psOperand->aui32Swizzle[1]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[1]]; - psOperand->aeDataType[psOperand->aui32Swizzle[2]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[2]]; - psOperand->aeDataType[psOperand->aui32Swizzle[3]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[3]]; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; - } - } - } -} - -// Mark scalars from CBs. TODO: Do we need to do the same for vec2/3's as well? There may be swizzles involved which make it vec4 or something else again. -static void GLSLSetCBOperandComponents(HLSLCrossCompilerContext* psContext, Operand* psOperand) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - int rebase = 0; - - if (psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER) - return; - - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - - if (psVarType->Class == SVC_SCALAR) - psOperand->iNumComponents = 1; -} - -void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount) -{ - int32_t i; - Instruction* psFirstInst = psInst; - - SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; - - if (psContext->psShader->ui32MajorVersion <= 3) - { - for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) - { - aeTempVecType[i] = SVT_FLOAT; - } - } - else - { - // Start with void, then move up the chain void->int->uint->float - for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) - { - aeTempVecType[i] = SVT_VOID; - } - } - - // if (psContext->psShader->ui32MajorVersion <= 3) - { - // First pass, do analysis: deduce the data type based on opcodes, fill out aeTempVecType table - // Only ever to int->float promotion (or int->uint), never the other way around - for (i = 0; i < i32InstCount; ++i, psInst++) - { - if (psInst->ui32NumOperands == 0) - continue; - - switch (psInst->eOpcode) - { - // All float-only ops - case OPCODE_ADD: - case OPCODE_DERIV_RTX: - case OPCODE_DERIV_RTY: - case OPCODE_DIV: - case OPCODE_DP2: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_EQ: - case OPCODE_EXP: - case OPCODE_FRC: - case OPCODE_LOG: - case OPCODE_MAD: - case OPCODE_MIN: - case OPCODE_MAX: - case OPCODE_MUL: - case OPCODE_NE: - case OPCODE_ROUND_NE: - case OPCODE_ROUND_NI: - case OPCODE_ROUND_PI: - case OPCODE_ROUND_Z: - case OPCODE_RSQ: - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_D: - case OPCODE_SAMPLE_B: - case OPCODE_SQRT: - case OPCODE_SINCOS: - case OPCODE_LOD: - case OPCODE_GATHER4: - - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_GATHER4_C: - case OPCODE_GATHER4_PO: - case OPCODE_GATHER4_PO_C: - case OPCODE_RCP: - - GLSLMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); - break; - - // Int-only ops, no need to do anything - case OPCODE_AND: - case OPCODE_BREAKC: - case OPCODE_CALLC: - case OPCODE_CONTINUEC: - case OPCODE_IADD: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_IF: - case OPCODE_NOT: - case OPCODE_OR: - case OPCODE_RETC: - case OPCODE_XOR: - case OPCODE_BUFINFO: - case OPCODE_COUNTBITS: - case OPCODE_FIRSTBIT_HI: - case OPCODE_FIRSTBIT_LO: - case OPCODE_FIRSTBIT_SHI: - case OPCODE_UBFE: - case OPCODE_IBFE: - case OPCODE_BFI: - case OPCODE_BFREV: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_MOV: - case OPCODE_MOVC: - case OPCODE_SWAPC: - GLSLMarkAllOperandsAs(psInst, SVT_INT, aeTempVecType); - break; - // uint ops - case OPCODE_UDIV: - case OPCODE_ULT: - case OPCODE_UGE: - case OPCODE_UMUL: - case OPCODE_UMAD: - case OPCODE_UMAX: - case OPCODE_UMIN: - case OPCODE_USHR: - case OPCODE_UADDC: - case OPCODE_USUBB: - GLSLMarkAllOperandsAs(psInst, SVT_UINT, aeTempVecType); - break; - - // Need special handling - case OPCODE_FTOI: - case OPCODE_FTOU: - GLSLMarkOperandAs(&psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOI ? SVT_INT : SVT_UINT, aeTempVecType); - GLSLMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_GE: - case OPCODE_LT: - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_UINT, aeTempVecType); - GLSLMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); - GLSLMarkOperandAs(&psInst->asOperands[2], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_ITOF: - case OPCODE_UTOF: - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - GLSLMarkOperandAs(&psInst->asOperands[1], psInst->eOpcode == OPCODE_ITOF ? SVT_INT : SVT_UINT, aeTempVecType); - break; - - case OPCODE_LD: - case OPCODE_LD_MS: - // TODO: Would need to know the sampler return type - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_RESINFO: - { - if (psInst->eResInfoReturnType != RESINFO_INSTRUCTION_RETURN_UINT) - GLSLMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); - break; - } - - case OPCODE_SAMPLE_INFO: - // TODO decode the _uint flag - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_SAMPLE_POS: - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_LD_UAV_TYPED: - case OPCODE_STORE_UAV_TYPED: - case OPCODE_LD_RAW: - case OPCODE_STORE_RAW: - case OPCODE_LD_STRUCTURED: - case OPCODE_STORE_STRUCTURED: - GLSLMarkOperandAs(&psInst->asOperands[0], SVT_INT, aeTempVecType); - break; - - case OPCODE_F32TOF16: - case OPCODE_F16TOF32: - // TODO - break; - - // No-operands, should never get here anyway - /* case OPCODE_BREAK: - case OPCODE_CALL: - case OPCODE_CASE: - case OPCODE_CONTINUE: - case OPCODE_CUT: - case OPCODE_DEFAULT: - case OPCODE_DISCARD: - case OPCODE_ELSE: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_ENDIF: - case OPCODE_ENDLOOP: - case OPCODE_ENDSWITCH: - - case OPCODE_LABEL: - case OPCODE_LOOP: - case OPCODE_CUSTOMDATA: - case OPCODE_NOP: - case OPCODE_RET: - case OPCODE_SWITCH: - case OPCODE_DCL_RESOURCE: // DCL* opcodes have - case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. - case OPCODE_DCL_SAMPLER: - case OPCODE_DCL_INDEX_RANGE: - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - case OPCODE_DCL_INPUT: - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_SIV: - case OPCODE_DCL_INPUT_PS: - case OPCODE_DCL_INPUT_PS_SGV: - case OPCODE_DCL_INPUT_PS_SIV: - case OPCODE_DCL_OUTPUT: - case OPCODE_DCL_OUTPUT_SGV: - case OPCODE_DCL_OUTPUT_SIV: - case OPCODE_DCL_TEMPS: - case OPCODE_DCL_INDEXABLE_TEMP: - case OPCODE_DCL_GLOBAL_FLAGS: - - - case OPCODE_HS_DECLS: // token marks beginning of HS sub-shader - case OPCODE_HS_CONTROL_POINT_PHASE: // token marks beginning of HS sub-shader - case OPCODE_HS_FORK_PHASE: // token marks beginning of HS sub-shader - case OPCODE_HS_JOIN_PHASE: // token marks beginning of HS sub-shader - - case OPCODE_EMIT_STREAM: - case OPCODE_CUT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - case OPCODE_INTERFACE_CALL: - - - case OPCODE_DCL_STREAM: - case OPCODE_DCL_FUNCTION_BODY: - case OPCODE_DCL_FUNCTION_TABLE: - case OPCODE_DCL_INTERFACE: - - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - case OPCODE_DCL_TESS_DOMAIN: - case OPCODE_DCL_TESS_PARTITIONING: - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - case OPCODE_DCL_HS_MAX_TESSFACTOR: - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - case OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: - - case OPCODE_DCL_THREAD_GROUP: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - case OPCODE_DCL_RESOURCE_RAW: - case OPCODE_DCL_RESOURCE_STRUCTURED: - case OPCODE_SYNC: - - // TODO - case OPCODE_DADD: - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_DTOF: - case OPCODE_FTOD: - - case OPCODE_EVAL_SNAPPED: - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_CENTROID: - - case OPCODE_DCL_GS_INSTANCE_COUNT: - - case OPCODE_ABORT: - case OPCODE_DEBUG_BREAK:*/ - - default: - break; - } - } - } - - // Fill the rest of aeTempVecType, just in case. - for (i = 0; i < MAX_TEMP_VEC4 * 4; i++) - { - if (aeTempVecType[i] == SVT_VOID) - aeTempVecType[i] = SVT_INT; - } - - // Now the aeTempVecType table has been filled with (mostly) valid data, write it back to all operands - psInst = psFirstInst; - for (i = 0; i < i32InstCount; ++i, psInst++) - { - int k = 0; - - if (psInst->ui32NumOperands == 0) - continue; - - // Preserve the current type on dest array index - if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) - { - Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; - if (psSubOperand != 0) - { - GLSLWriteOperandTypes(psSubOperand, aeTempVecType); - } - } - if (psInst->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) - GLSLSetCBOperandComponents(psContext, &psInst->asOperands[0]); - - // Preserve the current type on sources. - for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) - { - int32_t subOperand; - Operand* psOperand = &psInst->asOperands[k]; - - GLSLWriteOperandTypes(psOperand, aeTempVecType); - if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - GLSLSetCBOperandComponents(psContext, psOperand); - - for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) - { - if (psOperand->psSubOperand[subOperand] != 0) - { - Operand* psSubOperand = psOperand->psSubOperand[subOperand]; - GLSLWriteOperandTypes(psSubOperand, aeTempVecType); - if (psSubOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - GLSLSetCBOperandComponents(psContext, psSubOperand); - } - } - - // Set immediates - if (GLSLIsIntegerImmediateOpcode(psInst->eOpcode)) - { - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) - { - psOperand->iIntegerImmediate = 1; - } - } - } - - // Process the destination last in order to handle instructions - // where the destination register is also used as a source. - for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) - { - Operand* psOperand = &psInst->asOperands[k]; - GLSLWriteOperandTypes(psOperand, aeTempVecType); - } - } -} - -void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst) -{ - bstring glsl = *psContext->currentShaderString; - int numParenthesis = 0; - -#ifdef _DEBUG - AddIndentation(psContext); - bformata(glsl, "//Instruction %d\n", psInst->id); -#if 0 - if(psInst->id == 73) - { - ASSERT(1); //Set breakpoint here to debug an instruction from its ID. - } -#endif -#endif - - switch (psInst->eOpcode) - { - case OPCODE_FTOI: - case OPCODE_FTOU: - { - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_FTOU) - bcatcstr(glsl, "//FTOU\n"); - else - bcatcstr(glsl, "//FTOI\n"); -#endif - - AddIndentation(psContext); - - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); - bcatcstr(glsl, GetConstructorForType(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); - bcatcstr(glsl, "("); // 1 - TranslateOperand(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(glsl, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - AddSwizzleUsingElementCount(psContext, dstCount); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - - case OPCODE_MOV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MOV\n"); -#endif - AddIndentation(psContext); - GLSLAddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1]); - break; - } - case OPCODE_ITOF: // signed to float - case OPCODE_UTOF: // unsigned to float - { - uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_ITOF) - { - bcatcstr(glsl, "//ITOF\n"); - } - else - { - bcatcstr(glsl, "//UTOF\n"); - } -#endif - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, srcCount, &numParenthesis); - bcatcstr(glsl, GetConstructorForType(SVT_FLOAT, srcCount == dstCount ? dstCount : 4)); - bcatcstr(glsl, "("); // 1 - TranslateOperand(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT); - bcatcstr(glsl, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - AddSwizzleUsingElementCount(psContext, dstCount); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_MAD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MAD\n"); -#endif - GLSLCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_NONE); - break; - } - case OPCODE_IMAD: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMAD\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - GLSLCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); - break; - } - case OPCODE_DADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DADD\n"); -#endif - GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_DOUBLE); - break; - } - case OPCODE_IADD: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IADD\n"); -#endif - // Is this a signed or unsigned add? - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ADD\n"); -#endif - GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_OR: - { - /*Todo: vector version */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//OR\n"); -#endif - GLSLCallBinaryOp(psContext, "|", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//AND\n"); -#endif - GLSLCallBinaryOp(psContext, "&", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_GE: - { - /* - dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); - Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. - */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GE\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_MUL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MUL\n"); -#endif - GLSLCallBinaryOp(psContext, "*", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_IMUL: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMUL\n"); -#endif - if (GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_UINT) - { - eType = SVT_UINT; - } - - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); - - GLSLCallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); - break; - } - case OPCODE_UDIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UDIV\n"); -#endif - // destQuotient, destRemainder, src0, src1 - GLSLCallBinaryOp(psContext, "/", psInst, 0, 2, 3, SVT_UINT); - GLSLCallBinaryOp(psContext, "%", psInst, 1, 2, 3, SVT_UINT); - break; - } - case OPCODE_DIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DIV\n"); -#endif - GLSLCallBinaryOp(psContext, "/", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_SINCOS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SINCOS\n"); -#endif - // Need careful ordering if src == dest[0], as then the cos() will be reading from wrong value - if (psInst->asOperands[0].eType == psInst->asOperands[2].eType && - psInst->asOperands[0].ui32RegisterNumber == psInst->asOperands[2].ui32RegisterNumber) - { - // sin() result overwrites source, do cos() first. - // The case where both write the src shouldn't really happen anyway. - if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) - { - GLSLCallHelper1(psContext, "cos", psInst, 1, 2, 1); - } - - if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) - { - GLSLCallHelper1(psContext, "sin", psInst, 0, 2, 1); - } - } - else - { - if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) - { - GLSLCallHelper1(psContext, "sin", psInst, 0, 2, 1); - } - - if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) - { - GLSLCallHelper1(psContext, "cos", psInst, 1, 2, 1); - } - } - break; - } - - case OPCODE_DP2: - { - int numParenthesis2 = 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP2\n"); -#endif - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); - bcatcstr(glsl, "dot("); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT, 3 /* .xy */); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT, 3 /* .xy */); - bcatcstr(glsl, ")"); - GLSLAddAssignPrologue(psContext, numParenthesis2); - break; - } - case OPCODE_DP3: - { - int numParenthesis2 = 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP3\n"); -#endif - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); - bcatcstr(glsl, "dot("); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT, 7 /* .xyz */); - bcatcstr(glsl, ", "); - TranslateOperandWithMask(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT, 7 /* .xyz */); - bcatcstr(glsl, ")"); - GLSLAddAssignPrologue(psContext, numParenthesis2); - break; - } - case OPCODE_DP4: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP4\n"); -#endif - GLSLCallHelper2(psContext, "dot", psInst, 0, 1, 2, 0); - break; - } - case OPCODE_INE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INE\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_NE, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//NE\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_NE, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_IGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IGE\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_INTEGER, psNextInst); - break; - } - case OPCODE_ILT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ILT\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_LT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LT\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_IEQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IEQ\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_EQ, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_ULT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ULT\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_UNSIGNED_INTEGER, NULL); - break; - } - case OPCODE_UGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//UGE\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_UNSIGNED_INTEGER, NULL); - break; - } - case OPCODE_MOVC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MOVC\n"); -#endif - GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); - break; - } - case OPCODE_SWAPC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SWAPC\n"); -#endif - // TODO needs temps!! - GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); - GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); - break; - } - - case OPCODE_LOG: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOG\n"); -#endif - GLSLCallHelper1(psContext, "log2", psInst, 0, 1, 1); - break; - } - case OPCODE_RSQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RSQ\n"); -#endif - GLSLCallHelper1(psContext, "inversesqrt", psInst, 0, 1, 1); - break; - } - case OPCODE_EXP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EXP\n"); -#endif - GLSLCallHelper1(psContext, "exp2", psInst, 0, 1, 1); - break; - } - case OPCODE_SQRT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SQRT\n"); -#endif - GLSLCallHelper1(psContext, "sqrt", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_PI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_PI\n"); -#endif - GLSLCallHelper1(psContext, "ceil", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_NI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_NI\n"); -#endif - GLSLCallHelper1(psContext, "floor", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_Z: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_Z\n"); -#endif - GLSLCallHelper1(psContext, "trunc", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ROUND_NE\n"); -#endif - GLSLCallHelper1(psContext, "roundEven", psInst, 0, 1, 1); - break; - } - case OPCODE_FRC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FRC\n"); -#endif - GLSLCallHelper1(psContext, "fract", psInst, 0, 1, 1); - break; - } - case OPCODE_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMAX\n"); -#endif - GLSLCallHelper2Int(psContext, "max", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_MAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MAX\n"); -#endif - GLSLCallHelper2(psContext, "max", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMIN\n"); -#endif - GLSLCallHelper2Int(psContext, "min", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_MIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//MIN\n"); -#endif - GLSLCallHelper2(psContext, "min", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_GATHER4: - { - // dest, coords, tex, sampler - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4\n"); -#endif - // gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x - AddIndentation(psContext); // TODO FIXME integer samplers - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(glsl, "textureGather("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); - - bcatcstr(glsl, ", "); - GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(glsl, ")"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_GATHER4_PO_C: - { - // dest, coords, offset, tex, sampler, srcReferenceValue - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_PO_C\n"); -#endif - - AddIndentation(psContext); // TODO FIXME integer samplers - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(glsl, "textureGatherOffset("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 1); - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - - bcatcstr(glsl, ", "); - - GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_NONE); - - bcatcstr(glsl, ", ivec2("); - // ivec2 offset - psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_GATHER4_PO: - { - // dest, coords, offset, tex, sampler - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_PO\n"); -#endif - - AddIndentation(psContext); // TODO FIXME integer samplers - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(glsl, "textureGatherOffset("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 0); - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0)); - - bcatcstr(glsl, ", "); - // Texture coord cannot be vec4 - // Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - - bcatcstr(glsl, ", ivec2("); - // ivec2 offset - psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_GATHER4_C: - { - // dest, coords, tex, sampler srcReferenceValue - const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//GATHER4_C\n"); -#endif - - AddIndentation(psContext); // TODO FIXME integer samplers - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(glsl, "textureGather("); - - if (!useCombinedTextureSamplers) - ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); - else - bconcat(glsl, - TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - - bcatcstr(glsl, ", "); - // Texture coord cannot be vec4 - // Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_NONE); - bcatcstr(glsl, ")"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); - AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_SAMPLE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE\n"); -#endif - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); - break; - } - case OPCODE_SAMPLE_L: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_L\n"); -#endif - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); - break; - } - case OPCODE_SAMPLE_C: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_C\n"); -#endif - - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE); - break; - } - case OPCODE_SAMPLE_C_LZ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_C_LZ\n"); -#endif - - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE | TEXSMP_FLAG_FIRSTLOD); - break; - } - case OPCODE_SAMPLE_D: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_D\n"); -#endif - - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); - break; - } - case OPCODE_SAMPLE_B: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SAMPLE_B\n"); -#endif - - GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); - break; - } - case OPCODE_RET: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RET\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - } - AddIndentation(psContext); - bcatcstr(glsl, "return;\n"); - break; - } - case OPCODE_INTERFACE_CALL: - { - const char* name; - ShaderVar* psVar; - uint32_t varFound; - - uint32_t funcPointer; - uint32_t funcTableIndex; - uint32_t funcTable; - uint32_t funcBodyIndex; - uint32_t funcBody; - uint32_t ui32NumBodiesPerTable; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INTERFACE_CALL\n"); -#endif - - ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); - - funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; - funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; - funcBodyIndex = psInst->ui32FuncIndexWithinInterface; - - ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; - - funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; - - funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; - - varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); - - ASSERT(varFound); - - name = &psVar->Name[0]; - - AddIndentation(psContext); - bcatcstr(glsl, name); - TranslateOperandIndexMAD(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); - // bformata(glsl, "[%d]", funcBodyIndex); - bcatcstr(glsl, "();\n"); - break; - } - case OPCODE_LABEL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LABEL\n"); -#endif - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); // Closing brace ends the previous function. - AddIndentation(psContext); - - bcatcstr(glsl, "subroutine(SubroutineType)\n"); - bcatcstr(glsl, "void "); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, "(){\n"); - ++psContext->indent; - break; - } - case OPCODE_COUNTBITS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//COUNTBITS\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(glsl, " = bitCount("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_FIRSTBIT_HI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_HI\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(glsl, " = findMSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_FIRSTBIT_LO: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_LO\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(glsl, " = findLSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_FIRSTBIT_SHI: // signed high - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//FIRSTBIT_SHI\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(glsl, " = findMSB("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_BFREV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BFREV\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(glsl, " = bitfieldReverse("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_BFI: - { - uint32_t numelements_width = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t numelements_offset = GetNumSwizzleElements(&psInst->asOperands[2]); - uint32_t numelements_dest = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t numoverall_elements = min(min(numelements_width, numelements_offset), numelements_dest); - uint32_t i, j; - static const char* bfi_elementidx[] = {"x", "y", "z", "w"}; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BFI\n"); -#endif - - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bformata(glsl, " = ivec%d(", numoverall_elements); - for (i = 0; i < numoverall_elements; ++i) - { - bcatcstr(glsl, "bitfieldInsert("); - - for (j = 4; j >= 1; --j) - { - uint32_t opSwizzleCount = GetNumSwizzleElements(&psInst->asOperands[j]); - - if (opSwizzleCount != 1) - bcatcstr(glsl, " ("); - TranslateOperand(psContext, &psInst->asOperands[j], TO_FLAG_INTEGER); - if (opSwizzleCount != 1) - bformata(glsl, " ).%s", bfi_elementidx[i]); - if (j != 1) - bcatcstr(glsl, ","); - } - - bcatcstr(glsl, ") "); - if (i + 1 != numoverall_elements) - bcatcstr(glsl, ", "); - } - - bcatcstr(glsl, ")."); - for (i = 0; i < numoverall_elements; ++i) - bformata(glsl, "%s", bfi_elementidx[i]); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_CUT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EndPrimitive();\n"); - break; - } - case OPCODE_EMIT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMIT\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - } - - AddIndentation(psContext); - bcatcstr(glsl, "EmitVertex();\n"); - break; - } - case OPCODE_EMITTHENCUT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMITTHENCUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EmitVertex();\nEndPrimitive();\n"); - break; - } - - case OPCODE_CUT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EndStreamPrimitive("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - - break; - } - case OPCODE_EMIT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMIT_STREAM\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- Post shader code ---\n"); -#endif - bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//--- End post shader code ---\n"); -#endif - } - - AddIndentation(psContext); - bcatcstr(glsl, "EmitStreamVertex("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_EMITTHENCUT_STREAM: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EMITTHENCUT\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "EmitStreamVertex("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - bcatcstr(glsl, "EndStreamPrimitive("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_REP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//REP\n"); -#endif - // Need to handle nesting. - // Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx - - AddIndentation(psContext); - bcatcstr(glsl, "RepCounter = "); - TranslateOperandWithMask(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(glsl, ";\n"); - - AddIndentation(psContext); - bcatcstr(glsl, "while(RepCounter!=0){\n"); - ++psContext->indent; - break; - } - case OPCODE_ENDREP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ENDREP\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "RepCounter--;\n"); - - --psContext->indent; - - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_LOOP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOOP\n"); -#endif - AddIndentation(psContext); - - if (psInst->ui32NumOperands == 2) - { - // DX9 version - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); - bcatcstr(glsl, "for("); - bcatcstr(glsl, "LoopCounter = "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".y, ZeroBasedCounter = 0;"); - bcatcstr(glsl, "ZeroBasedCounter < "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".x;"); - - bcatcstr(glsl, "LoopCounter += "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ".z, ZeroBasedCounter++){\n"); - ++psContext->indent; - } - else - { - bcatcstr(glsl, "while(true){\n"); - ++psContext->indent; - } - break; - } - case OPCODE_ENDLOOP: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ENDLOOP\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_BREAK: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BREAK\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "break;\n"); - break; - } - case OPCODE_BREAKC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//BREAKC\n"); -#endif - AddIndentation(psContext); - - GLSLTranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_CONTINUEC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//CONTINUEC\n"); -#endif - AddIndentation(psContext); - - GLSLTranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_IF: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IF\n"); -#endif - AddIndentation(psContext); - - GLSLTranslateConditional(psContext, psInst, glsl); - ++psContext->indent; - break; - } - case OPCODE_RETC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RETC\n"); -#endif - AddIndentation(psContext); - - GLSLTranslateConditional(psContext, psInst, glsl); - break; - } - case OPCODE_ELSE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ELSE\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "} else {\n"); - psContext->indent++; - break; - } - case OPCODE_ENDSWITCH: - case OPCODE_ENDIF: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "//ENDIF\n"); - AddIndentation(psContext); - bcatcstr(glsl, "}\n"); - break; - } - case OPCODE_CONTINUE: - { - AddIndentation(psContext); - bcatcstr(glsl, "continue;\n"); - break; - } - case OPCODE_DEFAULT: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(glsl, "default:\n"); - ++psContext->indent; - break; - } - case OPCODE_NOP: - { - break; - } - case OPCODE_SYNC: - { - const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SYNC\n"); -#endif - - if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) - { - AddIndentation(psContext); - bcatcstr(glsl, "groupMemoryBarrier();\n"); - } - if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) - { - AddIndentation(psContext); - bcatcstr(glsl, "memoryBarrierShared();\n"); - } - if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) - { - AddIndentation(psContext); - bcatcstr(glsl, "memoryBarrier();\n"); - } - break; - } - case OPCODE_SWITCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//SWITCH\n"); -#endif - AddIndentation(psContext); - bcatcstr(glsl, "switch(int("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")){\n"); - - psContext->indent += 2; - break; - } - case OPCODE_CASE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//case\n"); -#endif - AddIndentation(psContext); - - bcatcstr(glsl, "case "); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ":\n"); - - ++psContext->indent; - break; - } - case OPCODE_EQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EQ\n"); -#endif - GLSLAddComparision(psContext, psInst, GLSL_CMP_EQ, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_USHR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//USHR\n"); -#endif - GLSLCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_ISHL: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ISHL\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - - GLSLCallBinaryOp(psContext, "<<", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_ISHR: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//ISHR\n"); -#endif - - if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - - GLSLCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_LD: - case OPCODE_LD_MS: - { - ResourceBinding* psBinding = 0; -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_LD) - bcatcstr(glsl, "//LD\n"); - else - bcatcstr(glsl, "//LD_MS\n"); -#endif - - GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - - if (psInst->bAddressOffset) - { - GLSLTranslateTexelFetchOffset(psContext, psInst, psBinding, glsl); - } - else - { - GLSLTranslateTexelFetch(psContext, psInst, psBinding, glsl); - } - break; - } - case OPCODE_DISCARD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DISCARD\n"); -#endif - AddIndentation(psContext); - if (psContext->psShader->ui32MajorVersion <= 3) - { - bcatcstr(glsl, "if(any(lessThan(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); - - if (psContext->psShader->ui32MajorVersion == 1) - { - /* SM1.X only kills based on the rgb channels */ - bcatcstr(glsl, ").xyz, vec3(0)))){discard;}\n"); - } - else - { - bcatcstr(glsl, "), vec4(0)))){discard;}\n"); - } - } - else if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")==0){discard;}\n"); - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(glsl, "if(("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")!=0){discard;}\n"); - } - break; - } - case OPCODE_LOD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LOD\n"); -#endif - // LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) - - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 4, &numParenthesis); - - // If the core language does not have query-lod feature, - // then the extension is used. The name of the function - // changed between extension and core. - if (HaveQueryLod(psContext->psShader->eTargetLanguage)) - { - bcatcstr(glsl, "textureQueryLod("); - } - else - { - bcatcstr(glsl, "textureQueryLOD("); - } - - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ","); - GLSLTranslateTexCoord(psContext, psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], &psInst->asOperands[1]); - bcatcstr(glsl, ")"); - - // The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. - - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[2], GetOperandWriteMask(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_EVAL_CENTROID: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_CENTROID\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = interpolateAtCentroid("); - // interpolateAtCentroid accepts in-qualified variables. - // As long as bytecode only writes vX registers in declarations - // we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_EVAL_SAMPLE_INDEX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_SAMPLE_INDEX\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = interpolateAtSample("); - // interpolateAtSample accepts in-qualified variables. - // As long as bytecode only writes vX registers in declarations - // we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_EVAL_SNAPPED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//EVAL_SNAPPED\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = interpolateAtOffset("); - // interpolateAtOffset accepts in-qualified variables. - // As long as bytecode only writes vX registers in declarations - // we should be able to use the declared name directly. - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); - bcatcstr(glsl, ".xy);\n"); - break; - } - case OPCODE_LD_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_STRUCTURED\n"); -#endif - GLSLTranslateShaderStorageLoad(psContext, psInst); - break; - } - case OPCODE_LD_UAV_TYPED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_UAV_TYPED\n"); -#endif - switch (psInst->eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = imageLoad("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").x)"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - bcatcstr(glsl, ";\n"); - break; - case RESOURCE_DIMENSION_TEXTURECUBE: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE2DMS: - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = imageLoad("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").xy)"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - bcatcstr(glsl, ";\n"); - break; - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = imageLoad("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ", ("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bformata(glsl, ").xyz)"); - TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); - bcatcstr(glsl, ";\n"); - break; - } - break; - } - case OPCODE_STORE_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_RAW\n"); -#endif - GLSLTranslateShaderStorageStore(psContext, psInst); - break; - } - case OPCODE_STORE_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_STRUCTURED\n"); -#endif - GLSLTranslateShaderStorageStore(psContext, psInst); - break; - } - - case OPCODE_STORE_UAV_TYPED: - { - ResourceBinding* psRes; - int foundResource; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//STORE_UAV_TYPED\n"); -#endif - AddIndentation(psContext); - - foundResource = GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); - - ASSERT(foundResource); - - bcatcstr(glsl, "imageStore("); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); - switch (psRes->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - bcatcstr(glsl, ", int("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, "), "); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - bcatcstr(glsl, ", ivec2("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ".xy), "); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - bcatcstr(glsl, ", ivec3("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ".xyz), "); - break; - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - bcatcstr(glsl, ", ivec4("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(glsl, ".xyzw) "); - break; - }; - - TranslateOperand(psContext, &psInst->asOperands[2], GLSLResourceReturnTypeToFlag(psRes->ui32ReturnType)); - bformata(glsl, ");\n"); - - break; - } - case OPCODE_LD_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LD_RAW\n"); -#endif - - GLSLTranslateShaderStorageLoad(psContext, psInst); - break; - } - - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - TranslateAtomicMemOp(psContext, psInst); - break; - } - case OPCODE_UBFE: - case OPCODE_IBFE: - { -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_UBFE) - bcatcstr(glsl, "//OPCODE_UBFE\n"); - else - bcatcstr(glsl, "//OPCODE_IBFE\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = bitfieldExtract("); - TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ", "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, ");\n"); - break; - } - case OPCODE_RCP: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RCP\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = (vec4(1.0) / vec4("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, "))"); - AddSwizzleUsingElementCount(psContext, destElemCount); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_F32TOF16: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//F32TOF16\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = {".x", ".y", ".z", ".w"}; - - // unpackHalf2x16 converts two f16s packed into uint to two f32s. - - // dest.swiz.x = unpackHalf2x16(src.swiz.x).x - // dest.swiz.y = unpackHalf2x16(src.swiz.y).x - // dest.swiz.z = unpackHalf2x16(src.swiz.z).x - // dest.swiz.w = unpackHalf2x16(src.swiz.w).x - - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - if (destElemCount > 1) - bcatcstr(glsl, swizzle[destElem]); - - bcatcstr(glsl, " = unpackHalf2x16("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - if (s0ElemCount > 1) - bcatcstr(glsl, swizzle[destElem]); - bcatcstr(glsl, ").x;\n"); - } - break; - } - case OPCODE_F16TOF32: - { - const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//F16TOF32\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = {".x", ".y", ".z", ".w"}; - - // packHalf2x16 converts two f32s to two f16s packed into a uint. - - // dest.swiz.x = packHalf2x16(vec2(src.swiz.x)) & 0xFFFF - // dest.swiz.y = packHalf2x16(vec2(src.swiz.y)) & 0xFFFF - // dest.swiz.z = packHalf2x16(vec2(src.swiz.z)) & 0xFFFF - // dest.swiz.w = packHalf2x16(vec2(src.swiz.w)) & 0xFFFF - - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_UNSIGNED_INTEGER); - if (destElemCount > 1) - bcatcstr(glsl, swizzle[destElem]); - - bcatcstr(glsl, " = packHalf2x16(vec2("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - if (s0ElemCount > 1) - bcatcstr(glsl, swizzle[destElem]); - bcatcstr(glsl, ")) & 0xFFFF;\n"); - } - break; - } - case OPCODE_INEG: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INEG\n"); -#endif - // dest = 0 - src0 - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_INTEGER); - bcatcstr(glsl, " = 0 - "); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DERIV_RTX\n"); -#endif - GLSLCallHelper1(psContext, "dFdx", psInst, 0, 1, 1); - break; - } - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_DERIV_RTY: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DERIV_RTY\n"); -#endif - GLSLCallHelper1(psContext, "dFdy", psInst, 0, 1, 1); - break; - } - case OPCODE_LRP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//LRP\n"); -#endif - GLSLCallHelper3(psContext, "mix", psInst, 0, 2, 3, 1, 1); - break; - } - case OPCODE_DP2ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//DP2ADD\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = dot(vec2("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, "), vec2("); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ")) + "); - TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_NONE); - bcatcstr(glsl, ";\n"); - break; - } - case OPCODE_POW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//POW\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = pow(abs("); - TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(glsl, "), "); - TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(glsl, ");\n"); - break; - } - - case OPCODE_IMM_ATOMIC_ALLOC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_ALLOC\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(glsl, " = int(atomicCounterIncrement("); - ResourceName(glsl, psContext, RGROUP_UAV, psInst->asOperands[1].ui32RegisterNumber, 0); - bformata(glsl, "_counter"); - bcatcstr(glsl, "));\n"); - break; - } - case OPCODE_IMM_ATOMIC_CONSUME: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//IMM_ATOMIC_CONSUME\n"); -#endif - AddIndentation(psContext); - TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - // Temps are always signed and atomci counters are always unsigned - // at the moment. - bcatcstr(glsl, " = int(atomicCounterDecrement("); - ResourceName(glsl, psContext, RGROUP_UAV, psInst->asOperands[1].ui32RegisterNumber, 0); - bformata(glsl, "_counter"); - bcatcstr(glsl, "));\n"); - break; - } - - case OPCODE_NOT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//INOT\n"); -#endif - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, GetNumSwizzleElements(&psInst->asOperands[1]), &numParenthesis); - - bcatcstr(glsl, "~"); - TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, GetOperandWriteMask(&psInst->asOperands[0])); - GLSLAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//XOR\n"); -#endif - - GLSLCallBinaryOp(psContext, "^", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_RESINFO: - { - uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(glsl, "//RESINFO\n"); -#endif - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - - GetResInfoData(psContext, psInst, psInst->asOperands[2].aui32Swizzle[destElem], destElem); - } - - break; - } - - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_DTOF: - case OPCODE_FTOD: - case OPCODE_DDIV: - case OPCODE_DFMA: - case OPCODE_DRCP: - case OPCODE_MSAD: - case OPCODE_DTOI: - case OPCODE_DTOU: - case OPCODE_ITOD: - case OPCODE_UTOD: - default: - { - ASSERT(0); - break; - } - } - - if (psInst->bSaturate) // Saturate is only for floating point data (float opcodes or MOV) - { - int dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); - AddIndentation(psContext); - GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, dstCount, &numParenthesis); - bcatcstr(glsl, "clamp("); - - TranslateOperand(psContext, &psInst->asOperands[0], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(glsl, ", 0.0, 1.0)"); - GLSLAddAssignPrologue(psContext, numParenthesis); - } -} - -static int GLSLIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode) -{ - switch (eOpcode) - { - case OPCODE_IADD: - case OPCODE_IF: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_ITOF: - case OPCODE_USHR: - case OPCODE_AND: - case OPCODE_OR: - case OPCODE_XOR: - case OPCODE_BREAKC: - case OPCODE_CONTINUEC: - case OPCODE_RETC: - case OPCODE_DISCARD: - // MOV is typeless. - // Treat immediates as int, bitcast to float if necessary - case OPCODE_MOV: - case OPCODE_MOVC: - { - return 1; - } - default: - { - return 0; - } - } -} - -int InstructionUsesRegister(const Instruction* psInst, const Operand* psOperand) -{ - uint32_t operand; - for (operand = 0; operand < psInst->ui32NumOperands; ++operand) - { - if (psInst->asOperands[operand].eType == psOperand->eType) - { - if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) - { - if (CompareOperandSwizzles(&psInst->asOperands[operand], psOperand)) - { - return 1; - } - } - } - } - return 0; -} - -void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext) -{ - const uint32_t count = psContext->psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; - Instruction* psInst = psContext->psShader->asPhase[MAIN_PHASE].ppsInst[0]; - uint32_t i; - - for (i = 0; i < count;) - { - if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) - { - uint32_t k; - - for (k = i + 1; k < count; ++k) - { - if (psInst[k].eOpcode == OPCODE_ILT) - { - k = k; - } - if (InstructionUsesRegister(&psInst[k], &psInst[i].asOperands[0])) - { - if (GLSLIsIntegerImmediateOpcode(psInst[k].eOpcode)) - { - psInst[i].asOperands[1].iIntegerImmediate = 1; - } - - goto next_iteration; - } - } - } - next_iteration: - ++i; - } -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c deleted file mode 100644 index f6595ad2cf..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c +++ /dev/null @@ -1,1869 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toGLSLOperand.h" -#include "bstrlib.h" -#include "hlslcc.h" -#include "internal_includes/debug.h" -#include "internal_includes/toGLSLDeclaration.h" - -#include <float.h> -#include <stdlib.h> - -#ifdef _MSC_VER -#define isnan(x) _isnan(x) -#define isinf(x) (!_finite(x)) -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType) -{ - if (eType == SVT_UINT) - { - return TO_FLAG_UNSIGNED_INTEGER; - } - else if (eType == SVT_INT) - { - return TO_FLAG_INTEGER; - } - else if (eType == SVT_BOOL) - { - return TO_FLAG_INTEGER; // TODO bools? - } - else - { - return TO_FLAG_NONE; - } -} - -SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags) -{ - if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT)) - return SVT_INT; - if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT)) - return SVT_UINT; - return SVT_FLOAT; -} - -uint32_t GetOperandWriteMask(const Operand* psOperand) -{ - if (psOperand->eSelMode != OPERAND_4_COMPONENT_MASK_MODE || psOperand->ui32CompMask == 0) - return OPERAND_4_COMPONENT_MASK_ALL; - - return psOperand->ui32CompMask; -} - -const char* GetConstructorForType(const SHADER_VARIABLE_TYPE eType, const int components) -{ - static const char* const uintTypes[] = {" ", "uint", "uvec2", "uvec3", "uvec4"}; - static const char* const intTypes[] = {" ", "int", "ivec2", "ivec3", "ivec4"}; - static const char* const floatTypes[] = {" ", "float", "vec2", "vec3", "vec4"}; - - if (components < 1 || components > 4) - return "ERROR TOO MANY COMPONENTS IN VECTOR"; - - switch (eType) - { - case SVT_UINT: - return uintTypes[components]; - case SVT_INT: - return intTypes[components]; - case SVT_FLOAT: - return floatTypes[components]; - default: - return "ERROR UNSUPPORTED TYPE"; - } -} - -const char* GetConstructorForTypeFlag(const uint32_t ui32Flag, const int components) -{ - if (ui32Flag & TO_FLAG_UNSIGNED_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_UINT) - { - return GetConstructorForType(SVT_UINT, components); - } - else if (ui32Flag & TO_FLAG_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_INT) - { - return GetConstructorForType(SVT_INT, components); - } - else - { - return GetConstructorForType(SVT_FLOAT, components); - } -} - -int GetMaxComponentFromComponentMask(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) - { - // Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && - psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 4; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 3; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 1; - } - } - } - else - // Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - return 4; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return 1; - } - } - - return 4; -} - -// Single component repeated -// e..g .wwww -uint32_t IsSwizzleReplicated(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) - { - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == WWWW_SWIZZLE || psOperand->ui32Swizzle == ZZZZ_SWIZZLE || psOperand->ui32Swizzle == YYYY_SWIZZLE || - psOperand->ui32Swizzle == XXXX_SWIZZLE) - { - return 1; - } - } - } - return 0; -} - -static uint32_t GLSLGetNumberBitsSet(uint32_t a) -{ - // Calculate number of bits in a - // Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 - // Works only up to 14 bits (we're only using up to 4) - return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; -} - -// e.g. -//.z = 1 -//.x = 1 -//.yw = 2 -uint32_t GetNumSwizzleElements(const Operand* psOperand) -{ - return GetNumSwizzleElementsWithMask(psOperand, OPERAND_4_COMPONENT_MASK_ALL); -} - -// Get the number of elements returned by operand, taking additional component mask into account -uint32_t GetNumSwizzleElementsWithMask(const Operand* psOperand, uint32_t ui32CompMask) -{ - uint32_t count = 0; - - switch (psOperand->eType) - { - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: - return 1; // TODO: does mask make any sense here? - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: - case OPERAND_TYPE_INPUT_THREAD_ID: - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: - // Adjust component count and break to more processing - ((Operand*)psOperand)->iNumComponents = 3; - break; - case OPERAND_TYPE_IMMEDIATE32: - case OPERAND_TYPE_IMMEDIATE64: - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH: - { - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - uint32_t compMask = (1 << psOperand->iNumComponents) - 1; - - compMask &= ui32CompMask; - // Calculate bits left in compMask - return GLSLGetNumberBitsSet(compMask); - } - default: - { - break; - } - } - - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents != 1) - { - // Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t compMask = psOperand->ui32CompMask; - if (compMask == 0) - compMask = OPERAND_4_COMPONENT_MASK_ALL; - compMask &= ui32CompMask; - - if (compMask == OPERAND_4_COMPONENT_MASK_ALL) - return 4; - - if (compMask & OPERAND_4_COMPONENT_MASK_X) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_Y) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_Z) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_W) - { - count++; - } - } - else - // Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if ((ui32CompMask & (1 << i)) == 0) - continue; - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - count++; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - count++; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - count++; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - count++; - } - } - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && (ui32CompMask & OPERAND_4_COMPONENT_MASK_X)) - { - count++; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y && (ui32CompMask & OPERAND_4_COMPONENT_MASK_Y)) - { - count++; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z && (ui32CompMask & OPERAND_4_COMPONENT_MASK_Z)) - { - count++; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W && (ui32CompMask & OPERAND_4_COMPONENT_MASK_W)) - { - count++; - } - } - - // Component Select 1 - } - - if (!count) - { - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - uint32_t compMask = (1 << psOperand->iNumComponents) - 1; - - compMask &= ui32CompMask; - // Calculate bits left in compMask - return GLSLGetNumberBitsSet(compMask); - } - - return count; -} - -void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count) -{ - bstring glsl = *psContext->currentShaderString; - if (count == 4) - return; - if (count) - { - bcatcstr(glsl, "."); - bcatcstr(glsl, "x"); - count--; - } - if (count) - { - bcatcstr(glsl, "y"); - count--; - } - if (count) - { - bcatcstr(glsl, "z"); - count--; - } - if (count) - { - bcatcstr(glsl, "w"); - count--; - } -} - -static uint32_t GLSLConvertOperandSwizzleToComponentMask(const Operand* psOperand) -{ - uint32_t mask = 0; - - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) - { - // Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - mask = psOperand->ui32CompMask; - } - else - // Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - - // Component Select 1 - } - - return mask; -} - -// Non-zero means the components overlap -int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB) -{ - uint32_t maskA = GLSLConvertOperandSwizzleToComponentMask(psOperandA); - uint32_t maskB = GLSLConvertOperandSwizzleToComponentMask(psOperandB); - - return maskA & maskB; -} - -void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - TranslateOperandSwizzleWithMask(psContext, psOperand, OPERAND_4_COMPONENT_MASK_ALL); -} - -void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask) -{ - bstring glsl = *psContext->currentShaderString; - - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return; - } - } - - if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - /*ConstantBuffer* psCBuf = NULL; - ShaderVar* psVar = NULL; - int32_t index = -1; - GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) - //then apply the sizzle. - - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); - - bformata(glsl, ".%s", psVar->Name); - if(index != -1) - { - bformata(glsl, "[%d]", index); - }*/ - - // return; - } - - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents != 1) - { - // Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t mask; - if (psOperand->ui32CompMask != 0) - mask = psOperand->ui32CompMask & ui32ComponentMask; - else - mask = ui32ComponentMask; - - if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) - { - bcatcstr(glsl, "."); - if (mask & OPERAND_4_COMPONENT_MASK_X) - { - bcatcstr(glsl, "x"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Y) - { - bcatcstr(glsl, "y"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Z) - { - bcatcstr(glsl, "z"); - } - if (mask & OPERAND_4_COMPONENT_MASK_W) - { - bcatcstr(glsl, "w"); - } - } - } - else - // Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || - !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && - psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W)) - { - uint32_t i; - - bcatcstr(glsl, "."); - - for (i = 0; i < 4; ++i) - { - if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) - continue; - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - bcatcstr(glsl, "x"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(glsl, "y"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(glsl, "z"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - bcatcstr(glsl, "w"); - } - } - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case - { - bcatcstr(glsl, "."); - - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - bcatcstr(glsl, "x"); - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(glsl, "y"); - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(glsl, "z"); - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - bcatcstr(glsl, "w"); - } - } - - // Component Select 1 - } -} - -int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return -1; - } - } - - if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) - { - // Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && - psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 0; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 1; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 3; - } - } - } - else - // Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - - // Component Select 1 - } - - return -1; -} - -void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) -{ - int i = index; - int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; - - bstring glsl = *psContext->currentShaderString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0 || isGeoShader) - { - bformata(glsl, "[%d]", psOperand->aui32ArraySizes[i]); - } - else - { - bformata(glsl, "%d", psOperand->aui32ArraySizes[i]); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(glsl, "["); // Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bformata(glsl, " + %d]", psOperand->aui32ArraySizes[i]); - break; - } - default: - { - break; - } - } -} - -void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) -{ - int i = index; - int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; - - bstring glsl = *psContext->currentShaderString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0 || isGeoShader) - { - bformata(glsl, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - } - else - { - bformata(glsl, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(glsl, "[int("); // Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); - bformata(glsl, ")*%d+%d]", multiply, add); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(glsl, "[(int("); // Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); - bformata(glsl, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - break; - } - default: - { - break; - } - } -} - -// Returns nonzero if a direct constructor can convert src->dest -static int GLSLCanDoDirectCast(HLSLCrossCompilerContext* psContext, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) -{ - // Only option on pre-SM4 stuff - if (psContext->psShader->ui32MajorVersion < 4) - return 1; - - // uint<->int<->bool conversions possible - if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL) && (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL)) - return 1; - - // float<->double possible - if ((src == SVT_FLOAT || src == SVT_DOUBLE) && (dest == SVT_FLOAT || dest == SVT_DOUBLE)) - return 1; - - return 0; -} - -static const char* GetBitcastOp(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) -{ - if (to == SVT_FLOAT && from == SVT_INT) - return "intBitsToFloat"; - else if (to == SVT_FLOAT && from == SVT_UINT) - return "uintBitsToFloat"; - else if (to == SVT_INT && from == SVT_FLOAT) - return "floatBitsToInt"; - else if (to == SVT_UINT && from == SVT_FLOAT) - return "floatBitsToUint"; - - return "ERROR missing components in GetBitcastOp()"; -} - -// Helper function to print out a single 32-bit immediate value in desired format -static void GLSLprintImmediate32(HLSLCrossCompilerContext* psContext, uint32_t value, SHADER_VARIABLE_TYPE eType) -{ - bstring glsl = *psContext->currentShaderString; - int needsParenthesis = 0; - - // Print floats as bit patterns. - if (eType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) - { - bcatcstr(glsl, "intBitsToFloat("); - eType = SVT_INT; - needsParenthesis = 1; - } - - switch (eType) - { - default: - case SVT_INT: - // Need special handling for anything >= uint 0x3fffffff - if (value > 0x3ffffffe) - bformata(glsl, "int(0x%Xu)", value); - else - bformata(glsl, "0x%X", value); - break; - case SVT_UINT: - bformata(glsl, "%uu", value); - break; - case SVT_FLOAT: - bformata(glsl, "%f", *((float*)(&value))); - break; - } - if (needsParenthesis) - bcatcstr(glsl, ")"); -} - -static void GLSLGLSLTranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, - const Operand* psOperand, - uint32_t ui32TOFlag, - uint32_t* pui32IgnoreSwizzle, - uint32_t ui32CompMask) -{ - int numParenthesis = 0; - int hasCtor = 0; - bstring glsl = *psContext->currentShaderString; - SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTType(ui32TOFlag); - SHADER_VARIABLE_TYPE eType = GetOperandDataTypeEx(psContext, psOperand, requestedType); - int numComponents = GetNumSwizzleElementsWithMask(psOperand, ui32CompMask); - int requestedComponents = 0; - - if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC2) - requestedComponents = 2; - else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC3) - requestedComponents = 3; - else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC4) - requestedComponents = 4; - - requestedComponents = max(requestedComponents, numComponents); - - *pui32IgnoreSwizzle = 0; - - if (!(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) - { - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32 || psOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - // Mark the operand type to match whatever we're asking for in the flags. - ((Operand*)psOperand)->aeDataType[0] = requestedType; - ((Operand*)psOperand)->aeDataType[1] = requestedType; - ((Operand*)psOperand)->aeDataType[2] = requestedType; - ((Operand*)psOperand)->aeDataType[3] = requestedType; - } - - if (eType != requestedType) - { - if (GLSLCanDoDirectCast(psContext, eType, requestedType)) - { - bformata(glsl, "%s(", GetConstructorForType(requestedType, requestedComponents)); - numParenthesis++; - hasCtor = 1; - } - else - { - // Direct cast not possible, need to do bitcast. - bformata(glsl, "%s(", GetBitcastOp(eType, requestedType)); - numParenthesis++; - } - } - - // Add ctor if needed (upscaling) - if (numComponents < requestedComponents && (hasCtor == 0)) - { - ASSERT(numComponents == 1); - bformata(glsl, "%s(", GetConstructorForType(requestedType, requestedComponents)); - numParenthesis++; - hasCtor = 1; - } - } - - switch (psOperand->eType) - { - case OPERAND_TYPE_IMMEDIATE32: - { - if (psOperand->iNumComponents == 1) - { - GLSLprintImmediate32(psContext, *((unsigned int*)(&psOperand->afImmediates[0])), requestedType); - } - else - { - int i; - int firstItemAdded = 0; - if (hasCtor == 0) - { - bformata(glsl, "%s(", GetConstructorForType(requestedType, numComponents)); - numParenthesis++; - hasCtor = 1; - } - for (i = 0; i < 4; i++) - { - uint32_t uval; - if (!(ui32CompMask & (1 << i))) - continue; - - if (firstItemAdded) - bcatcstr(glsl, ", "); - uval = *((uint32_t*)(&psOperand->afImmediates[i])); - GLSLprintImmediate32(psContext, uval, requestedType); - firstItemAdded = 1; - } - bcatcstr(glsl, ")"); - *pui32IgnoreSwizzle = 1; - numParenthesis--; - } - break; - } - case OPERAND_TYPE_IMMEDIATE64: - { - if (psOperand->iNumComponents == 1) - { - bformata(glsl, "%f", psOperand->adImmediates[0]); - } - else - { - bformata(glsl, "dvec4(%f, %f, %f, %f)", psOperand->adImmediates[0], psOperand->adImmediates[1], psOperand->adImmediates[2], - psOperand->adImmediates[3]); - if (psOperand->iNumComponents != 4) - { - AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - switch (psOperand->iIndexDims) - { - case INDEX_2D: - { - if (psOperand->aui32ArraySizes[1] == 0) // Input index zero - position. - { - bcatcstr(glsl, "gl_in"); - TranslateOperandIndex(psContext, psOperand, 0); // Vertex index - bcatcstr(glsl, ".gl_Position"); - } - else - { - const char* name = "Input"; - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); - } - - bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); - TranslateOperandIndex(psContext, psOperand, 0); // Vertex index - } - break; - } - default: - { - if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) - { - bformata(glsl, "Input%d[", psOperand->ui32RegisterNumber); - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - } - else - { - if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) - { - const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; - bformata(glsl, "Input%d[%d]", parentIndex, psOperand->ui32RegisterNumber - parentIndex); - } - else - { - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - const char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); - bcatcstr(glsl, name); - } - else - { - bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); - } - } - } - break; - } - } - break; - } - case OPERAND_TYPE_OUTPUT: - { - bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); - if (psOperand->psSubOperand[0]) - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_AUTO_BITCAST_TO_INT); - bcatcstr(glsl, "]"); - } - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH: - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bcatcstr(glsl, "gl_FragDepth"); - break; - } - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eType2 = GetOperandDataType(psContext, psOperand); - bcatcstr(glsl, "Temp"); - - if (eType2 == SVT_INT) - { - bcatcstr(glsl, "_int"); - } - else if (eType2 == SVT_UINT) - { - bcatcstr(glsl, "_uint"); - } - else if (eType2 == SVT_DOUBLE) - { - bcatcstr(glsl, "_double"); - } - else if (eType2 == SVT_VOID && (ui32TOFlag & TO_FLAG_DESTINATION)) - { - ASSERT(0 && "Should never get here!"); - /* if(ui32TOFlag & TO_FLAG_INTEGER) - { - bcatcstr(glsl, "_int"); - } - else - if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(glsl, "_uint"); - }*/ - } - - bformata(glsl, "[%d]", psOperand->ui32RegisterNumber); - - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONSTINT: - { - bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONST: - { - if (psOperand->psSubOperand[0] != NULL) - { - if (psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] != 0) - bformata(glsl, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); - else - bcatcstr(glsl, "ImmConstArray["); - TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(glsl, "]"); - } - else - { - bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber); - } - break; - } - case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: - { - bcatcstr(glsl, "BaseColour"); - break; - } - case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: - { - bcatcstr(glsl, "OffsetColour"); - break; - } - case OPERAND_TYPE_SPECIAL_POSITION: - { - bcatcstr(glsl, "gl_Position"); - break; - } - case OPERAND_TYPE_SPECIAL_FOG: - { - bcatcstr(glsl, "Fog"); - break; - } - case OPERAND_TYPE_SPECIAL_POINTSIZE: - { - bcatcstr(glsl, "gl_PointSize"); - break; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - { - bcatcstr(glsl, "Address"); - break; - } - case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: - { - bcatcstr(glsl, "LoopCounter"); - pui32IgnoreSwizzle[0] = 1; - break; - } - case OPERAND_TYPE_SPECIAL_TEXCOORD: - { - bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - const char* StageName = "VS"; - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - StageName = "PS"; - break; - } - case HULL_SHADER: - { - StageName = "HS"; - break; - } - case DOMAIN_SHADER: - { - StageName = "DS"; - break; - } - case GEOMETRY_SHADER: - { - StageName = "GS"; - break; - } - case COMPUTE_SHADER: - { - StageName = "CS"; - break; - } - default: - { - break; - } - } - - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - pui32IgnoreSwizzle[0] = 1; - } - - // FIXME: With ES 3.0 the buffer name is often not prepended to variable names - if (((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) && - ((psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT) != HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT)) - { - if (psCBuf) - { - //$Globals. - if (psCBuf->Name[0] == '$') - { - bformata(glsl, "Globals%s", StageName); - } - else - { - bformata(glsl, "%s%s", psCBuf->Name, StageName); - } - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(glsl, "."); - } - } - else - { - // bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]); - } - } - - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - // Work out the variable name. Don't apply swizzle to that variable yet. - int32_t rebase = 0; - - if (psCBuf && !psCBuf->blob) - { - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - - bformata(glsl, "%s", psVarType->FullName); - } - else if (psCBuf) - { - bformata(glsl, "%s%s_data", psCBuf->Name, StageName); - index = psOperand->aui32ArraySizes[1]; - } - else // We don't have a semantic for this variable, so try the raw dump appoach. - { - bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]); // - index = psOperand->aui32ArraySizes[1]; - } - - // Dx9 only? - if (psOperand->psSubOperand[0] != NULL) - { - // Array of matrices is treated as array of vec4s in HLSL, - // but that would mess up uniform types in GLSL. Do gymnastics. - uint32_t opFlags = TO_FLAG_INTEGER; - - if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays - bcatcstr(glsl, "[("); - TranslateOperand(psContext, psOperand->psSubOperand[0], opFlags); - bformata(glsl, ") / 4]"); - if (psContext->psShader->eTargetLanguage <= LANG_120) - { - bcatcstr(glsl, "[int(mod(float("); - TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); - bformata(glsl, "), 4.0))]"); - } - else - { - bcatcstr(glsl, "[(("); - TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); - bformata(glsl, ") %% 4)]"); - } - } - else - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[0], opFlags); - bformata(glsl, "]"); - } - } - else if (index != -1 && psOperand->psSubOperand[1] != NULL) - { - // Array of matrices is treated as array of vec4s in HLSL, - // but that would mess up uniform types in GLSL. Do gymnastics. - SHADER_VARIABLE_TYPE eType2 = GetOperandDataType(psContext, psOperand->psSubOperand[1]); - uint32_t opFlags = TO_FLAG_INTEGER; - if (eType2 != SVT_INT && eType2 != SVT_UINT) - opFlags = TO_AUTO_BITCAST_TO_INT; - - if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays - bcatcstr(glsl, "[("); - TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); - bformata(glsl, " + %d) / 4]", index); - if (psContext->psShader->eTargetLanguage <= LANG_120) - { - bcatcstr(glsl, "[int(mod(float("); - TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); - bformata(glsl, " + %d), 4.0))]", index); - } - else - { - bcatcstr(glsl, "[(("); - TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); - bformata(glsl, " + %d) %% 4)]", index); - } - } - else - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); - bformata(glsl, " + %d]", index); - } - } - else if (index != -1) - { - if ((psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays, open them up into vec4's - size_t matidx = index / 4; - size_t rowidx = index - (matidx * 4); - bformata(glsl, "[%d][%d]", matidx, rowidx); - } - else - { - bformata(glsl, "[%d]", index); - } - } - else if (psOperand->psSubOperand[1] != NULL) - { - bcatcstr(glsl, "["); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bcatcstr(glsl, "]"); - } - - if (psVarType && psVarType->Class == SVC_VECTOR) - { - switch (rebase) - { - case 4: - { - if (psVarType->Columns == 2) - { - //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) - bcatcstr(glsl, ".xxyx"); - } - else if (psVarType->Columns == 3) - { - //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL) - bcatcstr(glsl, ".xxyz"); - } - break; - } - case 8: - { - if (psVarType->Columns == 2) - { - //.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL) - bcatcstr(glsl, ".xxxy"); - } - break; - } - case 0: - default: - { - // No rebase, but extend to vec4. - if (psVarType->Columns == 2) - { - bcatcstr(glsl, ".xyxx"); - } - else if (psVarType->Columns == 3) - { - bcatcstr(glsl, ".xyzx"); - } - break; - } - } - } - - if (psVarType && psVarType->Class == SVC_SCALAR) - { - *pui32IgnoreSwizzle = 1; - } - } - break; - } - case OPERAND_TYPE_RESOURCE: - { - ResourceName(glsl, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_SAMPLER: - { - bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_FUNCTION_BODY: - { - const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; - const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; - // const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; - const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; - const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; - const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; - - bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); - break; - } - case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: - { - bcatcstr(glsl, "forkInstanceID"); - *pui32IgnoreSwizzle = 1; - return; - } - case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: - { - bcatcstr(glsl, "immediateConstBufferF"); - - if (psOperand->psSubOperand[0]) - { - bcatcstr(glsl, "("); // Indexes must be integral. - TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(glsl, ")"); - } - break; - } - case OPERAND_TYPE_INPUT_DOMAIN_POINT: - { - bcatcstr(glsl, "gl_TessCoord"); - break; - } - case OPERAND_TYPE_INPUT_CONTROL_POINT: - { - if (psOperand->aui32ArraySizes[1] == 0) // Input index zero - position. - { - bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); - } - else - { - bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); - } - break; - } - case OPERAND_TYPE_NULL: - { - // Null register, used to discard results of operations - bcatcstr(glsl, "//null"); - break; - } - case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: - { - bcatcstr(glsl, "gl_InvocationID"); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - bcatcstr(glsl, "gl_SampleMask[0]"); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_COVERAGE_MASK: - { - bcatcstr(glsl, "gl_SampleMaskIn[0]"); - // Skip swizzle on scalar types. - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID: // SV_DispatchThreadID - { - bcatcstr(glsl, "gl_GlobalInvocationID"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: // SV_GroupThreadID - { - bcatcstr(glsl, "gl_LocalInvocationID"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: // SV_GroupID - { - bcatcstr(glsl, "gl_WorkGroupID"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: // SV_GroupIndex - { - bcatcstr(glsl, "gl_LocalInvocationIndex"); - *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. - break; - } - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - { - ResourceName(glsl, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); - break; - } - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_PRIMITIVEID: - { - bcatcstr(glsl, "gl_PrimitiveID"); - break; - } - case OPERAND_TYPE_INDEXABLE_TEMP: - { - bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]); - bcatcstr(glsl, "["); - if (psOperand->aui32ArraySizes[1] != 0 || !psOperand->psSubOperand[1]) - bformata(glsl, "%d", psOperand->aui32ArraySizes[1]); - - if (psOperand->psSubOperand[1]) - { - if (psOperand->aui32ArraySizes[1] != 0) - bcatcstr(glsl, "+"); - TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - } - bcatcstr(glsl, "]"); - break; - } - case OPERAND_TYPE_STREAM: - { - bformata(glsl, "%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: - { - // In HLSL the instance id is uint, so cast here. - bcatcstr(glsl, "uint(gl_InvocationID)"); - break; - } - case OPERAND_TYPE_THIS_POINTER: - { - /* - The "this" register is a register that provides up to 4 pieces of information: - X: Which CB holds the instance data - Y: Base element offset of the instance data within the instance CB - Z: Base sampler index - W: Base Texture index - - Can be different for each function call - */ - break; - } - case OPERAND_TYPE_INPUT_PATCH_CONSTANT: - { - bformata(glsl, "myPatchConst%d", psOperand->ui32RegisterNumber); - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (hasCtor && (*pui32IgnoreSwizzle == 0)) - { - TranslateOperandSwizzleWithMask(psContext, psOperand, ui32CompMask); - *pui32IgnoreSwizzle = 1; - } - - while (numParenthesis != 0) - { - bcatcstr(glsl, ")"); - numParenthesis--; - } -} - -static void GLSLTranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) -{ - GLSLGLSLTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL); -} - -SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - return GetOperandDataTypeEx(psContext, psOperand, SVT_INT); -} - -SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates) -{ - switch (psOperand->eType) - { - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; - int i = 0; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - return psOperand->aeDataType[0]; - } - - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - for (; i < 4; ++i) - { - if (ui32CompMask & (1 << i)) - { - eCurrentType = psOperand->aeDataType[i]; - break; - } - } - -#ifdef _DEBUG - // Check if all elements have the same basic type. - for (; i < 4; ++i) - { - if (psOperand->ui32CompMask & (1 << i)) - { - if (eCurrentType != psOperand->aeDataType[i]) - { - ASSERT(0); - } - } - } -#endif - return eCurrentType; - } - - ASSERT(0); - - break; - } - case OPERAND_TYPE_OUTPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psOut; - - if (GetOutputSignatureFromRegister(psContext->currentPhase, ui32Register, psOperand->ui32CompMask, 0, &psContext->psShader->sInfo, &psOut)) - { - if (psOut->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psIn; - - // UINT in DX, INT in GL. - if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) - { - return SVT_INT; - } - - if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) - { - if (psIn->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - int32_t rebase = -1; - int foundVar; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - if (psCBuf && !psCBuf->blob) - { - foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) - { - return psVarType->Type; - } - } - else - { - // Todo: this isn't correct yet. - return SVT_FLOAT; - } - break; - } - case OPERAND_TYPE_IMMEDIATE32: - { - return ePreferredTypeForImmediates; - } - - case OPERAND_TYPE_INPUT_THREAD_ID: - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: - { - return SVT_UINT; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: - { - return SVT_INT; - } - case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: - { - return SVT_UINT; - } - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - return SVT_INT; - } - case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: - { - return SVT_INT; - } - default: - { - return SVT_FLOAT; - } - } - - return SVT_FLOAT; -} - -void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) -{ - TranslateOperandWithMask(psContext, psOperand, ui32TOFlag, OPERAND_4_COMPONENT_MASK_ALL); -} - -void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t ui32IgnoreSwizzle = 0; - - if (psContext->psShader->ui32MajorVersion <= 3) - { - ui32TOFlag &= ~(TO_AUTO_BITCAST_TO_FLOAT | TO_AUTO_BITCAST_TO_INT | TO_AUTO_BITCAST_TO_UINT); - } - - if (ui32TOFlag & TO_FLAG_NAME_ONLY) - { - GLSLTranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); - return; - } - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - bcatcstr(glsl, "(-"); - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(glsl, "abs("); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(glsl, "-abs("); - break; - } - } - - GLSLGLSLTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask); - - if (!ui32IgnoreSwizzle) - { - TranslateOperandSwizzleWithMask(psContext, psOperand, ui32ComponentMask); - } - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - bcatcstr(glsl, ")"); - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(glsl, ")"); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(glsl, ")"); - break; - } - } -} - -void ResourceName(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare) -{ - bstring glsl = (targetStr == NULL) ? *psContext->currentShaderString : targetStr; - ResourceBinding* psBinding = 0; - int found; - - found = GetResourceFromBindingPoint(group, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - - if (bZCompare) - { - bcatcstr(glsl, "hlslcc_zcmp"); - } - - if (found) - { - int i = 0; - char name[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32ArrayOffset = ui32RegisterNumber - psBinding->ui32BindPoint; - - while (psBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) - { - name[i] = psBinding->Name[i]; - - // array syntax [X] becomes _0_ - // Otherwise declarations could end up as: - // uniform sampler2D SomeTextures[0]; - // uniform sampler2D SomeTextures[1]; - if (name[i] == '[' || name[i] == ']') - name[i] = '_'; - - ++i; - } - - name[i] = '\0'; - - if (ui32ArrayOffset) - { - bformata(glsl, "%s%d", name, ui32ArrayOffset); - } - else - { - bformata(glsl, "%s", name); - } - } - else - { - bformata(glsl, "UnknownResource%d", ui32RegisterNumber); - } -} - -bstring TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) -{ - bstring result; - ResourceBinding* psTextureBinding = 0; - ResourceBinding* psSamplerBinding = 0; - int foundTexture, foundSampler; - uint32_t i = 0; - char textureName[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32ArrayOffset; - - foundTexture = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegisterNumber, psShaderInfo, &psTextureBinding); - foundSampler = GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegisterNumber, psShaderInfo, &psSamplerBinding); - - if (!foundTexture || !foundSampler) - { - result = bformat("UnknownResource%d_%d", ui32TextureRegisterNumber, ui32SamplerRegisterNumber); - return result; - } - - ui32ArrayOffset = ui32TextureRegisterNumber - psTextureBinding->ui32BindPoint; - - while (psTextureBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) - { - textureName[i] = psTextureBinding->Name[i]; - - // array syntax [X] becomes _0_ - // Otherwise declarations could end up as: - // uniform sampler2D SomeTextures[0]; - // uniform sampler2D SomeTextures[1]; - if (textureName[i] == '[' || textureName[i] == ']') - { - textureName[i] = '_'; - } - - ++i; - } - textureName[i] = '\0'; - - result = bfromcstr(""); - - if (bZCompare) - { - bcatcstr(result, "hlslcc_zcmp"); - } - - if (ui32ArrayOffset) - { - bformata(result, "%s%d_X_%s", textureName, ui32ArrayOffset, psSamplerBinding->Name); - } - else - { - if ((i > 0) && (textureName[i - 1] == '_')) // Prevent double underscore which is reserved - { - bformata(result, "%sX_%s", textureName, psSamplerBinding->Name); - } - else - { - bformata(result, "%s_X_%s", textureName, psSamplerBinding->Name); - } - } - - return result; -} - -void ConcatTextureSamplerName(bstring str, - ShaderInfo* psShaderInfo, - const uint32_t ui32TextureRegisterNumber, - const uint32_t ui32SamplerRegisterNumber, - const int bZCompare) -{ - bstring texturesamplername = TextureSamplerName(psShaderInfo, ui32TextureRegisterNumber, ui32SamplerRegisterNumber, bZCompare); - bconcat(str, texturesamplername); - bdestroy(texturesamplername); -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c deleted file mode 100644 index 8e3a719950..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c +++ /dev/null @@ -1,440 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/tokens.h" -#include "internal_includes/structs.h" -#include "internal_includes/decode.h" -#include "stdlib.h" -#include "stdio.h" -#include "bstrlib.h" -#include "internal_includes/toMETALInstruction.h" -#include "internal_includes/toMETALOperand.h" -#include "internal_includes/toMETALDeclaration.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/structsMetal.h" - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); -extern void UpdateFullName(ShaderVarType* psParentVarType); -extern void MangleIdentifiersPerStage(ShaderData* psShader); - - -void TranslateToMETAL(HLSLCrossCompilerContext* psContext, ShaderLang* planguage) -{ - bstring metal; - uint32_t i; - ShaderData* psShader = psContext->psShader; - ShaderLang language = *planguage; - uint32_t ui32InstCount = 0; - uint32_t ui32DeclCount = 0; - - psContext->indent = 0; - - /*psShader->sPhase[MAIN_PHASE].ui32InstanceCount = 1; - psShader->sPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); - psShader->sPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); - psShader->sPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); - psShader->sPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t));*/ - - if(language == LANG_DEFAULT) - { - language = LANG_METAL; - *planguage = language; - } - - metal = bfromcstralloc (1024, ""); - - psContext->mainShader = metal; - psContext->stagedInputDeclarations = bfromcstralloc(1024, ""); - psContext->parameterDeclarations = bfromcstralloc(1024, ""); - psContext->declaredOutputs = bfromcstralloc(1024, ""); - psContext->earlyMain = bfromcstralloc (1024, ""); - for(i=0; i<NUM_PHASES;++i) - { - psContext->postShaderCode[i] = bfromcstralloc (1024, ""); - } - - psContext->needsFragmentTestHint = 0; - - for (i = 0; i < MAX_COLOR_MRT; i++) - psContext->gmemOutputNumElements[i] = 0; - - psContext->currentShaderString = &metal; - psShader->eTargetLanguage = language; - psContext->currentPhase = MAIN_PHASE; - - bcatcstr(metal, "#include <metal_stdlib>\n"); - bcatcstr(metal, "using namespace metal;\n"); - - - bcatcstr(metal, "struct float1 {\n"); - bcatcstr(metal, "\tfloat x;\n"); - bcatcstr(metal, "};\n"); - - bcatcstr(metal, "struct uint1 {\n"); - bcatcstr(metal, "\tuint x;\n"); - bcatcstr(metal, "};\n"); - - bcatcstr(metal, "struct int1 {\n"); - bcatcstr(metal, "\tint x;\n"); - bcatcstr(metal, "};\n"); - - - ui32InstCount = psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; - ui32DeclCount = psShader->asPhase[MAIN_PHASE].pui32DeclCount[0]; - - AtomicVarList atomicList; - atomicList.Filled = 0; - atomicList.Size = ui32InstCount; - atomicList.AtomicVars = (const ShaderVarType**)hlslcc_malloc(ui32InstCount * sizeof(ShaderVarType*)); - - for (i = 0; i < ui32InstCount; ++i) - { - DetectAtomicInstructionMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0] + i, i + 1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0] + i + 1 : 0, &atomicList); - } - - for(i=0; i < ui32DeclCount; ++i) - { - TranslateDeclarationMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsDecl[0] + i, &atomicList); - } - - if(psContext->psShader->ui32NumDx9ImmConst) - { - bformata(psContext->mainShader, "float4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); - } - - MarkIntegerImmediatesMETAL(psContext); - - SetDataTypesMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0], ui32InstCount); - - switch (psShader->eShaderType) - { - case VERTEX_SHADER: - { - int hasStageInput = 0; - int hasOutput = 0; - if (blength(psContext->stagedInputDeclarations) > 0) - { - hasStageInput = 1; - bcatcstr(metal, "struct metalVert_stageIn\n{\n"); - bconcat(metal, psContext->stagedInputDeclarations); - bcatcstr(metal, "};\n"); - } - if (blength(psContext->declaredOutputs) > 0) - { - hasOutput = 1; - bcatcstr(metal, "struct metalVert_out\n{\n"); - bconcat(metal, psContext->declaredOutputs); - bcatcstr(metal, "};\n"); - } - - bformata(metal, "vertex %s metalMain(\n%s", - hasOutput ? "metalVert_out" : "void", - hasStageInput ? "\tmetalVert_stageIn stageIn [[ stage_in ]]" : ""); - - int userInputDeclLength = blength(psContext->parameterDeclarations); - if (userInputDeclLength > 2) - { - if (hasStageInput) - bformata(metal, ",\n"); - bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove ",\n" - } - - bconcat(metal, psContext->parameterDeclarations); - bcatcstr(metal, hasOutput ? "\t)\n{\n\tmetalVert_out output;\n" : ")\n{\n"); - break; - } - case PIXEL_SHADER: - { - int hasStageInput = 0; - int hasOutput = 0; - int userInputDeclLength = blength(psContext->parameterDeclarations); - if (blength(psContext->stagedInputDeclarations) > 0) - { - hasStageInput = 1; - bcatcstr(metal, "struct metalFrag_stageIn\n{\n"); - bconcat(metal, psContext->stagedInputDeclarations); - bcatcstr(metal, "};\n"); - } - if (blength(psContext->declaredOutputs) > 0) - { - hasOutput = 1; - bcatcstr(metal, "struct metalFrag_out\n{\n"); - bconcat(metal, psContext->declaredOutputs); - bcatcstr(metal, "};\n"); - } - - bcatcstr(metal, "fragment "); - if (psContext->needsFragmentTestHint) - { - bcatcstr(metal, "\n#ifndef MTLLanguage1_1\n"); - bcatcstr(metal, "[[ early_fragment_tests ]]\n"); - bcatcstr(metal, "#endif\n"); - } - - bformata(metal, "%s metalMain(\n%s", hasOutput ? "metalFrag_out" : "void", - hasStageInput ? "\tmetalFrag_stageIn stageIn [[ stage_in ]]" : ""); - if (userInputDeclLength > 2) - { - if (hasStageInput) - bcatcstr(metal, ",\n"); - bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space - } - bconcat(metal, psContext->parameterDeclarations); - bcatcstr(metal, hasOutput ? ")\n{\n\tmetalFrag_out output;\n" : ")\n{\n"); - break; - } - case COMPUTE_SHADER: - { - int hasStageInput = 0; - int hasOutput = 0; - if (blength(psContext->stagedInputDeclarations) > 0) - { - hasStageInput = 1; - bcatcstr(metal, "struct metalCompute_stageIn\n{\n"); - bconcat(metal, psContext->stagedInputDeclarations); - bcatcstr(metal, "};\n"); - } - if (blength(psContext->declaredOutputs) > 0) - { - hasOutput = 1; - bcatcstr(metal, "struct metalCompute_out\n{\n"); - bconcat(metal, psContext->declaredOutputs); - bcatcstr(metal, "};\n"); - } - - bformata(metal, "kernel %s metalMain(\n%s", - hasOutput ? "metalCompute_out" : "void", - hasStageInput ? "\tmetalCompute_stageIn stageIn [[ stage_in ]]" : ""); - - int userInputDeclLength = blength(psContext->parameterDeclarations); - if (userInputDeclLength > 2) - { - if (hasStageInput) - bformata(metal, ",\n"); - bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove ",\n" - } - - bconcat(metal, psContext->parameterDeclarations); - bcatcstr(metal, hasOutput ? "\t)\n{\n\tmetalCompute_out output;\n" : ")\n{\n"); - break; - } - default: - { - ASSERT(0); - // Geometry, Hull, and Domain shaders unsupported by Metal - // int userInputDeclLength = blength(psContext->parameterDeclarations); - // if (blength(psContext->outputDeclarations) > 0) - // { - // bcatcstr(metal, "struct metalComp_out\n{\n"); - // bconcat(metal, psContext->outputDeclarations); - // bcatcstr(metal, "};\n"); - // if (userInputDeclLength > 2) - // bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space - // bformata(metal, "kernel metalComp_out metalMain(%s)\n{\n\tmetalComp_out output;\n", psContext->parameterDeclarations); - // } - // else - // { - // if (userInputDeclLength > 2) - // bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space - // bformata(metal, "kernel void metalMain(%s)\n{\n", psContext->parameterDeclarations); - // } - break; - } - } - - psContext->indent++; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//--- Start Early Main ---\n"); -#endif - bconcat(metal, psContext->earlyMain); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//--- End Early Main ---\n"); -#endif - - - for(i=0; i < ui32InstCount; ++i) - { - TranslateInstructionMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0]+i, i+1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0]+i+1 : 0); - } - - hlslcc_free((void*)atomicList.AtomicVars); - - psContext->indent--; - - bcatcstr(metal, "}\n"); -} - -static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) -{ - uint32_t ui32Inst; - for(ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) - { - Instruction* psCurrentInst = &psInst[ui32Inst]; - const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; - uint32_t ui32Operand; - - for(ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) - { - uint32_t ui32SubOperand; - for(ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) - { - if(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) - { - hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); - psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; - } - } - } - } -} - -typedef enum { - MTLFunctionTypeVertex = 1, - MTLFunctionTypeFragment = 2, - MTLFunctionTypeKernel = 3 -} MTLFunctionType; - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToMETAL(const char* shader, - unsigned int flags, - ShaderLang language, - Shader* result) -{ - uint32_t* tokens; - ShaderData* psShader; - char* glslcstr = NULL; - int ShaderType = MTLFunctionTypeFragment; - int success = 0; - uint32_t i; - - tokens = (uint32_t*)shader; - - psShader = DecodeDXBC(tokens); - - if(psShader) - { - HLSLCrossCompilerContext sContext; - - sContext.psShader = psShader; - sContext.flags = flags; - - for(i=0; i<NUM_PHASES;++i) - { - sContext.havePostShaderCode[i] = 0; - } - - TranslateToMETAL(&sContext, &language); - - switch(psShader->eShaderType) - { - case VERTEX_SHADER: - { - ShaderType = MTLFunctionTypeVertex; - break; - } - case COMPUTE_SHADER: - { - ShaderType = MTLFunctionTypeKernel; - break; - } - default: - { - break; - } - } - - glslcstr = bstr2cstr(sContext.mainShader, '\0'); - - bdestroy(sContext.mainShader); - bdestroy(sContext.earlyMain); - for(i=0; i<NUM_PHASES; ++i) - { - bdestroy(sContext.postShaderCode[i]); - } - - for(i=0; i<NUM_PHASES;++i) - { - if(psShader->asPhase[i].ppsDecl != 0) - { - uint32_t k; - for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) - { - hlslcc_free(psShader->asPhase[i].ppsDecl[k]); - } - hlslcc_free(psShader->asPhase[i].ppsDecl); - } - if(psShader->asPhase[i].ppsInst != 0) - { - uint32_t k; - for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) - { - FreeSubOperands(psShader->asPhase[i].ppsInst[k], psShader->asPhase[i].pui32InstCount[k]); - hlslcc_free(psShader->asPhase[i].ppsInst[k]); - } - hlslcc_free(psShader->asPhase[i].ppsInst); - } - } - - memcpy(&result->reflection,&psShader->sInfo,sizeof(psShader->sInfo)); - - result->textureSamplerInfo.ui32NumTextureSamplerPairs = psShader->textureSamplerInfo.ui32NumTextureSamplerPairs; - for (i=0; i<result->textureSamplerInfo.ui32NumTextureSamplerPairs; i++) - strcpy(result->textureSamplerInfo.aTextureSamplerPair[i].Name, psShader->textureSamplerInfo.aTextureSamplerPair[i].Name); - - hlslcc_free(psShader); - - success = 1; - } - - shader = 0; - tokens = 0; - - /* Fill in the result struct */ - - result->shaderType = ShaderType; - result->sourceCode = glslcstr; - result->GLSLLanguage = language; - - return success; -} - -HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToMETAL(const char* filename, - unsigned int flags, - ShaderLang language, - Shader* result) -{ - FILE* shaderFile; - int length; - size_t readLength; - char* shader; - int success = 0; - - shaderFile = fopen(filename, "rb"); - - if(!shaderFile) - { - return 0; - } - - fseek(shaderFile, 0, SEEK_END); - length = ftell(shaderFile); - fseek(shaderFile, 0, SEEK_SET); - - shader = (char*)hlslcc_malloc(length+1); - - readLength = fread(shader, 1, length, shaderFile); - - fclose(shaderFile); - shaderFile = 0; - - shader[readLength] = '\0'; - - success = TranslateHLSLFromMemToMETAL(shader, flags, language, result); - - hlslcc_free(shader); - - return success; -} \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c deleted file mode 100644 index 79dcb809fd..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c +++ /dev/null @@ -1,2281 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "hlslcc.h" -#include "internal_includes/toMETALDeclaration.h" -#include "internal_includes/toMETALOperand.h" -#include "internal_includes/languages.h" -#include "bstrlib.h" -#include "internal_includes/debug.h" -#include "internal_includes/hlslcc_malloc.h" -#include "internal_includes/structsMetal.h" -#include <math.h> -#include <float.h> - -#if defined(__clang__) -#pragma clang diagnostic ignored "-Wpointer-sign" -#endif - -#ifdef _MSC_VER -#ifndef isnan -#define isnan(x) _isnan(x) -#endif - -#ifndef isinf -#define isinf(x) (!_finite(x)) -#endif -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) - -typedef enum -{ - GLVARTYPE_FLOAT, - GLVARTYPE_INT, - GLVARTYPE_FLOAT4, -} GLVARTYPE; - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -const char* GetTypeStringMETAL(GLVARTYPE eType) -{ - switch (eType) - { - case GLVARTYPE_FLOAT: - { - return "float"; - } - case GLVARTYPE_INT: - { - return "int"; - } - case GLVARTYPE_FLOAT4: - { - return "float4"; - } - default: - { - return ""; - } - } -} -const uint32_t GetTypeElementCountMETAL(GLVARTYPE eType) -{ - switch (eType) - { - case GLVARTYPE_FLOAT: - case GLVARTYPE_INT: - { - return 1; - } - case GLVARTYPE_FLOAT4: - { - return 4; - } - default: - { - return 0; - } - } -} - -void AddToDx9ImmConstIndexableArrayMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - bstring* savedStringPtr = psContext->currentShaderString; - - psContext->currentShaderString = &psContext->earlyMain; - psContext->indent++; - AddIndentation(psContext); - psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; - bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); - TranslateOperandMETAL(psContext, psOperand, TO_FLAG_NONE); - bcatcstr(psContext->earlyMain, ";\n"); - psContext->indent--; - psContext->psShader->ui32NumDx9ImmConst++; - - psContext->currentShaderString = savedStringPtr; -} - -void DeclareConstBufferShaderVariableMETAL(bstring metal, const char* Name, const struct ShaderVarType_TAG* psType, int pointerType, int const createDummyAlignment, AtomicVarList* psAtomicList) -//const SHADER_VARIABLE_CLASS eClass, const SHADER_VARIABLE_TYPE eType, -//const char* pszName) -{ - if (psType->Class == SVC_STRUCT) - { - bformata(metal, "%s_Type %s%s", Name, pointerType ? "*" : "", Name); - if (psType->Elements > 1) - { - bformata(metal, "[%d]", psType->Elements); - } - } - else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) - { - switch (psType->Type) - { - case SVT_FLOAT: - { - bformata(metal, "\tfloat%d %s%s[%d", psType->Columns, pointerType ? "*" : "", Name, psType->Rows); - break; - } - case SVT_FLOAT16: - { - bformata(metal, "\thalf%d %s%s[%d", psType->Columns, pointerType ? "*" : "", Name, psType->Rows); - break; - } - default: - { - ASSERT(0); - break; - } - } - if (psType->Elements > 1) - { - bformata(metal, " * %d", psType->Elements); - } - bformata(metal, "]"); - } - else - if (psType->Class == SVC_VECTOR) - { - switch (psType->Type) - { - case SVT_DOUBLE: - case SVT_FLOAT: - { - bformata(metal, "\tfloat%d %s%s", psType->Columns, pointerType ? "*" : "", Name); - break; - } - case SVT_FLOAT16: - { - bformata(metal, "\thalf%d %s%s", psType->Columns, pointerType ? "*" : "", Name); - break; - } - case SVT_UINT: - { - bformata(metal, "\tuint%d %s%s", psType->Columns, pointerType ? "*" : "", Name); - break; - } - case SVT_INT: - case SVT_BOOL: - { - bformata(metal, "\tint%d %s%s", psType->Columns, pointerType ? "*" : "", Name); - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (psType->Elements > 1) - { - bformata(metal, "[%d]", psType->Elements); - } - } - else - if (psType->Class == SVC_SCALAR) - { - switch (psType->Type) - { - case SVT_DOUBLE: - case SVT_FLOAT: - { - bformata(metal, "\tfloat %s%s", pointerType ? "*" : "", Name); - break; - } - case SVT_FLOAT16: - { - bformata(metal, "\thalf %s%s", pointerType ? "*" : "", Name); - break; - } - case SVT_UINT: - { - if (IsAtomicVar(psType, psAtomicList)) - { - bformata(metal, "\tvolatile atomic_uint %s%s", pointerType ? "*" : "", Name); - } - else - { - bformata(metal, "\tuint %s%s", pointerType ? "*" : "", Name); - } - break; - } - case SVT_INT: - { - if (IsAtomicVar(psType, psAtomicList)) - { - bformata(metal, "\tvolatile atomic_int %s%s", pointerType ? "*" : "", Name); - } - else - { - bformata(metal, "\tint %s%s", pointerType ? "*" : "", Name); - } - break; - } - case SVT_BOOL: - { - //Use int instead of bool. - //Allows implicit conversions to integer and - //bool consumes 4-bytes in HLSL and metal anyway. - bformata(metal, "\tint %s%s", pointerType ? "*" : "", Name); - // Also change the definition in the type tree. - ((ShaderVarType*)psType)->Type = SVT_INT; - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (psType->Elements > 1) - { - bformata(metal, "[%d]", psType->Elements); - } - } - if (!pointerType) - { - bformata(metal, ";\n"); - } - - // We need to add more dummies if float2 or less since they are not 16 bytes aligned - // float = 4 - // float2 = 8 - // float3 = float4 = 16 - // https://developer.apple.com/library/ios/documentation/Metal/Reference/MetalShadingLanguageGuide/data-types/data-types.html - if (createDummyAlignment) - { - uint16_t sizeInBytes = 16; - if (1 == psType->Columns) - { - sizeInBytes = 4; - } - else if (2 == psType->Columns) - { - sizeInBytes = 8; - } - - if (4 == sizeInBytes) - { - bformata(metal, "\tfloat offsetDummy_4Bytes_%s;\n", Name); - bformata(metal, "\tfloat2 offsetDummy_8Bytes_%s;\n", Name); - } - else if (8 == sizeInBytes) - { - bformata(metal, "\tfloat2 offsetDummy_8Bytes_%s;\n", Name); - } - } -} - -//In metal embedded structure definitions are not supported. -void PreDeclareStructTypeMETAL(bstring metal, const char* Name, const struct ShaderVarType_TAG* psType, AtomicVarList* psAtomicList) -{ - uint32_t i; - - for (i = 0; i < psType->MemberCount; ++i) - { - if (psType->Members[i].Class == SVC_STRUCT) - { - PreDeclareStructTypeMETAL(metal, psType->Members[i].Name, &psType->Members[i], psAtomicList); - } - } - - if (psType->Class == SVC_STRUCT) - { -#if defined(_DEBUG) - uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; -#endif - - //Not supported at the moment - ASSERT(!unnamed_struct); - - bformata(metal, "struct %s_Type {\n", Name); - - for (i = 0; i < psType->MemberCount; ++i) - { - ASSERT(psType->Members != 0); - - DeclareConstBufferShaderVariableMETAL(metal, psType->Members[i].Name, &psType->Members[i], 0, 0, psAtomicList); - } - - bformata(metal, "};\n"); - } -} - -char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) -{ - bstring inputName; - char* cstr; - InOutSignature* psIn; - - if (eShaderType == PIXEL_SHADER) - { - inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else - { - ASSERT(eShaderType == VERTEX_SHADER); - inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); - } - if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn)) - { - bformata(inputName, "_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); - } - - cstr = bstr2cstr(inputName, '\0'); - bdestroy(inputName); - return cstr; -} - -char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, - const SHADER_TYPE eShaderType, - const Operand* psOperand) -{ - bstring outputName = bformat(""); - char* cstr; - InOutSignature* psOut; - -#if defined(_DEBUG) - int foundOutput = -#endif - GetOutputSignatureFromRegister( - psContext->currentPhase, - psOperand->ui32RegisterNumber, - psOperand->ui32CompMask, - psContext->psShader->ui32CurrentVertexOutputStream, - &psContext->psShader->sInfo, - &psOut); - - ASSERT(foundOutput); - - if (eShaderType == VERTEX_SHADER) - { - outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); - } - else if (eShaderType == PIXEL_SHADER) - { - outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); - } - - if (psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) - { - bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); - } - - cstr = bstr2cstr(outputName, '\0'); - bdestroy(outputName); - return cstr; -} - -const char* GetInterpolationStringMETAL(INTERPOLATION_MODE eMode) -{ - switch (eMode) - { - case INTERPOLATION_CONSTANT: - { - return "flat"; - } - case INTERPOLATION_LINEAR: - { - return "center_perspective"; - } - case INTERPOLATION_LINEAR_CENTROID: - { - return "centroid_perspective"; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE: - { - return "center_no_perspective"; - break; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: - { - return "centroid_no_perspective"; - } - case INTERPOLATION_LINEAR_SAMPLE: - { - return "sample_perspective"; - } - case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: - { - return "sample_no_perspective"; - } - default: - { - return ""; - } - } -} - -static void DeclareInput( - HLSLCrossCompilerContext* psContext, - const Declaration* psDecl, const char* StorageQualifier, OPERAND_MIN_PRECISION minPrecision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) -{ - ShaderData* psShader = psContext->psShader; - psContext->currentShaderString = &psContext->parameterDeclarations; - bstring metal = *psContext->currentShaderString; - - // This falls within the specified index ranges. The default is 0 if no input range is specified - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - return; - } - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - - InOutSignature* psSignature = NULL; - - const char* type = "float"; - if (minPrecision == OPERAND_MIN_PRECISION_FLOAT_16) - { - type = "half"; - } - if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature)) - { - switch (psSignature->eComponentType) - { - case INOUT_COMPONENT_UINT32: - { - type = "uint"; - break; - } - case INOUT_COMPONENT_SINT32: - { - type = "int"; - break; - } - case INOUT_COMPONENT_FLOAT32: - { - break; - } - } - } - - bstring qual = bfromcstralloc(256, StorageQualifier); - - if (biseqcstr(qual, "attribute")) - { - bformata(qual, "(%d)", psDecl->asOperands[0].ui32RegisterNumber); - psContext->currentShaderString = &psContext->stagedInputDeclarations; - metal = *psContext->currentShaderString; - } - else if (biseqcstr(qual, "user")) - { - bformata(qual, "(varying%d)", psDecl->asOperands[0].ui32RegisterNumber); - psContext->currentShaderString = &psContext->stagedInputDeclarations; - metal = *psContext->currentShaderString; - } - else if (biseqcstr(qual, "buffer")) - { - bformata(qual, "(%d)", psDecl->asOperands[0].ui32RegisterNumber); - } - - if (metal == psContext->stagedInputDeclarations) - { - bformata(metal, "\t%s", type); - if (iNumComponents > 1) - { - bformata(metal, "%d", iNumComponents); - } - } - else - { - if (iNumComponents > 1) - { - bformata(metal, "\tdevice %s%d*", type, iNumComponents); - } - else - { - bformata(metal, "\tdevice %s*", type, iNumComponents); - } - } - - - if (psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) - { - InputName = "TexCoord"; - } - - bformata(metal, " %s", InputName); - - switch (eIndexDim) - { - case INDEX_2D: - { - if (iNumComponents == 1) - { - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - - const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; - - bformata(metal, " [%d]", arraySize); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; - break; - } - default: - { - if (iNumComponents == 1) - { - psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; - } - else - { - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) - { - bformata(metal, "[%d]", type, iNumComponents, InputName, - psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; - } - else - { - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; - } - } - break; - } - } - - if (blength(qual) > 0) - { - bformata(metal, " [[ %s ]]", bdata(qual)); - } - bdestroy(qual); - - bformata(metal, "%c\n", (metal == psContext->stagedInputDeclarations) ? ';' : ','); - - if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) - { - const char* stageInString = (metal == psContext->stagedInputDeclarations) ? "stageIn." : ""; - const char* bufferAccessString = (metal == psContext->stagedInputDeclarations) ? "" : "[vId]"; - - psContext->currentShaderString = &psContext->earlyMain; - metal = *psContext->currentShaderString; - psContext->indent++; - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array - { - AddIndentation(psContext); - bformata(metal, "%s%d Input%d = %s%s%s;\n", type, iNumComponents, - psDecl->asOperands[0].ui32RegisterNumber, stageInString, InputName, bufferAccessString); - } - else - { - int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; - bformata(metal, "%s%d Input%d[%d];\n", type, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, - psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); - - while (arrayIndex) - { - AddIndentation(psContext); - bformata(metal, "Input%d[%d] = %s%s%s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex - 1, - stageInString, InputName, bufferAccessString, arrayIndex - 1); - - arrayIndex--; - } - } - psContext->indent--; - } - } - psContext->currentShaderString = &psContext->mainShader; -} - -static void AddBuiltinInputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName, const char* type) -{ - psContext->currentShaderString = &psContext->stagedInputDeclarations; - bstring metal = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - char* InputName = GetDeclaredInputNameMETAL(psContext, PIXEL_SHADER, &psDecl->asOperands[0]); - - if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) - { - // CONFETTI NOTE: DAVID SROUR - // vertex_id and instance_id must be part of the function's params -- not part of stage_in! - if (psDecl->asOperands[0].eSpecialName == NAME_INSTANCE_ID || psDecl->asOperands[0].eSpecialName == NAME_VERTEX_ID) - { - bformata(psContext->parameterDeclarations, "\t%s %s [[ %s ]],\n", type, &psDecl->asOperands[0].pszSpecialName, builtinName); - } - else - { - bformata(metal, "\t%s %s [[ %s ]];\n", type, InputName, builtinName); - } - - psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; - } - - if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) - { - psContext->currentShaderString = &psContext->earlyMain; - metal = *psContext->currentShaderString; - psContext->indent++; - AddIndentation(psContext); - - if (psDecl->asOperands[0].eSpecialName == NAME_INSTANCE_ID || psDecl->asOperands[0].eSpecialName == NAME_VERTEX_ID) - { - bformata(metal, "uint4 "); - bformata(metal, "Input%d; Input%d.x = %s;\n", - psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, &psDecl->asOperands[0].pszSpecialName); - } - else if (!strcmp(type, "bool")) - { - bformata(metal, "int4 "); - bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", - psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else if (!strcmp(type, "float")) - { - bformata(metal, "float4 "); - bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", - psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else if (!strcmp(type, "int")) - { - bformata(metal, "int4 "); - bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", - psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else if (!strcmp(type, "uint")) - { - bformata(metal, "uint4 "); - bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", - psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - else - { - bformata(metal, "%s Input%d = stageIn.%s;\n", type, - psDecl->asOperands[0].ui32RegisterNumber, InputName); - } - - if (psDecl->asOperands[0].eSpecialName == NAME_POSITION) - { - if (psContext->psShader->eShaderType == PIXEL_SHADER) - { - if (psDecl->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE && - psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) - { - if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - bformata(metal, "Input%d.w = 1.0 / Input%d.w;", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); - } - } - } - } - - psContext->indent--; - } - bcstrfree(InputName); - - psContext->currentShaderString = &psContext->mainShader; -} - -int OutputNeedsDeclaringMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) -{ - ShaderData* psShader = psContext->psShader; - - // Depth Output operands are a special case and won't have a ui32RegisterNumber, - // so first we have to check if the output operand is depth. - if (psShader->eShaderType == PIXEL_SHADER) - { - if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || - psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) - { - return 1; - } - } - - const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; - ASSERT(psOperand->ui32RegisterNumber >= 0); - ASSERT(psOperand->ui32RegisterNumber < MAX_SHADER_VEC4_OUTPUT); - if (psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) - { - int offset; - - for (offset = 0; offset < count; offset++) - { - psShader->aiOutputDeclared[psOperand->ui32RegisterNumber + offset] = declared; - } - return 1; - } - - return 0; -} - -void AddBuiltinOutputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) -{ - (void)type; - - bstring metal = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - psContext->havePostShaderCode[psContext->currentPhase] = 1; - - if (OutputNeedsDeclaringMETAL(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) - { - psContext->currentShaderString = &psContext->declaredOutputs; - metal = *psContext->currentShaderString; - InOutSignature* psSignature = NULL; - - int regNum = psDecl->asOperands[0].ui32RegisterNumber; - - GetOutputSignatureFromRegister(psContext->currentPhase, regNum, - psDecl->asOperands[0].ui32CompMask, - 0, - &psShader->sInfo, &psSignature); - - if (psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) - { - int max = GetMaxComponentFromComponentMaskMETAL(&psDecl->asOperands[0]); - bformata(metal, "\tfloat %s [%d] [[ %s ]];\n", builtinName, max, builtinName); - } - else - { - bformata(metal, "\tfloat4 %s [[ %s ]];\n", builtinName, builtinName); - } - bformata(metal, "#define Output%d output.%s\n", regNum, builtinName); - - psContext->currentShaderString = &psContext->mainShader; - } -} - -void AddUserOutputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) -{ - psContext->currentShaderString = &psContext->declaredOutputs; - bstring metal = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - if (OutputNeedsDeclaringMETAL(psContext, &psDecl->asOperands[0], 1)) - { - const Operand* psOperand = &psDecl->asOperands[0]; - const char* type = "\tfloat"; - const SHADER_VARIABLE_TYPE eOutType = GetOperandDataTypeMETAL(psContext, &psDecl->asOperands[0]); - - switch (eOutType) - { - case SVT_UINT: - { - type = "\tuint"; - break; - } - case SVT_INT: - { - type = "\tint"; - break; - } - case SVT_FLOAT16: - { - type = "\thalf"; - break; - } - case SVT_FLOAT: - { - break; - } - } - - switch (psShader->eShaderType) - { - case PIXEL_SHADER: - { - switch (psDecl->asOperands[0].eType) - { - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH: - { - bformata(metal, "%s PixOutDepthAny [[ depth(any) ]];\n", type); - bformata(metal, "#define DepthAny output.PixOutDepthAny\n"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - { - bformata(metal, "%s PixOutDepthGreater [[ depth(greater) ]];\n", type); - bformata(metal, "#define DepthGreater output.PixOutDepthGreater\n"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bformata(metal, "%s PixOutDepthLess [[ depth(less) ]];\n", type); - bformata(metal, "#define DepthLess output.PixOutDepthLess\n"); - break; - } - default: - { - uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; - - if (!psContext->gmemOutputNumElements[psDecl->asOperands[0].ui32RegisterNumber]) - { - bformata(metal, "%s4 PixOutColor%d [[ color(%d) ]];\n", type, renderTarget, renderTarget); - } - else // GMEM output type must match the input! - { - bformata(metal, "float%d PixOutColor%d [[ color(%d) ]];\n", psContext->gmemOutputNumElements[psDecl->asOperands[0].ui32RegisterNumber], renderTarget, renderTarget); - } - bformata(metal, "#define Output%d output.PixOutColor%d\n", psDecl->asOperands[0].ui32RegisterNumber, renderTarget); - - break; - } - } - break; - } - case VERTEX_SHADER: - { - int iNumComponents = 4;//GetMaxComponentFromComponentMaskMETAL(&psDecl->asOperands[0]); - char* OutputName = GetDeclaredOutputNameMETAL(psContext, VERTEX_SHADER, psOperand); - - bformata(metal, "%s%d %s [[ user(varying%d) ]];\n", type, iNumComponents, OutputName, psDecl->asOperands[0].ui32RegisterNumber); - bformata(metal, "#define Output%d output.%s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); - bcstrfree(OutputName); - - break; - } - } - } - - psContext->currentShaderString = &psContext->mainShader; -} - -void DeclareBufferVariableMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, const Operand* psOperand, - const ResourceType eResourceType, - bstring metal, AtomicVarList* psAtomicList) -{ - (void)ui32BindingPoint; - - bstring StructName; -#if !defined(NDEBUG) - uint32_t unnamed_struct = strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; -#endif - - ASSERT(psCBuf->ui32NumVars == 1); - ASSERT(unnamed_struct); - - StructName = bfromcstr(""); - - //TranslateOperandMETAL(psContext, psOperand, TO_FLAG_NAME_ONLY); - if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) - { - ResourceNameMETAL(StructName, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); - } - else if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) - { - bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); - } - else - { - ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); - } - - PreDeclareStructTypeMETAL(metal, - bstr2cstr(StructName, '\0'), - &psCBuf->asVars[0].sType, psAtomicList); - - - bcatcstr(psContext->parameterDeclarations, "\t"); - if (eResourceType == RTYPE_STRUCTURED) - { - bcatcstr(psContext->parameterDeclarations, "constant "); - } - else - { - bcatcstr(psContext->parameterDeclarations, "device "); - } - - - DeclareConstBufferShaderVariableMETAL(psContext->parameterDeclarations, - bstr2cstr(StructName, '\0'), - &psCBuf->asVars[0].sType, - 1, 0, psAtomicList); - if (eResourceType == RTYPE_UAV_RWSTRUCTURED) - { - //If it is UAV raw structured, let Metal compiler assign it with the first available location index - bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", psOperand->ui32RegisterNumber + UAV_BUFFER_START_SLOT); - //modify the reflection data to match the binding index - int count = 0; - for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) - { - if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) - { - count++; - //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; - psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_CBUFFER; - } - } - //If count >2, the logic here is wrong and need to be modified. - ASSERT(count < 2); - } - else - { - bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", psOperand->ui32RegisterNumber); - } - - bdestroy(StructName); -} - -static uint32_t ComputeVariableTypeSize(const ShaderVarType* psType) -{ - if (psType->Class == SVC_STRUCT) - { - uint32_t i; - uint32_t size = 0; - for (i = 0; i < psType->MemberCount; ++i) - { - size += ComputeVariableTypeSize(&psType->Members[i]); - } - - if (psType->Elements > 1) - { - return size * psType->Elements; - } - else - { - return size; - } - } - else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) - { - if (psType->Elements > 1) - { - return psType->Rows * psType->Elements; - } - else - { - return psType->Rows; - } - } - else - if (psType->Class == SVC_VECTOR) - { - if (psType->Elements > 1) - { - return psType->Elements; - } - else - { - return 1; - } - } - - return 1; -} - - -void DeclareStructConstantsMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, - ConstantBuffer* psCBuf, const Operand* psOperand, - bstring metal, AtomicVarList* psAtomicList) -{ - (void)psOperand; - - uint32_t i; - const char* StageName = "VS"; - uint32_t nextBufferRegister = 0; - uint32_t numDummyBuffers = 0; - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - PreDeclareStructTypeMETAL(metal, - psCBuf->asVars[i].sType.Name, - &psCBuf->asVars[i].sType, psAtomicList); - } - - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - StageName = "PS"; - break; - } - case COMPUTE_SHADER: - { - StageName = "CS"; - break; - } - default: - { - break; - } - } - - bformata(metal, "struct %s%s_Type {\n", psCBuf->Name, StageName); - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - uint32_t ui32RegNum = psCBuf->asVars[i].ui32StartOffset / 16; - if (ui32RegNum > nextBufferRegister) - { - bformata(metal, "\tfloat4 offsetDummy_%d[%d];\n", numDummyBuffers++, ui32RegNum - nextBufferRegister); - } - - DeclareConstBufferShaderVariableMETAL(metal, - psCBuf->asVars[i].sType.Name, - &psCBuf->asVars[i].sType, 0, i < psCBuf->ui32NumVars - 1, psAtomicList); - - uint32_t varSize = ComputeVariableTypeSize(&psCBuf->asVars[i].sType); - nextBufferRegister = ui32RegNum + varSize; - } - - bcatcstr(metal, "};\n"); - - bcatcstr(psContext->parameterDeclarations, "\tconstant "); - bformata(psContext->parameterDeclarations, "%s%s_Type ", psCBuf->Name, StageName); - bcatcstr(psContext->parameterDeclarations, "& "); - - bformata(psContext->parameterDeclarations, "%s%s_In", psCBuf->Name, StageName); - bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", ui32BindingPoint); - - for (i = 0; i < psCBuf->ui32NumVars; ++i) - { - const struct ShaderVarType_TAG* psType = &psCBuf->asVars[i].sType; - const char* Name = psCBuf->asVars[i].sType.Name; - const char* addressSpace = "constant"; - - if (psType->Class == SVC_STRUCT) - { - bformata(psContext->earlyMain, "\t%s %s_Type%s const &%s", addressSpace, Name, psType->Elements > 1 ? "*" : "", Name); - } - else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) - { - switch (psType->Type) - { - case SVT_FLOAT: - { - bformata(psContext->earlyMain, "\t%s float%d%s const &%s", addressSpace, psType->Columns, "*", Name, psType->Rows); - break; - } - case SVT_FLOAT16: - { - bformata(psContext->earlyMain, "\t%s half%d%s const &%s", addressSpace, psType->Columns, "*", Name, psType->Rows); - break; - } - default: - { - ASSERT(0); - break; - } - } - } - else - if (psType->Class == SVC_VECTOR) - { - switch (psType->Type) - { - case SVT_FLOAT: - case SVT_DOUBLE: // double is not supported in metal - { - bformata(psContext->earlyMain, "\t%s float%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_FLOAT16: - { - bformata(psContext->earlyMain, "\t%s half%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_UINT: - { - bformata(psContext->earlyMain, "\t%s uint%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_INT: - { - bformata(psContext->earlyMain, "\t%s int%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); - break; - } - default: - { - ASSERT(0); - break; - } - } - } - else - if (psType->Class == SVC_SCALAR) - { - switch (psType->Type) - { - case SVT_FLOAT: - case SVT_DOUBLE: // double is not supported in metal - { - bformata(psContext->earlyMain, "\t%s float%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_FLOAT16: - { - bformata(psContext->earlyMain, "\t%s half%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_UINT: - { - bformata(psContext->earlyMain, "\t%s uint%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_INT: - { - bformata(psContext->earlyMain, "\t%s int%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); - break; - } - case SVT_BOOL: - { - //Use int instead of bool. - //Allows implicit conversions to integer - bformata(psContext->earlyMain, "\t%s int%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); - break; - } - default: - { - ASSERT(0); - break; - } - } - } - - bformata(psContext->earlyMain, " = %s%s_In.%s;\n", psCBuf->Name, StageName, psCBuf->asVars[i].sType.Name); - } -} - -char* GetSamplerTypeMETAL(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eDimension, - const uint32_t ui32RegisterNumber, const uint32_t isShadow) -{ - ResourceBinding* psBinding = 0; - RESOURCE_RETURN_TYPE eType = RETURN_TYPE_UNORM; - int found; - found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - if (found) - { - eType = (RESOURCE_RETURN_TYPE)psBinding->ui32ReturnType; - } - switch (eDimension) - { - case RESOURCE_DIMENSION_BUFFER: - { - switch (eType) - { - case RETURN_TYPE_SINT: - return ""; - case RETURN_TYPE_UINT: - return ""; - default: - return ""; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE1D: - { - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture1d<int>"; - case RETURN_TYPE_UINT: - return "\ttexture1d<uint>"; - default: - return "\ttexture1d<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2D: - { - if (isShadow) - { - return "\tdepth2d<float>"; - } - - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture2d<int>"; - case RETURN_TYPE_UINT: - return "\ttexture2d<uint>"; - default: - return "\ttexture2d<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - if (isShadow) - { - return "\tdepth2d_ms<float>"; - } - - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture2d_ms<int>"; - case RETURN_TYPE_UINT: - return "\ttexture2d_ms<uint>"; - default: - return "\ttexture2d_ms<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE3D: - { - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture3d<int>"; - case RETURN_TYPE_UINT: - return "\ttexture3d<uint>"; - default: - return "\ttexture3d<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURECUBE: - { - if (isShadow) - { - return "\tdepthcube<float>"; - } - - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexturecube<int>"; - case RETURN_TYPE_UINT: - return "\ttexturecube<uint>"; - default: - return "\ttexturecube<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture1d_array<int>"; - case RETURN_TYPE_UINT: - return "\ttexture1d_array<uint>"; - default: - return "\ttexture1d_array<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - if (isShadow) - { - return "\tdepth2d_array<float>"; - } - - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexture2d_array<int>"; - case RETURN_TYPE_UINT: - return "\ttexture2d_array<uint>"; - default: - return "\ttexture2d_array<float>"; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - //Metal does not support this type of resource - ASSERT(0); - switch (eType) - { - case RETURN_TYPE_SINT: - return ""; - case RETURN_TYPE_UINT: - return ""; - default: - return ""; - } - break; - } - - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - switch (eType) - { - case RETURN_TYPE_SINT: - return "\ttexturecube_array<int>"; - case RETURN_TYPE_UINT: - return "\ttexturecube_array<uint>"; - default: - return "\ttexturecube_array<float>"; - } - break; - } - } - - return "sampler2D"; -} - -static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, uint32_t samplerCanDoShadowCmp) -{ - bstring metal = *psContext->currentShaderString; - - const char* samplerTypeName = GetSamplerTypeMETAL(psContext, - psDecl->value.eResourceDimension, - psDecl->asOperands[0].ui32RegisterNumber, samplerCanDoShadowCmp && psDecl->ui32IsShadowTex); - - if (samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) - { - //Create shadow and non-shadow sampler. - //HLSL does not have separate types for depth compare, just different functions. - bcatcstr(metal, samplerTypeName); - bcatcstr(metal, " "); - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 1); - } - else - { - bcatcstr(metal, samplerTypeName); - bcatcstr(metal, " "); - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 0); - } -} - -void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, AtomicVarList* psAtomicList) -{ - bstring metal = *psContext->currentShaderString; - ShaderData* psShader = psContext->psShader; - - switch (psDecl->eOpcode) - { - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_PS_SGV: - { - const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; - - if (psShader->eShaderType == PIXEL_SHADER) - { - switch (eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinInputMETAL(psContext, psDecl, "position", "float4"); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinInputMETAL(psContext, psDecl, "clip_distance", "float"); - break; - } - case NAME_INSTANCE_ID: - { - AddBuiltinInputMETAL(psContext, psDecl, "instance_id", "uint"); - break; - } - case NAME_IS_FRONT_FACE: - { - /* - Cast to int used because - if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. - Suggests no implicit conversion for bool<->int. - */ - - AddBuiltinInputMETAL(psContext, psDecl, "front_facing", "bool"); - break; - } - case NAME_SAMPLE_INDEX: - { - AddBuiltinInputMETAL(psContext, psDecl, "sample_id", "uint"); - break; - } - default: - { - DeclareInput(psContext, psDecl, - "user", OPERAND_MIN_PRECISION_DEFAULT, 4, INDEX_1D, psDecl->asOperands[0].pszSpecialName); - } - } - } - else if (psShader->eShaderType == VERTEX_SHADER) - { - switch (eSpecialName) - { - case NAME_VERTEX_ID: - { - AddBuiltinInputMETAL(psContext, psDecl, "vertex_id", "uint"); - break; - } - case NAME_INSTANCE_ID: - { - AddBuiltinInputMETAL(psContext, psDecl, "instance_id", "uint"); - break; - } - default: - { - DeclareInput(psContext, psDecl, - "attribute", OPERAND_MIN_PRECISION_DEFAULT, 4, INDEX_1D, psDecl->asOperands[0].pszSpecialName); - } - } - } - break; - } - - case OPCODE_DCL_OUTPUT_SIV: - { - switch (psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinOutputMETAL(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "position"); - break; - } - case NAME_CLIP_DISTANCE: - { - AddBuiltinOutputMETAL(psContext, psDecl, GLVARTYPE_FLOAT, 0, "clip_distance"); - break; - } - case NAME_VERTEX_ID: - { - ASSERT(0); //VertexID is not an output - break; - } - case NAME_INSTANCE_ID: - { - ASSERT(0); //InstanceID is not an output - break; - } - case NAME_IS_FRONT_FACE: - { - ASSERT(0); //FrontFacing is not an output - break; - } - default: - { - bformata(metal, "float4 %s;\n", psDecl->asOperands[0].pszSpecialName); - - bcatcstr(metal, "#define "); - TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(metal, " %s\n", psDecl->asOperands[0].pszSpecialName); - break; - } - } - break; - } - case OPCODE_DCL_INPUT: - { - const Operand* psOperand = &psDecl->asOperands[0]; - //Force the number of components to be 4. - /*dcl_output o3.xy - dcl_output o3.z - - Would generate a vec2 and a vec3. We discard the second one making .z invalid! - - */ - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); - const char* InputName; - - if ((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT) || - (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID) || - (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK) || - (psOperand->eType == OPERAND_TYPE_INPUT_FORK_INSTANCE_ID)) - { - break; - } - if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID) - { - bformata(psContext->parameterDeclarations, "\tuint3 vThreadID [[ thread_position_in_grid ]],\n"); - break; - } - if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP) - { - bformata(psContext->parameterDeclarations, "\tuint3 vThreadIDInGroup [[ thread_position_in_threadgroup ]],\n"); - break; - } - if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID) - { - bformata(psContext->parameterDeclarations, "\tuint3 vThreadGroupID [[ threadgroup_position_in_grid ]],\n"); - break; - } - if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED) - { - bformata(psContext->parameterDeclarations, "\tuint vThreadIDInGroupFlattened [[ thread_index_in_threadgroup ]],\n"); - break; - } - //Already declared as part of an array. - if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) - { - break; - } - - InputName = GetDeclaredInputNameMETAL(psContext, psShader->eShaderType, psOperand); - - DeclareInput(psContext, psDecl, - "attribute", (OPERAND_MIN_PRECISION)psOperand->eMinPrecision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); - - break; - } - case OPCODE_DCL_INPUT_PS_SIV: - { - switch (psDecl->asOperands[0].eSpecialName) - { - case NAME_POSITION: - { - AddBuiltinInputMETAL(psContext, psDecl, "position", "float4"); - break; - } - } - break; - } - case OPCODE_DCL_INPUT_SIV: - { - break; - } - case OPCODE_DCL_INPUT_PS: - { - const Operand* psOperand = &psDecl->asOperands[0]; - int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); - const char* InputName = GetDeclaredInputNameMETAL(psContext, PIXEL_SHADER, psOperand); - - DeclareInput(psContext, psDecl, - "user", (OPERAND_MIN_PRECISION)psOperand->eMinPrecision, iNumComponents, INDEX_1D, InputName); - - break; - } - case OPCODE_DCL_TEMPS: - { - const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; - - if (ui32NumTemps > 0) - { - bformata(psContext->earlyMain, "\tfloat4 Temp[%d];\n", ui32NumTemps); - - bformata(psContext->earlyMain, "\tint4 Temp_int[%d];\n", ui32NumTemps); - bformata(psContext->earlyMain, "\tuint4 Temp_uint[%d];\n", ui32NumTemps); - bformata(psContext->earlyMain, "\thalf4 Temp_half[%d];\n", ui32NumTemps); - } - - break; - } - case OPCODE_SPECIAL_DCL_IMMCONST: - { - const Operand* psDest = &psDecl->asOperands[0]; - const Operand* psSrc = &psDecl->asOperands[1]; - - ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); - if (psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) - { - bformata(metal, "const int4 IntImmConst%d = ", psDest->ui32RegisterNumber); - } - else - { - bformata(metal, "const float4 ImmConst%d = ", psDest->ui32RegisterNumber); - AddToDx9ImmConstIndexableArrayMETAL(psContext, psDest); - } - TranslateOperandMETAL(psContext, psSrc, psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT ? TO_FLAG_INTEGER : TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(metal, ";\n"); - - break; - } - case OPCODE_DCL_CONSTANT_BUFFER: - { - const Operand* psOperand = &psDecl->asOperands[0]; - const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; - - const char* StageName = "VS"; - - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - StageName = "PS"; - break; - } - case HULL_SHADER: - { - StageName = "HS"; - break; - } - case DOMAIN_SHADER: - { - StageName = "DS"; - break; - } - case GEOMETRY_SHADER: - { - StageName = "GS"; - break; - } - case COMPUTE_SHADER: - { - StageName = "CS"; - break; - } - default: - { - break; - } - } - - ConstantBuffer* psCBuf = NULL; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - if (psCBuf) - { - // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. - // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads - // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. - psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; - } - - // We don't have a original resource name, maybe generate one??? - if (!psCBuf) - { - bformata(metal, "struct ConstantBuffer%d {\n\tfloat4 data[%d];\n};\n", ui32BindingPoint, psOperand->aui32ArraySizes[1], ui32BindingPoint); - // For vertex shaders HLSLcc generates code that expectes the - // constant buffer to be a pointer. For other shaders it generates - // code that expects a reference instead... - if (psContext->psShader->eShaderType == VERTEX_SHADER) - { - bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d* cb%d [[ buffer(%d) ]],\n", ui32BindingPoint, ui32BindingPoint, ui32BindingPoint); - } - else - { - bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d& cb%d [[ buffer(%d) ]],\n", ui32BindingPoint, ui32BindingPoint, ui32BindingPoint); - } - break; - } - else if (psCBuf->blob) - { - // For vertex shaders HLSLcc generates code that expectes the - // constant buffer to be a pointer. For other shaders it generates - // code that expects a reference instead... - bformata(metal, "struct ConstantBuffer%d {\n\tfloat4 %s[%d];\n};\n", ui32BindingPoint, psCBuf->asVars->Name, psOperand->aui32ArraySizes[1], ui32BindingPoint); - if (psContext->psShader->eShaderType == VERTEX_SHADER) - { - bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d* %s%s_data [[ buffer(%d) ]],\n", ui32BindingPoint, psCBuf->Name, StageName, ui32BindingPoint); - } - else - { - bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d& %s%s_data [[ buffer(%d) ]],\n", ui32BindingPoint, psCBuf->Name, StageName, ui32BindingPoint); - } - break; - } - - DeclareStructConstantsMETAL(psContext, ui32BindingPoint, psCBuf, psOperand, metal, psAtomicList); - - break; - } - case OPCODE_DCL_SAMPLER: - { - if (psDecl->bIsComparisonSampler) - { - psContext->currentShaderString = &psContext->mainShader; - metal = *psContext->currentShaderString; - - bcatcstr(metal, "constexpr sampler "); - ResourceNameMETAL(metal, psContext, RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, 1); - bformata(metal, "(compare_func::less);\n", psDecl->asOperands[0].ui32RegisterNumber); - } - - /* CONFETTI NOTE (DAVID SROUR): - * The following declaration still needs to occur for comparison samplers. - * The Metal layer of the engine will still try to bind a sampler in the appropriate slot. - * This parameter of the shader's entrance function acts as a dummy comparison sampler for the engine. - * Note that 0 is always passed for the "bZCompare" argument of ResourceNameMETAL(...) as to give the dummy - * sampler a different name as the constexpr one. - */ - { - psContext->currentShaderString = &psContext->parameterDeclarations; - metal = *psContext->currentShaderString; - - bcatcstr(metal, "\tsampler "); - ResourceNameMETAL(metal, psContext, RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(metal, "[[ sampler(%d) ]],\n", psDecl->asOperands[0].ui32RegisterNumber); - } - break; - } - case OPCODE_DCL_RESOURCE: - { - // CONFETTI BEGIN: David Srour - // METAL PIXEL SHADER RT FETCH - if (psDecl->asOperands[0].ui32RegisterNumber >= GMEM_FLOAT_START_SLOT) - { - int regNum = GetGmemInputResourceSlotMETAL(psDecl->asOperands[0].ui32RegisterNumber); - int numElements = GetGmemInputResourceNumElementsMETAL(psDecl->asOperands[0].ui32RegisterNumber); - - switch (numElements) - { - case 1: - bformata(psContext->parameterDeclarations, "\tfloat"); - break; - case 2: - bformata(psContext->parameterDeclarations, "\tfloat2"); - break; - case 3: - bformata(psContext->parameterDeclarations, "\tfloat3"); - break; - case 4: - bformata(psContext->parameterDeclarations, "\tfloat4"); - break; - default: - bformata(psContext->parameterDeclarations, "\tfloat4"); - break; - } - - psContext->gmemOutputNumElements[regNum] = numElements; - - // Function input framebuffer - bformata(psContext->parameterDeclarations, " GMEM_Input%d [[ color(%d) ]],\n", regNum, regNum); - - break; - } - // CONFETTI END - - psContext->currentShaderString = &psContext->parameterDeclarations; - metal = *psContext->currentShaderString; - - switch (psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_BUFFER: - { - break; - } - case RESOURCE_DIMENSION_TEXTURE1D: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - TranslateResourceTexture(psContext, psDecl, 0); - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - TranslateResourceTexture(psContext, psDecl, 0); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - TranslateResourceTexture(psContext, psDecl, 1); - break; - } - } - - bformata(metal, "[[ texture(%d) ]],\n", psDecl->asOperands[0].ui32RegisterNumber); - psContext->currentShaderString = &psContext->mainShader; - metal = *psContext->currentShaderString; - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); - psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; - break; - } - case OPCODE_DCL_OUTPUT: - { - AddUserOutputMETAL(psContext, psDecl); - break; - } - case OPCODE_DCL_GLOBAL_FLAGS: - { - uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; - - if (ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL) - { - psContext->needsFragmentTestHint = 1; - } - if (!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) - { - //TODO add precise - //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx - } - if (ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) - { - // TODO - // Is there something for this in METAL? - } - - break; - } - - case OPCODE_DCL_THREAD_GROUP: - { - /* CONFETTI NOTE: - The thread group information need to be passed to engine side. Add the information - into reflection data. - */ - psContext->psShader->sInfo.ui32Thread_x = psDecl->value.aui32WorkGroupSize[0]; - psContext->psShader->sInfo.ui32Thread_y = psDecl->value.aui32WorkGroupSize[1]; - psContext->psShader->sInfo.ui32Thread_z = psDecl->value.aui32WorkGroupSize[2]; - break; - } - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - { - break; - } - case OPCODE_DCL_TESS_DOMAIN: - { - break; - } - case OPCODE_DCL_TESS_PARTITIONING: - { - break; - } - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - { - break; - } - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - { - break; - } - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - { - break; - } - case OPCODE_DCL_INTERFACE: - { - break; - } - case OPCODE_DCL_FUNCTION_BODY: - { - //bformata(metal, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); - break; - } - case OPCODE_DCL_FUNCTION_TABLE: - { - break; - } - case OPCODE_CUSTOMDATA: - { - const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; - const uint32_t ui32NumVec4Minus1 = (ui32NumVec4 - 1); - uint32_t ui32ConstIndex = 0; - float x, y, z, w; - - //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. - //else 2 buffers - one integer and one float. - More data - - if (ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) - { - bcatcstr(metal, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(metal, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); - - bformata(metal, "static constant float4 immediateConstBuffer[%d] = {\n", ui32NumVec4, ui32NumVec4); - for (; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) - { - float loopLocalX, loopLocalY, loopLocalZ, loopLocalW; - loopLocalX = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - loopLocalY = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - loopLocalZ = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - loopLocalW = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - - //A single vec4 can mix integer and float types. - //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. - if (fpcheck(loopLocalX)) - { - loopLocalX = 0; - } - if (fpcheck(loopLocalY)) - { - loopLocalY = 0; - } - if (fpcheck(loopLocalZ)) - { - loopLocalZ = 0; - } - if (fpcheck(loopLocalW)) - { - loopLocalW = 0; - } - - bformata(metal, "\tfloat4(%f, %f, %f, %f), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); - } - //No trailing comma on this one - x = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; - y = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; - z = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; - w = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; - if (fpcheck(x)) - { - x = 0; - } - if (fpcheck(y)) - { - y = 0; - } - if (fpcheck(z)) - { - z = 0; - } - if (fpcheck(w)) - { - w = 0; - } - bformata(metal, "\tfloat4(%f, %f, %f, %f)\n", x, y, z, w); - bcatcstr(metal, "};\n"); - } - else - { - bcatcstr(metal, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); - bcatcstr(metal, "#define immediateConstBufferF(idx) as_type<float4>(immediateConstBufferInt[idx])\n"); - } - - { - uint32_t ui32ConstIndex2 = 0; - int x2, y2, z2, w2; - - bformata(metal, "static constant int4 immediateConstBufferInt[%d] = {\n", ui32NumVec4, ui32NumVec4); - for (; ui32ConstIndex2 < ui32NumVec4Minus1; ui32ConstIndex2++) - { - int loopLocalX, loopLocalY, loopLocalZ, loopLocalW; - loopLocalX = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; - loopLocalY = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; - loopLocalZ = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; - loopLocalW = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; - - bformata(metal, "\tint4(%d, %d, %d, %d), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); - } - //No trailing comma on this one - x2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; - y2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; - z2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; - w2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; - - bformata(metal, "\tint4(%d, %d, %d, %d)\n", x2, y2, z2, w2); - bcatcstr(metal, "};\n"); - } - - break; - } - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - { - break; - } - case OPCODE_DCL_INDEXABLE_TEMP: - { - const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; - const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; - const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; - bformata(psContext->earlyMain, "float%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - bformata(psContext->earlyMain, "int%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - if (HaveUVec(psShader->eTargetLanguage)) - { - bformata(psContext->earlyMain, "uint%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); - } - break; - } - case OPCODE_DCL_INDEX_RANGE: - { - break; - } - case OPCODE_HS_DECLS: - { - break; - } - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - { - break; - } - case OPCODE_HS_FORK_PHASE: - { - break; - } - case OPCODE_HS_JOIN_PHASE: - { - break; - } - case OPCODE_DCL_HS_MAX_TESSFACTOR: - { - //For metal the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - { - psContext->currentShaderString = &psContext->parameterDeclarations; - metal = *psContext->currentShaderString; - - if (psDecl->value.eResourceDimension == RESOURCE_DIMENSION_BUFFER) - { - { - //give write access - bcatcstr(metal, "\tdevice "); - } - switch (psDecl->sUAV.Type) - { - case RETURN_TYPE_FLOAT: - bcatcstr(metal, "float "); - break; - case RETURN_TYPE_UNORM: - bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_UNORM "); - break; - case RETURN_TYPE_SNORM: - bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_SNORM "); - break; - case RETURN_TYPE_UINT: - bcatcstr(metal, "uint "); - break; - case RETURN_TYPE_SINT: - bcatcstr(metal, "int "); - break; - default: - ASSERT(0); - } - bstring StructName; - StructName = bfromcstr(""); - ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(metal, " * "); - TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(metal, " [[buffer(%d)]], \n", psDecl->asOperands[0].ui32RegisterNumber + UAV_BUFFER_START_SLOT); - int count = 0; - for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) - { - if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) - { - count++; - //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; - psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_CBUFFER; - } - } - //If count >2, the logic here is wrong and need to be modified. - ASSERT(count < 2); - } - else - { - switch (psDecl->value.eResourceDimension) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - bformata(metal, "\ttexture1d<"); - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - bformata(metal, "\ttexture2d<"); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMS: - { - //metal does not support this - ASSERT(0); - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - bformata(metal, "\ttexture3d<"); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - bformata(metal, "\ttexturecube<"); - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - bformata(metal, "\ttexture1d_array<"); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - bformata(metal, "\ttexture2d_array<"); - break; - } - case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - { - //metal does not suuport this. - ASSERT(0); - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - bformata(metal, "\ttexturecube_array<"); - break; - } - } - switch (psDecl->sUAV.Type) - { - case RETURN_TYPE_FLOAT: - bcatcstr(metal, "float "); - break; - case RETURN_TYPE_UNORM: - bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_UNORM "); - break; - case RETURN_TYPE_SNORM: - bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_SNORM "); - break; - case RETURN_TYPE_UINT: - bcatcstr(metal, "uint "); - break; - case RETURN_TYPE_SINT: - bcatcstr(metal, "int "); - break; - default: - ASSERT(0); - } - if (psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) - { - bcatcstr(metal, "> "); - } - else - { - //give write access - bcatcstr(metal, ", access::write> "); - } - bstring StructName; - StructName = bfromcstr(""); - ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(metal, " [[texture(%d)]], \n", psDecl->asOperands[0].ui32RegisterNumber + UAV_BUFFER_START_SLOT); - int count = 0; - for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) - { - if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) - { - count++; - //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; - psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_TEXTURE; - } - } - //If count >2, the logic here is wrong and need to be modified. - ASSERT(count < 2); - //TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - } - psContext->currentShaderString = &psContext->mainShader; - metal = *psContext->currentShaderString; - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - { - const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; - ConstantBuffer* psCBuf = NULL; - - if (psDecl->sUAV.bCounter) - { - bformata(metal, "atomic_uint "); - ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(metal, "_counter; \n"); - } - - GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); - - DeclareBufferVariableMETAL(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], RTYPE_UAV_RWSTRUCTURED, metal, psAtomicList); - break; - } - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - { - if (psDecl->sUAV.bCounter) - { - bformata(metal, "atomic_uint "); - ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bformata(metal, "_counter; \n"); - } - - bformata(metal, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); - ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); - bcatcstr(metal, "[];\n};\n"); - - break; - } - case OPCODE_DCL_RESOURCE_STRUCTURED: - { - ConstantBuffer* psCBuf = NULL; - - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - DeclareBufferVariableMETAL(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], - RTYPE_STRUCTURED, psContext->mainShader, psAtomicList); - break; - } - case OPCODE_DCL_RESOURCE_RAW: - { - bformata(metal, "buffer Block%d {\n\tuint RawRes%d[];\n};\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - { - psContext->currentShaderString = &psContext->earlyMain; - metal = *psContext->currentShaderString; - - ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; - - ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); - - bcatcstr(metal, "\tthreadgroup struct {\n"); - bformata(metal, "\t\tuint value[%d];\n", psDecl->sTGSM.ui32Stride / 4); - bcatcstr(metal, "\t} "); - TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(metal, "[%d];\n", - psDecl->sTGSM.ui32Count); - - memset(psVarType, 0, sizeof(ShaderVarType)); - strcpy(psVarType->Name, "$Element"); - - psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; - psVarType->Elements = psDecl->sTGSM.ui32Count; - - psContext->currentShaderString = &psContext->mainShader; - metal = *psContext->currentShaderString; - break; - } - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - { -#ifdef _DEBUG - //AddIndentation(psContext); - //bcatcstr(metal, "//TODO: OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW\n"); -#endif - psContext->currentShaderString = &psContext->earlyMain; - metal = *psContext->currentShaderString; - bcatcstr(metal, "\tthreadgroup "); - bformata(metal, "atomic_uint "); - //psDecl->asOperands - TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); - bformata(metal, "[%d]; \n", psDecl->sTGSM.ui32Stride / 4); - - psContext->currentShaderString = &psContext->mainShader; - metal = *psContext->currentShaderString; - break; - } - case OPCODE_DCL_STREAM: - { - break; - } - case OPCODE_DCL_GS_INSTANCE_COUNT: - { - break; - } - default: - { - ASSERT(0); - break; - } - } -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c deleted file mode 100644 index 547f293733..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c +++ /dev/null @@ -1,4946 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toMETALInstruction.h" -#include "internal_includes/toMETALOperand.h" -#include "internal_includes/languages.h" -#include "bstrlib.h" -#include "stdio.h" -#include <stdlib.h> -#include "hlslcc.h" -#include <internal_includes/toGLSLOperand.h> -#include "internal_includes/debug.h" - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); -static int METALIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode); - -// Calculate the bits set in mask -static int METALWriteMaskToComponentCount(uint32_t writeMask) -{ - uint32_t count; - // In HLSL bytecode writemask 0 also means everything - if (writeMask == 0) - { - return 4; - } - - // Count bits set - // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 - count = (writeMask * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; - - return (int)count; -} - -static uint32_t METALBuildComponentMaskFromElementCount(int count) -{ - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - return (1 << count) - 1; -} - - -// This function prints out the destination name, possible destination writemask, assignment operator -// and any possible conversions needed based on the eSrcType+ui32SrcElementCount (type and size of data expected to be coming in) -// As an output, pNeedsParenthesis will be filled with the amount of closing parenthesis needed -// and pSrcCount will be filled with the number of components expected -// ui32CompMask can be used to only write to 1 or more components (used by MOVC) -static void METALAddOpAssignToDestWithMask(HLSLCrossCompilerContext* psContext, const Operand* psDest, - SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char* szAssignmentOp, int* pNeedsParenthesis, uint32_t ui32CompMask) -{ - uint32_t ui32DestElementCount = GetNumSwizzleElementsWithMaskMETAL(psDest, ui32CompMask); - bstring metal = *psContext->currentShaderString; - SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, psDest); - ASSERT(pNeedsParenthesis != NULL); - - *pNeedsParenthesis = 0; - - uint32_t flags = TO_FLAG_DESTINATION; - // Default is full floats. Handle half floats if the source is half precision - if (eSrcType == SVT_FLOAT16) - { - flags |= TO_FLAG_FLOAT16; - } - TranslateOperandWithMaskMETAL(psContext, psDest, flags, ui32CompMask); - - //GMEM data output types can only be full floats. - if(eDestDataType== SVT_FLOAT16 && psDest->eType== OPERAND_TYPE_OUTPUT && psContext->gmemOutputNumElements[0]>0 ) - { - eDestDataType = SVT_FLOAT; - } - - // Simple path: types match. - if (eDestDataType == eSrcType) - { - // Cover cases where the HLSL language expects the rest of the components to be default-filled - // eg. MOV r0, c0.x => Temp[0] = vec4(c0.x); - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(metal, " %s %s(", szAssignmentOp, GetConstructorForTypeMETAL(eDestDataType, ui32DestElementCount)); - *pNeedsParenthesis = 1; - } - else - { - bformata(metal, " %s ", szAssignmentOp); - } - return; - } - - switch (eDestDataType) - { - case SVT_INT: - { - if (1 == ui32DestElementCount) - { - bformata(metal, " %s as_type<int>(", szAssignmentOp); - } - else - { - bformata(metal, "%s as_type<int%d>(", szAssignmentOp, ui32DestElementCount); - } - break; - } - case SVT_UINT: - { - if (1 == ui32DestElementCount) - { - bformata(metal, " %s as_type<uint>(", szAssignmentOp); - } - else - { - bformata(metal, "%s as_type<uint%d>(", szAssignmentOp, ui32DestElementCount); - } - break; - } - case SVT_FLOAT: - { - const char* castType = eSrcType == SVT_FLOAT16 ? "static_cast" : "as_type"; - if (1 == ui32DestElementCount) - { - bformata(metal, " %s %s<float>(", szAssignmentOp, castType); - } - else - { - bformata(metal, "%s %s<float%d>(", szAssignmentOp, castType, ui32DestElementCount); - } - break; - } - case SVT_FLOAT16: - { - if (1 == ui32DestElementCount) - { - bformata(metal, " %s static_cast<half>(", szAssignmentOp); - } - else - { - bformata(metal, "%s static_cast<half%d>(", szAssignmentOp, ui32DestElementCount); - } - break; - } - default: - // TODO: Handle bools? - break; - } - - switch (eDestDataType) - { - case SVT_INT: - case SVT_UINT: - case SVT_FLOAT: - case SVT_FLOAT16: - { - // Cover cases where the HLSL language expects the rest of the components to be default-filled - if (ui32DestElementCount > ui32SrcElementCount) - { - bformata(metal, "%s(", GetConstructorForTypeMETAL(eSrcType, ui32DestElementCount)); - (*pNeedsParenthesis)++; - } - } - } - (*pNeedsParenthesis)++; - return; -} - -static void METALAddAssignToDest(HLSLCrossCompilerContext* psContext, const Operand* psDest, - SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis) -{ - METALAddOpAssignToDestWithMask(psContext, psDest, eSrcType, ui32SrcElementCount, "=", pNeedsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); -} - -static void METALAddAssignPrologue(HLSLCrossCompilerContext* psContext, int numParenthesis) -{ - bstring glsl = *psContext->currentShaderString; - while (numParenthesis != 0) - { - bcatcstr(glsl, ")"); - numParenthesis--; - } - bcatcstr(glsl, ";\n"); -} -static uint32_t METALResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType) -{ - if (eType == RETURN_TYPE_SINT) - { - return TO_FLAG_INTEGER; - } - else if (eType == RETURN_TYPE_UINT) - { - return TO_FLAG_UNSIGNED_INTEGER; - } - else - { - return TO_FLAG_NONE; - } -} - - -typedef enum -{ - METAL_CMP_EQ, - METAL_CMP_LT, - METAL_CMP_GE, - METAL_CMP_NE, -} METALComparisonType; - -static void METALAddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, METALComparisonType eType, - uint32_t typeFlag, Instruction* psNextInst) -{ - (void)psNextInst; - - // Multiple cases to consider here: - // For shader model <=3: all comparisons are floats - // otherwise: - // OPCODE_LT, _GT, _NE etc: inputs are floats, outputs UINT 0xffffffff or 0. typeflag: TO_FLAG_NONE - // OPCODE_ILT, _IGT etc: comparisons are signed ints, outputs UINT 0xffffffff or 0 typeflag TO_FLAG_INTEGER - // _ULT, UGT etc: inputs unsigned ints, outputs UINTs typeflag TO_FLAG_UNSIGNED_INTEGER - // - // Additional complexity: if dest swizzle element count is 1, we can use normal comparison operators, otherwise glsl intrinsics. - - uint32_t orig_type = typeFlag; - - bstring metal = *psContext->currentShaderString; - const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - const uint32_t s1ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[2]); - - uint32_t minElemCount = destElemCount < s0ElemCount ? destElemCount : s0ElemCount; - - int needsParenthesis = 0; - - ASSERT(s0ElemCount == s1ElemCount || s1ElemCount == 1 || s0ElemCount == 1); - if (s0ElemCount != s1ElemCount) - { - // Set the proper auto-expand flag is either argument is scalar - typeFlag |= (TO_AUTO_EXPAND_TO_VEC2 << (max(s0ElemCount, s1ElemCount) - 2)); - } - - const char* metalOpcode[] = { - "==", - "<", - ">=", - "!=", - }; - - //Scalar compare - - // Optimization shortcut for the IGE+BREAKC_NZ combo: - // First print out the if(cond)->break directly, and then - // to guarantee correctness with side-effects, re-run - // the actual comparison. In most cases, the second run will - // be removed by the shader compiler optimizer pass (dead code elimination) - // This also makes it easier for some GLSL optimizers to recognize the for loop. - - //if (psInst->eOpcode == OPCODE_IGE && - // psNextInst && - // psNextInst->eOpcode == OPCODE_BREAKC && - // (psInst->asOperands[0].ui32RegisterNumber == psNextInst->asOperands[0].ui32RegisterNumber)) - //{ - - // AddIndentation(psContext); - // bcatcstr(glsl, "// IGE+BREAKC opt\n"); - // AddIndentation(psContext); - - // if (psNextInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO) - // bcatcstr(glsl, "if (("); - // else - // bcatcstr(glsl, "if (!("); - // TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); - // bformata(glsl, "%s ", glslOpcode[eType]); - // TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); - // bcatcstr(glsl, ")) { break; }\n"); - - // // Mark the BREAKC instruction as already handled - // psNextInst->eOpcode = OPCODE_NOP; - - // // Continue as usual - //} - - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, destElemCount, &needsParenthesis); - - bcatcstr(metal, "select("); - - /* Confetti note: - ASM returns 0XFFFFFFFF or 0 - It's important to use int. - A sign intrinsic converts to the following: - lt r0.x, l(0.000000), v0.z - lt r0.y, v0.z, l(0.000000) - iadd r0.x, -r0.x, r0.y - itof o0.xyzw, r0.xxxx - */ - - if (destElemCount == 1) - { - bcatcstr(metal, "0, (int)0xFFFFFFFF, ("); - } - else - { - bformata(metal, "int%d(0), int%d(0xFFFFFFFF), (", destElemCount, destElemCount); - } - - TranslateOperandMETAL(psContext, &psInst->asOperands[1], typeFlag); - bcatcstr(metal, ")"); - if (destElemCount > 1) - { - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - } - else if (s0ElemCount > minElemCount) - { - AddSwizzleUsingElementCountMETAL(psContext, minElemCount); - } - bformata(metal, " %s (", metalOpcode[eType]); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], typeFlag); - bcatcstr(metal, ")"); - if (destElemCount > 1) - { - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - } - else if (s1ElemCount > minElemCount || orig_type != typeFlag) - { - AddSwizzleUsingElementCountMETAL(psContext, minElemCount); - } - bcatcstr(metal, ")"); - METALAddAssignPrologue(psContext, needsParenthesis); -} - - -static void METALAddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, Operand* pSrc) -{ - int numParenthesis = 0; - int srcSwizzleCount = GetNumSwizzleElementsMETAL(pSrc); - uint32_t writeMask = GetOperandWriteMaskMETAL(pDest); - - const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataTypeExMETAL(psContext, pSrc, GetOperandDataTypeMETAL(psContext, pDest)); - uint32_t flags = SVTTypeToFlagMETAL(eSrcType); - - METALAddAssignToDest(psContext, pDest, eSrcType, srcSwizzleCount, &numParenthesis); - TranslateOperandWithMaskMETAL(psContext, pSrc, flags, writeMask); - - METALAddAssignPrologue(psContext, numParenthesis); -} - -static uint32_t METALElemCountToAutoExpandFlag(uint32_t elemCount) -{ - return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2); -} - -static void METALAddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, const Operand* src0, Operand* src1, Operand* src2) -{ - bstring metal = *psContext->currentShaderString; - uint32_t destElemCount = GetNumSwizzleElementsMETAL(pDest); - uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(src0); - uint32_t s1ElemCount = GetNumSwizzleElementsMETAL(src1); - uint32_t s2ElemCount = GetNumSwizzleElementsMETAL(src2); - uint32_t destWriteMask = GetOperandWriteMaskMETAL(pDest); - uint32_t destElem; - - const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, pDest); - /* - for each component in dest[.mask] - if the corresponding component in src0 (POS-swizzle) - has any bit set - { - copy this component (POS-swizzle) from src1 into dest - } - else - { - copy this component (POS-swizzle) from src2 into dest - } - endfor - */ - - /* Single-component conditional variable (src0) */ - if (s0ElemCount == 1 || IsSwizzleReplicatedMETAL(src0)) - { - int numParenthesis = 0; - AddIndentation(psContext); - - bcatcstr(metal, "if ("); - TranslateOperandMETAL(psContext, src0, TO_AUTO_BITCAST_TO_INT); - if (s0ElemCount > 1) - { - bcatcstr(metal, ".x"); - } - - bcatcstr(metal, " != 0)\n"); - AddIndentation(psContext); - AddIndentation(psContext); - - METALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); - - if (s1ElemCount == 1 && destElemCount > 1) - { - TranslateOperandMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType) | METALElemCountToAutoExpandFlag(destElemCount)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType), destWriteMask); - } - - bcatcstr(metal, ";\n"); - AddIndentation(psContext); - bcatcstr(metal, "else\n"); - AddIndentation(psContext); - AddIndentation(psContext); - - METALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); - - if (s2ElemCount == 1 && destElemCount > 1) - { - TranslateOperandMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType) | METALElemCountToAutoExpandFlag(destElemCount)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType), destWriteMask); - } - - METALAddAssignPrologue(psContext, numParenthesis); - } - else - { - // TODO: We can actually do this in one op using mix(). - int srcElem = 0; - for (destElem = 0; destElem < 4; ++destElem) - { - int numParenthesis = 0; - if (pDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && pDest->ui32CompMask != 0 && !(pDest->ui32CompMask & (1 << destElem))) - { - continue; - } - - AddIndentation(psContext); - - bcatcstr(metal, "if ("); - TranslateOperandWithMaskMETAL(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << destElem); - bcatcstr(metal, " != 0)\n"); - - AddIndentation(psContext); - AddIndentation(psContext); - - METALAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); - - TranslateOperandWithMaskMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType), 1 << destElem); - - bcatcstr(metal, ";\n"); - AddIndentation(psContext); - bcatcstr(metal, "else\n"); - AddIndentation(psContext); - AddIndentation(psContext); - - METALAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); - TranslateOperandWithMaskMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType), 1 << destElem); - - METALAddAssignPrologue(psContext, numParenthesis); - - srcElem++; - } - } -} - -// Returns nonzero if operands are identical, only cares about temp registers currently. -static int METALAreTempOperandsIdentical(const Operand* psA, const Operand* psB) -{ - if (!psA || !psB) - { - return 0; - } - - if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP) - { - return 0; - } - - if (psA->eModifier != psB->eModifier) - { - return 0; - } - - if (psA->iNumComponents != psB->iNumComponents) - { - return 0; - } - - if (psA->ui32RegisterNumber != psB->ui32RegisterNumber) - { - return 0; - } - - if (psA->eSelMode != psB->eSelMode) - { - return 0; - } - - if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask) - { - return 0; - } - - if (psA->eSelMode != OPERAND_4_COMPONENT_MASK_MODE && psA->ui32Swizzle != psB->ui32Swizzle) - { - return 0; - } - - return 1; -} - -// Returns nonzero if the operation is commutative -static int METALIsOperationCommutative(OPCODE_TYPE eOpCode) -{ - switch (eOpCode) - { - case OPCODE_DADD: - case OPCODE_IADD: - case OPCODE_ADD: - case OPCODE_MUL: - case OPCODE_IMUL: - case OPCODE_OR: - case OPCODE_AND: - return 1; - default: - return 0; - } -} - -static void METALCallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t src1SwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[src1]); - uint32_t src0SwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[src0]); - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[dest]); - int needsParenthesis = 0; - - AddIndentation(psContext); - - if (src1SwizCount == src0SwizCount == dstSwizCount) - { - // Optimization for readability (and to make for loops in WebGL happy): detect cases where either src == dest and emit +=, -= etc. instead. - if (METALAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src0]) != 0) - { - METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); - TranslateOperandMETAL(psContext, &psInst->asOperands[src1], SVTTypeToFlagMETAL(eDataType)); - METALAddAssignPrologue(psContext, needsParenthesis); - return; - } - else if (METALAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src1]) != 0 && (METALIsOperationCommutative(psInst->eOpcode) != 0)) - { - METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); - TranslateOperandMETAL(psContext, &psInst->asOperands[src0], SVTTypeToFlagMETAL(eDataType)); - METALAddAssignPrologue(psContext, needsParenthesis); - return; - } - } - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, &needsParenthesis); - - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], SVTTypeToFlagMETAL(eDataType), destMask); - bformata(glsl, " %s ", name); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], SVTTypeToFlagMETAL(eDataType), destMask); - METALAddAssignPrologue(psContext, needsParenthesis); -} - -static void METALCallTernaryOp(HLSLCrossCompilerContext* psContext, const char* op1, const char* op2, Instruction* psInst, - int dest, int src0, int src1, int src2, uint32_t dataType) -{ - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[dest]); - - const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); - uint32_t ui32Flags = dataType | SVTTypeToFlagMETAL(eDestType); - int numParenthesis = 0; - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], TypeFlagsToSVTTypeMETAL(dataType), dstSwizCount, &numParenthesis); - - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bformata(glsl, " %s ", op1); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - bformata(glsl, " %s ", op2); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src2], ui32Flags, destMask); - METALAddAssignPrologue(psContext, numParenthesis); -} - -static void METALCallHelper3(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask) -{ - const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestType); - - bstring glsl = *psContext->currentShaderString; - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - int numParenthesis = 0; - - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src2], ui32Flags, destMask); - METALAddAssignPrologue(psContext, numParenthesis); -} - -static void METALCallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestType); - - bstring glsl = *psContext->currentShaderString; - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - - int isDotProduct = (strncmp(name, "dot", 3) == 0) ? 1 : 0; - int numParenthesis = 0; - - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, isDotProduct ? 1 : dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - - METALAddAssignPrologue(psContext, numParenthesis); -} - -static void METALCallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - METALAddAssignPrologue(psContext, numParenthesis); -} - -static void METALCallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int src1, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_UINT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_UINT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - bcatcstr(glsl, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); - METALAddAssignPrologue(psContext, numParenthesis); -} - -static void METALCallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, - int dest, int src0, int paramsShouldFollowWriteMask) -{ - uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; - bstring glsl = *psContext->currentShaderString; - uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); - uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; - int numParenthesis = 0; - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); - - bformata(glsl, "%s(", name); - numParenthesis++; - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); - METALAddAssignPrologue(psContext, numParenthesis); -} - -////Result is an int. -//static void METALCallHelper1Int(HLSLCrossCompilerContext* psContext, -// const char* name, -// Instruction* psInst, -// const int dest, -// const int src0, -// int paramsShouldFollowWriteMask) -//{ -// uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; -// bstring glsl = *psContext->currentShaderString; -// uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); -// uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); -// uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; -// int numParenthesis = 0; -// -// AddIndentation(psContext); -// -// METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); -// -// bformata(glsl, "%s(", name); -// numParenthesis++; -// TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); -// METALAddAssignPrologue(psContext, numParenthesis); -//} - -static void METALTranslateTexelFetch(HLSLCrossCompilerContext* psContext, - Instruction* psInst, - ResourceBinding* psBinding, - bstring metal) -{ - int numParenthesis = 0; - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTTypeMETAL(METALResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, &numParenthesis); - - switch (psBinding->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - { - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").x)"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").x, ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").y)"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - { - // METAL PIXEL SHADER RT FETCH - if (psInst->asOperands[2].ui32RegisterNumber >= GMEM_FLOAT_START_SLOT) - { - bformata(metal, "(GMEM_Input%d", GetGmemInputResourceSlotMETAL(psInst->asOperands[2].ui32RegisterNumber)); - - int gmemNumElements = GetGmemInputResourceNumElementsMETAL(psInst->asOperands[2].ui32RegisterNumber); - - int destNumElements = 0; - - if (psInst->asOperands[0].iNumComponents != 1) - { - //Component Mask - uint32_t mask = psInst->asOperands[0].ui32CompMask; - - if (mask == OPERAND_4_COMPONENT_MASK_ALL) - { - destNumElements = 4; - } - else if (mask != 0) - { - if (mask & OPERAND_4_COMPONENT_MASK_X) - { - destNumElements++; - } - if (mask & OPERAND_4_COMPONENT_MASK_Y) - { - destNumElements++; - } - if (mask & OPERAND_4_COMPONENT_MASK_Z) - { - destNumElements++; - } - if (mask & OPERAND_4_COMPONENT_MASK_W) - { - destNumElements++; - } - } - } - else - { - destNumElements = 4; - } - - TranslateGmemOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], OPERAND_4_COMPONENT_MASK_ALL, gmemNumElements); - bcatcstr(metal, ")"); - - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - } - else - { - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").xy, ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").w)"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - } - - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").xy, ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").z, ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").w)"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - { - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").xyz, ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").w)"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - { - ASSERT(psInst->eOpcode == OPCODE_LD_MS); - - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ".read("); - - bcatcstr(metal, "("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ").xy, "); - TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ")"); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); - - break; - } - case REFLECT_RESOURCE_DIMENSION_BUFFER: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - case REFLECT_RESOURCE_DIMENSION_BUFFEREX: - default: - { - ASSERT(0); - break; - } - } - - METALAddAssignPrologue(psContext, numParenthesis); -} - -//static void METALTranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, -// Instruction* psInst, -// ResourceBinding* psBinding, -// bstring metal) -//{ -// int numParenthesis = 0; -// uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); -// AddIndentation(psContext); -// METALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(METALResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, &numParenthesis); -// -// bcatcstr(metal, "texelFetchOffset("); -// -// switch (psBinding->eDimension) -// { -// case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: -// { -// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); -// bcatcstr(metal, ", "); -// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); -// bformata(metal, ", 0, %d)", psInst->iUAddrOffset); -// break; -// } -// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: -// { -// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); -// bcatcstr(metal, ", "); -// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); -// bformata(metal, ", 0, int2(%d, %d))", -// psInst->iUAddrOffset, -// psInst->iVAddrOffset); -// break; -// } -// case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: -// { -// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); -// bcatcstr(metal, ", "); -// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); -// bformata(metal, ", 0, int3(%d, %d, %d))", -// psInst->iUAddrOffset, -// psInst->iVAddrOffset, -// psInst->iWAddrOffset); -// break; -// } -// case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: -// { -// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); -// bcatcstr(metal, ", "); -// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); -// bformata(metal, ", 0, int2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); -// break; -// } -// case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: -// { -// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); -// bcatcstr(metal, ", "); -// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); -// bformata(metal, ", 0, int(%d))", psInst->iUAddrOffset); -// break; -// } -// case REFLECT_RESOURCE_DIMENSION_BUFFER: -// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: -// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: -// case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: -// case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: -// case REFLECT_RESOURCE_DIMENSION_BUFFEREX: -// default: -// { -// ASSERT(0); -// break; -// } -// } -// -// AddSwizzleUsingElementCount(psContext, destCount); -// METALAddAssignPrologue(psContext, numParenthesis); -//} - - -//Makes sure the texture coordinate swizzle is appropriate for the texture type. -//i.e. vecX for X-dimension texture. -//Currently supports floating point coord only, so not used for texelFetch. -static void METALTranslateTexCoord(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eResDim, - Operand* psTexCoordOperand) -{ - uint32_t flags = TO_AUTO_BITCAST_TO_FLOAT; - bstring glsl = *psContext->currentShaderString; - uint32_t opMask = OPERAND_4_COMPONENT_MASK_ALL; - int isArray = 0; - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - //Vec1 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X; - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - //Vec2 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; - flags |= TO_AUTO_EXPAND_TO_VEC2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - case RESOURCE_DIMENSION_TEXTURE3D: - { - //Vec3 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z; - flags |= TO_AUTO_EXPAND_TO_VEC3; - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - //Vec3 texcoord. Mask out the other components. - opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; - flags |= TO_AUTO_EXPAND_TO_VEC2; - isArray = 1; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - flags |= TO_AUTO_EXPAND_TO_VEC4; - break; - } - default: - { - ASSERT(0); - break; - } - } - - //FIXME detect when integer coords are needed. - TranslateOperandWithMaskMETAL(psContext, psTexCoordOperand, flags, opMask); - if (isArray) - { - bformata(glsl, ","); - TranslateOperandWithMaskMETAL(psContext, psTexCoordOperand, 0, OPERAND_4_COMPONENT_MASK_Z); - } -} - -static int METALGetNumTextureDimensions(HLSLCrossCompilerContext* psContext, - const RESOURCE_DIMENSION eResDim) -{ - (void)psContext; - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - return 1; - } - case RESOURCE_DIMENSION_TEXTURE2D: - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBE: - { - return 2; - } - - case RESOURCE_DIMENSION_TEXTURE3D: - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - return 3; - } - default: - { - ASSERT(0); - break; - } - } - return 0; -} - -void GetResInfoDataMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index, int destElem) -{ - bstring metal = *psContext->currentShaderString; - int numParenthesis = 0; - const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - AddIndentation(psContext); - METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", &numParenthesis, 1 << destElem); - - //[width, height, depth or array size, total-mip-count] - if (index < 3) - { - int dim = METALGetNumTextureDimensions(psContext, eResDim); - bcatcstr(metal, "("); - if (dim < (index + 1)) - { - bcatcstr(metal, eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? "0u" : "0.0"); - } - else - { - if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - { - bformata(metal, "uint%d(textureSize(", dim); - } - else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) - { - bformata(metal, "float%d(1.0) / float%d(textureSize(", dim, dim); - } - else - { - bformata(metal, "float%d(textureSize(", dim); - } - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ", "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(metal, "))"); - - switch (index) - { - case 0: - bcatcstr(metal, ".x"); - break; - case 1: - bcatcstr(metal, ".y"); - break; - case 2: - bcatcstr(metal, ".z"); - break; - } - } - - bcatcstr(metal, ")"); - } - else - { - if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) - { - bcatcstr(metal, "uint("); - } - else - { - bcatcstr(metal, "float("); - } - bcatcstr(metal, "textureQueryLevels("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, "))"); - } - METALAddAssignPrologue(psContext, numParenthesis); -} - -#define TEXSMP_FLAG_NONE 0x0 -#define TEXSMP_FLAG_LOD 0x1 //LOD comes from operand -#define TEXSMP_FLAG_DEPTHCOMPARE 0x2 -#define TEXSMP_FLAG_FIRSTLOD 0x4 //LOD is 0 -#define TEXSMP_FLAG_BIAS 0x8 -#define TEXSMP_FLAGS_GRAD 0x10 - -// TODO FIXME: non-float samplers! -static void METALTranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, - uint32_t ui32Flags) -{ - bstring metal = *psContext->currentShaderString; - int numParenthesis = 0; - - const char* funcName = "sample"; - const char* depthCmpCoordType = ""; - const char* gradSwizzle = ""; - - uint32_t ui32NumOffsets = 0; - - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - - ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); - switch (eResDim) - { - case RESOURCE_DIMENSION_TEXTURE1D: - { - gradSwizzle = ".x"; - ui32NumOffsets = 1; - break; - } - case RESOURCE_DIMENSION_TEXTURE2D: - { - depthCmpCoordType = "float2"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBE: - { - depthCmpCoordType = "float3"; - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - break; - } - case RESOURCE_DIMENSION_TEXTURE3D: - { - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - break; - } - case RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - gradSwizzle = ".x"; - ui32NumOffsets = 1; - break; - } - case RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - depthCmpCoordType = "float2"; - gradSwizzle = ".xy"; - ui32NumOffsets = 2; - break; - } - case RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - //bformata(metal, "TODO:Sample from texture cube array LOD\n"); - gradSwizzle = ".xyz"; - ui32NumOffsets = 3; - //ASSERT(0); - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) - { - //For non-cubeMap Arrays the reference value comes from the - //texture coord vector in GLSL. For cubmap arrays there is a - //separate parameter. - //It is always separate paramter in HLSL. - SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); - - bcatcstr(metal, "(float4("); - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); - bformata(metal, ".%s_compare(", funcName); - bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); - bformata(metal, ", %s(", depthCmpCoordType); - METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - bcatcstr(metal, "), "); - //.z = reference. - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(metal, ", level(0)"); - } - - if (psInst->bAddressOffset) - { - if (ui32NumOffsets == 2) - { - bformata(metal, ", int2(%d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset); - } - else - if (ui32NumOffsets == 3) - { - bformata(metal, ", int3(%d, %d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset, - psInst->iWAddrOffset); - } - } - bcatcstr(metal, ")))"); - - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - } - else - { - SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); - - bcatcstr(metal, "("); - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); - bformata(metal, ".%s(", funcName); - bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); - bformata(metal, ", "); - METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - if (ui32NumOffsets > 1) - { - if (ui32Flags & (TEXSMP_FLAG_LOD)) - { - bcatcstr(metal, ", level("); - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(metal, ")"); - } - else - if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) - { - bcatcstr(metal, ", level(0)"); - } - else - if (ui32Flags & (TEXSMP_FLAG_BIAS)) - { - bcatcstr(metal, ", bias("); - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(metal, ")"); - } - else - if (ui32Flags & TEXSMP_FLAGS_GRAD) - { - if (eResDim == RESOURCE_DIMENSION_TEXTURECUBE) - { - bcatcstr(metal, ", gradientcube(float4("); - } - else - { - bformata(metal, ", gradient%dd(float4(", ui32NumOffsets); - } - - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); //dx - bcatcstr(metal, ")"); - bcatcstr(metal, gradSwizzle); - bcatcstr(metal, ", float4("); - TranslateOperandMETAL(psContext, &psInst->asOperands[5], TO_AUTO_BITCAST_TO_FLOAT); //dy - bcatcstr(metal, ")"); - bcatcstr(metal, gradSwizzle); - bcatcstr(metal, ")"); - } - } - - if (psInst->bAddressOffset) - { - if (ui32NumOffsets == 1) - { - bformata(metal, ", %d", - psInst->iUAddrOffset); - } - else - if (ui32NumOffsets == 2) - { - bformata(metal, ", int2(%d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset); - } - else - if (ui32NumOffsets == 3) - { - bformata(metal, ", int3(%d, %d, %d)", - psInst->iUAddrOffset, - psInst->iVAddrOffset, - psInst->iWAddrOffset); - } - } - - bcatcstr(metal, "))"); - } - - if (!(ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE)) - { - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - } - METALAddAssignPrologue(psContext, numParenthesis); -} - -static ShaderVarType* METALLookupStructuredVar(HLSLCrossCompilerContext* psContext, - Operand* psResource, - Operand* psByteOffset, - uint32_t ui32Component) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; - int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; - int vec4Offset = 0; - int32_t index = -1; - int32_t rebase = -1; - int found; - - ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); - //TODO: multi-component stores and vector writes need testing. - - //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; - switch (psResource->eType) - { - case OPERAND_TYPE_RESOURCE: - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - //dcl_tgsm_structured defines the amount of memory and a stride. - ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); - return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; - } - default: - ASSERT(0); - break; - } - - switch (byteOffset % 16) - { - case 0: - aui32Swizzle[0] = 0; - break; - case 4: - aui32Swizzle[0] = 1; - break; - case 8: - aui32Swizzle[0] = 2; - break; - case 12: - aui32Swizzle[0] = 3; - break; - } - vec4Offset = byteOffset / 16; - - found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - ASSERT(found); - - return psVarType; -} - -static ShaderVarType* METALLookupStructuredVarAtomic(HLSLCrossCompilerContext* psContext, - Operand* psResource, - Operand* psByteOffset, - uint32_t ui32Component) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; - int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; - int vec4Offset = 0; - int32_t index = -1; - int32_t rebase = -1; - int found; - - ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); - //TODO: multi-component stores and vector writes need testing. - - //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; - switch (psResource->eType) - { - case OPERAND_TYPE_RESOURCE: - GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - break; - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - //dcl_tgsm_structured defines the amount of memory and a stride. - ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); - return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; - } - default: - ASSERT(0); - break; - } - - if (psCBuf->asVars->sType.Class == SVC_STRUCT) - { - //recalculate offset based on address.y; - int offset = *((int*)(&psByteOffset->afImmediates[1])); - if (offset > 0) - { - byteOffset = offset + 4 * ui32Component; - } - } - - switch (byteOffset % 16) - { - case 0: - aui32Swizzle[0] = 0; - break; - case 4: - aui32Swizzle[0] = 1; - break; - case 8: - aui32Swizzle[0] = 2; - break; - case 12: - aui32Swizzle[0] = 3; - break; - } - vec4Offset = byteOffset / 16; - - found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - ASSERT(found); - - return psVarType; -} - -static void METALTranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring metal = *psContext->currentShaderString; - ShaderVarType* psVarType = NULL; - int component; - int srcComponent = 0; - - Operand* psDest = 0; - Operand* psDestAddr = 0; - Operand* psDestByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_STORE_STRUCTURED: - psDest = &psInst->asOperands[0]; - psDestAddr = &psInst->asOperands[1]; - psDestByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - - break; - case OPCODE_STORE_RAW: - psDest = &psInst->asOperands[0]; - psDestByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - for (component = 0; component < 4; component++) - { - const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; - ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); - if (psInst->asOperands[0].ui32CompMask & (1 << component)) - { - - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - psVarType = METALLookupStructuredVar(psContext, psDest, psDestByteOff, component); - } - - AddIndentation(psContext); - - if (!structured && (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(metal, "atomic_store_explicit( &"); - TranslateOperandMETAL(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - bformata(metal, "["); - if (structured) //Dest address and dest byte offset - { - if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "].value["); - TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "/4u ");//bytes to floats - } - else - { - TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - } - else - { - TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - //RAW: change component using index offset - if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(metal, " + %d", component); - } - bformata(metal, "],"); - - if (structured) - { - uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; - if (psVarType) - { - if (psVarType->Type == SVT_INT) - { - flags = TO_FLAG_INTEGER; - } - else if (psVarType->Type == SVT_FLOAT) - { - flags = TO_FLAG_NONE; - } - else if (psVarType->Type == SVT_FLOAT16) - { - flags = TO_FLAG_FLOAT16; - } - else - { - ASSERT(0); - } - } - //TGSM always uint - bformata(metal, " ("); - if (GetNumSwizzleElementsMETAL(psSrc) > 1) - { - TranslateOperandWithMaskMETAL(psContext, psSrc, flags, 1 << (srcComponent++)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); - } - } - else - { - //Dest type is currently always a uint array. - bformata(metal, " ("); - if (GetNumSwizzleElementsMETAL(psSrc) > 1) - { - TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); - } - } - - //Double takes an extra slot. - if (psVarType && psVarType->Type == SVT_DOUBLE) - { - if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - bcatcstr(metal, ")"); - } - component++; - } - - bformata(metal, "),"); - bformata(metal, "memory_order_relaxed"); - bformata(metal, ");\n"); - return; - } - - if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) - { - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDest->ui32RegisterNumber, 0); - } - else - { - TranslateOperandMETAL(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - } - bformata(metal, "["); - if (structured) //Dest address and dest byte offset - { - if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "].value["); - TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "/4u ");//bytes to floats - } - else - { - TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - } - else - { - TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - } - - //RAW: change component using index offset - if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) - { - bformata(metal, " + %d", component); - } - - bformata(metal, "]"); - - if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - if (strcmp(psVarType->Name, "$Element") != 0) - { - bformata(metal, ".%s", psVarType->Name); - } - if (psVarType->Columns > 1 || psVarType->Rows > 1) - { - bformata(metal, "%s", swizzleString[((((int*)psDestByteOff->afImmediates)[0] + 4 * component - psVarType->Offset) % 16 / 4)]); - } - } - - if (structured) - { - uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; - if (psVarType) - { - if (psVarType->Type == SVT_INT) - { - flags = TO_FLAG_INTEGER; - } - else if (psVarType->Type == SVT_FLOAT) - { - flags = TO_FLAG_NONE; - } - else if (psVarType->Type == SVT_FLOAT16) - { - flags = TO_FLAG_FLOAT16; - } - else - { - ASSERT(0); - } - } - //TGSM always uint - bformata(metal, " = ("); - if (GetNumSwizzleElementsMETAL(psSrc) > 1) - { - TranslateOperandWithMaskMETAL(psContext, psSrc, flags, 1 << (srcComponent++)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); - } - } - else - { - //Dest type is currently always a uint array. - bformata(metal, " = ("); - if (GetNumSwizzleElementsMETAL(psSrc) > 1) - { - TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); - } - else - { - TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); - } - } - - //Double takes an extra slot. - if (psVarType && psVarType->Type == SVT_DOUBLE) - { - if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - bcatcstr(metal, ")"); - } - component++; - } - - bformata(metal, ");\n"); - } - } -} - -static void METALTranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring metal = *psContext->currentShaderString; - int component; - Operand* psDest = 0; - Operand* psSrcAddr = 0; - Operand* psSrcByteOff = 0; - Operand* psSrc = 0; - int structured = 0; - - switch (psInst->eOpcode) - { - case OPCODE_LD_STRUCTURED: - psDest = &psInst->asOperands[0]; - psSrcAddr = &psInst->asOperands[1]; - psSrcByteOff = &psInst->asOperands[2]; - psSrc = &psInst->asOperands[3]; - structured = 1; - break; - case OPCODE_LD_RAW: - psDest = &psInst->asOperands[0]; - psSrcByteOff = &psInst->asOperands[1]; - psSrc = &psInst->asOperands[2]; - break; - } - - if (psInst->eOpcode == OPCODE_LD_RAW) - { - int numParenthesis = 0; - int firstItemAdded = 0; - uint32_t destCount = GetNumSwizzleElementsMETAL(psDest); - uint32_t destMask = GetOperandWriteMaskMETAL(psDest); - AddIndentation(psContext); - METALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); - if (destCount > 1) - { - bformata(metal, "%s(", GetConstructorForTypeMETAL(SVT_UINT, destCount)); - numParenthesis++; - } - for (component = 0; component < 4; component++) - { - if (!(destMask & (1 << component))) - { - continue; - } - - if (firstItemAdded) - { - bcatcstr(metal, ", "); - } - else - { - firstItemAdded = 1; - } - - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - //ld from threadgroup shared memory - bformata(metal, "atomic_load_explicit( &"); - bformata(metal, "TGSM%d[((", psSrc->ui32RegisterNumber); - TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(metal, ") >> 2)"); - if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) - { - bformata(metal, " + %d", psSrc->aui32Swizzle[component]); - } - bcatcstr(metal, "]"); - bcatcstr(metal, " , "); - bcatcstr(metal, "memory_order::memory_order_relaxed"); - bformata(metal, ")"); - - /* - bformata(metal, "TGSM%d[((", psSrc->ui32RegisterNumber); - TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(metal, ") >> 2)"); - if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) - { - bformata(metal, " + %d", psSrc->aui32Swizzle[component]); - } - bcatcstr(metal, "]"); - */ - } - else - { - //ld from raw buffer - bformata(metal, "RawRes%d[((", psSrc->ui32RegisterNumber); - TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); - bcatcstr(metal, ") >> 2)"); - if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) - { - bformata(metal, " + %d", psSrc->aui32Swizzle[component]); - } - bcatcstr(metal, "]"); - } - } - METALAddAssignPrologue(psContext, numParenthesis); - } - else - { - int numParenthesis = 0; - int firstItemAdded = 0; - uint32_t destCount = GetNumSwizzleElementsMETAL(psDest); - uint32_t destMask = GetOperandWriteMaskMETAL(psDest); - ASSERT(psInst->eOpcode == OPCODE_LD_STRUCTURED); - AddIndentation(psContext); - METALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); - if (destCount > 1) - { - bformata(metal, "%s(", GetConstructorForTypeMETAL(SVT_UINT, destCount)); - numParenthesis++; - } - for (component = 0; component < 4; component++) - { - ShaderVarType* psVar = NULL; - int addedBitcast = 0; - if (!(destMask & (1 << component))) - { - continue; - } - - if (firstItemAdded) - { - bcatcstr(metal, ", "); - } - else - { - firstItemAdded = 1; - } - - if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - // input already in uints - TranslateOperandMETAL(psContext, psSrc, TO_FLAG_NAME_ONLY); - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(metal, "].value[("); - TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, " >> 2u) + %d]", psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - } - else - { - ConstantBuffer* psCBuf = NULL; - psVar = METALLookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); - GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); - - if (psVar->Type == SVT_FLOAT) - { - bcatcstr(metal, "as_type<uint>("); - bcatcstr(metal, "("); - addedBitcast = 1; - } - else if (psVar->Type == SVT_DOUBLE) - { - bcatcstr(metal, "as_type<uint>("); - bcatcstr(metal, "("); - addedBitcast = 1; - } - if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) - { - bformata(metal, "%s[", psCBuf->Name); - TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(metal, "]"); - if (strcmp(psVar->Name, "$Element") != 0) - { - bcatcstr(metal, "."); - bcatcstr(metal, psVar->Name); - } - - int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; - int bytes = byteOffset - psVar->Offset; - if (psVar->Class != SVC_SCALAR) - { - static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; - int offset = (bytes % 16) / 4; - if (offset == 0) - { - bcatcstr(metal, ".x"); - } - if (offset == 1) - { - bcatcstr(metal, ".y"); - } - if (offset == 2) - { - bcatcstr(metal, ".z"); - } - if (offset == 3) - { - bcatcstr(metal, ".w"); - } - } - } - else - { - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psSrc->ui32RegisterNumber, 0); - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); - bcatcstr(metal, "]"); - if (strcmp(psVar->Name, "$Element") != 0) - { - bcatcstr(metal, "."); - bcatcstr(metal, psVar->Name); - int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; - int bytes = byteOffset - psVar->Offset; - if (psVar->Class == SVC_MATRIX_ROWS) - { - int offset = bytes / 16; - bcatcstr(metal, "["); - bformata(metal, "%i", offset); - bcatcstr(metal, "]"); - } - if (psVar->Class != SVC_SCALAR) - { - static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; - - int offset = (bytes % 16) / 4; - if (offset == 0) - { - bcatcstr(metal, ".x"); - } - if (offset == 1) - { - bcatcstr(metal, ".y"); - } - if (offset == 2) - { - bcatcstr(metal, ".z"); - } - if (offset == 3) - { - bcatcstr(metal, ".w"); - } - } - } - else if (psVar->Columns > 1) - { - int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; - int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; - int bytes = byteOffset - psVar->Offset; - - static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; - - int offset = (bytes % 16) / 4; - if (offset == 0) - { - bcatcstr(metal, ".x"); - } - if (offset == 1) - { - bcatcstr(metal, ".y"); - } - if (offset == 2) - { - bcatcstr(metal, ".z"); - } - if (offset == 3) - { - bcatcstr(metal, ".w"); - } - } - } - - if (addedBitcast) - { - bcatcstr(metal, "))"); - } - - if (psVar->Columns > 1) - { - int multiplier = 1; - - if (psVar->Type == SVT_DOUBLE) - { - multiplier++; // doubles take up 2 slots - } - //component += psVar->Columns * multiplier; - } - } - } - METALAddAssignPrologue(psContext, numParenthesis); - - return; - } -} - -void TranslateAtomicMemOpMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst) -{ - bstring metal = *psContext->currentShaderString; - int numParenthesis = 0; - ShaderVarType* psVarType = NULL; - uint32_t ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER; - const char* func = ""; - Operand* dest = 0; - Operand* previousValue = 0; - Operand* destAddr = 0; - Operand* src = 0; - Operand* compare = 0; - - switch (psInst->eOpcode) - { - case OPCODE_IMM_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_IADD\n"); -#endif - func = "atomic_fetch_add_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_IADD\n"); -#endif - func = "atomic_fetch_add_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_AND\n"); -#endif - func = "atomic_fetch_and_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_AND\n"); -#endif - func = "atomic_fetch_and_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_OR\n"); -#endif - func = "atomic_fetch_or_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_OR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_OR\n"); -#endif - func = "atomic_fetch_or_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_XOR\n"); -#endif - func = "atomic_fetch_xor_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_XOR\n"); -#endif - func = "atomic_fetch_xor_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - - case OPCODE_IMM_ATOMIC_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_EXCH\n"); -#endif - func = "atomic_exchange_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_CMP_EXC\n"); -#endif - func = "atomic_compare_exchange_weak_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - compare = &psInst->asOperands[3]; - src = &psInst->asOperands[4]; - break; - } - case OPCODE_ATOMIC_CMP_STORE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_CMP_STORE\n"); -#endif - func = "atomic_compare_exchange_weak_explicit"; - previousValue = 0; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - compare = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_IMM_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_UMIN\n"); -#endif - func = "atomic_fetch_min_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_UMIN\n"); -#endif - func = "atomic_fetch_min_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_IMIN\n"); -#endif - func = "atomic_fetch_min_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_IMIN\n"); -#endif - func = "atomic_fetch_min_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_UMAX\n"); -#endif - func = "atomic_fetch_max_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_UMAX\n"); -#endif - func = "atomic_fetch_max_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - case OPCODE_IMM_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMM_ATOMIC_IMAX\n"); -#endif - func = "atomic_fetch_max_explicit"; - previousValue = &psInst->asOperands[0]; - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - src = &psInst->asOperands[3]; - break; - } - case OPCODE_ATOMIC_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ATOMIC_IMAX\n"); -#endif - func = "atomic_fetch_max_explicit"; - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - src = &psInst->asOperands[2]; - break; - } - } - - AddIndentation(psContext); - - if (previousValue) - { - //all atomic operation returns uint or int - METALAddAssignToDest(psContext, previousValue, SVT_UINT, 1, &numParenthesis); - } - - bcatcstr(metal, func); - bformata(metal, "( &"); - TranslateOperandMETAL(psContext, dest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); - - if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - //threadgroup shared mem - bformata(metal, "["); - TranslateOperandMETAL(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "]"); - } - else - { - ResourceBinding* psRes; -#if defined(_DEBUG) - int foundResource = -#endif - GetResourceFromBindingPoint(RGROUP_UAV, - dest->ui32RegisterNumber, - &psContext->psShader->sInfo, - &psRes); - - ASSERT(foundResource); - - if (psRes->eBindArea == UAVAREA_CBUFFER) - { - //rwbuffer - if (psRes->eType == RTYPE_UAV_RWTYPED) - { - bformata(metal, "["); - TranslateOperandMETAL(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); - bformata(metal, "]"); - } - //rwstructured buffer - else if (psRes->eType == RTYPE_UAV_RWSTRUCTURED) - { - if (destAddr->eType == OPERAND_TYPE_IMMEDIATE32) - { - psVarType = METALLookupStructuredVarAtomic(psContext, dest, destAddr, 0); - } - if (psVarType->Type == SVT_UINT) - { - ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT; - } - else - { - ui32DataTypeFlag = TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT; - } - bformata(metal, "["); - bformata(metal, "%i", *((int*)(&destAddr->afImmediates[0]))); - bformata(metal, "]"); - if (strcmp(psVarType->Name, "$Element") != 0) - { - bformata(metal, ".%s", psVarType->Name); - } - } - } - else if (psRes->eBindArea == UAVAREA_TEXTURE) - { - //Atomic operation on texture uav not supported - ASSERT(0); - } - else - { - //UAV is not exist in either [[buffer]] or [[texture]] - ASSERT(0); - } - } - //ResourceNameMETAL(metal, psContext, RGROUP_UAV, dest->ui32RegisterNumber, 0); - - bcatcstr(metal, ", "); - - if (compare) - { - bcatcstr(metal, "& "); - TranslateOperandMETAL(psContext, compare, ui32DataTypeFlag); - bcatcstr(metal, ", "); - } - - TranslateOperandMETAL(psContext, src, ui32DataTypeFlag); - bcatcstr(metal, ", "); - if (compare) - { - bcatcstr(metal, "memory_order_relaxed "); - bcatcstr(metal, ","); - } - bcatcstr(metal, "memory_order_relaxed "); - bcatcstr(metal, ")"); - if (previousValue) - { - METALAddAssignPrologue(psContext, numParenthesis); - } - else - { - bcatcstr(metal, ";\n"); - } -} - -static void METALTranslateConditional(HLSLCrossCompilerContext* psContext, - Instruction* psInst, - bstring glsl) -{ - const char* statement = ""; - if (psInst->eOpcode == OPCODE_BREAKC) - { - statement = "break"; - } - else if (psInst->eOpcode == OPCODE_CONTINUEC) - { - statement = "continue"; - } - else if (psInst->eOpcode == OPCODE_RETC) - { - statement = "return"; - } - - if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(glsl, "if(("); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF) - { - bformata(glsl, ")==0u){%s;}\n", statement); - } - else - { - bcatcstr(glsl, ")==0u){\n"); - } - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(glsl, "if(("); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); - - if (psInst->eOpcode != OPCODE_IF) - { - bformata(glsl, ")!=0u){%s;}\n", statement); - } - else - { - bcatcstr(glsl, ")!=0u){\n"); - } - } -} - -// Returns the "more important" type of a and b, currently int < uint < float -static SHADER_VARIABLE_TYPE METALSelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b) -{ - if (a == SVT_FLOAT || b == SVT_FLOAT) - { - return SVT_FLOAT; - } - - if (a == SVT_FLOAT16 || b == SVT_FLOAT16) - { - return SVT_FLOAT16; - } - // Apart from floats, the enum values are fairly well-ordered, use that directly. - return a > b ? a : b; -} - -// Helper function to set the vector type of 1 or more components in a vector -// If the existing values (that we're writing to) are all SVT_VOID, just upgrade the value and we're done -// Otherwise, set all the components in the vector that currently are set to that same value OR are now being written to -// to the "highest" type value (ordering int->uint->float) -static void METALSetVectorType(SHADER_VARIABLE_TYPE* aeTempVecType, uint32_t regBaseIndex, uint32_t componentMask, SHADER_VARIABLE_TYPE eType) -{ - int existingTypesFound = 0; - int i = 0; - for (i = 0; i < 4; i++) - { - if (componentMask & (1 << i)) - { - if (aeTempVecType[regBaseIndex + i] != SVT_VOID) - { - existingTypesFound = 1; - break; - } - } - } - - if (existingTypesFound != 0) - { - // Expand the mask to include all components that are used, also upgrade type - for (i = 0; i < 4; i++) - { - if (aeTempVecType[regBaseIndex + i] != SVT_VOID) - { - componentMask |= (1 << i); - eType = METALSelectHigherType(eType, aeTempVecType[regBaseIndex + i]); - } - } - } - - // Now componentMask contains the components we actually need to update and eType may have been changed to something else. - // Write the results - for (i = 0; i < 4; i++) - { - if (componentMask & (1 << i)) - { - aeTempVecType[regBaseIndex + i] = eType; - } - } -} - -static void METALMarkOperandAs(Operand* psOperand, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) -{ - if (psOperand->eType == OPERAND_TYPE_INDEXABLE_TEMP || psOperand->eType == OPERAND_TYPE_TEMP) - { - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - METALSetVectorType(aeTempVecType, ui32RegIndex, 1 << psOperand->aui32Swizzle[0], eType); - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - // 0xf == all components, swizzle order doesn't matter. - METALSetVectorType(aeTempVecType, ui32RegIndex, 0xf, eType); - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - METALSetVectorType(aeTempVecType, ui32RegIndex, ui32CompMask, eType); - } - } -} - -static void METALMarkAllOperandsAs(Instruction* psInst, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) -{ - uint32_t i = 0; - for (i = 0; i < psInst->ui32NumOperands; i++) - { - METALMarkOperandAs(&psInst->asOperands[i], eType, aeTempVecType); - } -} - -static void METALWriteOperandTypes(Operand* psOperand, const SHADER_VARIABLE_TYPE* aeTempVecType) -{ - const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; - - if (psOperand->eType != OPERAND_TYPE_TEMP) - { - return; - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; - psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex + 1]; - psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex + 2]; - psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex + 3]; - } - else - { - psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; - psOperand->aeDataType[psOperand->aui32Swizzle[1]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[1]]; - psOperand->aeDataType[psOperand->aui32Swizzle[2]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[2]]; - psOperand->aeDataType[psOperand->aui32Swizzle[3]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[3]]; - } - } - else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - int c = 0; - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - - for (; c < 4; ++c) - { - if (ui32CompMask & (1 << c)) - { - psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; - } - } - } -} - -// Mark scalars from CBs. TODO: Do we need to do the same for vec2/3's as well? There may be swizzles involved which make it vec4 or something else again. -static void METALSetCBOperandComponents(HLSLCrossCompilerContext* psContext, Operand* psOperand) -{ - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - int rebase = 0; - - if (psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER) - { - return; - } - - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - - if (psVarType->Class == SVC_SCALAR) - { - psOperand->iNumComponents = 1; - } -} - - -void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount) -{ - int32_t i; - Instruction* psFirstInst = psInst; - - SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; - - // Start with void, then move up the chain void->int->uint->float - for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) - { - aeTempVecType[i] = SVT_VOID; - } - - { - // First pass, do analysis: deduce the data type based on opcodes, fill out aeTempVecType table - // Only ever to int->float promotion (or int->uint), never the other way around - for (i = 0; i < i32InstCount; ++i, psInst++) - { - if (psInst->ui32NumOperands == 0) - { - continue; - } - - switch (psInst->eOpcode) - { - // All float-only ops - case OPCODE_ADD: - case OPCODE_DERIV_RTX: - case OPCODE_DERIV_RTY: - case OPCODE_DIV: - case OPCODE_DP2: - case OPCODE_DP3: - case OPCODE_DP4: - case OPCODE_EQ: - case OPCODE_EXP: - case OPCODE_FRC: - case OPCODE_LOG: - case OPCODE_MAD: - case OPCODE_MIN: - case OPCODE_MAX: - case OPCODE_MUL: - case OPCODE_NE: - case OPCODE_ROUND_NE: - case OPCODE_ROUND_NI: - case OPCODE_ROUND_PI: - case OPCODE_ROUND_Z: - case OPCODE_RSQ: - case OPCODE_SAMPLE: - case OPCODE_SAMPLE_C: - case OPCODE_SAMPLE_C_LZ: - case OPCODE_SAMPLE_L: - case OPCODE_SAMPLE_D: - case OPCODE_SAMPLE_B: - case OPCODE_SQRT: - case OPCODE_SINCOS: - case OPCODE_LOD: - case OPCODE_GATHER4: - - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_GATHER4_C: - case OPCODE_GATHER4_PO: - case OPCODE_GATHER4_PO_C: - case OPCODE_RCP: - - METALMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); - break; - - // Int-only ops, no need to do anything - case OPCODE_AND: - case OPCODE_BREAKC: - case OPCODE_CALLC: - case OPCODE_CONTINUEC: - case OPCODE_IADD: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_IF: - case OPCODE_NOT: - case OPCODE_OR: - case OPCODE_RETC: - case OPCODE_XOR: - case OPCODE_BUFINFO: - case OPCODE_COUNTBITS: - case OPCODE_FIRSTBIT_HI: - case OPCODE_FIRSTBIT_LO: - case OPCODE_FIRSTBIT_SHI: - case OPCODE_UBFE: - case OPCODE_IBFE: - case OPCODE_BFI: - case OPCODE_BFREV: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_IMAX: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_MOV: - case OPCODE_MOVC: - case OPCODE_SWAPC: - METALMarkAllOperandsAs(psInst, SVT_INT, aeTempVecType); - break; - // uint ops - case OPCODE_UDIV: - case OPCODE_ULT: - case OPCODE_UGE: - case OPCODE_UMUL: - case OPCODE_UMAD: - case OPCODE_UMAX: - case OPCODE_UMIN: - case OPCODE_USHR: - case OPCODE_UADDC: - case OPCODE_USUBB: - METALMarkAllOperandsAs(psInst, SVT_UINT, aeTempVecType); - break; - - // Need special handling - case OPCODE_FTOI: - case OPCODE_FTOU: - METALMarkOperandAs(&psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOI ? SVT_INT : SVT_UINT, aeTempVecType); - METALMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_GE: - case OPCODE_LT: - METALMarkOperandAs(&psInst->asOperands[0], SVT_UINT, aeTempVecType); - METALMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); - METALMarkOperandAs(&psInst->asOperands[2], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_ITOF: - case OPCODE_UTOF: - METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - METALMarkOperandAs(&psInst->asOperands[1], psInst->eOpcode == OPCODE_ITOF ? SVT_INT : SVT_UINT, aeTempVecType); - break; - - case OPCODE_LD: - case OPCODE_LD_MS: - // TODO: Would need to know the sampler return type - METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - - case OPCODE_RESINFO: - { - if (psInst->eResInfoReturnType != RESINFO_INSTRUCTION_RETURN_UINT) - { - METALMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); - } - break; - } - - case OPCODE_SAMPLE_INFO: - // TODO decode the _uint flag - METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - case OPCODE_SAMPLE_POS: - METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); - break; - - - case OPCODE_LD_UAV_TYPED: - case OPCODE_STORE_UAV_TYPED: - case OPCODE_LD_RAW: - case OPCODE_STORE_RAW: - case OPCODE_LD_STRUCTURED: - case OPCODE_STORE_STRUCTURED: - { - METALMarkOperandAs(&psInst->asOperands[0], SVT_INT, aeTempVecType); - break; - } - case OPCODE_F32TOF16: - case OPCODE_F16TOF32: - // TODO - break; - - - - // No-operands, should never get here anyway - /* case OPCODE_BREAK: - case OPCODE_CALL: - case OPCODE_CASE: - case OPCODE_CONTINUE: - case OPCODE_CUT: - case OPCODE_DEFAULT: - case OPCODE_DISCARD: - case OPCODE_ELSE: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_ENDIF: - case OPCODE_ENDLOOP: - case OPCODE_ENDSWITCH: - - case OPCODE_LABEL: - case OPCODE_LOOP: - case OPCODE_CUSTOMDATA: - case OPCODE_NOP: - case OPCODE_RET: - case OPCODE_SWITCH: - case OPCODE_DCL_RESOURCE: // DCL* opcodes have - case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. - case OPCODE_DCL_SAMPLER: - case OPCODE_DCL_INDEX_RANGE: - case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: - case OPCODE_DCL_GS_INPUT_PRIMITIVE: - case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: - case OPCODE_DCL_INPUT: - case OPCODE_DCL_INPUT_SGV: - case OPCODE_DCL_INPUT_SIV: - case OPCODE_DCL_INPUT_PS: - case OPCODE_DCL_INPUT_PS_SGV: - case OPCODE_DCL_INPUT_PS_SIV: - case OPCODE_DCL_OUTPUT: - case OPCODE_DCL_OUTPUT_SGV: - case OPCODE_DCL_OUTPUT_SIV: - case OPCODE_DCL_TEMPS: - case OPCODE_DCL_INDEXABLE_TEMP: - case OPCODE_DCL_GLOBAL_FLAGS: - - - case OPCODE_HS_DECLS: // token marks beginning of HS sub-shader - case OPCODE_HS_CONTROL_POINT_PHASE: // token marks beginning of HS sub-shader - case OPCODE_HS_FORK_PHASE: // token marks beginning of HS sub-shader - case OPCODE_HS_JOIN_PHASE: // token marks beginning of HS sub-shader - - case OPCODE_EMIT_STREAM: - case OPCODE_CUT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - case OPCODE_INTERFACE_CALL: - - - case OPCODE_DCL_STREAM: - case OPCODE_DCL_FUNCTION_BODY: - case OPCODE_DCL_FUNCTION_TABLE: - case OPCODE_DCL_INTERFACE: - - case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: - case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: - case OPCODE_DCL_TESS_DOMAIN: - case OPCODE_DCL_TESS_PARTITIONING: - case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: - case OPCODE_DCL_HS_MAX_TESSFACTOR: - case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: - case OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: - - case OPCODE_DCL_THREAD_GROUP: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: - case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: - case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: - case OPCODE_DCL_RESOURCE_RAW: - case OPCODE_DCL_RESOURCE_STRUCTURED: - case OPCODE_SYNC: - - // TODO - case OPCODE_DADD: - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_DTOF: - case OPCODE_FTOD: - - case OPCODE_EVAL_SNAPPED: - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_CENTROID: - - case OPCODE_DCL_GS_INSTANCE_COUNT: - - case OPCODE_ABORT: - case OPCODE_DEBUG_BREAK:*/ - - default: - break; - } - } - } - - // Fill the rest of aeTempVecType, just in case. - for (i = 0; i < MAX_TEMP_VEC4 * 4; i++) - { - if (aeTempVecType[i] == SVT_VOID) - { - aeTempVecType[i] = SVT_INT; - } - } - - // Now the aeTempVecType table has been filled with (mostly) valid data, write it back to all operands - psInst = psFirstInst; - for (i = 0; i < i32InstCount; ++i, psInst++) - { - int k = 0; - - if (psInst->ui32NumOperands == 0) - { - continue; - } - - //Preserve the current type on dest array index - if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) - { - Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; - if (psSubOperand != 0) - { - METALWriteOperandTypes(psSubOperand, aeTempVecType); - } - } - if (psInst->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - METALSetCBOperandComponents(psContext, &psInst->asOperands[0]); - } - - //Preserve the current type on sources. - for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) - { - int32_t subOperand; - Operand* psOperand = &psInst->asOperands[k]; - - METALWriteOperandTypes(psOperand, aeTempVecType); - if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - METALSetCBOperandComponents(psContext, psOperand); - } - - for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) - { - if (psOperand->psSubOperand[subOperand] != 0) - { - Operand* psSubOperand = psOperand->psSubOperand[subOperand]; - METALWriteOperandTypes(psSubOperand, aeTempVecType); - if (psSubOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - METALSetCBOperandComponents(psContext, psSubOperand); - } - } - } - - //Set immediates - if (METALIsIntegerImmediateOpcode(psInst->eOpcode)) - { - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) - { - psOperand->iIntegerImmediate = 1; - } - } - } - - //Process the destination last in order to handle instructions - //where the destination register is also used as a source. - for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) - { - Operand* psOperand = &psInst->asOperands[k]; - METALWriteOperandTypes(psOperand, aeTempVecType); - } - } -} - -void DetectAtomicInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst, AtomicVarList* psAtomicList) -{ - (void)psNextInst; - - Operand* dest = 0; - Operand* destAddr = 0; - - switch (psInst->eOpcode) - { - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_ATOMIC_AND: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_IMAX: - dest = &psInst->asOperands[0]; - destAddr = &psInst->asOperands[1]; - break; - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - case OPCODE_IMM_ATOMIC_AND: - dest = &psInst->asOperands[1]; - destAddr = &psInst->asOperands[2]; - break; - default: - return; - } - - if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) - { - } - else - { - ResourceBinding* psRes; -#if defined(_DEBUG) - int foundResource = -#endif - GetResourceFromBindingPoint(RGROUP_UAV, - dest->ui32RegisterNumber, - &psContext->psShader->sInfo, - &psRes); - - ASSERT(foundResource); - - { - //rwbuffer - if (psRes->eType == RTYPE_UAV_RWTYPED) - { - } - //rwstructured buffer - else if (psRes->eType == RTYPE_UAV_RWSTRUCTURED) - { - if (destAddr->eType == OPERAND_TYPE_IMMEDIATE32) - { - psAtomicList->AtomicVars[psAtomicList->Filled] = METALLookupStructuredVarAtomic(psContext, dest, destAddr, 0); - psAtomicList->Filled++; - } - } - } - } -} - -void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst) -{ - bstring metal = *psContext->currentShaderString; - int numParenthesis = 0; - -#ifdef _DEBUG - AddIndentation(psContext); - bformata(metal, "//Instruction %d\n", psInst->id); -#if 0 - if (psInst->id == 73) - { - ASSERT(1); //Set breakpoint here to debug an instruction from its ID. - } -#endif -#endif - - switch (psInst->eOpcode) - { - case OPCODE_FTOI: - case OPCODE_FTOU: - { - uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_FTOU) - { - bcatcstr(metal, "//FTOU\n"); - } - else - { - bcatcstr(metal, "//FTOI\n"); - } -#endif - - AddIndentation(psContext); - - METALAddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); - bcatcstr(metal, GetConstructorForTypeMETAL(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); - bcatcstr(metal, "("); // 1 - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(metal, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - { - AddSwizzleUsingElementCountMETAL(psContext, dstCount); - } - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - - case OPCODE_MOV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MOV\n"); -#endif - AddIndentation(psContext); - METALAddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1]); - break; - } - case OPCODE_ITOF://signed to float - case OPCODE_UTOF://unsigned to float - { - uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[0]); - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_ITOF) - { - bcatcstr(metal, "//ITOF\n"); - } - else - { - bcatcstr(metal, "//UTOF\n"); - } -#endif - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, srcCount, &numParenthesis); - bcatcstr(metal, GetConstructorForTypeMETAL(SVT_FLOAT, dstCount)); - bcatcstr(metal, "("); // 1 - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT, destMask); - bcatcstr(metal, ")"); // 1 - // Add destination writemask if the component counts do not match - if (srcCount != dstCount) - { - AddSwizzleUsingElementCountMETAL(psContext, dstCount); - } - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_MAD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MAD\n"); -#endif - METALCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_NONE); - break; - } - case OPCODE_IMAD: - { - uint32_t ui32Flags = TO_FLAG_INTEGER; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMAD\n"); -#endif - - if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - ui32Flags = TO_FLAG_UNSIGNED_INTEGER; - } - - METALCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); - break; - } - case OPCODE_DADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DADD\n"); -#endif - METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_DOUBLE); - break; - } - case OPCODE_IADD: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IADD\n"); -#endif - //Is this a signed or unsigned add? - if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ADD\n"); -#endif - METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_OR: - { - /*Todo: vector version */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//OR\n"); -#endif - METALCallBinaryOp(psContext, "|", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_AND: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//AND\n"); -#endif - METALCallBinaryOp(psContext, "&", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_GE: - { - /* - dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); - Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. - */ -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//GE\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_MUL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MUL\n"); -#endif - METALCallBinaryOp(psContext, "*", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_IMUL: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMUL\n"); -#endif - if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[1]) == SVT_UINT) - { - eType = SVT_UINT; - } - - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); - - METALCallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); - break; - } - case OPCODE_UDIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//UDIV\n"); -#endif - //destQuotient, destRemainder, src0, src1 - METALCallBinaryOp(psContext, "/", psInst, 0, 2, 3, SVT_UINT); - METALCallBinaryOp(psContext, "%", psInst, 1, 2, 3, SVT_UINT); - break; - } - case OPCODE_DIV: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DIV\n"); -#endif - METALCallBinaryOp(psContext, "/", psInst, 0, 1, 2, SVT_FLOAT); - break; - } - case OPCODE_SINCOS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SINCOS\n"); -#endif - // Need careful ordering if src == dest[0], as then the cos() will be reading from wrong value - if (psInst->asOperands[0].eType == psInst->asOperands[2].eType && - psInst->asOperands[0].ui32RegisterNumber == psInst->asOperands[2].ui32RegisterNumber) - { - // sin() result overwrites source, do cos() first. - // The case where both write the src shouldn't really happen anyway. - if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) - { - METALCallHelper1(psContext, "cos", psInst, 1, 2, 1); - } - - if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) - { - METALCallHelper1(psContext, "sin", psInst, 0, 2, 1); - } - } - else - { - if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) - { - METALCallHelper1(psContext, "sin", psInst, 0, 2, 1); - } - - if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) - { - METALCallHelper1(psContext, "cos", psInst, 1, 2, 1); - } - } - break; - } - - case OPCODE_DP2: - { - SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); - int numParenthesis2 = 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DP2\n"); -#endif - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); - bcatcstr(metal, "dot("); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 3 /* .xy */); - bcatcstr(metal, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 3 /* .xy */); - bcatcstr(metal, ")"); - METALAddAssignPrologue(psContext, numParenthesis2); - break; - } - case OPCODE_DP3: - { - SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); - int numParenthesis2 = 0; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DP3\n"); -#endif - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); - bcatcstr(metal, "dot("); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 7 /* .xyz */); - bcatcstr(metal, ", "); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 7 /* .xyz */); - bcatcstr(metal, ")"); - METALAddAssignPrologue(psContext, numParenthesis2); - break; - } - case OPCODE_DP4: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DP4\n"); -#endif - METALCallHelper2(psContext, "dot", psInst, 0, 1, 2, 0); - break; - } - case OPCODE_INE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//INE\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_NE, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//NE\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_NE, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_IGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IGE\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_INTEGER, psNextInst); - break; - } - case OPCODE_ILT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ILT\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_LT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LT\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_IEQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IEQ\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_EQ, TO_FLAG_INTEGER, NULL); - break; - } - case OPCODE_ULT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ULT\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_UNSIGNED_INTEGER, NULL); - break; - } - case OPCODE_UGE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//UGE\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_UNSIGNED_INTEGER, NULL); - break; - } - case OPCODE_MOVC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MOVC\n"); -#endif - METALAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); - break; - } - case OPCODE_SWAPC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SWAPC\n"); -#endif - // TODO needs temps!! - METALAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); - METALAddMOVCBinaryOp(psContext, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); - break; - } - - case OPCODE_LOG: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LOG\n"); -#endif - METALCallHelper1(psContext, "log2", psInst, 0, 1, 1); - break; - } - case OPCODE_RSQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//RSQ\n"); -#endif - METALCallHelper1(psContext, "rsqrt", psInst, 0, 1, 1); - break; - } - case OPCODE_EXP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//EXP\n"); -#endif - METALCallHelper1(psContext, "exp2", psInst, 0, 1, 1); - break; - } - case OPCODE_SQRT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SQRT\n"); -#endif - METALCallHelper1(psContext, "sqrt", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_PI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ROUND_PI\n"); -#endif - METALCallHelper1(psContext, "ceil", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_NI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ROUND_NI\n"); -#endif - METALCallHelper1(psContext, "floor", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_Z: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ROUND_Z\n"); -#endif - METALCallHelper1(psContext, "trunc", psInst, 0, 1, 1); - break; - } - case OPCODE_ROUND_NE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ROUND_NE\n"); -#endif - METALCallHelper1(psContext, "rint", psInst, 0, 1, 1); - break; - } - case OPCODE_FRC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//FRC\n"); -#endif - METALCallHelper1(psContext, "fract", psInst, 0, 1, 1); - break; - } - case OPCODE_IMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMAX\n"); -#endif - METALCallHelper2Int(psContext, "max", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_MAX: - case OPCODE_UMAX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MAX\n"); -#endif - METALCallHelper2(psContext, "max", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_IMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IMIN\n"); -#endif - METALCallHelper2Int(psContext, "min", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_MIN: - case OPCODE_UMIN: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//MIN\n"); -#endif - METALCallHelper2(psContext, "min", psInst, 0, 1, 2, 1); - break; - } - case OPCODE_GATHER4: - case OPCODE_GATHER4_C: - { - //dest, coords, tex, sampler - const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_GATHER4_C) - { - bcatcstr(metal, "//GATHER4_C\n"); - } - else - { - bcatcstr(metal, "//GATHER4\n"); - } -#endif - //gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x - AddIndentation(psContext); // TODO FIXME integer samplers - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(metal, "("); - - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); - - bcatcstr(metal, ".gather("); - bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, psInst->eOpcode == OPCODE_GATHER4_PO_C)); - bcatcstr(metal, ", "); - METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); - - if (psInst->eOpcode == OPCODE_GATHER4_C) - { - bcatcstr(metal, ", "); - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_FLAG_NONE); - } - bcatcstr(metal, ")"); - - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); - bcatcstr(metal, ")"); - - AddSwizzleUsingElementCountMETAL(psContext, GetNumSwizzleElementsMETAL(&psInst->asOperands[0])); - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_GATHER4_PO: - case OPCODE_GATHER4_PO_C: - { - //dest, coords, offset, tex, sampler, srcReferenceValue - -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_GATHER4_PO_C) - { - bcatcstr(metal, "//GATHER4_PO_C\n"); - } - else - { - bcatcstr(metal, "//GATHER4_PO\n"); - } -#endif - - AddIndentation(psContext); // TODO FIXME integer samplers - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); - bcatcstr(metal, "("); - - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 0); - - bcatcstr(metal, ".gather("); - bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, psInst->eOpcode == OPCODE_GATHER4_PO_C)); - - bcatcstr(metal, ", "); - //Texture coord cannot be vec4 - //Determining if it is a vec3 for vec2 yet to be done. - psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - - if (psInst->eOpcode == OPCODE_GATHER4_PO_C) - { - bcatcstr(metal, ", "); - TranslateOperandMETAL(psContext, &psInst->asOperands[5], TO_FLAG_NONE); - } - - bcatcstr(metal, ", as_type<int2>("); - //ivec2 offset - psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; - psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, "))"); - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[3]); - bcatcstr(metal, ")"); - - AddSwizzleUsingElementCountMETAL(psContext, GetNumSwizzleElementsMETAL(&psInst->asOperands[0])); - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_SAMPLE: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE\n"); -#endif - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); - break; - } - case OPCODE_SAMPLE_L: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE_L\n"); -#endif - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); - break; - } - case OPCODE_SAMPLE_C: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE_C\n"); -#endif - - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE); - break; - } - case OPCODE_SAMPLE_C_LZ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE_C_LZ\n"); -#endif - - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE | TEXSMP_FLAG_FIRSTLOD); - break; - } - case OPCODE_SAMPLE_D: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE_D\n"); -#endif - - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); - break; - } - case OPCODE_SAMPLE_B: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SAMPLE_B\n"); -#endif - - METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); - break; - } - case OPCODE_RET: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//RET\n"); -#endif - if (psContext->havePostShaderCode[psContext->currentPhase]) - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//--- Post shader code ---\n"); -#endif - bconcat(metal, psContext->postShaderCode[psContext->currentPhase]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//--- End post shader code ---\n"); -#endif - } - AddIndentation(psContext); - if (blength(psContext->declaredOutputs) > 0) - { - //has output - bcatcstr(metal, "return output;\n"); - } - else - { - //no output declared - bcatcstr(metal, "return;\n"); - } - break; - } - case OPCODE_INTERFACE_CALL: - { - const char* name; - ShaderVar* psVar; - uint32_t varFound; - - uint32_t funcPointer; - uint32_t funcTableIndex; - uint32_t funcTable; - uint32_t funcBodyIndex; - uint32_t funcBody; - uint32_t ui32NumBodiesPerTable; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//INTERFACE_CALL\n"); -#endif - - ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); - - funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; - funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; - funcBodyIndex = psInst->ui32FuncIndexWithinInterface; - - ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; - - funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; - - funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; - - varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); - - ASSERT(varFound); - - name = &psVar->Name[0]; - - AddIndentation(psContext); - bcatcstr(metal, name); - TranslateOperandIndexMADMETAL(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); - //bformata(glsl, "[%d]", funcBodyIndex); - bcatcstr(metal, "();\n"); - break; - } - case OPCODE_LABEL: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LABEL\n"); -#endif - --psContext->indent; - AddIndentation(psContext); - bcatcstr(metal, "}\n"); //Closing brace ends the previous function. - AddIndentation(psContext); - - bcatcstr(metal, "subroutine(SubroutineType)\n"); - bcatcstr(metal, "void "); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, "(){\n"); - ++psContext->indent; - break; - } - case OPCODE_COUNTBITS: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//COUNTBITS\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(metal, " = popcount("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(metal, ");\n"); - break; - } - case OPCODE_FIRSTBIT_HI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//FIRSTBIT_HI\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(metal, " = (32 - clz("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, "));\n"); - break; - } - case OPCODE_FIRSTBIT_LO: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//FIRSTBIT_LO\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(metal, " = (1 + ctz("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ")));\n"); - break; - } - case OPCODE_FIRSTBIT_SHI: //signed high - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//FIRSTBIT_SHI\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); - bcatcstr(metal, " = (32 - clz("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(metal, " > 0 ? "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(metal, " : 0xFFFFFFFF ^ "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); - bcatcstr(metal, ")));\n"); - break; - } - case OPCODE_BFI: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//BFI\n"); -#endif - // This instruction is not available in Metal shading language. - // Need to expend it out (http://http.developer.nvidia.com/Cg/bitfieldInsert.html) - - int numComponents = psInst->asOperands[0].iNumComponents; - - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, " = 0;\n"); - - AddIndentation(psContext); - bcatcstr(metal, "{\n"); - - AddIndentation(psContext); - bformata(metal, " %s mask = ~(%s(0xffffffff) << ", GetConstructorForTypeMETAL(SVT_UINT, numComponents), GetConstructorForTypeMETAL(SVT_UINT, numComponents)); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ") << "); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ";\n"); - - AddIndentation(psContext); - bcatcstr(metal, " mask = ~mask;\n"); - - AddIndentation(psContext); - bcatcstr(metal, " "); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bformata(metal, " = ( as_type<%s>( (", GetConstructorForTypeMETAL(psInst->asOperands[0].aeDataType[0], numComponents)); - TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, " & mask) | ("); - TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, " << "); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ")) )"); - TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[0], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - bcatcstr(metal, ";\n"); - - AddIndentation(psContext); - bcatcstr(metal, "}\n"); - - - - break; - } - case OPCODE_BFREV: - case OPCODE_CUT: - case OPCODE_EMIT: - case OPCODE_EMITTHENCUT: - case OPCODE_CUT_STREAM: - case OPCODE_EMIT_STREAM: - case OPCODE_EMITTHENCUT_STREAM: - { - // not implemented in metal - ASSERT(0); - break; - } - case OPCODE_REP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//REP\n"); -#endif - //Need to handle nesting. - //Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx - - AddIndentation(psContext); - bcatcstr(metal, "RepCounter = as_type<int4>("); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(metal, ").x;\n"); - - AddIndentation(psContext); - bcatcstr(metal, "while(RepCounter!=0){\n"); - ++psContext->indent; - break; - } - case OPCODE_ENDREP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ENDREP\n"); -#endif - AddIndentation(psContext); - bcatcstr(metal, "RepCounter--;\n"); - - --psContext->indent; - - AddIndentation(psContext); - bcatcstr(metal, "}\n"); - break; - } - case OPCODE_LOOP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LOOP\n"); -#endif - AddIndentation(psContext); - - if (psInst->ui32NumOperands == 2) - { - //DX9 version - ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); - bcatcstr(metal, "for("); - bcatcstr(metal, "LoopCounter = "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, ".y, ZeroBasedCounter = 0;"); - bcatcstr(metal, "ZeroBasedCounter < "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, ".x;"); - - bcatcstr(metal, "LoopCounter += "); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, ".z, ZeroBasedCounter++){\n"); - ++psContext->indent; - } - else - { - bcatcstr(metal, "while(true){\n"); - ++psContext->indent; - } - break; - } - case OPCODE_ENDLOOP: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ENDLOOP\n"); -#endif - AddIndentation(psContext); - bcatcstr(metal, "}\n"); - break; - } - case OPCODE_BREAK: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//BREAK\n"); -#endif - AddIndentation(psContext); - bcatcstr(metal, "break;\n"); - break; - } - case OPCODE_BREAKC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//BREAKC\n"); -#endif - AddIndentation(psContext); - - METALTranslateConditional(psContext, psInst, metal); - break; - } - case OPCODE_CONTINUEC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//CONTINUEC\n"); -#endif - AddIndentation(psContext); - - METALTranslateConditional(psContext, psInst, metal); - break; - } - case OPCODE_IF: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//IF\n"); -#endif - AddIndentation(psContext); - - METALTranslateConditional(psContext, psInst, metal); - ++psContext->indent; - break; - } - case OPCODE_RETC: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//RETC\n"); -#endif - AddIndentation(psContext); - - METALTranslateConditional(psContext, psInst, metal); - break; - } - case OPCODE_ELSE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ELSE\n"); -#endif - AddIndentation(psContext); - bcatcstr(metal, "} else {\n"); - psContext->indent++; - break; - } - case OPCODE_ENDSWITCH: - case OPCODE_ENDIF: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(metal, "//ENDIF\n"); - AddIndentation(psContext); - bcatcstr(metal, "}\n"); - break; - } - case OPCODE_CONTINUE: - { - AddIndentation(psContext); - bcatcstr(metal, "continue;\n"); - break; - } - case OPCODE_DEFAULT: - { - --psContext->indent; - AddIndentation(psContext); - bcatcstr(metal, "default:\n"); - ++psContext->indent; - break; - } - case OPCODE_NOP: - { - break; - } - case OPCODE_SYNC: - { - const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SYNC\n"); -#endif - // warning. Although Metal documentation claims the flag can be combined - // this is not true in terms of binary operations. One can't simply OR flags - // but rather have to use pre-defined literals. - char* aszBarrierType[] = { - "mem_flags::mem_none", - "mem_flags::mem_threadgroup", - "mem_flags::mem_device", - "mem_flags::mem_device_and_threadgroup" - }; - typedef enum - { - BT_None, - BT_MemThreadGroup, - BT_MemDevice, - BT_MemDeviceAndMemThreadGroup - } BT; - BT barrierType = BT_None; - - if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) - { - AddIndentation(psContext); - bcatcstr(metal, "threadgroup_barrier("); - } - else - { - AddIndentation(psContext); - // simdgroup_barrier is faster than threadgroup_barrier. It is supported on iOS 10+ on all hardware. - bcatcstr(metal, "threadgroup_barrier("); - } - - if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) - { - barrierType = (BT)(barrierType | BT_MemThreadGroup); - } - if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) - { - barrierType = (BT)(barrierType | BT_MemDevice); - } - - bcatcstr(metal, aszBarrierType[barrierType]); - bcatcstr(metal, ");\n"); - - break; - } - case OPCODE_SWITCH: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//SWITCH\n"); -#endif - AddIndentation(psContext); - bcatcstr(metal, "switch(int("); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(metal, ")){\n"); - - psContext->indent += 2; - break; - } - case OPCODE_CASE: - { - --psContext->indent; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//case\n"); -#endif - AddIndentation(psContext); - - bcatcstr(metal, "case "); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(metal, ":\n"); - - ++psContext->indent; - break; - } - case OPCODE_EQ: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//EQ\n"); -#endif - METALAddComparision(psContext, psInst, METAL_CMP_EQ, TO_FLAG_NONE, NULL); - break; - } - case OPCODE_USHR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//USHR\n"); -#endif - METALCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_ISHL: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ISHL\n"); -#endif - - if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - - METALCallBinaryOp(psContext, "<<", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_ISHR: - { - SHADER_VARIABLE_TYPE eType = SVT_INT; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//ISHR\n"); -#endif - - if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) - { - eType = SVT_UINT; - } - - METALCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, eType); - break; - } - case OPCODE_LD: - case OPCODE_LD_MS: - { - ResourceBinding* psBinding = 0; -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_LD) - { - bcatcstr(metal, "//LD\n"); - } - else - { - bcatcstr(metal, "//LD_MS\n"); - } -#endif - - GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - - //if (psInst->bAddressOffset) - //{ - // METALTranslateTexelFetchOffset(psContext, psInst, psBinding, metal); - //} - //else - //{ - METALTranslateTexelFetch(psContext, psInst, psBinding, metal); - //} - break; - } - case OPCODE_DISCARD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DISCARD\n"); -#endif - AddIndentation(psContext); - - if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) - { - bcatcstr(metal, "if(all("); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(metal, "==0)){discard_fragment();}\n"); - } - else - { - ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); - bcatcstr(metal, "if(any("); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); - bcatcstr(metal, "!=0)){discard_fragment();}\n"); - } - break; - } - case OPCODE_LOD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LOD\n"); -#endif - //LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) - - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 4, &numParenthesis); - - //If the core language does not have query-lod feature, - //then the extension is used. The name of the function - //changed between extension and core. - if (HaveQueryLod(psContext->psShader->eTargetLanguage)) - { - bcatcstr(metal, "textureQueryLod("); - } - else - { - bcatcstr(metal, "textureQueryLOD("); - } - - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ","); - METALTranslateTexCoord(psContext, - psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], - &psInst->asOperands[1]); - bcatcstr(metal, ")"); - - //The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. - - // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms - // does not make sense. But need to re-enable to correctly swizzle this particular instruction. - psInst->asOperands[2].iWriteMaskEnabled = 1; - TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_EVAL_CENTROID: - case OPCODE_EVAL_SAMPLE_INDEX: - case OPCODE_EVAL_SNAPPED: - { - // ERROR: evaluation functions are not implemented in metal - ASSERT(0); - break; - } - case OPCODE_LD_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LD_STRUCTURED\n"); -#endif - METALTranslateShaderStorageLoad(psContext, psInst); - break; - } - case OPCODE_LD_UAV_TYPED: - { - // not implemented in metal - ASSERT(0); - break; - } - case OPCODE_STORE_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//STORE_RAW\n"); -#endif - METALTranslateShaderStorageStore(psContext, psInst); - break; - } - case OPCODE_STORE_STRUCTURED: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//STORE_STRUCTURED\n"); -#endif - METALTranslateShaderStorageStore(psContext, psInst); - break; - } - - case OPCODE_STORE_UAV_TYPED: - { - ResourceBinding* psRes; - int foundResource; - -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//STORE_UAV_TYPED\n"); -#endif - AddIndentation(psContext); - - foundResource = GetResourceFromBindingPoint(RGROUP_UAV, - psInst->asOperands[0].ui32RegisterNumber, - &psContext->psShader->sInfo, - &psRes); - - ASSERT(foundResource); - - if (psRes->eBindArea == UAVAREA_CBUFFER) - { - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(metal, "["); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(metal, "]="); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], METALResourceReturnTypeToFlag(psRes->ui32ReturnType), OPERAND_4_COMPONENT_MASK_X); - bcatcstr(metal, ";\n"); - } - else if (psRes->eBindArea == UAVAREA_TEXTURE) - { - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".write("); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], METALResourceReturnTypeToFlag(psRes->ui32ReturnType), OPERAND_4_COMPONENT_MASK_ALL); - switch (psRes->eDimension) - { - case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: - { - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ") "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: - { - bcatcstr(metal, ",as_type<uint2>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".xy) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: - { - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".x) "); - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".y) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: - { - bcatcstr(metal, ",as_type<uint2>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".xy) "); - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".z) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: - { - bcatcstr(metal, ", as_type<uint3>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".xyz) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: - { - bcatcstr(metal, ",as_type<uint2>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".xy) "); - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".z) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: - { - bcatcstr(metal, ",as_type<uint2>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".xy) "); - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".z) "); - bcatcstr(metal, ",as_type<uint>("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); - bcatcstr(metal, ".w) "); - break; - } - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: - case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: - //not supported in mnetal - ASSERT(0); - break; - } - ; - bcatcstr(metal, ");\n"); - } - else - { - //UAV is not exist in either [[buffer]] or [[texture]] - ASSERT(0); - } - break; - } - case OPCODE_LD_RAW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LD_RAW\n"); -#endif - - METALTranslateShaderStorageLoad(psContext, psInst); - break; - } - - case OPCODE_ATOMIC_CMP_STORE: - case OPCODE_IMM_ATOMIC_AND: - case OPCODE_ATOMIC_AND: - case OPCODE_IMM_ATOMIC_IADD: - case OPCODE_ATOMIC_IADD: - case OPCODE_ATOMIC_OR: - case OPCODE_ATOMIC_XOR: - case OPCODE_ATOMIC_IMIN: - case OPCODE_ATOMIC_UMIN: - case OPCODE_ATOMIC_UMAX: - case OPCODE_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMAX: - case OPCODE_IMM_ATOMIC_IMIN: - case OPCODE_IMM_ATOMIC_UMAX: - case OPCODE_IMM_ATOMIC_UMIN: - case OPCODE_IMM_ATOMIC_OR: - case OPCODE_IMM_ATOMIC_XOR: - case OPCODE_IMM_ATOMIC_EXCH: - case OPCODE_IMM_ATOMIC_CMP_EXCH: - { - TranslateAtomicMemOpMETAL(psContext, psInst); - break; - } - case OPCODE_UBFE: - case OPCODE_IBFE: - { -#ifdef _DEBUG - AddIndentation(psContext); - if (psInst->eOpcode == OPCODE_UBFE) - { - bcatcstr(metal, "//OPCODE_UBFE\n"); - } - else - { - bcatcstr(metal, "//OPCODE_IBFE\n"); - } -#endif - // These instructions are not available in Metal shading language. - // Need to expend it out (http://http.developer.nvidia.com/Cg/bitfieldExtract.html) - // NOTE: we assume bitoffset is always > 0 as to avoid dynamic branching. - // NOTE: We have taken out the -1 as this was breaking the GPU particles bitfields. - - int numComponents = psInst->asOperands[0].iNumComponents; - - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, " = 0;\n"); - - AddIndentation(psContext); - bcatcstr(metal, "{\n"); - - AddIndentation(psContext); - bformata(metal, " %s mask = ~(%s(0xffffffff) << ", GetConstructorForTypeMETAL(SVT_UINT, numComponents), GetConstructorForTypeMETAL(SVT_UINT, numComponents)); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ");\n"); - - AddIndentation(psContext); - bcatcstr(metal, " "); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bformata(metal, " = ( as_type<%s>((", GetConstructorForTypeMETAL(psInst->asOperands[0].aeDataType[0], numComponents)); - TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, " >> ( "); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); - bcatcstr(metal, ")) & mask) )"); - TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[0], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - bcatcstr(metal, ";\n"); - - AddIndentation(psContext); - bcatcstr(metal, "}\n"); - - break; - } - case OPCODE_RCP: - { - const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//RCP\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, " = (float4(1.0) / float4("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, "))"); - AddSwizzleUsingElementCountMETAL(psContext, destElemCount); - bcatcstr(metal, ";\n"); - break; - } - case OPCODE_F32TOF16: - { - const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//F32TOF16\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = { ".x", ".y", ".z", ".w" }; - - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - if (destElemCount > 1) - { - bcatcstr(metal, swizzle[destElem]); - } - - bcatcstr(metal, " = "); - - SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); - if (SVT_FLOAT == eDestDataType) - { - bcatcstr(metal, "as_type<float>"); - } - bcatcstr(metal, "( (uint( as_type<unsigned short>( (half)"); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - if (s0ElemCount > 1) - { - bcatcstr(metal, swizzle[destElem]); - } - bcatcstr(metal, " ) ) ) );\n"); - } - break; - } - case OPCODE_F16TOF32: - { - const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//F16TOF32\n"); -#endif - for (destElem = 0; destElem < destElemCount; ++destElem) - { - const char* swizzle[] = { ".x", ".y", ".z", ".w" }; - - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_UNSIGNED_INTEGER); - if (destElemCount > 1) - { - bcatcstr(metal, swizzle[destElem]); - } - - bcatcstr(metal, " = as_type<half> ((unsigned short)"); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); - if (s0ElemCount > 1) - { - bcatcstr(metal, swizzle[destElem]); - } - bcatcstr(metal, ");\n"); - } - break; - } - case OPCODE_INEG: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//INEG\n"); -#endif - uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); - - //dest = 0 - src0 - bcatcstr(metal, "-("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); - if (srcCount > dstCount) - { - AddSwizzleUsingElementCountMETAL(psContext, dstCount); - } - bcatcstr(metal, ")"); - bcatcstr(metal, ";\n"); - break; - } - case OPCODE_DERIV_RTX_COARSE: - case OPCODE_DERIV_RTX_FINE: - case OPCODE_DERIV_RTX: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DERIV_RTX\n"); -#endif - METALCallHelper1(psContext, "dfdx", psInst, 0, 1, 1); - break; - } - case OPCODE_DERIV_RTY_COARSE: - case OPCODE_DERIV_RTY_FINE: - case OPCODE_DERIV_RTY: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DERIV_RTY\n"); -#endif - METALCallHelper1(psContext, "dfdy", psInst, 0, 1, 1); - break; - } - case OPCODE_LRP: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//LRP\n"); -#endif - METALCallHelper3(psContext, "mix", psInst, 0, 2, 3, 1, 1); - break; - } - case OPCODE_DP2ADD: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//DP2ADD\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, " = dot(float2("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, "), float2("); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ")) + "); - TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_NONE); - bcatcstr(metal, ";\n"); - break; - } - case OPCODE_POW: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//POW\n"); -#endif - AddIndentation(psContext); - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); - bcatcstr(metal, " = pow(abs("); - TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); - bcatcstr(metal, "), "); - TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); - bcatcstr(metal, ");\n"); - break; - } - - case OPCODE_IMM_ATOMIC_ALLOC: - case OPCODE_IMM_ATOMIC_CONSUME: - { - // not implemented in metal - ASSERT(0); - break; - } - - case OPCODE_NOT: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//INOT\n"); -#endif - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, GetNumSwizzleElementsMETAL(&psInst->asOperands[1]), &numParenthesis); - - bcatcstr(metal, "~"); - TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, GetOperandWriteMaskMETAL(&psInst->asOperands[0])); - METALAddAssignPrologue(psContext, numParenthesis); - break; - } - case OPCODE_XOR: - { -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//XOR\n"); -#endif - - METALCallBinaryOp(psContext, "^", psInst, 0, 1, 2, SVT_UINT); - break; - } - case OPCODE_RESINFO: - { - uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - uint32_t destElem; -#ifdef _DEBUG - AddIndentation(psContext); - bcatcstr(metal, "//RESINFO\n"); -#endif - - for (destElem = 0; destElem < destElemCount; ++destElem) - { - - GetResInfoDataMETAL(psContext, psInst, psInst->asOperands[2].aui32Swizzle[destElem], destElem); - } - - break; - } - - - case OPCODE_DMAX: - case OPCODE_DMIN: - case OPCODE_DMUL: - case OPCODE_DEQ: - case OPCODE_DGE: - case OPCODE_DLT: - case OPCODE_DNE: - case OPCODE_DMOV: - case OPCODE_DMOVC: - case OPCODE_DTOF: - case OPCODE_FTOD: - case OPCODE_DDIV: - case OPCODE_DFMA: - case OPCODE_DRCP: - case OPCODE_MSAD: - case OPCODE_DTOI: - case OPCODE_DTOU: - case OPCODE_ITOD: - case OPCODE_UTOD: - default: - { - ASSERT(0); - break; - } - } - - if (psInst->bSaturate) //Saturate is only for floating point data (float opcodes or MOV) - { - int dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); - AddIndentation(psContext); - METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, dstCount, &numParenthesis); - bcatcstr(metal, "clamp("); - - TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_AUTO_BITCAST_TO_FLOAT); - bcatcstr(metal, ", 0.0, 1.0)"); - METALAddAssignPrologue(psContext, numParenthesis); - } -} - -static int METALIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode) -{ - switch (eOpcode) - { - case OPCODE_IADD: - case OPCODE_IF: - case OPCODE_IEQ: - case OPCODE_IGE: - case OPCODE_ILT: - case OPCODE_IMAD: - case OPCODE_IMAX: - case OPCODE_IMIN: - case OPCODE_IMUL: - case OPCODE_INE: - case OPCODE_INEG: - case OPCODE_ISHL: - case OPCODE_ISHR: - case OPCODE_ITOF: - case OPCODE_USHR: - case OPCODE_AND: - case OPCODE_OR: - case OPCODE_XOR: - case OPCODE_BREAKC: - case OPCODE_CONTINUEC: - case OPCODE_RETC: - case OPCODE_DISCARD: - //MOV is typeless. - //Treat immediates as int, bitcast to float if necessary - case OPCODE_MOV: - case OPCODE_MOVC: - { - return 1; - } - default: - { - return 0; - } - } -} - -int InstructionUsesRegisterMETAL(const Instruction* psInst, const Operand* psOperand) -{ - uint32_t operand; - for (operand = 0; operand < psInst->ui32NumOperands; ++operand) - { - if (psInst->asOperands[operand].eType == psOperand->eType) - { - if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) - { - if (CompareOperandSwizzlesMETAL(&psInst->asOperands[operand], psOperand)) - { - return 1; - } - } - } - } - return 0; -} - -void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext) -{ - const uint32_t count = psContext->psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; - Instruction* psInst = psContext->psShader->asPhase[MAIN_PHASE].ppsInst[0]; - uint32_t i; - - for (i = 0; i < count; ) - { - if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && - psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) - { - uint32_t k; - - for (k = i + 1; k < count; ++k) - { - if (psInst[k].eOpcode == OPCODE_ILT) - { - k = k; - } - if (InstructionUsesRegisterMETAL(&psInst[k], &psInst[i].asOperands[0])) - { - if (METALIsIntegerImmediateOpcode(psInst[k].eOpcode)) - { - psInst[i].asOperands[1].iIntegerImmediate = 1; - } - - goto next_iteration; - } - } - } -next_iteration: - ++i; - } -} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c deleted file mode 100644 index f1ab027108..0000000000 --- a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c +++ /dev/null @@ -1,2377 +0,0 @@ -// Modifications copyright Amazon.com, Inc. or its affiliates -// Modifications copyright Crytek GmbH - -#include "internal_includes/toMETALOperand.h" -#include "internal_includes/toMETALDeclaration.h" -#include "bstrlib.h" -#include "hlslcc.h" -#include "internal_includes/debug.h" - -#include <float.h> -#include <stdlib.h> - -#ifdef _MSC_VER -#define isnan(x) _isnan(x) -#define isinf(x) (!_finite(x)) -#endif - -#define fpcheck(x) (isnan(x) || isinf(x)) -#define MAX_STR_LENGTH 128 - -extern void AddIndentation(HLSLCrossCompilerContext* psContext); - -uint32_t SVTTypeToFlagMETAL(const SHADER_VARIABLE_TYPE eType) -{ - if (eType == SVT_UINT) - { - return TO_FLAG_UNSIGNED_INTEGER; - } - else if (eType == SVT_INT) - { - return TO_FLAG_INTEGER; - } - else if (eType == SVT_BOOL) - { - return TO_FLAG_INTEGER; // TODO bools? - } - else if (eType == SVT_FLOAT16) - { - return TO_FLAG_FLOAT16; - } - else - { - return TO_FLAG_NONE; - } -} - -SHADER_VARIABLE_TYPE TypeFlagsToSVTTypeMETAL(const uint32_t typeflags) -{ - if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT)) - { - return SVT_INT; - } - if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT)) - { - return SVT_UINT; - } - if (typeflags & (TO_FLAG_FLOAT16 | TO_AUTO_BITCAST_TO_FLOAT16)) - { - return SVT_FLOAT16; - } - return SVT_FLOAT; -} - -uint32_t GetOperandWriteMaskMETAL(const Operand* psOperand) -{ - if (psOperand->eSelMode != OPERAND_4_COMPONENT_MASK_MODE || psOperand->ui32CompMask == 0) - { - return OPERAND_4_COMPONENT_MASK_ALL; - } - - return psOperand->ui32CompMask; -} - - -const char* GetConstructorForTypeMETAL(const SHADER_VARIABLE_TYPE eType, - const int components) -{ - static const char* const uintTypes[] = { " ", "uint", "uint2", "uint3", "uint4" }; - static const char* const intTypes[] = { " ", "int", "int2", "int3", "int4" }; - static const char* const floatTypes[] = { " ", "float", "float2", "float3", "float4" }; - static const char* const float16Types[] = { " ", "half", "half2", "half3", "half4" }; - - if (components < 1 || components > 4) - { - return "ERROR TOO MANY COMPONENTS IN VECTOR"; - } - - switch (eType) - { - case SVT_UINT: - return uintTypes[components]; - case SVT_INT: - return intTypes[components]; - case SVT_FLOAT: - return floatTypes[components]; - case SVT_FLOAT16: - return float16Types[components]; - default: - return "ERROR UNSUPPORTED TYPE"; - } -} - - -const char* GetConstructorForTypeFlagMETAL(const uint32_t ui32Flag, - const int components) -{ - if (ui32Flag & TO_FLAG_UNSIGNED_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_UINT) - { - return GetConstructorForTypeMETAL(SVT_UINT, components); - } - else if (ui32Flag & TO_FLAG_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_INT) - { - return GetConstructorForTypeMETAL(SVT_INT, components); - } - else - { - return GetConstructorForTypeMETAL(SVT_FLOAT, components); - } -} - -int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 4; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 3; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 1; - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - return 4; - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return 1; - } - } - - return 4; -} - -//Single component repeated -//e..g .wwww -uint32_t IsSwizzleReplicatedMETAL(const Operand* psOperand) -{ - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == WWWW_SWIZZLE || - psOperand->ui32Swizzle == ZZZZ_SWIZZLE || - psOperand->ui32Swizzle == YYYY_SWIZZLE || - psOperand->ui32Swizzle == XXXX_SWIZZLE) - { - return 1; - } - } - } - return 0; -} - -static uint32_t METALGetNumberBitsSet(uint32_t a) -{ - // Calculate number of bits in a - // Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 - // Works only up to 14 bits (we're only using up to 4) - return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; -} - -//e.g. -//.z = 1 -//.x = 1 -//.yw = 2 -uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand) -{ - return GetNumSwizzleElementsWithMaskMETAL(psOperand, OPERAND_4_COMPONENT_MASK_ALL); -} - -// Get the number of elements returned by operand, taking additional component mask into account -uint32_t GetNumSwizzleElementsWithMaskMETAL(const Operand* psOperand, uint32_t ui32CompMask) -{ - uint32_t count = 0; - - switch (psOperand->eType) - { - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: - return 1; // TODO: does mask make any sense here? - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: - case OPERAND_TYPE_INPUT_THREAD_ID: - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: - // Adjust component count and break to more processing - ((Operand*)psOperand)->iNumComponents = 3; - break; - case OPERAND_TYPE_IMMEDIATE32: - case OPERAND_TYPE_IMMEDIATE64: - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - case OPERAND_TYPE_OUTPUT_DEPTH: - { - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - uint32_t compMask = (1 << psOperand->iNumComponents) - 1; - - compMask &= ui32CompMask; - // Calculate bits left in compMask - return METALGetNumberBitsSet(compMask); - } - default: - { - break; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents != 1) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t compMask = psOperand->ui32CompMask; - if (compMask == 0) - { - compMask = OPERAND_4_COMPONENT_MASK_ALL; - } - compMask &= ui32CompMask; - - if (compMask == OPERAND_4_COMPONENT_MASK_ALL) - { - return 4; - } - - if (compMask & OPERAND_4_COMPONENT_MASK_X) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_Y) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_Z) - { - count++; - } - if (compMask & OPERAND_4_COMPONENT_MASK_W) - { - count++; - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if ((ui32CompMask & (1 << i)) == 0) - { - continue; - } - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - count++; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - count++; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - count++; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - count++; - } - } - - //Component Select 1 - } - - if (!count) - { - // Translate numComponents into bitmask - // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 - uint32_t compMask = (1 << psOperand->iNumComponents) - 1; - - compMask &= ui32CompMask; - // Calculate bits left in compMask - return METALGetNumberBitsSet(compMask); - } - - return count; -} - -void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count) -{ - bstring metal = *psContext->currentShaderString; - if (count == 4) - { - return; - } - if (count) - { - bcatcstr(metal, "."); - bcatcstr(metal, "x"); - count--; - } - if (count) - { - bcatcstr(metal, "y"); - count--; - } - if (count) - { - bcatcstr(metal, "z"); - count--; - } - if (count) - { - bcatcstr(metal, "w"); - count--; - } -} - -static uint32_t METALConvertOperandSwizzleToComponentMask(const Operand* psOperand) -{ - uint32_t mask = 0; - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - mask = psOperand->ui32CompMask; - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - mask |= OPERAND_4_COMPONENT_MASK_X; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - mask |= OPERAND_4_COMPONENT_MASK_Y; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - mask |= OPERAND_4_COMPONENT_MASK_Z; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - mask |= OPERAND_4_COMPONENT_MASK_W; - } - } - - //Component Select 1 - } - - return mask; -} - -//Non-zero means the components overlap -int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB) -{ - uint32_t maskA = METALConvertOperandSwizzleToComponentMask(psOperandA); - uint32_t maskB = METALConvertOperandSwizzleToComponentMask(psOperandB); - - return maskA & maskB; -} - - -void TranslateOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, OPERAND_4_COMPONENT_MASK_ALL); -} - -void TranslateOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask) -{ - bstring metal = *psContext->currentShaderString; - - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return; - } - } - - if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) - { - /*ConstantBuffer* psCBuf = NULL; - ShaderVar* psVar = NULL; - int32_t index = -1; - GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) - //then apply the sizzle. - - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); - - bformata(metal, ".%s", psVar->Name); - if(index != -1) - { - bformata(metal, "[%d]", index); - }*/ - - //return; - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents != 1) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t mask; - if (psOperand->ui32CompMask != 0) - { - mask = psOperand->ui32CompMask & ui32ComponentMask; - } - else - { - mask = ui32ComponentMask; - } - - if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) - { - bcatcstr(metal, "."); - if (mask & OPERAND_4_COMPONENT_MASK_X) - { - bcatcstr(metal, "x"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Y) - { - bcatcstr(metal, "y"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Z) - { - bcatcstr(metal, "z"); - } - if (mask & OPERAND_4_COMPONENT_MASK_W) - { - bcatcstr(metal, "w"); - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || - !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && - psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && - psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && - psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W - ) - ) - { - uint32_t i; - - bcatcstr(metal, "."); - - for (i = 0; i < 4; ++i) - { - if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) - { - continue; - } - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(metal, "y"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(metal, "z"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - bcatcstr(metal, "w"); - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case - { - bcatcstr(metal, "."); - - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - bcatcstr(metal, "y"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - bcatcstr(metal, "z"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - bcatcstr(metal, "w"); - } - } - - //Component Select 1 - } -} - -void TranslateGmemOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements) -{ - // Similar as TranslateOperandSwizzleWithMaskMETAL but need to considerate max # of elements - - bstring metal = *psContext->currentShaderString; - - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents != 1) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t mask; - if (psOperand->ui32CompMask != 0) - { - mask = psOperand->ui32CompMask & ui32ComponentMask; - } - else - { - mask = ui32ComponentMask; - } - - if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) - { - bcatcstr(metal, "."); - if (mask & OPERAND_4_COMPONENT_MASK_X) - { - bcatcstr(metal, "x"); - } - if (mask & OPERAND_4_COMPONENT_MASK_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - if (mask & OPERAND_4_COMPONENT_MASK_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - if (mask & OPERAND_4_COMPONENT_MASK_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || - !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && - psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && - psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && - psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W - ) - ) - { - uint32_t i; - - bcatcstr(metal, "."); - - for (i = 0; i < 4; ++i) - { - if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) - { - continue; - } - - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case - { - bcatcstr(metal, "."); - - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - bcatcstr(metal, "x"); - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - if (gmemNumElements < 2) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "y"); - } - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - if (gmemNumElements < 3) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "z"); - } - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - if (gmemNumElements < 4) - { - bcatcstr(metal, "x"); - } - else - { - bcatcstr(metal, "w"); - } - } - } - - //Component Select 1 - } -} - -int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - if (psOperand->eType == OPERAND_TYPE_INPUT) - { - if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) - { - return -1; - } - } - - if (psOperand->iWriteMaskEnabled && - psOperand->iNumComponents == 4) - { - //Component Mask - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) - { - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) - { - return 0; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) - { - return 1; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) - { - return 2; - } - if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) - { - return 3; - } - } - } - else - //Component Swizzle - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle != (NO_SWIZZLE)) - { - uint32_t i; - - for (i = 0; i < 4; ++i) - { - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else - if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - } - } - else - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) - { - return 0; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) - { - return 1; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) - { - return 2; - } - else - if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) - { - return 3; - } - } - - //Component Select 1 - } - - return -1; -} - -void TranslateOperandIndexMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) -{ - int i = index; - - bstring metal = *psContext->currentShaderString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0) - { - bformata(metal, "[%d]", psOperand->aui32ArraySizes[i]); - } - else - { - bformata(metal, "%d", psOperand->aui32ArraySizes[i]); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bcatcstr(metal, "]"); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(metal, "["); //Indexes must be integral. - TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); - bformata(metal, " + %d]", psOperand->aui32ArraySizes[i]); - break; - } - default: - { - break; - } - } -} - -void TranslateOperandIndexMADMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) -{ - int i = index; - - bstring metal = *psContext->currentShaderString; - - ASSERT(index < psOperand->iIndexDims); - - switch (psOperand->eIndexRep[i]) - { - case OPERAND_INDEX_IMMEDIATE32: - { - if (i > 0) - { - bformata(metal, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - } - else - { - bformata(metal, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); - } - break; - } - case OPERAND_INDEX_RELATIVE: - { - bcatcstr(metal, "[int("); //Indexes must be integral. - TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); - bformata(metal, ")*%d+%d]", multiply, add); - break; - } - case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: - { - bcatcstr(metal, "[(int("); //Indexes must be integral. - TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); - bformata(metal, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); - break; - } - default: - { - break; - } - } -} - -// Returns nonzero if a direct constructor can convert src->dest -static int METALCanDoDirectCast( SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) -{ - // uint<->int<->bool conversions possible - if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL) && (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL)) - { - return 1; - } - - // float<->double possible - if ((src == SVT_FLOAT || src == SVT_DOUBLE) && (dest == SVT_FLOAT || dest == SVT_DOUBLE)) - { - return 1; - } - - return 0; -} - -// Returns true if one of the src or dest is half float while the other is not -static int IsHalfFloatCastNeeded(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) -{ - // uint<->int<->bool conversions possible - if ((src == SVT_FLOAT16) && (dest != SVT_FLOAT16)) - { - return 1; - } - - // float<->double possible - if ((src != SVT_FLOAT16) && (dest == SVT_FLOAT16)) - { - return 1; - } - - return 0; -} - -static const char* GetOpDestType(SHADER_VARIABLE_TYPE to) -{ - switch (to) - { - case SVT_FLOAT: - return "float"; - break; - case SVT_FLOAT16: - return "half"; - break; - case SVT_INT: - return "int"; - break; - case SVT_UINT: - return "uint"; - break; - default: - ASSERT(0); - return ""; - } -} - -static const char* GetOpCastType(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) -{ - if (to == SVT_FLOAT && (from == SVT_INT || from == SVT_UINT)) - { - return "as_type"; - } - else if (to == SVT_INT && (from == SVT_FLOAT || from == SVT_UINT)) - { - return "as_type"; - } - else if (to == SVT_UINT && (from == SVT_FLOAT || from == SVT_INT)) - { - return "as_type"; - } - - ASSERT(0); - return "ERROR missing components in GetBitcastOp()"; -} - -// Helper function to print out a single 32-bit immediate value in desired format -static void METALprintImmediate32(HLSLCrossCompilerContext* psContext, uint32_t value, SHADER_VARIABLE_TYPE eType) -{ - bstring metal = *psContext->currentShaderString; - int needsParenthesis = 0; - - if (eType == SVT_FLOAT || eType == SVT_FLOAT16) - { - // Print floats as bit patterns. - switch (eType) - { - case SVT_FLOAT: - bcatcstr(metal, "as_type<float>("); - break; - case SVT_FLOAT16: - bcatcstr(metal, "static_cast<half>("); - break; - } - - eType = SVT_INT; - needsParenthesis = 1; - } - - - - switch (eType) - { - default: - case SVT_INT: - // Need special handling for anything >= uint 0x3fffffff - if (value > 0x3ffffffe) - { - bformata(metal, "int(0x%Xu)", value); - } - else - { - bformata(metal, "0x%X", value); - } - break; - case SVT_UINT: - bformata(metal, "%uu", value); - break; - case SVT_FLOAT: - bformata(metal, "%f", *((float*)(&value))); - break; - } - if (needsParenthesis) - { - bcatcstr(metal, ")"); - } -} - -static void METALMETALTranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask) -{ - int numParenthesis = 0; - int hasCtor = 0; - bstring metal = *psContext->currentShaderString; - SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTTypeMETAL(ui32TOFlag); - SHADER_VARIABLE_TYPE eType = GetOperandDataTypeExMETAL(psContext, psOperand, requestedType); - int numComponents = GetNumSwizzleElementsWithMaskMETAL(psOperand, ui32CompMask); - int requestedComponents = 0; - - if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC2) - { - requestedComponents = 2; - } - else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC3) - { - requestedComponents = 3; - } - else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC4) - { - requestedComponents = 4; - } - - requestedComponents = max(requestedComponents, numComponents); - - *pui32IgnoreSwizzle = 0; - - - if (!(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) - { - if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32 || psOperand->eType == OPERAND_TYPE_IMMEDIATE64) - { - // Mark the operand type to match whatever we're asking for in the flags. - ((Operand*)psOperand)->aeDataType[0] = requestedType; - ((Operand*)psOperand)->aeDataType[1] = requestedType; - ((Operand*)psOperand)->aeDataType[2] = requestedType; - ((Operand*)psOperand)->aeDataType[3] = requestedType; - } - - if (eType != requestedType) - { - if (METALCanDoDirectCast(eType, requestedType)) - { - bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, requestedComponents)); - hasCtor = 1; - } - else if (IsHalfFloatCastNeeded(eType, requestedType)) - { - // half float static cast needed - if (requestedComponents > 1) - { - bformata(metal, "static_cast<%s%i>(", GetOpDestType(requestedType), requestedComponents); - } - else - { - bformata(metal, "static_cast<%s>(", GetOpDestType(requestedType)); - } - } - else - { - // Direct cast not possible, need to do bitcast. - if (requestedComponents > 1) - { - bformata(metal, "%s<%s%i>(", GetOpCastType(eType, requestedType), GetOpDestType(requestedType), requestedComponents); - } - else - { - bformata(metal, "%s<%s>(", GetOpCastType(eType, requestedType), GetOpDestType(requestedType)); - } - } - numParenthesis++; - } - - // Add ctor if needed (upscaling) - if (numComponents < requestedComponents && (hasCtor == 0)) - { - ASSERT(numComponents == 1); - bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, requestedComponents)); - numParenthesis++; - hasCtor = 1; - } - } - - - switch (psOperand->eType) - { - case OPERAND_TYPE_IMMEDIATE32: - { - if (psOperand->iNumComponents == 1) - { - METALprintImmediate32(psContext, *((unsigned int*)(&psOperand->afImmediates[0])), requestedType); - } - else - { - int i; - int firstItemAdded = 0; - if (hasCtor == 0) - { - bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, numComponents)); - numParenthesis++; - hasCtor = 1; - } - for (i = 0; i < 4; i++) - { - uint32_t uval; - if (!(ui32CompMask & (1 << i))) - { - continue; - } - - if (firstItemAdded) - { - bcatcstr(metal, ", "); - } - uval = *((uint32_t*)(&psOperand->afImmediates[i])); - METALprintImmediate32(psContext, uval, requestedType); - firstItemAdded = 1; - } - bcatcstr(metal, ")"); - *pui32IgnoreSwizzle = 1; - numParenthesis--; - } - break; - } - case OPERAND_TYPE_IMMEDIATE64: - { - if (psOperand->iNumComponents == 1) - { - bformata(metal, "%f", - psOperand->adImmediates[0]); - } - else - { - bformata(metal, "float4(%f, %f, %f, %f)", - psOperand->adImmediates[0], - psOperand->adImmediates[1], - psOperand->adImmediates[2], - psOperand->adImmediates[3]); - if (psOperand->iNumComponents != 4) - { - AddSwizzleUsingElementCountMETAL(psContext, psOperand->iNumComponents); - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - switch (psOperand->iIndexDims) - { - case INDEX_2D: - { - if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. - { - bcatcstr(metal, "stageIn"); - TranslateOperandIndexMETAL(psContext, psOperand, 0); //Vertex index - bcatcstr(metal, ".position"); - } - else - { - const char* name = "Input"; - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - name = GetDeclaredInputNameMETAL(psContext, psContext->psShader->eShaderType, psOperand); - } - - bformata(metal, "%s%d", name, psOperand->aui32ArraySizes[1]); - TranslateOperandIndexMETAL(psContext, psOperand, 0); //Vertex index - } - break; - } - default: - { - if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) - { - bformata(metal, "Input%d[", psOperand->ui32RegisterNumber); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(metal, "]"); - } - else - { - if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) - { - const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; - bformata(metal, "Input%d[%d]", parentIndex, - psOperand->ui32RegisterNumber - parentIndex); - } - else - { - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - const char* name = GetDeclaredInputNameMETAL(psContext, psContext->psShader->eShaderType, psOperand); - bcatcstr(metal, name); - } - else - { - bformata(metal, "Input%d", psOperand->ui32RegisterNumber); - } - } - } - break; - } - } - break; - } - case OPERAND_TYPE_OUTPUT: - { - bformata(metal, "Output%d", psOperand->ui32RegisterNumber); - if (psOperand->psSubOperand[0]) - { - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_AUTO_BITCAST_TO_INT); - bcatcstr(metal, "]"); - } - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH: - { - bcatcstr(metal, "DepthAny"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: - { - bcatcstr(metal, "DepthGreater"); - break; - } - case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: - { - bcatcstr(metal, "DepthLess"); - break; - } - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eType2 = GetOperandDataTypeMETAL(psContext, psOperand); - bcatcstr(metal, "Temp"); - - if (eType2 == SVT_INT) - { - bcatcstr(metal, "_int"); - } - else if (eType2 == SVT_UINT) - { - bcatcstr(metal, "_uint"); - } - else if (eType2 == SVT_DOUBLE) - { - bcatcstr(metal, "_double"); - } - else if (eType2 == SVT_FLOAT16) - { - bcatcstr(metal, "_half"); - } - else if (eType2 == SVT_VOID && - (ui32TOFlag & TO_FLAG_DESTINATION)) - { - ASSERT(0 && "Should never get here!"); - /* if(ui32TOFlag & TO_FLAG_INTEGER) - { - bcatcstr(metal, "_int"); - } - else - if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) - { - bcatcstr(metal, "_uint"); - }*/ - } - - bformata(metal, "[%d]", psOperand->ui32RegisterNumber); - - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONSTINT: - { - bformata(metal, "IntImmConst%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_SPECIAL_IMMCONST: - { - if (psOperand->psSubOperand[0] != NULL) - { - if (psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] != 0) - { - bformata(metal, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); - } - else - { - bcatcstr(metal, "ImmConstArray["); - } - TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); - bcatcstr(metal, "]"); - } - else - { - bformata(metal, "ImmConst%d", psOperand->ui32RegisterNumber); - } - break; - } - case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: - { - bcatcstr(metal, "BaseColour"); - break; - } - case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: - { - bcatcstr(metal, "OffsetColour"); - break; - } - case OPERAND_TYPE_SPECIAL_POSITION: - { - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "stageIn."); - } - bcatcstr(metal, "position"); - break; - } - case VERTEX_SHADER: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "output."); - } - bcatcstr(metal, "position"); - break; - } - default: - { - break; - } - } - break; - } - case OPERAND_TYPE_SPECIAL_FOG: - { - bcatcstr(metal, "Fog"); - break; - } - case OPERAND_TYPE_SPECIAL_POINTSIZE: - { - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "stageIn."); - } - bcatcstr(metal, "pointSize"); - break; - } - case VERTEX_SHADER: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "output."); - } - bcatcstr(metal, "pointSize"); - break; - } - default: - { - break; - } - } - break; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - { - bcatcstr(metal, "Address"); - break; - } - case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: - { - bcatcstr(metal, "LoopCounter"); - pui32IgnoreSwizzle[0] = 1; - break; - } - case OPERAND_TYPE_SPECIAL_TEXCOORD: - { - bformata(metal, "TexCoord%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - const char* StageName = "VS"; - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - - switch (psContext->psShader->eShaderType) - { - case PIXEL_SHADER: - { - StageName = "PS"; - break; - } - ////////////////////// FOLLOWING SHOULDN'T HIT IN METAL AS IT'S NOT SUPPORTED ////////////////////////////////////////// - case HULL_SHADER: - { - StageName = "HS"; - break; - } - case DOMAIN_SHADER: - { - StageName = "DS"; - break; - } - case GEOMETRY_SHADER: - { - StageName = "GS"; - break; - } - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - case COMPUTE_SHADER: - { - StageName = "CS"; - break; - } - default: - { - break; - } - } - - if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) - { - pui32IgnoreSwizzle[0] = 1; - } - - // FIXME: With ES 3.0 the buffer name is often not prepended to variable names - if (((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) && - ((psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT) != HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT)) - { - if (psCBuf) - { - //$Globals. - if (psCBuf->Name[0] == '$') - { - bformata(metal, "Globals%s", StageName); - } - else - { - bformata(metal, "%s%s", psCBuf->Name, StageName); - } - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "."); - } - } - else - { - //bformata(metal, "cb%d", psOperand->aui32ArraySizes[0]); - } - } - - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - //Work out the variable name. Don't apply swizzle to that variable yet. - int32_t rebase = 0; - - if (psCBuf && !psCBuf->blob) - { - GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - - bformata(metal, "%s", psVarType->FullName); - } - else if (psCBuf) - { - bformata(metal, "%s%s_data", psCBuf->Name, StageName); - if (psContext->psShader->eShaderType == PIXEL_SHADER) - { - bformata(metal, ".%s", psCBuf->asVars->Name); - } - else if (psContext->psShader->eShaderType == VERTEX_SHADER) - { - bformata(metal, "->%s", psCBuf->asVars->Name); - } - else - { - ASSERT(0); - } - index = psOperand->aui32ArraySizes[1]; - } - else // We don't have a semantic for this variable, so try the raw dump appoach. - { - bformata(metal, "cb%d.data", psOperand->aui32ArraySizes[0]); // - index = psOperand->aui32ArraySizes[1]; - } - - //Dx9 only? - if (psOperand->psSubOperand[0] != NULL) - { - // Array of matrices is treated as array of vec4s in HLSL, - // but that would mess up uniform types in metal. Do gymnastics. - uint32_t opFlags = TO_FLAG_INTEGER; - - if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays - bcatcstr(metal, "[("); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], opFlags); - bformata(metal, ") / 4]"); - if (psContext->psShader->eTargetLanguage <= LANG_120) - { - bcatcstr(metal, "[int(mod(float("); - TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); - bformata(metal, "), 4.0))]"); - } - else - { - bcatcstr(metal, "[(("); - TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); - bformata(metal, ") %% 4)]"); - } - } - else - { - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], opFlags); - bformata(metal, "]"); - } - } - else - if (index != -1 && psOperand->psSubOperand[1] != NULL) - { - // Array of matrices is treated as array of vec4s in HLSL, - // but that would mess up uniform types in metal. Do gymnastics. - SHADER_VARIABLE_TYPE eType2 = GetOperandDataTypeMETAL(psContext, psOperand->psSubOperand[1]); - uint32_t opFlags = TO_FLAG_INTEGER; - if (eType2 != SVT_INT && eType2 != SVT_UINT) - { - opFlags = TO_AUTO_BITCAST_TO_INT; - } - - if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays - bcatcstr(metal, "[("); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); - bformata(metal, " + %d) / 4]", index); - if (psContext->psShader->eTargetLanguage <= LANG_120) - { - bcatcstr(metal, "[int(mod(float("); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); - bformata(metal, " + %d), 4.0))]", index); - } - else - { - bcatcstr(metal, "[(("); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); - bformata(metal, " + %d) %% 4)]", index); - } - } - else - { - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); - bformata(metal, " + %d]", index); - } - } - else if (index != -1) - { - if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) - { - // Special handling for matrix arrays, open them up into vec4's - size_t matidx = index / 4; - size_t rowidx = index - (matidx * 4); - bformata(metal, "[%d][%d]", matidx, rowidx); - } - else - { - bformata(metal, "[%d]", index); - } - } - else if (psOperand->psSubOperand[1] != NULL) - { - bcatcstr(metal, "["); - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - bcatcstr(metal, "]"); - } - - if (psVarType && psVarType->Class == SVC_VECTOR) - { - switch (rebase) - { - case 4: - { - if (psVarType->Columns == 2) - { - //.x(metal) is .y(HLSL). .y(metal) is .z(HLSL) - bcatcstr(metal, ".xxyx"); - } - else if (psVarType->Columns == 3) - { - //.x(metal) is .y(HLSL). .y(metal) is .z(HLSL) .z(metal) is .w(HLSL) - bcatcstr(metal, ".xxyz"); - } - break; - } - case 8: - { - if (psVarType->Columns == 2) - { - //.x(metal) is .z(HLSL). .y(metal) is .w(HLSL) - bcatcstr(metal, ".xxxy"); - } - break; - } - case 0: - default: - { - //No rebase, but extend to vec4. - if (psVarType->Columns == 2) - { - bcatcstr(metal, ".xyxx"); - } - else if (psVarType->Columns == 3) - { - bcatcstr(metal, ".xyzx"); - } - break; - } - } - } - - if (psVarType && psVarType->Class == SVC_SCALAR) - { - *pui32IgnoreSwizzle = 1; - } - } - break; - } - case OPERAND_TYPE_RESOURCE: - { - ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_SAMPLER: - { - bformata(metal, "Sampler%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_FUNCTION_BODY: - { - const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; - const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; - //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; - const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; - const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; - const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; - - bformata(metal, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); - break; - } - case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: - { - bcatcstr(metal, "forkInstanceID"); - *pui32IgnoreSwizzle = 1; - return; - } - case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: - { - bcatcstr(metal, "immediateConstBufferF"); - - if (psOperand->psSubOperand[0]) - { - bcatcstr(metal, "("); //Indexes must be integral. - TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); - bcatcstr(metal, ")"); - } - break; - } - case OPERAND_TYPE_INPUT_DOMAIN_POINT: - { - bcatcstr(metal, "gl_TessCoord"); - break; - } - case OPERAND_TYPE_INPUT_CONTROL_POINT: - { - if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "stageIn."); - } - bformata(metal, "position", psOperand->aui32ArraySizes[0]); - } - else - { - bformata(metal, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); - } - break; - } - case OPERAND_TYPE_NULL: - { - // Null register, used to discard results of operations - bcatcstr(metal, "//null"); - break; - } - case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: - { - break; - } - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "output."); - } - bcatcstr(metal, "sampleMask"); - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_COVERAGE_MASK: - { - if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) - { - bcatcstr(metal, "stageIn."); - } - bcatcstr(metal, "sampleMask"); - //Skip swizzle on scalar types. - *pui32IgnoreSwizzle = 1; - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID: //SV_DispatchThreadID - { - bcatcstr(metal, "vThreadID"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: //SV_GroupThreadID - { - bcatcstr(metal, "vThreadGroupID"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: //SV_GroupID - { - bcatcstr(metal, "vThreadIDInGroup"); - break; - } - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: //SV_GroupIndex - { - bcatcstr(metal, "vThreadIDInGroupFlattened"); - *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. - break; - } - case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: - { - ResourceNameMETAL(metal, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); - if (ui32TOFlag | TO_FLAG_NAME_ONLY) - { - *pui32IgnoreSwizzle = 1; - } - break; - } - case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: - { - bformata(metal, "TGSM%d", psOperand->ui32RegisterNumber); - *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. - break; - } - case OPERAND_TYPE_INPUT_PRIMITIVEID: - { - break; - } - case OPERAND_TYPE_INDEXABLE_TEMP: - { - bformata(metal, "TempArray%d", psOperand->aui32ArraySizes[0]); - bcatcstr(metal, "["); - if (psOperand->aui32ArraySizes[1] != 0 || !psOperand->psSubOperand[1]) - { - bformata(metal, "%d", psOperand->aui32ArraySizes[1]); - } - - if (psOperand->psSubOperand[1]) - { - if (psOperand->aui32ArraySizes[1] != 0) - { - bcatcstr(metal, "+"); - } - TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); - } - bcatcstr(metal, "]"); - break; - } - case OPERAND_TYPE_STREAM: - { - bformata(metal, "%d", psOperand->ui32RegisterNumber); - break; - } - case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: - { - // No GS in METAL - break; - } - case OPERAND_TYPE_THIS_POINTER: - { - /* - The "this" register is a register that provides up to 4 pieces of information: - X: Which CB holds the instance data - Y: Base element offset of the instance data within the instance CB - Z: Base sampler index - W: Base Texture index - - Can be different for each function call - */ - break; - } - case OPERAND_TYPE_INPUT_PATCH_CONSTANT: - { - bformata(metal, "myPatchConst%d", psOperand->ui32RegisterNumber); - break; - } - default: - { - ASSERT(0); - break; - } - } - - if (hasCtor && (*pui32IgnoreSwizzle == 0)) - { - TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, ui32CompMask); - *pui32IgnoreSwizzle = 1; - } - - if (*pui32IgnoreSwizzle == 0) - { - TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, ui32CompMask); - } - - while (numParenthesis != 0) - { - bcatcstr(metal, ")"); - numParenthesis--; - } -} - -static void METALTranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) -{ - METALMETALTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL); -} - - -SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) -{ - return GetOperandDataTypeExMETAL(psContext, psOperand, SVT_INT); -} - -SHADER_VARIABLE_TYPE GetOperandDataTypeExMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates) -{ - - // The min precision qualifier overrides all of the stuff below - if (psOperand->eMinPrecision == OPERAND_MIN_PRECISION_FLOAT_16) - { - return SVT_FLOAT16; - } - - switch (psOperand->eType) - { - case OPERAND_TYPE_TEMP: - { - SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; - int i = 0; - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) - { - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) - { - if (psOperand->ui32Swizzle == (NO_SWIZZLE)) - { - return psOperand->aeDataType[0]; - } - - return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; - } - - if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) - { - uint32_t ui32CompMask = psOperand->ui32CompMask; - if (!psOperand->ui32CompMask) - { - ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; - } - for (; i < 4; ++i) - { - if (ui32CompMask & (1 << i)) - { - eCurrentType = psOperand->aeDataType[i]; - break; - } - } - - #ifdef _DEBUG - //Check if all elements have the same basic type. - for (; i < 4; ++i) - { - if (psOperand->ui32CompMask & (1 << i)) - { - if (eCurrentType != psOperand->aeDataType[i]) - { - ASSERT(0); - } - } - } - #endif - return eCurrentType; - } - - ASSERT(0); - - break; - } - case OPERAND_TYPE_OUTPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psOut; - - if (GetOutputSignatureFromRegister(psContext->currentPhase, - ui32Register, - psOperand->ui32CompMask, - 0, - &psContext->psShader->sInfo, - &psOut)) - { - if (psOut->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_INPUT: - { - const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; - InOutSignature* psIn; - - //UINT in DX, INT in GL. - if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) - { - return SVT_INT; - } - if (psOperand->eSpecialName == NAME_IS_FRONT_FACE) - { - return SVT_BOOL; - } - - if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) - { - if (psIn->eComponentType == INOUT_COMPONENT_UINT32) - { - return SVT_UINT; - } - else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) - { - return SVT_INT; - } - } - break; - } - case OPERAND_TYPE_CONSTANT_BUFFER: - { - ConstantBuffer* psCBuf = NULL; - ShaderVarType* psVarType = NULL; - int32_t index = -1; - int32_t rebase = -1; - int foundVar; - GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); - if (psCBuf && !psCBuf->blob) - { - foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); - if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) - { - return psVarType->Type; - } - } - else - { - // Todo: this isn't correct yet. - return SVT_FLOAT; - } - break; - } - case OPERAND_TYPE_IMMEDIATE32: - { - return ePreferredTypeForImmediates; - } - - case OPERAND_TYPE_INPUT_THREAD_ID: - case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: - case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: - { - return SVT_UINT; - } - case OPERAND_TYPE_SPECIAL_ADDRESS: - case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: - { - return SVT_INT; - } - case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: - { - return SVT_UINT; - } - case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: - { - return SVT_INT; - } - case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: - { - return SVT_INT; - } - default: - { - return SVT_FLOAT; - } - } - - return SVT_FLOAT; -} - -void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) -{ - TranslateOperandWithMaskMETAL(psContext, psOperand, ui32TOFlag, OPERAND_4_COMPONENT_MASK_ALL); -} - -void TranslateOperandWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask) -{ - bstring metal = *psContext->currentShaderString; - uint32_t ui32IgnoreSwizzle = 0; - - if (ui32TOFlag & TO_FLAG_NAME_ONLY) - { - METALTranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); - return; - } - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - bcatcstr(metal, "(-"); - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(metal, "abs("); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(metal, "-abs("); - break; - } - } - - METALMETALTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask); - - switch (psOperand->eModifier) - { - case OPERAND_MODIFIER_NONE: - { - break; - } - case OPERAND_MODIFIER_NEG: - { - bcatcstr(metal, ")"); - break; - } - case OPERAND_MODIFIER_ABS: - { - bcatcstr(metal, ")"); - break; - } - case OPERAND_MODIFIER_ABSNEG: - { - bcatcstr(metal, ")"); - break; - } - } -} - -void ResourceNameMETAL(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare) -{ - bstring metal = (targetStr == NULL) ? *psContext->currentShaderString : targetStr; - ResourceBinding* psBinding = 0; - int found; - - found = GetResourceFromBindingPoint(group, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); - - if (found) - { - int i = 0; - char name[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32ArrayOffset = ui32RegisterNumber - psBinding->ui32BindPoint; - - while (psBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) - { - name[i] = psBinding->Name[i]; - - //array syntax [X] becomes _0_ - //Otherwise declarations could end up as: - //uniform sampler2D SomeTextures[0]; - //uniform sampler2D SomeTextures[1]; - if (name[i] == '[' || name[i] == ']') - { - name[i] = '_'; - } - - ++i; - } - - name[i] = '\0'; - - if (ui32ArrayOffset) - { - bformata(metal, "%s%d", name, ui32ArrayOffset); - } - else - { - bformata(metal, "%s", name); - } - - if (RGROUP_SAMPLER == group) - { - if (bZCompare) - { - bcatcstr(metal, "_cmp"); - } - else - { - bcatcstr(metal, "_s"); - } - } - } - else - { - bformata(metal, "UnknownResource%d", ui32RegisterNumber); - } -} - -bstring TextureSamplerNameMETAL(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) -{ - bstring result; - ResourceBinding* psTextureBinding = 0; - ResourceBinding* psSamplerBinding = 0; - int foundTexture, foundSampler; - uint32_t i = 0; - char samplerName[MAX_REFLECT_STRING_LENGTH]; - uint32_t ui32ArrayOffset; - - foundTexture = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegisterNumber, psShaderInfo, &psTextureBinding); - foundSampler = GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegisterNumber, psShaderInfo, &psSamplerBinding); - - if (!foundTexture || !foundSampler) - { - result = bformat("UnknownResource%d_%d", ui32TextureRegisterNumber, ui32SamplerRegisterNumber); - return result; - } - - ui32ArrayOffset = ui32SamplerRegisterNumber - psSamplerBinding->ui32BindPoint; - - while (psSamplerBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) - { - samplerName[i] = psSamplerBinding->Name[i]; - - //array syntax [X] becomes _0_ - //Otherwise declarations could end up as: - //uniform sampler2D SomeTextures[0]; - //uniform sampler2D SomeTextures[1]; - if (samplerName[i] == '[' || samplerName[i] == ']') - { - samplerName[i] = '_'; - } - - ++i; - } - samplerName[i] = '\0'; - - result = bfromcstr(""); - - - - if (ui32ArrayOffset) - { - bformata(result, "%s%d", samplerName, ui32ArrayOffset); - } - else - { - bformata(result, "%s", samplerName); - } - - if (bZCompare) - { - bcatcstr(result, "_cmp"); - } - else - { - bcatcstr(result, "_s"); - } - - return result; -} - -void ConcatTextureSamplerNameMETAL(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) -{ - bstring texturesamplername = TextureSamplerNameMETAL(psShaderInfo, ui32TextureRegisterNumber, ui32SamplerRegisterNumber, bZCompare); - bconcat(str, texturesamplername); - bdestroy(texturesamplername); -} - -uint32_t GetGmemInputResourceSlotMETAL(uint32_t const slotIn) -{ - if (slotIn >= GMEM_FLOAT4_START_SLOT) - { - return slotIn - GMEM_FLOAT4_START_SLOT; - } - if (slotIn >= GMEM_FLOAT3_START_SLOT) - { - return slotIn - GMEM_FLOAT3_START_SLOT; - } - if (slotIn >= GMEM_FLOAT2_START_SLOT) - { - return slotIn - GMEM_FLOAT2_START_SLOT; - } - if (slotIn >= GMEM_FLOAT_START_SLOT) - { - return slotIn - GMEM_FLOAT_START_SLOT; - } - return slotIn; -} - -uint32_t GetGmemInputResourceNumElementsMETAL(uint32_t const slotIn) -{ - if (slotIn >= GMEM_FLOAT4_START_SLOT) - { - return 4; - } - if (slotIn >= GMEM_FLOAT3_START_SLOT) - { - return 3; - } - if (slotIn >= GMEM_FLOAT2_START_SLOT) - { - return 2; - } - if (slotIn >= GMEM_FLOAT_START_SLOT) - { - return 1; - } - return 0; -} From 12cbba5fad5a2d0b9e1a82c3461c4856ee4b81ba Mon Sep 17 00:00:00 2001 From: greerdv <greerdv@amazon.com> Date: Tue, 20 Apr 2021 17:42:38 +0100 Subject: [PATCH 18/96] adding test for Aabb::MultiplyByScale --- Code/Framework/AzCore/AzCore/Math/Aabb.inl | 1 + Code/Framework/AzCore/Tests/Math/AabbTests.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/Code/Framework/AzCore/AzCore/Math/Aabb.inl b/Code/Framework/AzCore/AzCore/Math/Aabb.inl index 25a03d20b9..13549a30f6 100644 --- a/Code/Framework/AzCore/AzCore/Math/Aabb.inl +++ b/Code/Framework/AzCore/AzCore/Math/Aabb.inl @@ -296,6 +296,7 @@ namespace AZ { m_min *= scale; m_max *= scale; + AZ_MATH_ASSERT(IsValid(), "Min must be less than Max"); } diff --git a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp index 6b7317f5b3..44cc800616 100644 --- a/Code/Framework/AzCore/Tests/Math/AabbTests.cpp +++ b/Code/Framework/AzCore/Tests/Math/AabbTests.cpp @@ -446,4 +446,17 @@ namespace UnitTest EXPECT_THAT(transformedAabb.GetMin(), IsClose(aabbContainingTransformedObb.GetMin())); EXPECT_THAT(transformedAabb.GetMax(), IsClose(aabbContainingTransformedObb.GetMax())); } + + TEST(MATH_AabbTransform, MultiplyByScale) + { + Vector3 min(2.0f, 6.0f, 8.0f); + Vector3 max(6.0f, 9.0f, 10.0f); + Aabb aabb = Aabb::CreateFromMinMax(min, max); + + Vector3 scale(0.5f, 2.0f, 1.5f); + aabb.MultiplyByScale(scale); + + EXPECT_THAT(aabb.GetMin(), IsClose(Vector3(1.0f, 12.0f, 12.0f))); + EXPECT_THAT(aabb.GetMax(), IsClose(Vector3(3.0f, 18.0f, 15.0f))); + } } From 2b6b4f5d170d85b22cb3eb6c752625de5c8b4660 Mon Sep 17 00:00:00 2001 From: pereslav <pereslav@amazon.com> Date: Tue, 20 Apr 2021 17:49:17 +0100 Subject: [PATCH 19/96] Removed OnEntityAdded/OnEntityRemoved from NetworkEntityManager --- .../NetworkEntity/NetworkEntityManager.cpp | 32 ------------------- .../NetworkEntity/NetworkEntityManager.h | 4 --- 2 files changed, 36 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 257173b347..43302efdaa 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -34,8 +34,6 @@ namespace Multiplayer : m_networkEntityAuthorityTracker(*this) , m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event")) , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) - , m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); }) - , m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); }) { AZ::Interface<INetworkEntityManager>::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); @@ -52,12 +50,6 @@ namespace Multiplayer m_hostId = hostId; m_entityDomain = AZStd::move(entityDomain); m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); - if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr) - { - // Null guard needed for unit tests - AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler); - AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler); - } } NetworkEntityTracker* NetworkEntityManager::GetNetworkEntityTracker() @@ -281,30 +273,6 @@ namespace Multiplayer } } - void NetworkEntityManager::OnEntityAdded(AZ::Entity* entity) - { - NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>(); - if (netBindComponent != nullptr) - { - // @pereslav - // Note that this is a total hack.. we should not be listening to this event on a client - // Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage() - const bool isClient = AZ::Interface<IMultiplayer>::Get()->GetAgentType() == MultiplayerAgentType::Client; - const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority; - const NetEntityId netEntityId = m_nextEntityId++; - netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole); - } - } - - void NetworkEntityManager::OnEntityRemoved(AZ::Entity* entity) - { - NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>(); - if (netBindComponent != nullptr) - { - MarkForRemoval(netBindComponent->GetEntityHandle()); - } - } - void NetworkEntityManager::RemoveEntities() { //RewindableObjectState::ClearRewoundEntities(); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index d9d21d6b7b..148645c638 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -79,8 +79,6 @@ namespace Multiplayer //! @} private: - void OnEntityAdded(AZ::Entity* entity); - void OnEntityRemoved(AZ::Entity* entity); void RemoveEntities(); NetEntityId NextId(); @@ -100,8 +98,6 @@ namespace Multiplayer AZ::Event<> m_onEntityNotifyChanges; ControllersActivatedEvent m_controllersActivatedEvent; ControllersDeactivatedEvent m_controllersDeactivatedEvent; - AZ::EntityAddedEvent::Handler m_entityAddedEventHandler; - AZ::EntityRemovedEvent::Handler m_entityRemovedEventHandler; HostId m_hostId = InvalidHostId; NetEntityId m_nextEntityId = NetEntityId{ 0 }; From 7b42402b1890e872ad7b52733ceeafa220d4a303 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 11:54:31 -0500 Subject: [PATCH 20/96] Removing hlsl refs in cmake build files --- Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt | 1 - Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt | 1 - 2 files changed, 2 deletions(-) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt index 0b612f0883..dd62bad4f3 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt @@ -46,7 +46,6 @@ if(DXGL_TRAIT_BUILD_OPENGL_SUPPORTED AND (NOT LY_MONOLITHIC_GAME OR LY_TRAIT_USE BUILD_DEPENDENCIES PUBLIC AZ::AzFramework - AZ::HLSLcc.Headers 3rdParty::lz4 3rdParty::glad Legacy::CryCommon diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt index b8e97a1ca6..0ade50fb7a 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt @@ -41,7 +41,6 @@ if(DXGL_TRAIT_BUILD_DXMETAL_SUPPORTED AND NOT LY_MONOLITHIC_GAME) # Only Atom is BUILD_DEPENDENCIES PUBLIC AZ::AzFramework - AZ::HLSLcc.Headers Legacy::CryCommon Legacy::CryCommon.EngineSettings.Static ) From 6f33e1404e44722a83f8d246152ebfa7d4b301e7 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:27:05 -0500 Subject: [PATCH 21/96] Linux/mac hlsl header refs removed --- .../DXGL/Implementation/GLBlitFramebufferHelper.cpp | 4 ---- .../XRenderD3D9/DXGL/Implementation/GLExtensions.hpp | 5 ----- .../RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp | 5 ----- .../RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp | 3 --- .../XRenderD3D9/DXMETAL/Implementation/GLShader.cpp | 5 ----- 5 files changed, 22 deletions(-) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp index cb26d81c89..c0bc403b25 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp @@ -14,10 +14,6 @@ #include <Implementation/GLBlitFramebufferHelper.hpp> #include <Implementation/GLBlitShaders.hpp> #include <Implementation/GLContext.hpp> -#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include <hlslcc.hpp> -#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include <hlslcc_bin.hpp> namespace NCryOpenGL { diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp index 6983bd4fdf..d83ba2c95f 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp @@ -21,11 +21,6 @@ #define CryEngine_GLExtensions_hpp #pragma once -#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include "hlslcc.hpp" -#include "hlslcc_bin.hpp" -#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER - #if DXGLES && DXGLES_VERSION == DXGLES_VERSION_30 && defined(GL_EXT_separate_shader_objects) && defined(IOS) // On OpenGL ES separate shader programs are available as an extesion, so we // just define the normal api here to avoid ifdefing the entire code diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp index 7974411481..13f5cb2d15 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp @@ -19,11 +19,6 @@ #include "GLDevice.hpp" #include <Common/RenderCapabilities.h> -#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include "hlslcc.hpp" -#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include "hlslcc_bin.hpp" - struct SAutoBindProgram { SAutoBindProgram(const GLuint uProgram) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp index 430a5bf1c8..195b29fff0 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp @@ -18,9 +18,6 @@ #define __GLSHADER__ #include "GLCommon.hpp" -#if !DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER -#include "hlslcc.hpp" -#endif //!DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER #if DXGL_GLSL_FROM_HLSLCROSSCOMPILER && !DXGL_INPUT_GLSL && DXGL_SUPPORT_SHADER_STORAGE_BLOCKS #define DXGL_ENABLE_SHADER_TRACING 1 diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp index 2834559226..f105fda2cf 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp @@ -17,11 +17,6 @@ #include "MetalDevice.hpp" #include "GLExtensions.hpp" -// Confetti BEGIN: Igor Lobanchikov -#include "hlslcc.hpp" -#include "hlslcc_bin.hpp" -// Confetti End: Igor Lobanchikov - namespace NCryMetal { SSource::SSource(const char* pData, uint32 uDataSize) From 2a59b7e0e6e9321850fc9df596c514a5c7c90889 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:52:40 -0500 Subject: [PATCH 22/96] Revert "Linux/mac hlsl header refs removed" This reverts commit 6f33e1404e44722a83f8d246152ebfa7d4b301e7. --- .../DXGL/Implementation/GLBlitFramebufferHelper.cpp | 4 ++++ .../XRenderD3D9/DXGL/Implementation/GLExtensions.hpp | 5 +++++ .../RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp | 5 +++++ .../RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp | 3 +++ .../XRenderD3D9/DXMETAL/Implementation/GLShader.cpp | 5 +++++ 5 files changed, 22 insertions(+) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp index c0bc403b25..cb26d81c89 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLBlitFramebufferHelper.cpp @@ -14,6 +14,10 @@ #include <Implementation/GLBlitFramebufferHelper.hpp> #include <Implementation/GLBlitShaders.hpp> #include <Implementation/GLContext.hpp> +#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include <hlslcc.hpp> +#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include <hlslcc_bin.hpp> namespace NCryOpenGL { diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp index d83ba2c95f..6983bd4fdf 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLExtensions.hpp @@ -21,6 +21,11 @@ #define CryEngine_GLExtensions_hpp #pragma once +#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include "hlslcc.hpp" +#include "hlslcc_bin.hpp" +#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER + #if DXGLES && DXGLES_VERSION == DXGLES_VERSION_30 && defined(GL_EXT_separate_shader_objects) && defined(IOS) // On OpenGL ES separate shader programs are available as an extesion, so we // just define the normal api here to avoid ifdefing the entire code diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp index 13f5cb2d15..7974411481 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.cpp @@ -19,6 +19,11 @@ #include "GLDevice.hpp" #include <Common/RenderCapabilities.h> +#if DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include "hlslcc.hpp" +#endif //DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include "hlslcc_bin.hpp" + struct SAutoBindProgram { SAutoBindProgram(const GLuint uProgram) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp index 195b29fff0..430a5bf1c8 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/Implementation/GLShader.hpp @@ -18,6 +18,9 @@ #define __GLSHADER__ #include "GLCommon.hpp" +#if !DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER +#include "hlslcc.hpp" +#endif //!DXGL_INPUT_GLSL && DXGL_GLSL_FROM_HLSLCROSSCOMPILER #if DXGL_GLSL_FROM_HLSLCROSSCOMPILER && !DXGL_INPUT_GLSL && DXGL_SUPPORT_SHADER_STORAGE_BLOCKS #define DXGL_ENABLE_SHADER_TRACING 1 diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp index f105fda2cf..2834559226 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/Implementation/GLShader.cpp @@ -17,6 +17,11 @@ #include "MetalDevice.hpp" #include "GLExtensions.hpp" +// Confetti BEGIN: Igor Lobanchikov +#include "hlslcc.hpp" +#include "hlslcc_bin.hpp" +// Confetti End: Igor Lobanchikov + namespace NCryMetal { SSource::SSource(const char* pData, uint32 uDataSize) From 8410452067117bfdd7f6a5f621b93a9a0bcb0bf5 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:53:03 -0500 Subject: [PATCH 23/96] Revert "Removing hlsl refs in cmake build files" This reverts commit 7b42402b1890e872ad7b52733ceeafa220d4a303. --- Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt | 1 + Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt index dd62bad4f3..0b612f0883 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXGL/CMakeLists.txt @@ -46,6 +46,7 @@ if(DXGL_TRAIT_BUILD_OPENGL_SUPPORTED AND (NOT LY_MONOLITHIC_GAME OR LY_TRAIT_USE BUILD_DEPENDENCIES PUBLIC AZ::AzFramework + AZ::HLSLcc.Headers 3rdParty::lz4 3rdParty::glad Legacy::CryCommon diff --git a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt index 0ade50fb7a..b8e97a1ca6 100644 --- a/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt +++ b/Code/CryEngine/RenderDll/XRenderD3D9/DXMETAL/CMakeLists.txt @@ -41,6 +41,7 @@ if(DXGL_TRAIT_BUILD_DXMETAL_SUPPORTED AND NOT LY_MONOLITHIC_GAME) # Only Atom is BUILD_DEPENDENCIES PUBLIC AZ::AzFramework + AZ::HLSLcc.Headers Legacy::CryCommon Legacy::CryCommon.EngineSettings.Static ) From c07c57ca2ae1d1dae0722bc33a8edeb0aea75bc6 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:53:46 -0500 Subject: [PATCH 24/96] Revert "Removed HLSL cry compilers and tools" This reverts commit f8a72e5a040c62a5c489a87c8ad39f2256b9153a. --- Code/Tools/CMakeLists.txt | 2 + Code/Tools/CryFXC/cryfxc.sln | 26 + Code/Tools/CryFXC/cryfxc/cryfxc.cpp | 494 ++ Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj | 153 + Code/Tools/CryFXC/cryfxc/stdafx.cpp | 14 + Code/Tools/CryFXC/cryfxc/stdafx.h | 29 + Code/Tools/CryFXC/cryfxc/targetver.h | 16 + Code/Tools/HLSLCrossCompiler/CMakeLists.txt | 57 + .../Platform/Linux/platform_linux.cmake | 10 + .../Platform/Mac/platform_mac.cmake | 11 + .../Platform/Windows/platform_windows.cmake | 18 + Code/Tools/HLSLCrossCompiler/README | 71 + .../HLSLCrossCompiler/hlslcc_files.cmake | 60 + .../hlslcc_header_files.cmake | 18 + .../include/amazon_changes.h | 13 + Code/Tools/HLSLCrossCompiler/include/hlslcc.h | 580 ++ .../HLSLCrossCompiler/include/hlslcc.hpp | 7 + .../HLSLCrossCompiler/include/hlslcc_bin.hpp | 419 ++ .../Tools/HLSLCrossCompiler/include/pstdint.h | 801 +++ Code/Tools/HLSLCrossCompiler/jni/Android.mk | 32 + .../HLSLCrossCompiler/jni/Application.mk | 3 + .../lib/android-armeabi-v7a/libHLSLcc.a | 3 + .../lib/ios-arm64/libHLSLcc.a | 3 + .../lib/ios-simx86_64/libHLSLcc.a | 3 + .../HLSLCrossCompiler/lib/ios/libHLSLcc.a | 3 + .../HLSLCrossCompiler/lib/linux/libHLSLcc.a | 3 + .../HLSLCrossCompiler/lib/linux/libHLSLcc_d.a | 3 + .../HLSLCrossCompiler/lib/mac/libHLSLcc.a | 3 + .../HLSLCrossCompiler/lib/mac/libHLSLcc_d.a | 3 + .../HLSLCrossCompiler/lib/steamos/libHLSLcc.a | 3 + .../lib/steamos/libHLSLcc_d.a | 3 + .../HLSLCrossCompiler/lib/win32/libHLSLcc.lib | 3 + .../HLSLCrossCompiler/lib/win64/libHLSLcc.lib | 3 + Code/Tools/HLSLCrossCompiler/license.txt | 53 + .../HLSLCrossCompiler/offline/cjson/README | 247 + .../HLSLCrossCompiler/offline/cjson/cJSON.c | 578 ++ .../HLSLCrossCompiler/offline/cjson/cJSON.h | 142 + .../offline/compilerStandalone.cpp | 803 +++ Code/Tools/HLSLCrossCompiler/offline/hash.h | 152 + .../offline/serializeReflection.cpp | 207 + .../offline/serializeReflection.h | 11 + .../Tools/HLSLCrossCompiler/offline/timer.cpp | 40 + Code/Tools/HLSLCrossCompiler/offline/timer.h | 29 + .../HLSLCrossCompiler/src/amazon_changes.c | 219 + .../HLSLCrossCompiler/src/cbstring/bsafe.c | 20 + .../HLSLCrossCompiler/src/cbstring/bsafe.h | 45 + .../HLSLCrossCompiler/src/cbstring/bstraux.c | 1134 ++++ .../HLSLCrossCompiler/src/cbstring/bstraux.h | 113 + .../HLSLCrossCompiler/src/cbstring/bstrlib.c | 2976 +++++++++ .../HLSLCrossCompiler/src/cbstring/bstrlib.h | 305 + .../src/cbstring/bstrlib.txt | 3201 ++++++++++ .../src/cbstring/license.txt | 29 + .../src/cbstring/porting.txt | 172 + .../src/cbstring/security.txt | 221 + Code/Tools/HLSLCrossCompiler/src/decode.c | 1845 ++++++ Code/Tools/HLSLCrossCompiler/src/decodeDX9.c | 1113 ++++ .../HLSLCrossCompiler/src/hlslccToolkit.c | 167 + .../src/internal_includes/debug.h | 21 + .../src/internal_includes/decode.h | 21 + .../src/internal_includes/hlslccToolkit.h | 35 + .../src/internal_includes/hlslcc_malloc.c | 16 + .../src/internal_includes/hlslcc_malloc.h | 15 + .../src/internal_includes/languages.h | 242 + .../src/internal_includes/reflect.h | 42 + .../src/internal_includes/shaderLimits.h | 36 + .../src/internal_includes/structs.h | 374 ++ .../src/internal_includes/toGLSLDeclaration.h | 19 + .../src/internal_includes/toGLSLInstruction.h | 18 + .../src/internal_includes/toGLSLOperand.h | 46 + .../internal_includes/toMETALDeclaration.h | 16 + .../internal_includes/toMETALInstruction.h | 18 + .../src/internal_includes/toMETALOperand.h | 38 + .../src/internal_includes/tokens.h | 812 +++ .../src/internal_includes/tokensDX9.h | 304 + Code/Tools/HLSLCrossCompiler/src/reflect.c | 1075 ++++ Code/Tools/HLSLCrossCompiler/src/toGLSL.c | 1921 ++++++ .../HLSLCrossCompiler/src/toGLSLDeclaration.c | 2908 +++++++++ .../HLSLCrossCompiler/src/toGLSLInstruction.c | 5598 +++++++++++++++++ .../HLSLCrossCompiler/src/toGLSLOperand.c | 2121 +++++++ .../HLSLCrossCompilerMETAL/CMakeLists.txt | 54 + .../Platform/Linux/PAL_linux.cmake | 12 + .../Platform/Mac/PAL_mac.cmake | 12 + .../Platform/Windows/PAL_windows.cmake | 12 + Code/Tools/HLSLCrossCompilerMETAL/README | 52 + .../bin/win32/HLSLcc.exe | 3 + .../bin/win32/HLSLcc_d.exe | 3 + .../hlslcc_metal_files.cmake | 65 + .../HLSLCrossCompilerMETAL/include/hlslcc.h | 537 ++ .../HLSLCrossCompilerMETAL/include/hlslcc.hpp | 7 + .../include/hlslcc_bin.hpp | 448 ++ .../HLSLCrossCompilerMETAL/include/pstdint.h | 801 +++ .../HLSLCrossCompilerMETAL/jni/Android.mk | 32 + .../HLSLCrossCompilerMETAL/jni/Application.mk | 3 + .../lib/android-armeabi-v7a/libHLSLcc.a | 3 + .../lib/ios/libHLSLcc.a | 3 + .../lib/linux/libHLSLcc.a | 3 + .../lib/linux/libHLSLcc_d.a | 3 + .../lib/mac/libHLSLcc.a | 3 + .../lib/mac/libHLSLcc_d.a | 3 + .../lib/steamos/libHLSLcc.a | 3 + .../lib/steamos/libHLSLcc_d.a | 3 + .../lib/win32/Debug/libHLSLcc.lib | 3 + .../lib/win32/Release/libHLSLcc.lib | 3 + .../lib/win32/libHLSLcc.lib | 3 + .../lib/win64/Release/libHLSLcc.lib | 3 + .../lib/win64/libHLSLcc.lib | 3 + Code/Tools/HLSLCrossCompilerMETAL/license.txt | 52 + .../offline/cjson/README | 247 + .../offline/cjson/cJSON.c | 578 ++ .../offline/cjson/cJSON.h | 142 + .../offline/compilerStandalone.cpp | 825 +++ .../HLSLCrossCompilerMETAL/offline/hash.h | 128 + .../offline/serializeReflection.cpp | 207 + .../offline/serializeReflection.h | 11 + .../HLSLCrossCompilerMETAL/offline/timer.cpp | 40 + .../HLSLCrossCompilerMETAL/offline/timer.h | 29 + .../src/cbstring/bsafe.c | 20 + .../src/cbstring/bsafe.h | 39 + .../src/cbstring/bstraux.c | 1134 ++++ .../src/cbstring/bstraux.h | 113 + .../src/cbstring/bstrlib.c | 2976 +++++++++ .../src/cbstring/bstrlib.h | 305 + .../src/cbstring/bstrlib.txt | 3201 ++++++++++ .../src/cbstring/license.txt | 29 + .../src/cbstring/porting.txt | 172 + .../src/cbstring/security.txt | 221 + .../Tools/HLSLCrossCompilerMETAL/src/decode.c | 1750 ++++++ .../HLSLCrossCompilerMETAL/src/decodeDX9.c | 1133 ++++ .../src/internal_includes/debug.h | 21 + .../src/internal_includes/decode.h | 18 + .../src/internal_includes/hlslcc_malloc.c | 37 + .../src/internal_includes/hlslcc_malloc.h | 15 + .../src/internal_includes/languages.h | 213 + .../src/internal_includes/reflect.h | 73 + .../src/internal_includes/shaderLimits.h | 14 + .../src/internal_includes/structs.h | 338 + .../src/internal_includes/structsMETAL.c | 15 + .../src/internal_includes/structsMetal.h | 19 + .../src/internal_includes/toGLSLDeclaration.h | 19 + .../src/internal_includes/toGLSLInstruction.h | 18 + .../src/internal_includes/toGLSLOperand.h | 72 + .../internal_includes/toMETALDeclaration.h | 15 + .../internal_includes/toMETALInstruction.h | 20 + .../src/internal_includes/toMETALOperand.h | 78 + .../src/internal_includes/tokens.h | 819 +++ .../src/internal_includes/tokensDX9.h | 304 + .../HLSLCrossCompilerMETAL/src/reflect.c | 1213 ++++ .../Tools/HLSLCrossCompilerMETAL/src/toGLSL.c | 851 +++ .../src/toGLSLDeclaration.c | 2678 ++++++++ .../src/toGLSLInstruction.c | 4576 ++++++++++++++ .../src/toGLSLOperand.c | 1869 ++++++ .../HLSLCrossCompilerMETAL/src/toMETAL.c | 440 ++ .../src/toMETALDeclaration.c | 2281 +++++++ .../src/toMETALInstruction.c | 4946 +++++++++++++++ .../src/toMETALOperand.c | 2377 +++++++ 155 files changed, 71159 insertions(+) create mode 100644 Code/Tools/CryFXC/cryfxc.sln create mode 100644 Code/Tools/CryFXC/cryfxc/cryfxc.cpp create mode 100644 Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj create mode 100644 Code/Tools/CryFXC/cryfxc/stdafx.cpp create mode 100644 Code/Tools/CryFXC/cryfxc/stdafx.h create mode 100644 Code/Tools/CryFXC/cryfxc/targetver.h create mode 100644 Code/Tools/HLSLCrossCompiler/CMakeLists.txt create mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake create mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake create mode 100644 Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake create mode 100644 Code/Tools/HLSLCrossCompiler/README create mode 100644 Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake create mode 100644 Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake create mode 100644 Code/Tools/HLSLCrossCompiler/include/amazon_changes.h create mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc.h create mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp create mode 100644 Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp create mode 100644 Code/Tools/HLSLCrossCompiler/include/pstdint.h create mode 100644 Code/Tools/HLSLCrossCompiler/jni/Android.mk create mode 100644 Code/Tools/HLSLCrossCompiler/jni/Application.mk create mode 100644 Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompiler/license.txt create mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/README create mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c create mode 100644 Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h create mode 100644 Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp create mode 100644 Code/Tools/HLSLCrossCompiler/offline/hash.h create mode 100644 Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp create mode 100644 Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h create mode 100644 Code/Tools/HLSLCrossCompiler/offline/timer.cpp create mode 100644 Code/Tools/HLSLCrossCompiler/offline/timer.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/amazon_changes.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt create mode 100644 Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt create mode 100644 Code/Tools/HLSLCrossCompiler/src/decode.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/decodeDX9.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h create mode 100644 Code/Tools/HLSLCrossCompiler/src/reflect.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSL.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c create mode 100644 Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/README create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/license.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/decode.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c create mode 100644 Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c diff --git a/Code/Tools/CMakeLists.txt b/Code/Tools/CMakeLists.txt index 3cac4e7932..d2500dfd04 100644 --- a/Code/Tools/CMakeLists.txt +++ b/Code/Tools/CMakeLists.txt @@ -15,6 +15,8 @@ add_subdirectory(AWSNativeSDKInit) add_subdirectory(AzTestRunner) add_subdirectory(CryCommonTools) add_subdirectory(CryXML) +add_subdirectory(HLSLCrossCompiler) +add_subdirectory(HLSLCrossCompilerMETAL) add_subdirectory(News) add_subdirectory(PythonBindingsExample) add_subdirectory(RC) diff --git a/Code/Tools/CryFXC/cryfxc.sln b/Code/Tools/CryFXC/cryfxc.sln new file mode 100644 index 0000000000..26c5dc4e6d --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cryfxc", "cryfxc\cryfxc.vcxproj", "{A505D345-D712-4C80-8BDE-6FBC08A390D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|Win32.Build.0 = Debug|Win32 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|x64.ActiveCfg = Debug|x64 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Debug|x64.Build.0 = Debug|x64 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|Win32.ActiveCfg = Release|Win32 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|Win32.Build.0 = Release|Win32 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|x64.ActiveCfg = Release|x64 + {A505D345-D712-4C80-8BDE-6FBC08A390D8}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Code/Tools/CryFXC/cryfxc/cryfxc.cpp b/Code/Tools/CryFXC/cryfxc/cryfxc.cpp new file mode 100644 index 0000000000..0d7e3435dd --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc/cryfxc.cpp @@ -0,0 +1,494 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#include "stdafx.h" + +#pragma comment(lib, "D3Dcompiler.lib") + +#define CRYFXC_VER "1.01" + + +enum SwitchType +{ + FXC_E, FXC_T, FXC_Help, FXC_CmdOptFile, FXC_Cc, FXC_Compress, FXC_D, FXC_Decompress, FXC_Fc, + FXC_Fh, FXC_Fo, FXC_Fx, FXC_P, FXC_Gch, FXC_Gdp, FXC_Gec, FXC_Ges, FXC_Gfa, FXC_Gfp, FXC_Gis, + FXC_Gpp, FXC_I, FXC_LD, FXC_Ni, FXC_NoLogo, FXC_Od, FXC_Op, FXC_O0, FXC_O1, FXC_O2, FXC_O3, + FXC_Vd, FXC_Vi, FXC_Vn, FXC_Zi, FXC_Zpc, FXC_Zpr, + + FXC_NumArgs +}; + + +struct SwitchEntry +{ + SwitchType type; + const char* text; + bool hasValue; + bool supported; +}; + + +const static SwitchEntry s_switchEntries[] = +{ + {FXC_E, "/E", 1, true}, + {FXC_T, "/T", 1, true}, + {FXC_Fh, "/Fh", 1, true}, + {FXC_Fo, "/Fo", 1, true}, + + {FXC_Gec, "/Gec", 0, true}, + {FXC_Ges, "/Ges", 0, true}, + {FXC_Gfa, "/Gfa", 0, true}, + {FXC_Gfp, "/Gfp", 0, true}, + {FXC_Gis, "/Gis", 0, true}, + {FXC_Gpp, "/Gpp", 0, true}, + {FXC_Od, "/Od", 0, true}, + {FXC_O0, "/O0", 0, true}, + {FXC_O1, "/O1", 0, true}, + {FXC_O2, "/O2", 0, true}, + {FXC_O3, "/O3", 0, true}, + {FXC_Op, "/Op", 0, true}, + {FXC_Vd, "/Vd", 0, true}, + {FXC_Vn, "/Vn", 1, true}, + {FXC_Zi, "/Zi", 0, true}, + {FXC_Zpc, "/Zpc", 0, true}, + {FXC_Zpr, "/Zpr", 0, true}, + {FXC_NoLogo, "/nologo", 0, true}, + + {FXC_Help, "/?", 0, false}, + {FXC_Help, "/help", 0, false}, + {FXC_Cc, "/Cc", 0, false}, + {FXC_Compress, "/compress", 0, false}, + {FXC_D, "/D", 1, false}, + {FXC_Decompress, "/decompress", 0, false}, + {FXC_Fc, "/Fc", 1, false}, + {FXC_Fx, "/Fx", 1, false}, + {FXC_P, "/P", 1, false}, + {FXC_Gch, "/Gch", 0, false}, + {FXC_Gdp, "/Gdp", 0, false}, + {FXC_I, "/I", 1, false}, + {FXC_LD, "/LD", 0, false}, + {FXC_Ni, "/Ni", 0, false}, + {FXC_Vi, "/Vi", 0, false} +}; + + +bool IsSwitch(const char* p) +{ + assert(p); + return *p == '/' || *p == '@'; +} + + +const SwitchEntry* GetSwitch(const char* p) +{ + assert(p); + for (size_t i = 0; i < sizeof(s_switchEntries) / sizeof(s_switchEntries[0]); ++i) + { + if (_stricmp(s_switchEntries[i].text, p) == 0) + { + return &s_switchEntries[i]; + } + } + + if (*p == '@') + { + const static SwitchEntry sw = {FXC_CmdOptFile, "@", 0, false}; + return &sw; + } + + return 0; +} + + +struct ParserResults +{ + const char* pProfile; + const char* pEntry; + const char* pOutFile; + const char* pInFile; + const char* pHeaderVariableName; + unsigned int compilerFlags; + bool disassemble; + + void Init() + { + pProfile = 0; + pEntry = 0; + pOutFile = 0; + pInFile = 0; + pHeaderVariableName = 0; + compilerFlags = 0; + disassemble = false; + } +}; + + +bool ParseCommandLine(const char* const* args, size_t numargs, ParserResults& parserRes) +{ + parserRes.Init(); + + if (numargs < 4) + { + fprintf(stderr, "Failed to specify all required arguments: infile, outfile, profile and entry point\n"); + return false; + } + + for (size_t i = 1; i < numargs; ++i) + { + if (IsSwitch(args[i])) + { + const SwitchEntry* sw = GetSwitch(args[i]); + if (!sw) + { + fprintf(stderr, "Unknown switch: %s\n", args[i]); + return false; + } + + if (!sw->supported) + { + fprintf(stderr, "Unsupported switch: %s\n", sw->text); + return false; + } + + if (sw->hasValue) + { + if (i + 1 == numargs || IsSwitch(args[i + 1])) + { + fprintf(stderr, "Missing value for switch: %s\n", sw->text); + return false; + } + + const char* pValue = args[i + 1]; + switch (sw->type) + { + case FXC_E: + parserRes.pEntry = pValue; + break; + case FXC_T: + parserRes.pProfile = pValue; + break; + case FXC_Fh: + parserRes.pOutFile = pValue; + parserRes.disassemble = true; + break; + case FXC_Fo: + parserRes.pOutFile = pValue; + break; + case FXC_Vn: + parserRes.pHeaderVariableName = pValue; + break; + default: + fprintf(stderr, "Failed assigning switch: %s | value: %s\n", sw->text, pValue); + return false; + } + + ++i; + } + else + { + switch (sw->type) + { + case FXC_Gec: + parserRes.compilerFlags |= D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY; + break; + case FXC_Od: + parserRes.compilerFlags |= D3D10_SHADER_SKIP_OPTIMIZATION; + break; + case FXC_O0: + parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL0; + break; + case FXC_O1: + parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL1; + break; + case FXC_O2: + parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL2; + break; + case FXC_O3: + parserRes.compilerFlags |= D3D10_SHADER_OPTIMIZATION_LEVEL3; + break; + case FXC_Zi: + parserRes.compilerFlags |= D3D10_SHADER_DEBUG; + break; + case FXC_Zpc: + parserRes.compilerFlags |= D3D10_SHADER_PACK_MATRIX_COLUMN_MAJOR; + break; + case FXC_Zpr: + parserRes.compilerFlags |= D3D10_SHADER_PACK_MATRIX_ROW_MAJOR; + break; + case FXC_Ges: + parserRes.compilerFlags |= D3D10_SHADER_ENABLE_STRICTNESS; + break; + case FXC_Gfa: + parserRes.compilerFlags |= D3D10_SHADER_AVOID_FLOW_CONTROL; + break; + case FXC_Gfp: + parserRes.compilerFlags |= D3D10_SHADER_PREFER_FLOW_CONTROL; + break; + case FXC_Gis: + parserRes.compilerFlags |= D3D10_SHADER_IEEE_STRICTNESS; + break; + case FXC_Gpp: + parserRes.compilerFlags |= D3D10_SHADER_PARTIAL_PRECISION; + break; + case FXC_Op: + parserRes.compilerFlags |= D3D10_SHADER_NO_PRESHADER; + break; + case FXC_Vd: + parserRes.compilerFlags |= D3D10_SHADER_SKIP_VALIDATION; + break; + case FXC_NoLogo: + break; + default: + fprintf(stderr, "Failed assigning switch: %s\n", sw->text); + return false; + } + } + } + else if (i == numargs - 1) + { + parserRes.pInFile = args[i]; + } + else + { + fprintf(stderr, "Error in command line at token: %s\n", args[i]); + return false; + } + } + + const bool successful = parserRes.pProfile && parserRes.pEntry && parserRes.pInFile && parserRes.pOutFile; + if (!successful) + { + fprintf(stderr, "Failed to specify all required arguments: infile, outfile, profile and entry point\n"); + } + + return successful; +} + + +bool ReadInFile(const char* pInFile, std::vector<char>& data) +{ + if (!pInFile) + { + return false; + } + + bool read = false; + + FILE* fin = 0; + fopen_s(&fin, pInFile, "rb"); + if (fin) + { + fseek(fin, 0, SEEK_END); + const long l = ftell(fin); + if (l >= 0) + { + fseek(fin, 0, SEEK_SET); + const size_t len = l > 0 ? (size_t) l : 0; + data.resize(len); + fread(&data[0], 1, len, fin); + read = true; + } + + fclose(fin); + } + + return read; +} + + +bool WriteByteCode(const char* pFileName, const void* pCode, size_t codeSize) +{ + if (!pFileName || !pCode && codeSize) + { + return false; + } + + bool written = false; + + FILE* fout = 0; + fopen_s(&fout, pFileName, "wb"); + if (fout) + { + fwrite(pCode, 1, codeSize, fout); + fclose(fout); + written = true; + } + + return written; +} + + +bool WriteHexListing(const char* pFileName, const char* pHdrVarName, const char* pDisassembly, const void* pCode, size_t codeSize) +{ + if (!pFileName || !pHdrVarName || !pDisassembly || !pCode && codeSize) + { + return false; + } + + bool written = false; + + FILE* fout = 0; + fopen_s(&fout, pFileName, "w"); + if (fout) + { + fprintf(fout, "#if 0\n%s#endif\n\n", pDisassembly); + fprintf(fout, "const BYTE g_%s[] = \n{", pHdrVarName); + + const size_t blockSize = 6; + const size_t numBlocks = codeSize / blockSize; + + const unsigned char* p = (const unsigned char*) pCode; + + size_t i = 0; + for (; i < numBlocks * blockSize; i += blockSize) + { + fprintf(fout, "\n %3d, %3d, %3d, %3d, %3d, %3d", p[i], p[i + 1], p[i + 2], p[i + 3], p[i + 4], p[i + 5]); + if (i + blockSize < codeSize) + { + fprintf(fout, ","); + } + } + + if (i < codeSize) + { + fprintf(fout, "\n "); + + for (; i < codeSize; ++i) + { + fprintf(fout, "%3d", p[i]); + if (i < codeSize - 1) + { + fprintf(fout, ", "); + } + } + } + + fprintf(fout, "\n};\n"); + + fclose(fout); + written = true; + } + + return written; +} + + +void DisplayInfo() +{ + fprintf(stdout, "FXC stub for remote shader compile server\n(C) 2012 Crytek. All rights reserved.\n\nVersion "CRYFXC_VER " for %d bit, linked against D3DCompiler_%d.dll\n\n", sizeof(void*) * 8, D3DX11_SDK_VERSION); + fprintf(stdout, "Syntax: fxc SwitchOptions Filename\n\n"); + fprintf(stdout, "Supported switches: "); + + bool firstSw = true; + for (size_t i = 0; i < sizeof(s_switchEntries) / sizeof(s_switchEntries[0]); ++i) + { + if (s_switchEntries[i].supported) + { + fprintf(stdout, "%s%s", firstSw ? "" : ", ", s_switchEntries[i].text); + firstSw = false; + } + } + + fprintf(stdout, "\n"); +} + + +int _tmain(int argc, _TCHAR* argv[]) +{ + if (argc == 1) + { + DisplayInfo(); + return 0; + } + + ParserResults parserRes; + if (!ParseCommandLine(argv, argc, parserRes)) + { + return 1; + } + + std::vector<char> program; + if (!ReadInFile(parserRes.pInFile, program)) + { + fprintf(stderr, "Failed to read input file: %s\n", parserRes.pInFile); + return 1; + } + + ID3D10Blob* pShader = 0; + ID3D10Blob* pErr = 0; + + bool successful = SUCCEEDED(D3DCompile(&program[0], program.size(), parserRes.pInFile, 0, 0, parserRes.pEntry, parserRes.pProfile, parserRes.compilerFlags, 0, &pShader, &pErr)) && pShader; + + if (successful) + { + const unsigned char* pCode = (unsigned char*) pShader->GetBufferPointer(); + const size_t codeSize = pShader->GetBufferSize(); + + if (!parserRes.disassemble) + { + successful = WriteByteCode(parserRes.pOutFile, pCode, codeSize); + if (!successful) + { + fprintf(stderr, "Failed to write output file: %s\n", parserRes.pOutFile); + } + } + else + { + ID3D10Blob* pDisassembled = 0; + successful = SUCCEEDED(D3DDisassemble(pCode, codeSize, 0, 0, &pDisassembled)) && pDisassembled; + + if (successful) + { + const char* pDisassembly = (char*) pDisassembled->GetBufferPointer(); + const char* pHdrVarName = parserRes.pHeaderVariableName ? parserRes.pHeaderVariableName : parserRes.pEntry; + successful = WriteHexListing(parserRes.pOutFile, pHdrVarName, pDisassembly, pCode, codeSize); + if (!successful) + { + fprintf(stderr, "Failed to write output file: %s\n", parserRes.pOutFile); + } + } + else + { + fprintf(stderr, "Failed to disassemble shader code\n", parserRes.pOutFile); + } + + if (pDisassembled) + { + pDisassembled->Release(); + pDisassembled = 0; + } + } + } + else + { + if (pErr) + { + const char* pMsg = (const char*) pErr->GetBufferPointer(); + fprintf(stderr, "%s\n", pMsg); + } + } + + if (pShader) + { + pShader->Release(); + pShader = 0; + } + + if (pErr) + { + pErr->Release(); + pErr = 0; + } + + return successful ? 0 : 1; +} diff --git a/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj b/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj new file mode 100644 index 0000000000..ab57f4c7f6 --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc/cryfxc.vcxproj @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{A505D345-D712-4C80-8BDE-6FBC08A390D8}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>cryfxc</RootNamespace> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>true</UseDebugLibraries> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>Application</ConfigurationType> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <CharacterSet>MultiByte</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <WarningLevel>Level3</WarningLevel> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>Use</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <WarningLevel>Level3</WarningLevel> + <PrecompiledHeader>Use</PrecompiledHeader> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + </ClCompile> + <Link> + <SubSystem>Console</SubSystem> + <GenerateDebugInformation>true</GenerateDebugInformation> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="StdAfx.h" /> + <ClInclude Include="targetver.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="cryfxc.cpp" /> + <ClCompile Include="StdAfx.cpp"> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> + <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> + </ClCompile> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project> \ No newline at end of file diff --git a/Code/Tools/CryFXC/cryfxc/stdafx.cpp b/Code/Tools/CryFXC/cryfxc/stdafx.cpp new file mode 100644 index 0000000000..209929990b --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc/stdafx.cpp @@ -0,0 +1,14 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#include "stdafx.h" diff --git a/Code/Tools/CryFXC/cryfxc/stdafx.h b/Code/Tools/CryFXC/cryfxc/stdafx.h new file mode 100644 index 0000000000..698d14574b --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc/stdafx.h @@ -0,0 +1,29 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include <stdio.h> +#include <tchar.h> +#include <string.h> +#include <assert.h> + +#include <vector> + +#include <D3DX11.h> +#include <D3Dcompiler.h> diff --git a/Code/Tools/CryFXC/cryfxc/targetver.h b/Code/Tools/CryFXC/cryfxc/targetver.h new file mode 100644 index 0000000000..d139ba1901 --- /dev/null +++ b/Code/Tools/CryFXC/cryfxc/targetver.h @@ -0,0 +1,16 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +// Original file Copyright Crytek GMBH or its affiliates, used under license. + +#pragma once + +#include <SDKDDKVer.h> diff --git a/Code/Tools/HLSLCrossCompiler/CMakeLists.txt b/Code/Tools/HLSLCrossCompiler/CMakeLists.txt new file mode 100644 index 0000000000..3b60e715a8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +ly_add_target( + NAME HLSLcc.Headers HEADERONLY + NAMESPACE AZ + FILES_CMAKE + hlslcc_header_files.cmake + INCLUDE_DIRECTORIES + INTERFACE + include +) + +if (NOT PAL_TRAIT_BUILD_HOST_TOOLS) + return() +endif() + +ly_add_target( + NAME HLSLcc EXECUTABLE + NAMESPACE AZ + OUTPUT_SUBDIRECTORY Compiler/PCGL/V006 + FILES_CMAKE + hlslcc_files.cmake + PLATFORM_INCLUDE_FILES + Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake + INCLUDE_DIRECTORIES + PRIVATE + src + src/cbstring + offline/cjson + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + PUBLIC + AZ::HLSLcc.Headers +) +ly_add_source_properties( + SOURCES + offline/compilerStandalone.cpp + offline/cjson/cJSON.c + src/toGLSL.c + src/toGLSLDeclaration.c + src/cbstring/bstrlib.c + src/cbstring/bstraux.c + src/reflect.c + src/amazon_changes.c + PROPERTY COMPILE_DEFINITIONS + VALUES _CRT_SECURE_NO_WARNINGS +) diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake new file mode 100644 index 0000000000..4d5680a30d --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/Platform/Linux/platform_linux.cmake @@ -0,0 +1,10 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake new file mode 100644 index 0000000000..f5b9ea77a2 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/Platform/Mac/platform_mac.cmake @@ -0,0 +1,11 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + diff --git a/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake b/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake new file mode 100644 index 0000000000..926c831fb9 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/Platform/Windows/platform_windows.cmake @@ -0,0 +1,18 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +file(TO_CMAKE_PATH "$ENV{ProgramFiles\(x86\)}" program_files_path) + +ly_add_target_files( + TARGETS HLSLcc + FILES + "${program_files_path}/Windows Kits/10/bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64/d3dcompiler_47.dll" +) diff --git a/Code/Tools/HLSLCrossCompiler/README b/Code/Tools/HLSLCrossCompiler/README new file mode 100644 index 0000000000..4369f1a3b2 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/README @@ -0,0 +1,71 @@ +Overview: + This is a modified version of https://github.com/James-Jones/HLSLCrossCompiler + + It can be used either: + 1. As an executable. + This is the default use case for release builds + This is run by the RemoteShaderCompiler when compiling the shaders for the GL4 and GLES3 platforms. + 2. As a static library. + This is used by the DXGL translation layer if compiled with DXGL_USE_GLSL set to 0. + In this case DXGL translation layer to translate DirectX shader model 5 bytecode coming from the renderer front end (runtime translation). + +Editing: + When modifying the source code, in order to use the updated version in the engine, you will have to recompile the library. + To do this, please follow these steps: + + A. Edit /Code/Tools/HLSLCrossCompiler/bin/mk/rsc_version.txt and bump the version string. + Please use the format for released branches and main: + V[3_decimal_digits_version_number] + and optionally for development branches: + V[3_decimal_digits_version_number]_[custom_version_label] + + B. From a Windows machine: + Verify that the following folders and the contained files are writeable (checkout if needed): + - /Code/Tools/HLSLCrossCompiler/bin + - /Code/Tools/HLSLCrossCompiler/lib + - /Tools/RemoteShaderCompiler/Compiler/PCGL + Run: + /Code/Tools/HLSLCrossCompiler/mk/build_win_all.py + Note: + This will compile: + - The static library (2) for win32 and win64 in release + - The executable (1) with the PORTABLE define enabled (required to run from machines without Direct3D runtime, such ass the RSC servers) + for win64 release in and place it in /Tools/RemoteShaderCompiler/Compiler/PCGL/[rsc_version]/ + + C. From a Linux machine: + Verify that the following folder and the contained files are writeable (checkout if needed): + - /Code/Tools/HLSLCrossCompiler/lib + Run: + /Code/Tools/HLSLCrossCompiler/mk/build_linux_all.py + Note: + This will compile: + - The static library (2) for linux (64 bit) in release + - The static library (2) for android (android-armeabi-v7a) in release + + D. Edit: + /Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp + and update the two command lines in CShaderMan::mfGetShaderCompileFlags: + const char* pCompilerGL4="PCGL/[rsc_version]/HLSLcc.exe [generic_gl4_flags ...]"; + const char* pCompilerGLES3="PCGL/[rsc_version]/HLSLcc.exe [generic_gles3_flags ...]"; + with the rsc_version string chosen. + + E. Edit: + /Code/CryEngine/RenderDll/Common/Shaders/Shader.h + and bump by one minor decimal unit: + #define FX_CACHE_VER [major_decimal_digit_0].[minor_decimal_digit_0] + Note: + This is required to flush cached shaders generated with the previous versions that might be stored + in ShaderCache.pak or in a user cache folder. + +Submitting: + Before submitting any change to HLSLCrossCompiler source code, please + make sure to do so together with the updated: + /Code/Tools/HLSLCrossCompiler/bin/mk/rsc_version.txt + /Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib + /Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib + /Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a + /Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a + /Code/CryEngine/RenderDll/Common/Shaders/ShaderCache.cpp + /Code/CryEngine/RenderDll/Common/Shaders/Shader.h + /Tools/RemoteShaderCompiler/Compiler/PCGL/[rsc_version]/HLSLcc.exe + This will make sure there is no mismatch between any cached shaders, and remotely or locally compiled shaders. \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake b/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake new file mode 100644 index 0000000000..f19b52084a --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/hlslcc_files.cmake @@ -0,0 +1,60 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + offline/hash.h + offline/serializeReflection.h + offline/timer.h + offline/compilerStandalone.cpp + offline/serializeReflection.cpp + offline/timer.cpp + offline/cjson/cJSON.h + offline/cjson/cJSON.c + src/amazon_changes.c + src/decode.c + src/decodeDX9.c + src/reflect.c + src/toGLSL.c + src/toGLSLDeclaration.c + src/toGLSLInstruction.c + src/toGLSLOperand.c + src/hlslccToolkit.c + src/internal_includes/debug.h + src/internal_includes/decode.h + src/internal_includes/hlslcc_malloc.h + src/internal_includes/hlslcc_malloc.c + src/internal_includes/languages.h + src/internal_includes/reflect.h + src/internal_includes/shaderLimits.h + src/internal_includes/structs.h + src/internal_includes/toGLSLDeclaration.h + src/internal_includes/toGLSLInstruction.h + src/internal_includes/toGLSLOperand.h + src/internal_includes/tokens.h + src/internal_includes/tokensDX9.h + src/internal_includes/hlslccToolkit.h + src/cbstring/bsafe.h + src/cbstring/bstraux.h + src/cbstring/bstrlib.h + src/cbstring/bsafe.c + src/cbstring/bstraux.c + src/cbstring/bstrlib.c + include/amazon_changes.h + include/hlslcc.h + include/hlslcc.hpp + include/hlslcc_bin.hpp + include/pstdint.h +) + +set(SKIP_UNITY_BUILD_INCLUSION_FILES + # 'bsafe.c' tries to forward declar 'strncpy', 'strncat', etc, but they are already declared in other modules. Remove from unity builds conideration + src/cbstring/bsafe.c +) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake b/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake new file mode 100644 index 0000000000..f242cc95e6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/hlslcc_header_files.cmake @@ -0,0 +1,18 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES hlslcc_files.cmake + include/amazon_changes.h + include/hlslcc.h + include/hlslcc.hpp + include/pstdint.h + include/hlslcc_bin.hpp +) diff --git a/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h b/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h new file mode 100644 index 0000000000..bbc2b22625 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/include/amazon_changes.h @@ -0,0 +1,13 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef AMAZON_CHANGES_H +#define AMAZON_CHANGES_H + +// There is a bug on the Adreno 420 driver where reinterpret casts can destroy a variable. We need to replace all instances that look like this: +// floatBitsToInt(Temp2); +// We do not need to change cases that evaluate an expression within the cast operation, like so: +// floatBitsToInt(Temp2 + 1.0f); +void ModifyLineForQualcommReinterpretCastBug( HLSLCrossCompilerContext* psContext, bstring* originalString, bstring* overloadString ); + +#endif // AMAZON_CHANGES_H diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc.h b/Code/Tools/HLSLCrossCompiler/include/hlslcc.h new file mode 100644 index 0000000000..efa43d8f4f --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/include/hlslcc.h @@ -0,0 +1,580 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HLSLCC_H_ +#define HLSLCC_H_ + +#if defined (_WIN32) && defined(HLSLCC_DYNLIB) + #define HLSLCC_APIENTRY __stdcall + #if defined(libHLSLcc_EXPORTS) + #define HLSLCC_API __declspec(dllexport) + #else + #define HLSLCC_API __declspec(dllimport) + #endif +#else + #define HLSLCC_APIENTRY + #define HLSLCC_API +#endif + +#include <stdint.h> +#include <stddef.h> + +typedef enum +{ + LANG_DEFAULT,// Depends on the HLSL shader model. + LANG_ES_100, + LANG_ES_300, + LANG_ES_310, + LANG_120, + LANG_130, + LANG_140, + LANG_150, + LANG_330, + LANG_400, + LANG_410, + LANG_420, + LANG_430, + LANG_440, +} GLLang; + +typedef struct { + uint32_t ARB_explicit_attrib_location : 1; + uint32_t ARB_explicit_uniform_location : 1; + uint32_t ARB_shading_language_420pack : 1; +}GlExtensions; + +enum {MAX_SHADER_VEC4_OUTPUT = 512}; +enum {MAX_SHADER_VEC4_INPUT = 512}; +enum {MAX_TEXTURES = 128}; +enum {MAX_FORK_PHASES = 2}; +enum {MAX_FUNCTION_BODIES = 1024}; +enum {MAX_CLASS_TYPES = 1024}; +enum {MAX_FUNCTION_POINTERS = 128}; + +//Reflection +#define MAX_REFLECT_STRING_LENGTH 512 +#define MAX_SHADER_VARS 256 +#define MAX_CBUFFERS 256 +#define MAX_UAV 256 +#define MAX_FUNCTION_TABLES 256 +#define MAX_RESOURCE_BINDINGS 256 + +//Operands flags +#define TO_FLAG_NONE 0x0 +#define TO_FLAG_INTEGER 0x1 +#define TO_FLAG_NAME_ONLY 0x2 +#define TO_FLAG_DECLARATION_NAME 0x4 +#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. +#define TO_FLAG_UNSIGNED_INTEGER 0x10 +#define TO_FLAG_DOUBLE 0x20 +#define TO_FLAG_FLOAT 0x40 +#define TO_FLAG_COPY 0x80 + +typedef enum SPECIAL_NAME +{ + NAME_UNDEFINED = 0, + NAME_POSITION = 1, + NAME_CLIP_DISTANCE = 2, + NAME_CULL_DISTANCE = 3, + NAME_RENDER_TARGET_ARRAY_INDEX = 4, + NAME_VIEWPORT_ARRAY_INDEX = 5, + NAME_VERTEX_ID = 6, + NAME_PRIMITIVE_ID = 7, + NAME_INSTANCE_ID = 8, + NAME_IS_FRONT_FACE = 9, + NAME_SAMPLE_INDEX = 10, + // The following are added for D3D11 + NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11, + NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12, + NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13, + NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14, + NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15, + NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16, + NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17, + NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18, + NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19, + NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20, + NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21, + NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22, +} SPECIAL_NAME; + + +typedef enum { + INOUT_COMPONENT_UNKNOWN = 0, + INOUT_COMPONENT_UINT32 = 1, + INOUT_COMPONENT_SINT32 = 2, + INOUT_COMPONENT_FLOAT32 = 3 +} INOUT_COMPONENT_TYPE; + +typedef enum MIN_PRECISION { + MIN_PRECISION_DEFAULT = 0, + MIN_PRECISION_FLOAT_16 = 1, + MIN_PRECISION_FLOAT_2_8 = 2, + MIN_PRECISION_RESERVED = 3, + MIN_PRECISION_SINT_16 = 4, + MIN_PRECISION_UINT_16 = 5, + MIN_PRECISION_ANY_16 = 0xf0, + MIN_PRECISION_ANY_10 = 0xf1 +} MIN_PRECISION; + +typedef struct InOutSignature_TAG +{ + char SemanticName[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32SemanticIndex; + SPECIAL_NAME eSystemValueType; + INOUT_COMPONENT_TYPE eComponentType; + uint32_t ui32Register; + uint32_t ui32Mask; + uint32_t ui32ReadWriteMask; + + uint32_t ui32Stream; + MIN_PRECISION eMinPrec; + +} InOutSignature; + +typedef enum ResourceType_TAG +{ + RTYPE_CBUFFER,//0 + RTYPE_TBUFFER,//1 + RTYPE_TEXTURE,//2 + RTYPE_SAMPLER,//3 + RTYPE_UAV_RWTYPED,//4 + RTYPE_STRUCTURED,//5 + RTYPE_UAV_RWSTRUCTURED,//6 + RTYPE_BYTEADDRESS,//7 + RTYPE_UAV_RWBYTEADDRESS,//8 + RTYPE_UAV_APPEND_STRUCTURED,//9 + RTYPE_UAV_CONSUME_STRUCTURED,//10 + RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11 + RTYPE_COUNT, +} ResourceType; + +typedef enum ResourceGroup_TAG { + RGROUP_CBUFFER, + RGROUP_TEXTURE, + RGROUP_SAMPLER, + RGROUP_UAV, + RGROUP_COUNT, +} ResourceGroup; + +typedef enum REFLECT_RESOURCE_DIMENSION +{ + REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0, + REFLECT_RESOURCE_DIMENSION_BUFFER = 1, + REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2, + REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3, + REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7, + REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8, + REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9, + REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, + REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, +} REFLECT_RESOURCE_DIMENSION; + +typedef struct ResourceBinding_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + ResourceType eType; + uint32_t ui32BindPoint; + uint32_t ui32BindCount; + uint32_t ui32Flags; + REFLECT_RESOURCE_DIMENSION eDimension; + uint32_t ui32ReturnType; + uint32_t ui32NumSamples; +} ResourceBinding; + +// Do not change the value of these enums or they will not match what we find in the DXBC file +typedef enum _SHADER_VARIABLE_TYPE { + SVT_VOID = 0, + SVT_BOOL = 1, + SVT_INT = 2, + SVT_FLOAT = 3, + SVT_STRING = 4, + SVT_TEXTURE = 5, + SVT_TEXTURE1D = 6, + SVT_TEXTURE2D = 7, + SVT_TEXTURE3D = 8, + SVT_TEXTURECUBE = 9, + SVT_SAMPLER = 10, + SVT_PIXELSHADER = 15, + SVT_VERTEXSHADER = 16, + SVT_UINT = 19, + SVT_UINT8 = 20, + SVT_GEOMETRYSHADER = 21, + SVT_RASTERIZER = 22, + SVT_DEPTHSTENCIL = 23, + SVT_BLEND = 24, + SVT_BUFFER = 25, + SVT_CBUFFER = 26, + SVT_TBUFFER = 27, + SVT_TEXTURE1DARRAY = 28, + SVT_TEXTURE2DARRAY = 29, + SVT_RENDERTARGETVIEW = 30, + SVT_DEPTHSTENCILVIEW = 31, + SVT_TEXTURE2DMS = 32, + SVT_TEXTURE2DMSARRAY = 33, + SVT_TEXTURECUBEARRAY = 34, + SVT_HULLSHADER = 35, + SVT_DOMAINSHADER = 36, + SVT_INTERFACE_POINTER = 37, + SVT_COMPUTESHADER = 38, + SVT_DOUBLE = 39, + SVT_RWTEXTURE1D = 40, + SVT_RWTEXTURE1DARRAY = 41, + SVT_RWTEXTURE2D = 42, + SVT_RWTEXTURE2DARRAY = 43, + SVT_RWTEXTURE3D = 44, + SVT_RWBUFFER = 45, + SVT_BYTEADDRESS_BUFFER = 46, + SVT_RWBYTEADDRESS_BUFFER = 47, + SVT_STRUCTURED_BUFFER = 48, + SVT_RWSTRUCTURED_BUFFER = 49, + SVT_APPEND_STRUCTURED_BUFFER = 50, + SVT_CONSUME_STRUCTURED_BUFFER = 51, + + // Partial precision types + SVT_FLOAT10 = 53, + SVT_FLOAT16 = 54, + SVT_INT16 = 156, + SVT_INT12 = 157, + SVT_UINT16 = 158, + + SVT_FORCE_DWORD = 0x7fffffff +} SHADER_VARIABLE_TYPE; + +typedef enum _SHADER_VARIABLE_CLASS { + SVC_SCALAR = 0, + SVC_VECTOR = ( SVC_SCALAR + 1 ), + SVC_MATRIX_ROWS = ( SVC_VECTOR + 1 ), + SVC_MATRIX_COLUMNS = ( SVC_MATRIX_ROWS + 1 ), + SVC_OBJECT = ( SVC_MATRIX_COLUMNS + 1 ), + SVC_STRUCT = ( SVC_OBJECT + 1 ), + SVC_INTERFACE_CLASS = ( SVC_STRUCT + 1 ), + SVC_INTERFACE_POINTER = ( SVC_INTERFACE_CLASS + 1 ), + SVC_FORCE_DWORD = 0x7fffffff +} SHADER_VARIABLE_CLASS; + +typedef struct ShaderVarType_TAG { + SHADER_VARIABLE_CLASS Class; + SHADER_VARIABLE_TYPE Type; + uint32_t Rows; + uint32_t Columns; + uint32_t Elements; + uint32_t MemberCount; + uint32_t Offset; + char Name[MAX_REFLECT_STRING_LENGTH]; + + uint32_t ParentCount; + struct ShaderVarType_TAG * Parent; + + struct ShaderVarType_TAG * Members; +} ShaderVarType; + +typedef struct ShaderVar_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + int haveDefaultValue; + uint32_t* pui32DefaultValues; + //Offset/Size in bytes. + uint32_t ui32StartOffset; + uint32_t ui32Size; + uint32_t ui32Flags; + + ShaderVarType sType; +} ShaderVar; + +typedef struct ConstantBuffer_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + + uint32_t ui32NumVars; + ShaderVar asVars[MAX_SHADER_VARS]; + + uint32_t ui32TotalSizeInBytes; + int blob; +} ConstantBuffer; + +typedef struct ClassType_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + uint16_t ui16ID; + uint16_t ui16ConstBufStride; + uint16_t ui16Texture; + uint16_t ui16Sampler; +} ClassType; + +typedef struct ClassInstance_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + uint16_t ui16ID; + uint16_t ui16ConstBuf; + uint16_t ui16ConstBufOffset; + uint16_t ui16Texture; + uint16_t ui16Sampler; +} ClassInstance; + +typedef enum TESSELLATOR_PARTITIONING +{ + TESSELLATOR_PARTITIONING_UNDEFINED = 0, + TESSELLATOR_PARTITIONING_INTEGER = 1, + TESSELLATOR_PARTITIONING_POW2 = 2, + TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3, + TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4 +} TESSELLATOR_PARTITIONING; + +typedef enum TESSELLATOR_OUTPUT_PRIMITIVE +{ + TESSELLATOR_OUTPUT_UNDEFINED = 0, + TESSELLATOR_OUTPUT_POINT = 1, + TESSELLATOR_OUTPUT_LINE = 2, + TESSELLATOR_OUTPUT_TRIANGLE_CW = 3, + TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4 +} TESSELLATOR_OUTPUT_PRIMITIVE; + +typedef enum INTERPOLATION_MODE +{ + INTERPOLATION_UNDEFINED = 0, + INTERPOLATION_CONSTANT = 1, + INTERPOLATION_LINEAR = 2, + INTERPOLATION_LINEAR_CENTROID = 3, + INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, + INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, + INTERPOLATION_LINEAR_SAMPLE = 6, + INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, +} INTERPOLATION_MODE; + +typedef enum TRACE_VARIABLE_GROUP +{ + TRACE_VARIABLE_INPUT = 0, + TRACE_VARIABLE_TEMP = 1, + TRACE_VARIABLE_OUTPUT = 2 +} TRACE_VARIABLE_GROUP; + +typedef enum TRACE_VARIABLE_TYPE +{ + TRACE_VARIABLE_FLOAT = 0, + TRACE_VARIABLE_SINT = 1, + TRACE_VARIABLE_UINT = 2, + TRACE_VARIABLE_DOUBLE = 3, + TRACE_VARIABLE_UNKNOWN = 4 +} TRACE_VARIABLE_TYPE; + +typedef struct VariableTraceInfo_TAG +{ + TRACE_VARIABLE_GROUP eGroup; + TRACE_VARIABLE_TYPE eType; + uint8_t ui8Index; + uint8_t ui8Component; +} VariableTraceInfo; + +typedef struct StepTraceInfo_TAG +{ + uint32_t ui32NumVariables; + VariableTraceInfo* psVariables; +} StepTraceInfo; + +typedef enum SYMBOL_TYPE +{ + SYMBOL_TESSELLATOR_PARTITIONING = 0, + SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE = 1, + SYMBOL_INPUT_INTERPOLATION_MODE = 2, + SYMBOL_EMULATE_DEPTH_CLAMP = 3 +} SYMBOL_TYPE; + +typedef struct Symbol_TAG +{ + SYMBOL_TYPE eType; + uint32_t ui32ID; + uint32_t ui32Value; +} Symbol; + +typedef struct EmbeddedResourceName_TAG +{ + uint32_t ui20Offset : 20; + uint32_t ui12Size : 12; +} EmbeddedResourceName; + +typedef struct SamplerMask_TAG +{ + uint32_t ui10TextureBindPoint : 10; + uint32_t ui10SamplerBindPoint : 10; + uint32_t ui10TextureUnit : 10; + uint32_t bNormalSample : 1; + uint32_t bCompareSample : 1; +} SamplerMask; + +typedef struct Sampler_TAG +{ + SamplerMask sMask; + EmbeddedResourceName sNormalName; + EmbeddedResourceName sCompareName; +} Sampler; + +typedef struct Resource_TAG +{ + uint32_t ui32BindPoint; + ResourceGroup eGroup; + EmbeddedResourceName sName; +} Resource; + +typedef struct ShaderInfo_TAG +{ + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + + uint32_t ui32NumInputSignatures; + InOutSignature* psInputSignatures; + + uint32_t ui32NumOutputSignatures; + InOutSignature* psOutputSignatures; + + uint32_t ui32NumResourceBindings; + ResourceBinding* psResourceBindings; + + uint32_t ui32NumConstantBuffers; + ConstantBuffer* psConstantBuffers; + ConstantBuffer* psThisPointerConstBuffer; + + uint32_t ui32NumClassTypes; + ClassType* psClassTypes; + + uint32_t ui32NumClassInstances; + ClassInstance* psClassInstances; + + //Func table ID to class name ID. + uint32_t aui32TableIDToTypeID[MAX_FUNCTION_TABLES]; + + uint32_t aui32ResourceMap[RGROUP_COUNT][MAX_RESOURCE_BINDINGS]; + + // GLSL resources + Sampler asSamplers[MAX_RESOURCE_BINDINGS]; + Resource asImages[MAX_RESOURCE_BINDINGS]; + Resource asUniformBuffers[MAX_RESOURCE_BINDINGS]; + Resource asStorageBuffers[MAX_RESOURCE_BINDINGS]; + uint32_t ui32NumSamplers; + uint32_t ui32NumImages; + uint32_t ui32NumUniformBuffers; + uint32_t ui32NumStorageBuffers; + + // Trace info if tracing is enabled + uint32_t ui32NumTraceSteps; + StepTraceInfo* psTraceSteps; + + // Symbols imported + uint32_t ui32NumImports; + Symbol* psImports; + + // Symbols exported + uint32_t ui32NumExports; + Symbol* psExports; + + // Hash of the input shader for debugging purposes + uint32_t ui32InputHash; + + // Offset in the GLSL string where symbol definitions can be inserted + uint32_t ui32SymbolsOffset; + + TESSELLATOR_PARTITIONING eTessPartitioning; + TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; + + //Required if PixelInterpDependency is true + INTERPOLATION_MODE aePixelInputInterpolation[MAX_SHADER_VEC4_INPUT]; +} ShaderInfo; + +typedef struct +{ + int shaderType; //One of the GL enums. + char* sourceCode; + ShaderInfo reflection; + GLLang GLSLLanguage; +} GLSLShader; + +typedef enum _FRAMEBUFFER_FETCH_TYPE +{ + FBF_NONE = 0, + FBF_EXT_COLOR = 1 << 0, + FBF_ARM_COLOR = 1 << 1, + FBF_ARM_DEPTH = 1 << 2, + FBF_ARM_STENCIL = 1 << 3, + FBF_ANY = FBF_EXT_COLOR | FBF_ARM_COLOR | FBF_ARM_DEPTH | FBF_ARM_STENCIL +} FRAMEBUFFER_FETCH_TYPE; + +// NOTE: HLSLCC flags are specified by command line when executing this cross compiler. +// If these flags change, the command line switch '-flags=XXX' must change as well. +// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' + +/*HLSL constant buffers are treated as default-block unform arrays by default. This is done + to support versions of GLSL which lack ARB_uniform_buffer_object functionality. + Setting this flag causes each one to have its own uniform block. + Note: Currently the nth const buffer will be named UnformBufferN. This is likey to change to the original HLSL name in the future.*/ +static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT = 0x1; + +static const unsigned int HLSLCC_FLAG_ORIGIN_UPPER_LEFT = 0x2; + +static const unsigned int HLSLCC_FLAG_PIXEL_CENTER_INTEGER = 0x4; + +static const unsigned int HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO = 0x8; + +//GS enabled? +//Affects vertex shader (i.e. need to compile vertex shader again to use with/without GS). +//This flag is needed in order for the interfaces between stages to match when GS is in use. +//PS inputs VtxGeoOutput +//GS outputs VtxGeoOutput +//Vs outputs VtxOutput if GS enabled. VtxGeoOutput otherwise. +static const unsigned int HLSLCC_FLAG_GS_ENABLED = 0x10; + +static const unsigned int HLSLCC_FLAG_TESS_ENABLED = 0x20; + +//Either use this flag or glBindFragDataLocationIndexed. +//When set the first pixel shader output is the first input to blend +//equation, the others go to the second input. +static const unsigned int HLSLCC_FLAG_DUAL_SOURCE_BLENDING = 0x40; + +//If set, shader inputs and outputs are declared with their semantic name. +static const unsigned int HLSLCC_FLAG_INOUT_SEMANTIC_NAMES = 0x80; + +static const unsigned int HLSLCC_FLAG_INVERT_CLIP_SPACE_Y = 0x100; +static const unsigned int HLSLCC_FLAG_CONVERT_CLIP_SPACE_Z = 0x200; +static const unsigned int HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS = 0x400; +static const unsigned int HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING = 0x800; +static const unsigned int HLSLCC_FLAG_TRACING_INSTRUMENTATION = 0x1000; +static const unsigned int HLSLCC_FLAG_HASH_INPUT = 0x2000; +static const unsigned int HLSLCC_FLAG_ADD_DEBUG_HEADER = 0x4000; +static const unsigned int HLSLCC_FLAG_NO_VERSION_STRING = 0x8000; + +static const unsigned int HLSLCC_FLAG_AVOID_SHADER_LOAD_STORE_EXTENSION = 0x10000; + +// If set, HLSLcc will generate GLSL code which contains syntactic workarounds for +// driver bugs found in Qualcomm devices running OpenGL ES 3.0 +static const unsigned int HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND = 0x20000; + +// If set, HLSL DX9 lower precision qualifiers (e.g half) will be transformed to DX11 style (e.g min16float) +// before compiling. Necessary to preserve precision information. If not, FXC just silently transform +// everything to full precision (e.g float32). +static const unsigned int HLSLCC_FLAG_HALF_FLOAT_TRANSFORM = 0x40000; + +#ifdef __cplusplus +extern "C" { +#endif + +HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), + void* (*calloc_override)(size_t,size_t), + void (*free_override)(void *), + void* (*realloc_override)(void*,size_t)); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename, unsigned int flags, GLLang language, const GlExtensions *extensions, GLSLShader* result); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, size_t size, unsigned int flags, GLLang language, const GlExtensions *extensions, GLSLShader* result); + +HLSLCC_API const char* HLSLCC_APIENTRY GetVersionString(GLLang language); + +HLSLCC_API void HLSLCC_APIENTRY FreeGLSLShader(GLSLShader*); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp b/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp new file mode 100644 index 0000000000..193415f277 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/include/hlslcc.hpp @@ -0,0 +1,7 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +extern "C" { +#include "hlslcc.h" +} + diff --git a/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp b/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp new file mode 100644 index 0000000000..f2062e58ac --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/include/hlslcc_bin.hpp @@ -0,0 +1,419 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include <algorithm> + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 )) + +enum +{ + DXBC_BASE_ALIGNMENT = 4, + FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C'), + FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F'), + FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N'), + FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N'), + FOURCC_PCSG = FOURCC('P', 'C', 'S', 'G'), + FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R'), + FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X'), + FOURCC_GLSL = FOURCC('G', 'L', 'S', 'L'), + FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1'), // When lower precision float/int/uint is used + FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1'), // When lower precision float/int/uint is used +}; + +#undef FOURCC + +template <typename T> +inline T DXBCSwapBytes(const T& kValue) +{ + return kValue; +} + +#if defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN + +inline uint16_t DXBCSwapBytes(const uint16_t& uValue) +{ + return + (((uValue) >> 8) & 0xFF) | + (((uValue) << 8) & 0xFF); +} + +inline uint32_t DXBCSwapBytes(const uint32_t& uValue) +{ + return + (((uValue) >> 24) & 0x000000FF) | + (((uValue) >> 8) & 0x0000FF00) | + (((uValue) << 8) & 0x00FF0000) | + (((uValue) << 24) & 0xFF000000); +} + +#endif //defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN + +template <typename Element> +struct SDXBCBufferBase +{ + Element* m_pBegin; + Element* m_pEnd; + Element* m_pIter; + + SDXBCBufferBase(Element* pBegin, Element* pEnd) + : m_pBegin(pBegin) + , m_pEnd(pEnd) + , m_pIter(pBegin) + { + } + + bool SeekRel(int32_t iOffset) + { + Element* pIterAfter(m_pIter + iOffset); + if (pIterAfter > m_pEnd) + return false; + + m_pIter = pIterAfter; + return true; + } + + bool SeekAbs(uint32_t uPosition) + { + Element* pIterAfter(m_pBegin + uPosition); + if (pIterAfter > m_pEnd) + return false; + + m_pIter = pIterAfter; + return true; + } +}; + +struct SDXBCInputBuffer : SDXBCBufferBase<const uint8_t> +{ + SDXBCInputBuffer(const uint8_t* pBegin, const uint8_t* pEnd) + : SDXBCBufferBase(pBegin, pEnd) + { + } + + bool Read(void* pElements, size_t uSize) + { + const uint8_t* pIterAfter(m_pIter + uSize); + if (pIterAfter > m_pEnd) + return false; + + memcpy(pElements, m_pIter, uSize); + + m_pIter = pIterAfter; + return true; + } +}; + +struct SDXBCOutputBuffer : SDXBCBufferBase<uint8_t> +{ + SDXBCOutputBuffer(uint8_t* pBegin, uint8_t* pEnd) + : SDXBCBufferBase(pBegin, pEnd) + { + } + + bool Write(const void* pElements, size_t uSize) + { + uint8_t* pIterAfter(m_pIter + uSize); + if (pIterAfter > m_pEnd) + return false; + + memcpy(m_pIter, pElements, uSize); + + m_pIter = pIterAfter; + return true; + } +}; + +template <typename S, typename External, typename Internal> +inline bool DXBCReadAs(S& kStream, External& kValue) +{ + Internal kInternal; + bool bResult(kStream.Read(&kInternal, sizeof(Internal))); + kValue = static_cast<External>(DXBCSwapBytes(kInternal)); + return bResult; +} + +template <typename S, typename Internal> +inline bool DXBCWriteAs(S& kStream, Internal kValue) +{ + Internal kInternal(DXBCSwapBytes(kValue)); + return kStream.Write(&kInternal, sizeof(Internal)); +} + +template <typename S, typename T> bool DXBCReadUint8 (S& kStream, T& kValue) { return DXBCReadAs<S, T, uint8_t >(kStream, kValue); } +template <typename S, typename T> bool DXBCReadUint16(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint16_t>(kStream, kValue); } +template <typename S, typename T> bool DXBCReadUint32(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint32_t>(kStream, kValue); } + +template <typename S> bool DXBCWriteUint8 (S& kStream, uint8_t kValue) { return DXBCWriteAs<S, uint8_t >(kStream, kValue); } +template <typename S> bool DXBCWriteUint16(S& kStream, uint16_t kValue) { return DXBCWriteAs<S, uint16_t>(kStream, kValue); } +template <typename S> bool DXBCWriteUint32(S& kStream, uint32_t kValue) { return DXBCWriteAs<S, uint32_t>(kStream, kValue); } + +template <typename O, typename I> +bool DXBCCopy(O& kOutput, I& kInput, size_t uSize) +{ + char acBuffer[1024]; + while (uSize > 0) + { + size_t uToCopy(std::min<size_t>(uSize, sizeof(acBuffer))); + if (!kInput.Read(acBuffer, uToCopy) || + !kOutput.Write(acBuffer, uToCopy)) + return false; + uSize -= uToCopy; + } + return true; +} + +enum +{ + DXBC_SIZE_POSITION = 6 * 4, + DXBC_HEADER_SIZE = 7 * 4, + DXBC_CHUNK_HEADER_SIZE = 2 * 4, + DXBC_MAX_NUM_CHUNKS_IN = 128, + DXBC_MAX_NUM_CHUNKS_OUT = 8, + DXBC_OUT_CHUNKS_INDEX_SIZE = (1 + 1 + DXBC_MAX_NUM_CHUNKS_OUT) * 4, + DXBC_OUT_FIXED_SIZE = DXBC_HEADER_SIZE + DXBC_OUT_CHUNKS_INDEX_SIZE, +}; + +enum +{ + GLSL_HEADER_SIZE = 4 * 8, // uNumSamplers, uNumImages, uNumStorageBuffers, uNumUniformBuffers, uNumImports, uNumExports, uInputHash, uSymbolsOffset + GLSL_SAMPLER_SIZE = 4 * 3, // uSamplerField, uEmbeddedNormalName, uEmbeddedCompareName + GLSL_RESOURCE_SIZE = 4 * 2, // uBindPoint, uName + GLSL_SYMBOL_SIZE = 4 * 3, // uType, uID, uValue +}; + +inline void DXBCSizeGLSLChunk(uint32_t& uGLSLChunkSize, uint32_t& uGLSLSourceSize, const GLSLShader* pShader) +{ + uint32_t uNumSymbols( + pShader->reflection.ui32NumImports + + pShader->reflection.ui32NumExports); + uint32_t uGLSLInfoSize( + DXBC_CHUNK_HEADER_SIZE + + GLSL_HEADER_SIZE + + pShader->reflection.ui32NumSamplers * GLSL_SAMPLER_SIZE + + pShader->reflection.ui32NumImages * GLSL_RESOURCE_SIZE + + pShader->reflection.ui32NumStorageBuffers * GLSL_RESOURCE_SIZE + + pShader->reflection.ui32NumUniformBuffers * GLSL_RESOURCE_SIZE + + uNumSymbols * GLSL_SYMBOL_SIZE); + uGLSLSourceSize = (uint32_t)strlen(pShader->sourceCode) + 1; + uGLSLChunkSize = uGLSLInfoSize + uGLSLSourceSize; + uGLSLChunkSize += DXBC_BASE_ALIGNMENT - 1 - (uGLSLChunkSize - 1) % DXBC_BASE_ALIGNMENT; +} + +inline uint32_t DXBCSizeOutputChunk(uint32_t uCode, uint32_t uSizeIn) +{ + uint32_t uSizeOut; + switch (uCode) + { + case FOURCC_RDEF: + case FOURCC_ISGN: + case FOURCC_OSGN: + case FOURCC_PCSG: + case FOURCC_OSG1: + case FOURCC_ISG1: + // Preserve entire chunk + uSizeOut = uSizeIn; + break; + case FOURCC_SHDR: + case FOURCC_SHEX: + // Only keep the shader version + uSizeOut = uSizeIn < 4u ? uSizeIn : 4u; + break; + default: + // Discard the chunk + uSizeOut = 0; + break; + } + + return uSizeOut + DXBC_BASE_ALIGNMENT - 1 - (uSizeOut - 1) % DXBC_BASE_ALIGNMENT; +} + +template <typename I> +size_t DXBCGetCombinedSize(I& kDXBCInput, const GLSLShader* pShader) +{ + uint32_t uNumChunksIn; + if (!kDXBCInput.SeekAbs(DXBC_HEADER_SIZE) || + !DXBCReadUint32(kDXBCInput, uNumChunksIn)) + return 0; + + uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + if (!DXBCReadUint32(kDXBCInput, auChunkOffsetsIn[uChunk])) + return 0; + } + + uint32_t uNumChunksOut(0); + uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); + for (uint32_t uChunk = 0; uChunk < uNumChunksIn && uNumChunksOut < DXBC_MAX_NUM_CHUNKS_OUT; ++uChunk) + { + uint32_t uChunkCode, uChunkSizeIn; + if (!kDXBCInput.SeekAbs(auChunkOffsetsIn[uChunk]) || + !DXBCReadUint32(kDXBCInput, uChunkCode) || + !DXBCReadUint32(kDXBCInput, uChunkSizeIn)) + return 0; + + uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); + if (uChunkSizeOut > 0) + { + uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; + } + } + + uint32_t uGLSLSourceSize, uGLSLChunkSize; + DXBCSizeGLSLChunk(uGLSLChunkSize, uGLSLSourceSize, pShader); + uOutSize += uGLSLChunkSize; + + return uOutSize; +} + +template <typename I, typename O> +bool DXBCCombineWithGLSL(I& kInput, O& kOutput, const GLSLShader* pShader) +{ + uint32_t uNumChunksIn; + if (!DXBCCopy(kOutput, kInput, DXBC_HEADER_SIZE) || + !DXBCReadUint32(kInput, uNumChunksIn) || + uNumChunksIn > DXBC_MAX_NUM_CHUNKS_IN) + return false; + + uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + if (!DXBCReadUint32(kInput, auChunkOffsetsIn[uChunk])) + return false; + } + + uint32_t auZeroChunkIndex[DXBC_OUT_CHUNKS_INDEX_SIZE] = {0}; + if (!kOutput.Write(auZeroChunkIndex, DXBC_OUT_CHUNKS_INDEX_SIZE)) + return false; + + // Copy required input chunks just after the chunk index + uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); + uint32_t uNumChunksOut(0); + uint32_t auChunkOffsetsOut[DXBC_MAX_NUM_CHUNKS_OUT]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + uint32_t uChunkCode, uChunkSizeIn; + if (!kInput.SeekAbs(auChunkOffsetsIn[uChunk]) || + !DXBCReadUint32(kInput, uChunkCode) || + !DXBCReadUint32(kInput, uChunkSizeIn)) + return false; + + // Filter only input chunks of the specified types + uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); + if (uChunkSizeOut > 0) + { + if (uNumChunksOut >= DXBC_MAX_NUM_CHUNKS_OUT) + return false; + + if (!DXBCWriteUint32(kOutput, uChunkCode) || + !DXBCWriteUint32(kOutput, uChunkSizeOut) || + !DXBCCopy(kOutput, kInput, uChunkSizeOut)) + return false; + + auChunkOffsetsOut[uNumChunksOut] = uOutSize; + ++uNumChunksOut; + uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; + } + } + + // Write GLSL chunk + uint32_t uGLSLChunkOffset(uOutSize); + uint32_t uGLSLChunkSize, uGLSLSourceSize; + DXBCSizeGLSLChunk(uGLSLChunkSize, uGLSLSourceSize, pShader); + if (!DXBCWriteUint32(kOutput, (uint32_t)FOURCC_GLSL) || + !DXBCWriteUint32(kOutput, uGLSLChunkSize) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumSamplers) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImages) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumStorageBuffers) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumUniformBuffers) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImports) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumExports) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32InputHash) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32SymbolsOffset)) + return false; + for (uint32_t uSampler = 0; uSampler < pShader->reflection.ui32NumSamplers; ++uSampler) + { + uint32_t uSamplerField = + (pShader->reflection.asSamplers[uSampler].sMask.ui10TextureBindPoint << 22) | + (pShader->reflection.asSamplers[uSampler].sMask.ui10SamplerBindPoint << 12) | + (pShader->reflection.asSamplers[uSampler].sMask.ui10TextureUnit << 2) | + (pShader->reflection.asSamplers[uSampler].sMask.bNormalSample << 1) | + (pShader->reflection.asSamplers[uSampler].sMask.bCompareSample << 0); + if (!DXBCWriteUint32(kOutput, uSamplerField)) + return false; + + uint32_t uEmbeddedNormalName = + (pShader->reflection.asSamplers[uSampler].sNormalName.ui20Offset << 12) | + (pShader->reflection.asSamplers[uSampler].sNormalName.ui12Size << 0); + if (!DXBCWriteUint32(kOutput, uEmbeddedNormalName)) + return false; + + uint32_t uEmbeddedCompareName = + (pShader->reflection.asSamplers[uSampler].sCompareName.ui20Offset << 12) | + (pShader->reflection.asSamplers[uSampler].sCompareName.ui12Size << 0); + if (!DXBCWriteUint32(kOutput, uEmbeddedCompareName)) + return false; + } + for (uint32_t uImage = 0; uImage < pShader->reflection.ui32NumImages; ++uImage) + { + const Resource* psResource = pShader->reflection.asImages + uImage; + uint32_t uEmbeddedName = + (psResource->sName.ui20Offset << 12) | + (psResource->sName.ui12Size << 0); + if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || + !DXBCWriteUint32(kOutput, uEmbeddedName)) + return false; + } + for (uint32_t uStorageBuffer = 0; uStorageBuffer < pShader->reflection.ui32NumStorageBuffers; ++uStorageBuffer) + { + const Resource* psResource = pShader->reflection.asStorageBuffers + uStorageBuffer; + uint32_t uEmbeddedName = + (psResource->sName.ui20Offset << 12) | + (psResource->sName.ui12Size << 0); + if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || + !DXBCWriteUint32(kOutput, uEmbeddedName)) + return false; + } + for (uint32_t uUniformBuffer = 0; uUniformBuffer < pShader->reflection.ui32NumUniformBuffers; ++uUniformBuffer) + { + const Resource* psResource = pShader->reflection.asUniformBuffers + uUniformBuffer; + uint32_t uEmbeddedName = + (psResource->sName.ui20Offset << 12) | + (psResource->sName.ui12Size << 0); + if (!DXBCWriteUint32(kOutput, psResource->ui32BindPoint) || + !DXBCWriteUint32(kOutput, uEmbeddedName)) + return false; + } + for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumImports; ++uSymbol) + { + if (!DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].eType) || + !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32ID) || + !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32Value)) + return false; + } + for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumExports; ++uSymbol) + { + if (!DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].eType) || + !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32ID) || + !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32Value)) + return false; + } + if (!kOutput.Write(pShader->sourceCode, uGLSLSourceSize)) + return false; + uOutSize += uGLSLChunkSize; + + // Write total size and chunk index + if (!kOutput.SeekAbs(DXBC_SIZE_POSITION) || + !DXBCWriteUint32(kOutput, uOutSize) || + !kOutput.SeekAbs(DXBC_HEADER_SIZE) || + !DXBCWriteUint32(kOutput, uNumChunksOut + 1)) + return false; + for (uint32_t uChunk = 0; uChunk < uNumChunksOut; ++uChunk) + { + if (!DXBCWriteUint32(kOutput, auChunkOffsetsOut[uChunk])) + return false; + } + DXBCWriteUint32(kOutput, uGLSLChunkOffset); + + return true; +} diff --git a/Code/Tools/HLSLCrossCompiler/include/pstdint.h b/Code/Tools/HLSLCrossCompiler/include/pstdint.h new file mode 100644 index 0000000000..6998242aa1 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/include/pstdint.h @@ -0,0 +1,801 @@ +/* A portable stdint.h + **************************************************************************** + * BSD License: + **************************************************************************** + * + * Copyright (c) 2005-2011 Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************** + * + * Version 0.1.12 + * + * The ANSI C standard committee, for the C99 standard, specified the + * inclusion of a new standard include file called stdint.h. This is + * a very useful and long desired include file which contains several + * very precise definitions for integer scalar types that is + * critically important for making portable several classes of + * applications including cryptography, hashing, variable length + * integer libraries and so on. But for most developers its likely + * useful just for programming sanity. + * + * The problem is that most compiler vendors have decided not to + * implement the C99 standard, and the next C++ language standard + * (which has a lot more mindshare these days) will be a long time in + * coming and its unknown whether or not it will include stdint.h or + * how much adoption it will have. Either way, it will be a long time + * before all compilers come with a stdint.h and it also does nothing + * for the extremely large number of compilers available today which + * do not include this file, or anything comparable to it. + * + * So that's what this file is all about. Its an attempt to build a + * single universal include file that works on as many platforms as + * possible to deliver what stdint.h is supposed to. A few things + * that should be noted about this file: + * + * 1) It is not guaranteed to be portable and/or present an identical + * interface on all platforms. The extreme variability of the + * ANSI C standard makes this an impossibility right from the + * very get go. Its really only meant to be useful for the vast + * majority of platforms that possess the capability of + * implementing usefully and precisely defined, standard sized + * integer scalars. Systems which are not intrinsically 2s + * complement may produce invalid constants. + * + * 2) There is an unavoidable use of non-reserved symbols. + * + * 3) Other standard include files are invoked. + * + * 4) This file may come in conflict with future platforms that do + * include stdint.h. The hope is that one or the other can be + * used with no real difference. + * + * 5) In the current verison, if your platform can't represent + * int32_t, int16_t and int8_t, it just dumps out with a compiler + * error. + * + * 6) 64 bit integers may or may not be defined. Test for their + * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. + * Note that this is different from the C99 specification which + * requires the existence of 64 bit support in the compiler. If + * this is not defined for your platform, yet it is capable of + * dealing with 64 bits then it is because this file has not yet + * been extended to cover all of your system's capabilities. + * + * 7) (u)intptr_t may or may not be defined. Test for its presence + * with the test: #ifdef PTRDIFF_MAX. If this is not defined + * for your platform, then it is because this file has not yet + * been extended to cover all of your system's capabilities, not + * because its optional. + * + * 8) The following might not been defined even if your platform is + * capable of defining it: + * + * WCHAR_MIN + * WCHAR_MAX + * (u)int64_t + * PTRDIFF_MIN + * PTRDIFF_MAX + * (u)intptr_t + * + * 9) The following have not been defined: + * + * WINT_MIN + * WINT_MAX + * + * 10) The criteria for defining (u)int_least(*)_t isn't clear, + * except for systems which don't have a type that precisely + * defined 8, 16, or 32 bit types (which this include file does + * not support anyways). Default definitions have been given. + * + * 11) The criteria for defining (u)int_fast(*)_t isn't something I + * would trust to any particular compiler vendor or the ANSI C + * committee. It is well known that "compatible systems" are + * commonly created that have very different performance + * characteristics from the systems they are compatible with, + * especially those whose vendors make both the compiler and the + * system. Default definitions have been given, but its strongly + * recommended that users never use these definitions for any + * reason (they do *NOT* deliver any serious guarantee of + * improved performance -- not in this file, nor any vendor's + * stdint.h). + * + * 12) The following macros: + * + * PRINTF_INTMAX_MODIFIER + * PRINTF_INT64_MODIFIER + * PRINTF_INT32_MODIFIER + * PRINTF_INT16_MODIFIER + * PRINTF_LEAST64_MODIFIER + * PRINTF_LEAST32_MODIFIER + * PRINTF_LEAST16_MODIFIER + * PRINTF_INTPTR_MODIFIER + * + * are strings which have been defined as the modifiers required + * for the "d", "u" and "x" printf formats to correctly output + * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, + * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. + * PRINTF_INTPTR_MODIFIER is not defined for some systems which + * provide their own stdint.h. PRINTF_INT64_MODIFIER is not + * defined if INT64_MAX is not defined. These are an extension + * beyond what C99 specifies must be in stdint.h. + * + * In addition, the following macros are defined: + * + * PRINTF_INTMAX_HEX_WIDTH + * PRINTF_INT64_HEX_WIDTH + * PRINTF_INT32_HEX_WIDTH + * PRINTF_INT16_HEX_WIDTH + * PRINTF_INT8_HEX_WIDTH + * PRINTF_INTMAX_DEC_WIDTH + * PRINTF_INT64_DEC_WIDTH + * PRINTF_INT32_DEC_WIDTH + * PRINTF_INT16_DEC_WIDTH + * PRINTF_INT8_DEC_WIDTH + * + * Which specifies the maximum number of characters required to + * print the number of that type in either hexadecimal or decimal. + * These are an extension beyond what C99 specifies must be in + * stdint.h. + * + * Compilers tested (all with 0 warnings at their highest respective + * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 + * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio + * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 + * + * This file should be considered a work in progress. Suggestions for + * improvements, especially those which increase coverage are strongly + * encouraged. + * + * Acknowledgements + * + * The following people have made significant contributions to the + * development and testing of this file: + * + * Chris Howie + * John Steele Scott + * Dave Thorup + * John Dill + * + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#include <stddef.h> +#include <limits.h> +#include <signal.h> + +/* + * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and + * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. + */ + +#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED) +#include <stdint.h> +#define _PSTDINT_H_INCLUDED +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +# endif +# ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif + +/* + * Something really weird is going on with Open Watcom. Just pull some of + * these duplicated definitions from Open Watcom's stdint.h file for now. + */ + +# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 +# if !defined (INT64_C) +# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) +# endif +# if !defined (UINT64_C) +# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) +# endif +# if !defined (INT32_C) +# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) +# endif +# if !defined (UINT32_C) +# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) +# endif +# if !defined (INT16_C) +# define INT16_C(x) (x) +# endif +# if !defined (UINT16_C) +# define UINT16_C(x) (x) +# endif +# if !defined (INT8_C) +# define INT8_C(x) (x) +# endif +# if !defined (UINT8_C) +# define UINT8_C(x) (x) +# endif +# if !defined (UINT64_MAX) +# define UINT64_MAX 18446744073709551615ULL +# endif +# if !defined (INT64_MAX) +# define INT64_MAX 9223372036854775807LL +# endif +# if !defined (UINT32_MAX) +# define UINT32_MAX 4294967295UL +# endif +# if !defined (INT32_MAX) +# define INT32_MAX 2147483647L +# endif +# if !defined (INTMAX_MAX) +# define INTMAX_MAX INT64_MAX +# endif +# if !defined (INTMAX_MIN) +# define INTMAX_MIN INT64_MIN +# endif +# endif +#endif + +#ifndef _PSTDINT_H_INCLUDED +#define _PSTDINT_H_INCLUDED + +#ifndef SIZE_MAX +# define SIZE_MAX (~(size_t)0) +#endif + +/* + * Deduce the type assignments from limits.h under the assumption that + * integer sizes in bits are powers of 2, and follow the ANSI + * definitions. + */ + +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif +#ifndef uint8_t +# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) + typedef unsigned char uint8_t; +# define UINT8_C(v) ((uint8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef INT8_MAX +# define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +# define INT8_MIN INT8_C(0x80) +#endif +#ifndef int8_t +# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) + typedef signed char int8_t; +# define INT8_C(v) ((int8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 0xffff +#endif +#ifndef uint16_t +#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) + typedef unsigned int uint16_t; +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +# define UINT16_C(v) ((uint16_t) (v)) +#elif (USHRT_MAX == UINT16_MAX) + typedef unsigned short uint16_t; +# define UINT16_C(v) ((uint16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +# define INT16_MIN INT16_C(0x8000) +#endif +#ifndef int16_t +#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) + typedef signed int int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +#elif (SHRT_MAX == INT16_MAX) + typedef signed short int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (0xffffffffUL) +#endif +#ifndef uint32_t +#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) + typedef unsigned long uint32_t; +# define UINT32_C(v) v ## UL +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (UINT_MAX == UINT32_MAX) + typedef unsigned int uint32_t; +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# define UINT32_C(v) v ## U +#elif (USHRT_MAX == UINT32_MAX) + typedef unsigned short uint32_t; +# define UINT32_C(v) ((unsigned short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT32_MAX +# define INT32_MAX (0x7fffffffL) +#endif +#ifndef INT32_MIN +# define INT32_MIN INT32_C(0x80000000) +#endif +#ifndef int32_t +#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) + typedef signed long int32_t; +# define INT32_C(v) v ## L +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (INT_MAX == INT32_MAX) + typedef signed int int32_t; +# define INT32_C(v) v +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#elif (SHRT_MAX == INT32_MAX) + typedef signed short int32_t; +# define INT32_C(v) ((short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +/* + * The macro stdint_int64_defined is temporarily used to record + * whether or not 64 integer support is available. It must be + * defined for any 64 integer extensions for new platforms that are + * added. + */ + +#undef stdint_int64_defined +#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) +# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# endif +#endif + +#if !defined (stdint_int64_defined) +# if defined(__GNUC__) +# define stdint_int64_defined + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) +# define stdint_int64_defined + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# define UINT64_C(v) v ## UI64 +# define INT64_C(v) v ## I64 +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "I64" +# endif +# endif +#endif + +#if !defined (LONG_LONG_MAX) && defined (INT64_C) +# define LONG_LONG_MAX INT64_C (9223372036854775807) +#endif +#ifndef ULONG_LONG_MAX +# define ULONG_LONG_MAX UINT64_C (18446744073709551615) +#endif + +#if !defined (INT64_MAX) && defined (INT64_C) +# define INT64_MAX INT64_C (9223372036854775807) +#endif +#if !defined (INT64_MIN) && defined (INT64_C) +# define INT64_MIN INT64_C (-9223372036854775808) +#endif +#if !defined (UINT64_MAX) && defined (INT64_C) +# define UINT64_MAX UINT64_C (18446744073709551615) +#endif + +/* + * Width of hexadecimal for number field. + */ + +#ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +#endif +#ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +#endif +#ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +#endif +#ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +#endif + +#ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +#endif +#ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +#endif + +/* + * Ok, lets not worry about 128 bit integers for now. Moore's law says + * we don't need to worry about that until about 2040 at which point + * we'll have bigger things to worry about. + */ + +#ifdef stdint_int64_defined + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define INTMAX_MAX INT64_MAX +# define INTMAX_MIN INT64_MIN +# define UINTMAX_MAX UINT64_MAX +# define UINTMAX_C(v) UINT64_C(v) +# define INTMAX_C(v) INT64_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif +#else + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# define INTMAX_MAX INT32_MAX +# define UINTMAX_MAX UINT32_MAX +# define UINTMAX_C(v) UINT32_C(v) +# define INTMAX_C(v) INT32_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH +# endif +#endif + +/* + * Because this file currently only supports platforms which have + * precise powers of 2 as bit sizes for the default integers, the + * least definitions are all trivial. Its possible that a future + * version of this file could have different definitions. + */ + +#ifndef stdint_least_defined + typedef int8_t int_least8_t; + typedef uint8_t uint_least8_t; + typedef int16_t int_least16_t; + typedef uint16_t uint_least16_t; + typedef int32_t int_least32_t; + typedef uint32_t uint_least32_t; +# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER +# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER +# define UINT_LEAST8_MAX UINT8_MAX +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# ifdef stdint_int64_defined + typedef int64_t int_least64_t; + typedef uint64_t uint_least64_t; +# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER +# define UINT_LEAST64_MAX UINT64_MAX +# define INT_LEAST64_MAX INT64_MAX +# define INT_LEAST64_MIN INT64_MIN +# endif +#endif +#undef stdint_least_defined + +/* + * The ANSI C committee pretending to know or specify anything about + * performance is the epitome of misguided arrogance. The mandate of + * this file is to *ONLY* ever support that absolute minimum + * definition of the fast integer types, for compatibility purposes. + * No extensions, and no attempt to suggest what may or may not be a + * faster integer type will ever be made in this file. Developers are + * warned to stay away from these types when using this or any other + * stdint.h. + */ + +typedef int_least8_t int_fast8_t; +typedef uint_least8_t uint_fast8_t; +typedef int_least16_t int_fast16_t; +typedef uint_least16_t uint_fast16_t; +typedef int_least32_t int_fast32_t; +typedef uint_least32_t uint_fast32_t; +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#define INT_FAST32_MAX INT_LEAST32_MAX +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST32_MIN INT_LEAST32_MIN +#ifdef stdint_int64_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +# define UINT_FAST64_MAX UINT_LEAST64_MAX +# define INT_FAST64_MAX INT_LEAST64_MAX +# define INT_FAST64_MIN INT_LEAST64_MIN +#endif + +#undef stdint_int64_defined + +/* + * Whatever piecemeal, per compiler thing we can do about the wchar_t + * type limits. + */ + +#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) +# include <wchar.h> +# ifndef WCHAR_MIN +# define WCHAR_MIN 0 +# endif +# ifndef WCHAR_MAX +# define WCHAR_MAX ((wchar_t)-1) +# endif +#endif + +/* + * Whatever piecemeal, per compiler/platform thing we can do about the + * (u)intptr_t types and limits. + */ + +#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +#ifndef STDINT_H_UINTPTR_T_DEFINED +# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) +# define stdint_intptr_bits 64 +# elif defined (__WATCOMC__) || defined (__TURBOC__) +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define stdint_intptr_bits 16 +# else +# define stdint_intptr_bits 32 +# endif +# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) +# define stdint_intptr_bits 32 +# elif defined (__INTEL_COMPILER) +/* TODO -- what did Intel do about x86-64? */ +# endif + +# ifdef stdint_intptr_bits +# define stdint_intptr_glue3_i(a,b,c) a##b##c +# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) +# ifndef PRINTF_INTPTR_MODIFIER +# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) +# endif +# ifndef PTRDIFF_MAX +# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef PTRDIFF_MIN +# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef UINTPTR_MAX +# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MAX +# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MIN +# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef INTPTR_C +# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) +# endif +# ifndef UINTPTR_C +# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) +# endif + typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; + typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; +# else +/* TODO -- This following is likely wrong for some platforms, and does + nothing for the definition of uintptr_t. */ + typedef ptrdiff_t intptr_t; +# endif +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +/* + * Assumes sig_atomic_t is signed and we have a 2s complement machine. + */ + +#ifndef SIG_ATOMIC_MAX +# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) +#endif + +#endif + +#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) + +/* + * Please compile with the maximum warning settings to make sure macros are not + * defined more than once. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define glue3_aux(x,y,z) x ## y ## z +#define glue3(x,y,z) glue3_aux(x,y,z) + +#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); +#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); + +#define DECL(us,bits) glue3(DECL,us,) (bits) + +#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) + +int main () { + DECL(I,8) + DECL(U,8) + DECL(I,16) + DECL(U,16) + DECL(I,32) + DECL(U,32) +#ifdef INT64_MAX + DECL(I,64) + DECL(U,64) +#endif + intmax_t imax = INTMAX_C(0); + uintmax_t umax = UINTMAX_C(0); + char str0[256], str1[256]; + + sprintf (str0, "%d %x\n", 0, ~0); + + sprintf (str1, "%d %x\n", i8, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); + sprintf (str1, "%u %x\n", u8, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); + sprintf (str1, "%d %x\n", i16, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); + sprintf (str1, "%u %x\n", u16, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); +#ifdef INT64_MAX + sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); +#endif + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); + + TESTUMAX(8); + TESTUMAX(16); + TESTUMAX(32); +#ifdef INT64_MAX + TESTUMAX(64); +#endif + + return EXIT_SUCCESS; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/jni/Android.mk b/Code/Tools/HLSLCrossCompiler/jni/Android.mk new file mode 100644 index 0000000000..66e2bb4ecf --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/jni/Android.mk @@ -0,0 +1,32 @@ +# +# Android Makefile conversion +# +# Leander Beernaert +# +# How to build: $ANDROID_NDK/ndk-build +# +VERSION=1.17 + +LOCAL_PATH := $(call my-dir)/../ + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm +LOCAL_ARM_NEON := true + +LOCAL_MODULE := HLSLcc + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/src \ + $(LOCAL_PATH)/src/cbstring +LOCAL_CFLAGS += -Wall -W +# For dynamic library +#LOCAL_CFLAGS += -DHLSLCC_DYNLIB +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/src/*.c) \ + $(wildcard $(LOCAL_PATH)/src/cbstring/*.c) \ + $(wildcard $(LOCAL_PATH)/src/internal_includes/*.c) +#LOCAL_LDLIBS += -lGLESv3 + +include $(BUILD_STATIC_LIBRARY) + diff --git a/Code/Tools/HLSLCrossCompiler/jni/Application.mk b/Code/Tools/HLSLCrossCompiler/jni/Application.mk new file mode 100644 index 0000000000..a8ae0839b1 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/jni/Application.mk @@ -0,0 +1,3 @@ +APP_PLATFORM := android-18 +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a new file mode 100644 index 0000000000..6bab978a58 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/android-armeabi-v7a/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35c73c9602dbd539ddd4874c4231fe21d40e0db813394f89e1c837a59d4be755 +size 1092754 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a new file mode 100644 index 0000000000..4e5a152c7c --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/ios-arm64/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51ed960398777ebee83d838e344e4a1dd331acb4ae0e77cbf8a64f2c1146b2ce +size 184304 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a new file mode 100644 index 0000000000..cb80d6e7ee --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/ios-simx86_64/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26083d66db7a82295514575af1160ab7aec52aa32f8431edbd1a09011154901b +size 190552 diff --git a/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a new file mode 100644 index 0000000000..c9ef9a0047 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/ios/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b322870fdff43b12034b4d9bcf72b59a5ef2f0cdd1f3042369c9f1a6911931b +size 374904 diff --git a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a new file mode 100644 index 0000000000..2adc6a7397 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ea9be963e0674546c2e8af2fd9a34e95100d9a1806399457b1e06d033149456 +size 375378 diff --git a/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a new file mode 100644 index 0000000000..b1318b6000 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/linux/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:544de0a5688c776e28b42bb189a738bc87743828b737d4bf653e46cd2e05938b +size 1171448 diff --git a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a new file mode 100644 index 0000000000..85bf31eed4 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af9216c54d23dd3754f7ae18d56b97ae256eb29a0046d8e0d2a0716054d8c230 +size 218888 diff --git a/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a new file mode 100644 index 0000000000..00095a3615 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/mac/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a07bec349614cdd3e40c3577bddace1203148016f9276c7ef807bdbc37dcabf +size 671232 diff --git a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a new file mode 100644 index 0000000000..c7b92fcc1e --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88acec4cedad5699900ec2d1a3ce83ab5e9365ebea4b4af0ababba562382f399 +size 296852 diff --git a/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a new file mode 100644 index 0000000000..29dd7fbf7a --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/steamos/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c0625b7f534df5817646dd1335f9d7916389f27a83b7d118fadab504064d910 +size 1144250 diff --git a/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib b/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib new file mode 100644 index 0000000000..8ed661eb15 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/win32/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d49f4f011fe2835d5aafa7ac77fb660cf12078763ddef25e935da919bc65e6b +size 440242 diff --git a/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib b/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib new file mode 100644 index 0000000000..452aa95688 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/lib/win64/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a4a291f8b3d00e1865a98ad3c740d28ff10d43ca87b718403cfc920df2be9ab +size 618776 diff --git a/Code/Tools/HLSLCrossCompiler/license.txt b/Code/Tools/HLSLCrossCompiler/license.txt new file mode 100644 index 0000000000..29f302da75 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/license.txt @@ -0,0 +1,53 @@ +Copyright (c) 2012 James Jones +Further improvements Copyright (c) 2014-2016 Unity Technologies +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +This software makes use of the bstring library which is provided under the following license: + +Copyright (c) 2002-2008 Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of bstrlib nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/README b/Code/Tools/HLSLCrossCompiler/offline/cjson/README new file mode 100644 index 0000000000..7531c049a6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/cjson/README @@ -0,0 +1,247 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +Welcome to cJSON. + +cJSON aims to be the dumbest possible parser that you can get your job done with. +It's a single file of C, and a single header file. + +JSON is described best here: http://www.json.org/ +It's like XML, but fat-free. You use it to move data around, store things, or just +generally represent your program's state. + + +First up, how do I build? +Add cJSON.c to your project, and put cJSON.h somewhere in the header search path. +For example, to build the test app: + +gcc cJSON.c test.c -o test -lm +./test + + +As a library, cJSON exists to take away as much legwork as it can, but not get in your way. +As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it +in one of two modes: Auto and Manual. Let's have a quick run-through. + + +I lifted some JSON from this page: http://www.json.org/fatfree.html +That page inspired me to write cJSON, which is a parser that tries to share the same +philosophy as JSON itself. Simple, dumb, out of the way. + +Some JSON: +{ + "name": "Jack (\"Bee\") Nimble", + "format": { + "type": "rect", + "width": 1920, + "height": 1080, + "interlace": false, + "frame rate": 24 + } +} + +Assume that you got this from a file, a webserver, or magic JSON elves, whatever, +you have a char * to it. Everything is a cJSON struct. +Get it parsed: + cJSON *root = cJSON_Parse(my_json_string); + +This is an object. We're in C. We don't have objects. But we do have structs. +What's the framerate? + + cJSON *format = cJSON_GetObjectItem(root,"format"); + int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; + + +Want to change the framerate? + cJSON_GetObjectItem(format,"frame rate")->valueint=25; + +Back to disk? + char *rendered=cJSON_Print(root); + +Finished? Delete the root (this takes care of everything else). + cJSON_Delete(root); + +That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers +before you dereference them. If you want to see how you'd build this struct in code? + cJSON *root,*fmt; + root=cJSON_CreateObject(); + cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); + cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); + cJSON_AddStringToObject(fmt,"type", "rect"); + cJSON_AddNumberToObject(fmt,"width", 1920); + cJSON_AddNumberToObject(fmt,"height", 1080); + cJSON_AddFalseToObject (fmt,"interlace"); + cJSON_AddNumberToObject(fmt,"frame rate", 24); + +Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup. +Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and +a few from elsewhere. + +What about manual mode? First up you need some detail. +Let's cover how the cJSON objects represent the JSON data. +cJSON doesn't distinguish arrays from objects in handling; just type. +Each cJSON has, potentially, a child, siblings, value, a name. + +The root object has: Object Type and a Child +The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: +Sibling has type Object, name "format", and a child. +That child has type String, name "type", value "rect", and a sibling: +Sibling has type Number, name "width", value 1920, and a sibling: +Sibling has type Number, name "height", value 1080, and a sibling: +Sibling hs type False, name "interlace", and a sibling: +Sibling has type Number, name "frame rate", value 24 + +Here's the structure: +typedef struct cJSON { + struct cJSON *next,*prev; + struct cJSON *child; + + int type; + + char *valuestring; + int valueint; + double valuedouble; + + char *string; +} cJSON; + +By default all values are 0 unless set by virtue of being meaningful. + +next/prev is a doubly linked list of siblings. next takes you to your sibling, +prev takes you back from your sibling to you. +Only objects and arrays have a "child", and it's the head of the doubly linked list. +A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0. +The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in +cJSON.h + +A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read +valuedouble. + +Any entry which is in the linked list which is the child of an object will have a "string" +which is the "name" of the entry. When I said "name" in the above example, that's "string". +"string" is the JSON name for the 'variable name' if you will. + +Now you can trivially walk the lists, recursively, and parse as you please. +You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take +the root object, and traverse the structure (which is, formally, an N-tree), +and tokenise as you please. If you wanted to build a callback style parser, this is how +you'd do it (just an example, since these things are very specific): + +void parse_and_callback(cJSON *item,const char *prefix) +{ + while (item) + { + char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); + sprintf(newprefix,"%s/%s",prefix,item->name); + int dorecurse=callback(newprefix, item->type, item); + if (item->child && dorecurse) parse_and_callback(item->child,newprefix); + item=item->next; + free(newprefix); + } +} + +The prefix process will build you a separated list, to simplify your callback handling. +The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or +let you invoke it per-item. For the item above, your callback might look like this: + +int callback(const char *name,int type,cJSON *item) +{ + if (!strcmp(name,"name")) { /* populate name */ } + else if (!strcmp(name,"format/type") { /* handle "rect" */ } + else if (!strcmp(name,"format/width") { /* 800 */ } + else if (!strcmp(name,"format/height") { /* 600 */ } + else if (!strcmp(name,"format/interlace") { /* false */ } + else if (!strcmp(name,"format/frame rate") { /* 24 */ } + return 1; +} + +Alternatively, you might like to parse iteratively. +You'd use: + +void parse_object(cJSON *item) +{ + int i; for (i=0;i<cJSON_GetArraySize(item);i++) + { + cJSON *subitem=cJSON_GetArrayItem(item,i); + // handle subitem. + } +} + +Or, for PROPER manual mode: + +void parse_object(cJSON *item) +{ + cJSON *subitem=item->child; + while (subitem) + { + // handle subitem + if (subitem->child) parse_object(subitem->child); + + subitem=subitem->next; + } +} + +Of course, this should look familiar, since this is just a stripped-down version +of the callback-parser. + +This should cover most uses you'll find for parsing. The rest should be possible +to infer.. and if in doubt, read the source! There's not a lot of it! ;) + + +In terms of constructing JSON data, the example code above is the right way to do it. +You can, of course, hand your sub-objects to other functions to populate. +Also, if you find a use for it, you can manually build the objects. +For instance, suppose you wanted to build an array of objects? + +cJSON *objects[24]; + +cJSON *Create_array_of_anything(cJSON **items,int num) +{ + int i;cJSON *prev, *root=cJSON_CreateArray(); + for (i=0;i<24;i++) + { + if (!i) root->child=objects[i]; + else prev->next=objects[i], objects[i]->prev=prev; + prev=objects[i]; + } + return root; +} + +and simply: Create_array_of_anything(objects,24); + +cJSON doesn't make any assumptions about what order you create things in. +You can attach the objects, as above, and later add children to each +of those objects. + +As soon as you call cJSON_Print, it renders the structure to text. + + + +The test.c code shows how to handle a bunch of typical cases. If you uncomment +the code, it'll load, parse and print a bunch of test files, also from json.org, +which are more complex than I'd care to try and stash into a const char array[]. + + +Enjoy cJSON! + + +- Dave Gamble, Aug 2009 diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c new file mode 100644 index 0000000000..78b1634fbf --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.c @@ -0,0 +1,578 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +// Modifications copyright Amazon.com, Inc. or its affiliates. + +/* cJSON */ +/* JSON parser in C. */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <float.h> +#include <limits.h> +#include <ctype.h> +#include "cJSON.h" +#include <AzCore/PlatformDef.h> + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free are not static +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; +AZ_POP_DISABLE_WARNING + +static char* cJSON_strdup(const char* str) +{ + size_t len = strlen(str) + 1; + char* copy = (char*)cJSON_malloc(len); + + if (!copy) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + /* Could use sscanf for this? */ + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + sscanf(ptr+3,"%4x",&uc2);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str; + token = *ptr; + while (token && ++len) + { + if (strchr("\"\\\b\f\n\r\t",token)) len++; + else if (token<32) len+=5; + ptr++; + token = *ptr; + } + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item = cJSON_New_Item(); + if (!new_item) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=(int)strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); + cJSON_free(entries); + return 0; + } + + /* Compose the output array. */ + *out='['; + ptr=out+1;*ptr=0; + for (i=0;i<numentries;i++) + { + strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); + if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++=']';*ptr++=0; + return out; +} + +/* Build an object from the text. */ +static const char *parse_object(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='{') {ep=value;return 0;} /* not an object! */ + + item->type=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON* new_item = cJSON_New_Item(); + if (!new_item) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+3:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} + *ptr++='}';*ptr++=0; + return out; + } + /* Allocate space for the names and the objects */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + names=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!names) {cJSON_free(entries);return 0;} + memset(entries,0,sizeof(char*)*numentries); + memset(names,0,sizeof(char*)*numentries); + + /* Collect all the results into our arrays: */ + child=item->child;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=(int)(strlen(ret)+strlen(str))+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} + cJSON_free(names);cJSON_free(entries); + return 0; + } + + /* Compose the output: */ + *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; + for (i=0;i<numentries;i++) + { + if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; + strcpy(ptr,names[i]);ptr+=strlen(names[i]); + *ptr++=':';if (fmt) *ptr++='\t'; + strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); + if (i!=numentries-1) *ptr++=','; + if (fmt) *ptr++='\n';*ptr=0; + cJSON_free(names[i]);cJSON_free(entries[i]); + } + + cJSON_free(names);cJSON_free(entries); + if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; + *ptr++='}';*ptr++=0; + return out; +} + +/* Get Array size/item / object item. */ +int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} diff --git a/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h new file mode 100644 index 0000000000..50ae02b6f9 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/cjson/cJSON.h @@ -0,0 +1,142 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp b/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp new file mode 100644 index 0000000000..5a22aa553f --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/compilerStandalone.cpp @@ -0,0 +1,803 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include <inttypes.h> +#include "hlslcc.hpp" +#include "stdlib.h" +#include "stdio.h" +#include <string> +#include <string.h> +#include "hash.h" +#include "serializeReflection.h" +#include "hlslcc_bin.hpp" + +#include <algorithm> +#include <cctype> + +#ifdef _WIN32 +#include <direct.h> +#else +#include <sys/stat.h> +#endif + +#include "timer.h" + +#if defined(_WIN32) && !defined(PORTABLE) +//#define VALIDATE_OUTPUT // NOTE: THIS IS OK DURING HLSLcc DEV BUT SHOULD NOT BE USED IN PRODUCTION. SOME EXT USED ARE NO SUPPORTED ON WINDOWS. +#endif + +#if defined(VALIDATE_OUTPUT) +#if defined(_WIN32) +#include <windows.h> +#include <gl/GL.h> + + #pragma comment(lib, "opengl32.lib") + +typedef char GLcharARB; /* native character */ +typedef unsigned int GLhandleARB; /* shader object handle */ +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +typedef void (WINAPI * PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj); +typedef GLhandleARB (WINAPI * PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType); +typedef void (WINAPI * PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB** string, const GLint* length); +typedef void (WINAPI * PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj); +typedef void (WINAPI * PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei* length, GLcharARB* infoLog); +typedef void (WINAPI * PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint* params); +typedef GLhandleARB (WINAPI * PFNGLCREATEPROGRAMOBJECTARBPROC)(void); +typedef void (WINAPI * PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj); +typedef void (WINAPI * PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj); +typedef void (WINAPI * PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj); +typedef void (WINAPI * PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei* length, GLcharARB* infoLog); + +static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; +static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, const int* attribList); +static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; + +void InitOpenGL() +{ + HGLRC rc; + + // setup minimal required GL + HWND wnd = CreateWindowA( + "STATIC", + "GL", + WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, 16, 16, + NULL, NULL, + GetModuleHandle(NULL), NULL); + HDC dc = GetDC(wnd); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, + PFD_TYPE_RGBA, 32, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 16, 0, + 0, PFD_MAIN_PLANE, 0, 0, 0, 0 + }; + + int fmt = ChoosePixelFormat(dc, &pfd); + SetPixelFormat(dc, fmt, &pfd); + + rc = wglCreateContext(dc); + wglMakeCurrent(dc, rc); + + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + + if (wglCreateContextAttribsARB) + { + const int OpenGLContextAttribs [] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 3, + #if defined(_DEBUG) + //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, + #else + //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + #endif + //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0, 0 + }; + + const HGLRC OpenGLContext = wglCreateContextAttribsARB(dc, 0, OpenGLContextAttribs); + + wglMakeCurrent(dc, OpenGLContext); + + wglDeleteContext(rc); + + rc = OpenGLContext; + } + + glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB"); + glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB"); + glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB"); + glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB"); + glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB"); + glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB"); + glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB"); + glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB"); + glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB"); + glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB"); + glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog"); +} +#endif + +void PrintSingleLineError(FILE* pFile, const char* error) +{ + while (*error != '\0') + { + const char* pLineEnd = strchr(error, '\n'); + if (pLineEnd == 0) + { + pLineEnd = error + strlen(error) - 1; + } + fwrite(error, 1, pLineEnd - error, pFile); + fwrite("\r", 1, 1, pFile); + error = pLineEnd + 1; + } +} + +int TryCompileShader(GLenum eShaderType, const char* inFilename, const char* shader, double* pCompileTime, int useStdErr) +{ + GLint iCompileStatus; + GLuint hShader; + Timer_t timer; + + InitTimer(&timer); + + InitOpenGL(); + + hShader = glCreateShaderObjectARB(eShaderType); + glShaderSourceARB(hShader, 1, (const char**)&shader, NULL); + + ResetTimer(&timer); + glCompileShaderARB(hShader); + *pCompileTime = ReadTimer(&timer); + + /* Check it compiled OK */ + glGetObjectParameterivARB (hShader, GL_OBJECT_COMPILE_STATUS_ARB, &iCompileStatus); + + if (iCompileStatus != GL_TRUE) + { + FILE* errorFile = NULL; + GLint iInfoLogLength = 0; + char* pszInfoLog; + + glGetObjectParameterivARB (hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iInfoLogLength); + + pszInfoLog = new char[iInfoLogLength]; + + printf("Error: Failed to compile GLSL shader\n"); + + glGetInfoLogARB (hShader, iInfoLogLength, NULL, pszInfoLog); + + printf(pszInfoLog); + + if (!useStdErr) + { + std::string filename; + filename += inFilename; + filename += "_compileErrors.txt"; + + //Dump to file + fopen_s(&errorFile, filename.c_str(), "w"); + + fclose(errorFile); + } + else + { + // Present error to stderror with no "new lines" as required by remote shader compiler + fprintf(stderr, "%s(-) error: ", inFilename); + PrintSingleLineError(stderr, pszInfoLog); + fprintf(stderr, "\rshader: "); + PrintSingleLineError(stderr, shader); + } + + delete [] pszInfoLog; + + return 0; + } + + return 1; +} +#endif + +int fileExists(const char* path) +{ + FILE* shaderFile; + shaderFile = fopen(path, "rb"); + + if (shaderFile) + { + fclose(shaderFile); + return 1; + } + return 0; +} + +GLLang LanguageFromString(const char* str) +{ + if (strcmp(str, "es100") == 0) + { + return LANG_ES_100; + } + if (strcmp(str, "es300") == 0) + { + return LANG_ES_300; + } + if (strcmp(str, "es310") == 0) + { + return LANG_ES_310; + } + if (strcmp(str, "120") == 0) + { + return LANG_120; + } + if (strcmp(str, "130") == 0) + { + return LANG_130; + } + if (strcmp(str, "140") == 0) + { + return LANG_140; + } + if (strcmp(str, "150") == 0) + { + return LANG_150; + } + if (strcmp(str, "330") == 0) + { + return LANG_330; + } + if (strcmp(str, "400") == 0) + { + return LANG_400; + } + if (strcmp(str, "410") == 0) + { + return LANG_410; + } + if (strcmp(str, "420") == 0) + { + return LANG_420; + } + if (strcmp(str, "430") == 0) + { + return LANG_430; + } + if (strcmp(str, "440") == 0) + { + return LANG_440; + } + return LANG_DEFAULT; +} + +#define MAX_PATH_CHARS 256 +#define MAX_FXC_CMD_CHARS 1024 + +typedef struct +{ + GLLang language; + + int flags; + + const char* shaderFile; + char* outputShaderFile; + + char* reflectPath; + + char cacheKey[MAX_PATH_CHARS]; + + int bUseFxc; + std::string fxcCmdLine; +} Options; + +void InitOptions(Options* psOptions) +{ + psOptions->language = LANG_DEFAULT; + psOptions->flags = 0; + psOptions->reflectPath = NULL; + + psOptions->shaderFile = NULL; + + psOptions->bUseFxc = 0; +} + +void PrintHelp() +{ + printf("Command line options:\n"); + + printf("\t-lang=X \t GLSL language to use. e.g. es100 or 140 or metal.\n"); + printf("\t-flags=X \t The integer value of the HLSLCC_FLAGS to used.\n"); + printf("\t-reflect=X \t File to write reflection JSON to.\n"); + printf("\t-in=X \t Shader file to compile.\n"); + printf("\t-out=X \t File to write the compiled shader from -in to.\n"); + + printf("\t-hashout=[dir/]out-file-name \t Output file name is a hash of 'out-file-name', put in the directory 'dir'.\n"); + + printf("\t-fxc=\"CMD\" HLSL compiler command line. If specified the input shader will be first compiled through this command first and then the resulting bytecode translated.\n"); + + printf("\n"); +} + +int GetOptions(int argc, char** argv, Options* psOptions) +{ + int i; + int fullShaderChain = -1; + + InitOptions(psOptions); + + for (i = 1; i < argc; i++) + { + char* option; + + option = strstr(argv[i], "-help"); + if (option != NULL) + { + PrintHelp(); + return 0; + } + + option = strstr(argv[i], "-reflect="); + if (option != NULL) + { + psOptions->reflectPath = option + strlen("-reflect="); + } + + option = strstr(argv[i], "-lang="); + if (option != NULL) + { + psOptions->language = LanguageFromString((&option[strlen("-lang=")])); + } + + option = strstr(argv[i], "-flags="); + if (option != NULL) + { + psOptions->flags = atol(&option[strlen("-flags=")]); + } + + option = strstr(argv[i], "-in="); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->shaderFile = option + strlen("-in="); + if (!fileExists(psOptions->shaderFile)) + { + printf("Invalid path: %s\n", psOptions->shaderFile); + return 0; + } + } + + option = strstr(argv[i], "-out="); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->outputShaderFile = option + strlen("-out="); + } + + option = strstr(argv[i], "-hashout"); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->outputShaderFile = option + strlen("-hashout="); + + char* dir; + int64_t length; + + uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0); + + + dir = strrchr(psOptions->outputShaderFile, '\\'); + + if (!dir) + { + dir = strrchr(psOptions->outputShaderFile, '//'); + } + + if (!dir) + { + length = 0; + } + else + { + length = (int)(dir - psOptions->outputShaderFile) + 1; + } + + for (i = 0; i < length; ++i) + { + psOptions->cacheKey[i] = psOptions->outputShaderFile[i]; + } + + //sprintf(psOptions->cacheKey, "%x%x", high, low); + sprintf(&psOptions->cacheKey[i], "%010" PRIX64, hash); + + psOptions->outputShaderFile = psOptions->cacheKey; + } + + option = strstr(argv[i], "-fxc="); + if (option != NULL) + { + char* cmdLine = option + strlen("-fxc="); + size_t cmdLineLen = strlen(cmdLine); + if (cmdLineLen == 0 || cmdLineLen + 1 >= MAX_FXC_CMD_CHARS) + { + return 0; + } + psOptions->fxcCmdLine = std::string(cmdLine, cmdLineLen); + psOptions->bUseFxc = 1; + } + } + + return 1; +} + +void* malloc_hook(size_t size) +{ + return malloc(size); +} +void* calloc_hook(size_t num, size_t size) +{ + return calloc(num, size); +} +void* realloc_hook(void* p, size_t size) +{ + return realloc(p, size); +} +void free_hook(void* p) +{ + free(p); +} + +int Run(const char* srcPath, const char* destPath, GLLang language, int flags, const char* reflectPath, GLSLShader* shader, int useStdErr) +{ + FILE* outputFile; + GLSLShader tempShader; + GLSLShader* result = shader ? shader : &tempShader; + Timer_t timer; + int compiledOK = 0; + double crossCompileTime = 0; + + HLSLcc_SetMemoryFunctions(malloc_hook, calloc_hook, free_hook, realloc_hook); + + InitTimer(&timer); + + ResetTimer(&timer); + GlExtensions ext; + ext.ARB_explicit_attrib_location = 0; + ext.ARB_explicit_uniform_location = 0; + ext.ARB_shading_language_420pack = 0; + compiledOK = TranslateHLSLFromFile(srcPath, flags, language, &ext, result); + + crossCompileTime = ReadTimer(&timer); + + if (compiledOK) + { + printf("cc time: %.2f us\n", crossCompileTime); + + if (destPath) + { + //Dump to file + outputFile = fopen(destPath, "w"); + fprintf(outputFile, result->sourceCode); + fclose(outputFile); + } + + if (reflectPath) + { + const char* jsonString = SerializeReflection(&result->reflection); + outputFile = fopen(reflectPath, "w"); + fprintf(outputFile, jsonString); + fclose(outputFile); + } + +#if defined(VALIDATE_OUTPUT) + std::string shaderSource; + if (flags & HLSLCC_FLAG_NO_VERSION_STRING) + { + // Need to add the version string so that the shader will compile + shaderSource = GetVersionString(language); + shaderSource += result->sourceCode; + } + else + { + shaderSource = result->sourceCode; + } + compiledOK = TryCompileShader(result->shaderType, destPath ? destPath : "", shaderSource.c_str(), &glslCompileTime, useStdErr); + + if (compiledOK) + { + printf("glsl time: %.2f us\n", glslCompileTime); + } +#endif + + if (!shader) + { + FreeGLSLShader(result); + } + } + else if (useStdErr) + { + fprintf(stderr, "TranslateHLSLFromFile failed"); + } + + return compiledOK; +} + +struct SDXBCFile +{ + FILE* m_pFile; + + bool Read(void* pElements, size_t uSize) + { + return fread(pElements, 1, uSize, m_pFile) == uSize; + } + + bool Write(const void* pElements, size_t uSize) + { + return fwrite(pElements, 1, uSize, m_pFile) == uSize; + } + + bool SeekRel(int32_t iOffset) + { + return fseek(m_pFile, iOffset, SEEK_CUR) == 0; + } + + bool SeekAbs(uint32_t uPosition) + { + return fseek(m_pFile, uPosition, SEEK_SET) == 0; + } +}; + +int CombineDXBCWithGLSL(char* dxbcFileName, char* outputFileName, GLSLShader* shader) +{ + SDXBCFile dxbcFile = { fopen(dxbcFileName, "rb") }; + SDXBCFile outputFile = { fopen(outputFileName, "wb") }; + + bool result = + dxbcFile.m_pFile != NULL && outputFile.m_pFile != NULL && + DXBCCombineWithGLSL(dxbcFile, outputFile, shader); + + if (dxbcFile.m_pFile != NULL) + { + fclose(dxbcFile.m_pFile); + } + if (outputFile.m_pFile != NULL) + { + fclose(outputFile.m_pFile); + } + + return result; +} + +#if !defined(_MSC_VER) +#define sprintf_s(dest, size, ...) sprintf(dest, __VA_ARGS__) +#endif + +#if defined(_WIN32) && defined(PORTABLE) + +DWORD FilterException(DWORD uExceptionCode) +{ + const char* szExceptionName; + char acTemp[10]; + switch (uExceptionCode) + { +#define _CASE(_Name) \ +case _Name: \ + szExceptionName = #_Name; \ + break; + _CASE(EXCEPTION_ACCESS_VIOLATION) + _CASE(EXCEPTION_DATATYPE_MISALIGNMENT) + _CASE(EXCEPTION_BREAKPOINT) + _CASE(EXCEPTION_SINGLE_STEP) + _CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) + _CASE(EXCEPTION_FLT_DENORMAL_OPERAND) + _CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO) + _CASE(EXCEPTION_FLT_INEXACT_RESULT) + _CASE(EXCEPTION_FLT_INVALID_OPERATION) + _CASE(EXCEPTION_FLT_OVERFLOW) + _CASE(EXCEPTION_FLT_STACK_CHECK) + _CASE(EXCEPTION_FLT_UNDERFLOW) + _CASE(EXCEPTION_INT_DIVIDE_BY_ZERO) + _CASE(EXCEPTION_INT_OVERFLOW) + _CASE(EXCEPTION_PRIV_INSTRUCTION) + _CASE(EXCEPTION_IN_PAGE_ERROR) + _CASE(EXCEPTION_ILLEGAL_INSTRUCTION) + _CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION) + _CASE(EXCEPTION_STACK_OVERFLOW) + _CASE(EXCEPTION_INVALID_DISPOSITION) + _CASE(EXCEPTION_GUARD_PAGE) + _CASE(EXCEPTION_INVALID_HANDLE) + //_CASE(EXCEPTION_POSSIBLE_DEADLOCK) +#undef _CASE + default: + sprintf_s(acTemp, "0x%08X", uExceptionCode); + szExceptionName = acTemp; + } + + fprintf(stderr, "Hardware exception thrown (%s)\n", szExceptionName); + return 1; +} + +#endif + +const char* PatchHLSLShaderFile(const char* path) +{ + // Need to transform "half" into "min16float" so FXC preserve min precision to the operands. + static char patchedFileName[MAX_PATH_CHARS]; + const char* defines = "#define half min16float\n" + "#define half2 min16float2\n" + "#define half3 min16float3\n" + "#define half4 min16float4\n"; + + sprintf_s(patchedFileName, sizeof(patchedFileName), "%s.hlslPatched", path); + FILE* shaderFile = fopen(path, "rb"); + if (!shaderFile) + { + return NULL; + } + + FILE* patchedFile = fopen(patchedFileName, "wb"); + if (!patchedFile) + { + return NULL; + } + + // Get size of file + bool result = false; + fseek(shaderFile, 0, SEEK_END); + long size = ftell(shaderFile); + fseek(shaderFile, 0, SEEK_SET); + unsigned char* data = new unsigned char[size + 1]; // Extra byte for the '/0' character. + if (fread(data, 1, size, shaderFile) == size) + { + data[size] = '\0'; + fprintf(patchedFile, "%s%s", defines, data); + result = true; + } + + if (shaderFile) + { + fclose(shaderFile); + } + + if (patchedFile) + { + fclose(patchedFile); + } + + delete[] data; + return result ? patchedFileName : NULL; +} + +int main(int argc, char** argv) +{ + Options options; + +#if defined(_WIN32) && defined(PORTABLE) + __try + { +#endif + + if (!GetOptions(argc, argv, &options)) + { + return 1; + } + + if (options.bUseFxc) + { + char dxbcFileName[MAX_PATH_CHARS]; + char glslFileName[MAX_PATH_CHARS]; + char fullFxcCmdLine[MAX_FXC_CMD_CHARS]; + int retValue; + + if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) + { + options.shaderFile = PatchHLSLShaderFile(options.shaderFile); + if (!options.shaderFile) + { + return 1; + } + } + + sprintf_s(dxbcFileName, sizeof(dxbcFileName), "%s.dxbc", options.shaderFile); + sprintf_s(glslFileName, sizeof(glslFileName), "%s.patched", options.shaderFile); + + // Need to extract the path to the executable so we can enclose it in quotes + // in case it contains spaces. + const std::string fxcExeName = "fxc.exe"; + + // Case insensitive search + std::string::iterator fxcPos = std::search( + options.fxcCmdLine.begin(), options.fxcCmdLine.end(), + fxcExeName.begin(), fxcExeName.end(), + [](char ch1, char ch2) { return std::tolower(ch1) == std::tolower(ch2); } + ); + + if (fxcPos == options.fxcCmdLine.end()) + { + fprintf(stderr, "Could not find fxc.exe in command line"); + return 1; + } + + // Add the fxcExeName so it gets copied to the fxcExe path. + fxcPos += fxcExeName.length(); + std::string fxcExe(options.fxcCmdLine.begin(), fxcPos); + std::string fxcArguments(fxcPos, options.fxcCmdLine.end()); + +#if defined(APPLE) + fprintf(stderr, "fxc.exe cannot be executed on Mac"); + return 1; +#else + // Need an extra set of quotes around the full command line because the way "system" executes it using cmd. + sprintf_s(fullFxcCmdLine, sizeof(fullFxcCmdLine), "\"\"%s\" %s \"%s\" \"%s\"\"", fxcExe.c_str(), fxcArguments.c_str(), dxbcFileName, options.shaderFile); +#endif + + retValue = system(fullFxcCmdLine); + + if (retValue == 0) + { + GLSLShader shader; + retValue = !Run(dxbcFileName, glslFileName, options.language, options.flags, options.reflectPath, &shader, 1); + + if (retValue == 0) + { + retValue = !CombineDXBCWithGLSL(dxbcFileName, options.outputShaderFile, &shader); + FreeGLSLShader(&shader); + } + } + + remove(dxbcFileName); + remove(glslFileName); + if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) + { + // Removed the hlsl patched file that was created. + remove(options.shaderFile); + } + + return retValue; + } + + if (options.shaderFile) + { + if (!Run(options.shaderFile, options.outputShaderFile, options.language, options.flags, options.reflectPath, NULL, 0)) + { + return 1; + } + } + +#if defined(_WIN32) && defined(PORTABLE) +} +__except (FilterException(GetExceptionCode())) +{ + return 1; +} +#endif + + + return 0; +} diff --git a/Code/Tools/HLSLCrossCompiler/offline/hash.h b/Code/Tools/HLSLCrossCompiler/offline/hash.h new file mode 100644 index 0000000000..f93f3b65d3 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/hash.h @@ -0,0 +1,152 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HASH_H_ +#define HASH_H_ + +/* +-------------------------------------------------------------------- +mix -- mix 3 64-bit values reversibly. +mix() takes 48 machine instructions, but only 24 cycles on a superscalar + machine (like Intel's new MMX architecture). It requires 4 64-bit + registers for 4::2 parallelism. +All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of + (a,b,c), and all deltas of bottom bits were tested. All deltas were + tested both on random keys and on keys that were nearly all zero. + These deltas all cause every bit of c to change between 1/3 and 2/3 + of the time (well, only 113/400 to 287/400 of the time for some + 2-bit delta). These deltas all cause at least 80 bits to change + among (a,b,c) when the mix is run either forward or backward (yes it + is reversible). +This implies that a hash using mix64 has no funnels. There may be + characteristics with 3-bit deltas or bigger, I didn't test for + those. +-------------------------------------------------------------------- +*/ +#define mix64(a, b, c) \ + { \ + a -= b; a -= c; a ^= (c >> 43); \ + b -= c; b -= a; b ^= (a << 9); \ + c -= a; c -= b; c ^= (b >> 8); \ + a -= b; a -= c; a ^= (c >> 38); \ + b -= c; b -= a; b ^= (a << 23); \ + c -= a; c -= b; c ^= (b >> 5); \ + a -= b; a -= c; a ^= (c >> 35); \ + b -= c; b -= a; b ^= (a << 49); \ + c -= a; c -= b; c ^= (b >> 11); \ + a -= b; a -= c; a ^= (c >> 12); \ + b -= c; b -= a; b ^= (a << 18); \ + c -= a; c -= b; c ^= (b >> 22); \ + } + +/* +-------------------------------------------------------------------- +hash64() -- hash a variable-length key into a 64-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + level : can be any 8-byte value +Returns a 64-bit value. Every bit of the key affects every bit of +the return value. No funnels. Every 1-bit and 2-bit delta achieves +avalanche. About 41+5len instructions. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 64 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); + +By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may +use this code any way you wish, private, educational, or commercial, +but I would appreciate if you give me credit. + +See http://burtleburtle.net/bob/hash/evahash.html +Use for hash table lookup, or anything where one collision in 2^^64 +is acceptable. Do NOT use for cryptographic purposes. +-------------------------------------------------------------------- +*/ + +static uint64_t hash64(const uint8_t* k, uint32_t length, uint64_t initval) +{ + uint64_t a, b, c, len; + + /* Set up the internal state */ + len = length; + a = b = initval; /* the previous hash value */ + c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */ + + /*---------------------------------------- handle most of the key */ + while (len >= 24) + { + a += (k[0] + ((uint64_t)k[ 1] << 8) + ((uint64_t)k[ 2] << 16) + ((uint64_t)k[ 3] << 24) + + ((uint64_t)k[4 ] << 32) + ((uint64_t)k[ 5] << 40) + ((uint64_t)k[ 6] << 48) + ((uint64_t)k[ 7] << 56)); + b += (k[8] + ((uint64_t)k[ 9] << 8) + ((uint64_t)k[10] << 16) + ((uint64_t)k[11] << 24) + + ((uint64_t)k[12] << 32) + ((uint64_t)k[13] << 40) + ((uint64_t)k[14] << 48) + ((uint64_t)k[15] << 56)); + c += (k[16] + ((uint64_t)k[17] << 8) + ((uint64_t)k[18] << 16) + ((uint64_t)k[19] << 24) + + ((uint64_t)k[20] << 32) + ((uint64_t)k[21] << 40) + ((uint64_t)k[22] << 48) + ((uint64_t)k[23] << 56)); + mix64(a, b, c); + k += 24; + len -= 24; + } + + /*------------------------------------- handle the last 23 bytes */ + c += length; + switch (len) /* all the case statements fall through */ + { + case 23: + c += ((uint64_t)k[22] << 56); + case 22: + c += ((uint64_t)k[21] << 48); + case 21: + c += ((uint64_t)k[20] << 40); + case 20: + c += ((uint64_t)k[19] << 32); + case 19: + c += ((uint64_t)k[18] << 24); + case 18: + c += ((uint64_t)k[17] << 16); + case 17: + c += ((uint64_t)k[16] << 8); + /* the first byte of c is reserved for the length */ + case 16: + b += ((uint64_t)k[15] << 56); + case 15: + b += ((uint64_t)k[14] << 48); + case 14: + b += ((uint64_t)k[13] << 40); + case 13: + b += ((uint64_t)k[12] << 32); + case 12: + b += ((uint64_t)k[11] << 24); + case 11: + b += ((uint64_t)k[10] << 16); + case 10: + b += ((uint64_t)k[ 9] << 8); + case 9: + b += ((uint64_t)k[ 8]); + case 8: + a += ((uint64_t)k[ 7] << 56); + case 7: + a += ((uint64_t)k[ 6] << 48); + case 6: + a += ((uint64_t)k[ 5] << 40); + case 5: + a += ((uint64_t)k[ 4] << 32); + case 4: + a += ((uint64_t)k[ 3] << 24); + case 3: + a += ((uint64_t)k[ 2] << 16); + case 2: + a += ((uint64_t)k[ 1] << 8); + case 1: + a += ((uint64_t)k[ 0]); + /* case 0: nothing left to add */ + } + mix64(a, b, c); + /*-------------------------------------------- report the result */ + return c; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp new file mode 100644 index 0000000000..15fe8d5b96 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.cpp @@ -0,0 +1,207 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "serializeReflection.h" +#include "cJSON.h" +#include <string> +#include <sstream> + +void* jsonMalloc(size_t sz) +{ + return new char[sz]; +} +void jsonFree(void* ptr) +{ + char* charPtr = static_cast<char*>(ptr); + delete [] charPtr; +} + +static void AppendIntToString(std::string& str, uint32_t num) +{ + std::stringstream ss; + ss << num; + str += ss.str(); +} + +static void WriteInOutSignature(InOutSignature* psSignature, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "SemanticName", cJSON_CreateString(psSignature->SemanticName)); + cJSON_AddItemToObject(obj, "ui32SemanticIndex", cJSON_CreateNumber(psSignature->ui32SemanticIndex)); + cJSON_AddItemToObject(obj, "eSystemValueType", cJSON_CreateNumber(psSignature->eSystemValueType)); + cJSON_AddItemToObject(obj, "eComponentType", cJSON_CreateNumber(psSignature->eComponentType)); + cJSON_AddItemToObject(obj, "ui32Register", cJSON_CreateNumber(psSignature->ui32Register)); + cJSON_AddItemToObject(obj, "ui32Mask", cJSON_CreateNumber(psSignature->ui32Mask)); + cJSON_AddItemToObject(obj, "ui32ReadWriteMask", cJSON_CreateNumber(psSignature->ui32ReadWriteMask)); +} + +static void WriteResourceBinding(ResourceBinding* psBinding, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psBinding->Name)); + cJSON_AddItemToObject(obj, "eType", cJSON_CreateNumber(psBinding->eType)); + cJSON_AddItemToObject(obj, "ui32BindPoint", cJSON_CreateNumber(psBinding->ui32BindPoint)); + cJSON_AddItemToObject(obj, "ui32BindCount", cJSON_CreateNumber(psBinding->ui32BindCount)); + cJSON_AddItemToObject(obj, "ui32Flags", cJSON_CreateNumber(psBinding->ui32Flags)); + cJSON_AddItemToObject(obj, "eDimension", cJSON_CreateNumber(psBinding->eDimension)); + cJSON_AddItemToObject(obj, "ui32ReturnType", cJSON_CreateNumber(psBinding->ui32ReturnType)); + cJSON_AddItemToObject(obj, "ui32NumSamples", cJSON_CreateNumber(psBinding->ui32NumSamples)); +} + +static void WriteShaderVar(ShaderVar* psVar, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psVar->Name)); + if(psVar->haveDefaultValue) + { + cJSON_AddItemToObject(obj, "aui32DefaultValues", cJSON_CreateIntArray((int*)psVar->pui32DefaultValues, psVar->ui32Size/4)); + } + cJSON_AddItemToObject(obj, "ui32StartOffset", cJSON_CreateNumber(psVar->ui32StartOffset)); + cJSON_AddItemToObject(obj, "ui32Size", cJSON_CreateNumber(psVar->ui32Size)); +} + +static void WriteConstantBuffer(ConstantBuffer* psCBuf, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psCBuf->Name)); + cJSON_AddItemToObject(obj, "ui32NumVars", cJSON_CreateNumber(psCBuf->ui32NumVars)); + + for(uint32_t i = 0; i < psCBuf->ui32NumVars; ++i) + { + std::string name; + name += "var"; + AppendIntToString(name, i); + + cJSON* varObj = cJSON_CreateObject(); + cJSON_AddItemToObject(obj, name.c_str(), varObj); + + WriteShaderVar(&psCBuf->asVars[i], varObj); + } + + cJSON_AddItemToObject(obj, "ui32TotalSizeInBytes", cJSON_CreateNumber(psCBuf->ui32TotalSizeInBytes)); +} + +static void WriteClassType(ClassType* psClassType, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassType->Name)); + cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassType->ui16ID)); + cJSON_AddItemToObject(obj, "ui16ConstBufStride", cJSON_CreateNumber(psClassType->ui16ConstBufStride)); + cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassType->ui16Texture)); + cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassType->ui16Sampler)); +} + +static void WriteClassInstance(ClassInstance* psClassInst, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassInst->Name)); + cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassInst->ui16ID)); + cJSON_AddItemToObject(obj, "ui16ConstBuf", cJSON_CreateNumber(psClassInst->ui16ConstBuf)); + cJSON_AddItemToObject(obj, "ui16ConstBufOffset", cJSON_CreateNumber(psClassInst->ui16ConstBufOffset)); + cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassInst->ui16Texture)); + cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassInst->ui16Sampler)); +} + +const char* SerializeReflection(ShaderInfo* psReflection) +{ + cJSON* root; + + cJSON_Hooks hooks; + hooks.malloc_fn = jsonMalloc; + hooks.free_fn = jsonFree; + cJSON_InitHooks(&hooks); + + root=cJSON_CreateObject(); + cJSON_AddItemToObject(root, "ui32MajorVersion", cJSON_CreateNumber(psReflection->ui32MajorVersion)); + cJSON_AddItemToObject(root, "ui32MinorVersion", cJSON_CreateNumber(psReflection->ui32MinorVersion)); + + cJSON_AddItemToObject(root, "ui32NumInputSignatures", cJSON_CreateNumber(psReflection->ui32NumInputSignatures)); + + for(uint32_t i = 0; i < psReflection->ui32NumInputSignatures; ++i) + { + std::string name; + name += "input"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteInOutSignature(psReflection->psInputSignatures+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumOutputSignatures", cJSON_CreateNumber(psReflection->ui32NumOutputSignatures)); + + for(uint32_t i = 0; i < psReflection->ui32NumOutputSignatures; ++i) + { + std::string name; + name += "output"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteInOutSignature(psReflection->psOutputSignatures+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumResourceBindings", cJSON_CreateNumber(psReflection->ui32NumResourceBindings)); + + for(uint32_t i = 0; i < psReflection->ui32NumResourceBindings; ++i) + { + std::string name; + name += "resource"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteResourceBinding(psReflection->psResourceBindings+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumConstantBuffers", cJSON_CreateNumber(psReflection->ui32NumConstantBuffers)); + + for(uint32_t i = 0; i < psReflection->ui32NumConstantBuffers; ++i) + { + std::string name; + name += "cbuf"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteConstantBuffer(psReflection->psConstantBuffers+i, obj); + } + + //psThisPointerConstBuffer is a cache. Don't need to write this out. + //It just points to the $ThisPointer cbuffer within the psConstantBuffers array. + + for(uint32_t i = 0; i < psReflection->ui32NumClassTypes; ++i) + { + std::string name; + name += "classType"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteClassType(psReflection->psClassTypes+i, obj); + } + + for(uint32_t i = 0; i < psReflection->ui32NumClassInstances; ++i) + { + std::string name; + name += "classInst"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteClassInstance(psReflection->psClassInstances+i, obj); + } + + //psReflection->aui32TableIDToTypeID + //psReflection->aui32ConstBufferBindpointRemap + + cJSON_AddItemToObject(root, "eTessPartitioning", cJSON_CreateNumber(psReflection->eTessPartitioning)); + cJSON_AddItemToObject(root, "eTessOutPrim", cJSON_CreateNumber(psReflection->eTessOutPrim)); + + + const char* jsonString = cJSON_Print(root); + + cJSON_Delete(root); + + return jsonString; +} diff --git a/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h new file mode 100644 index 0000000000..c8c4175a6a --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/serializeReflection.h @@ -0,0 +1,11 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef SERIALIZE_REFLECTION_H_ +#define SERIALIZE_REFLECTION_H_ + +#include "hlslcc.h" + +const char* SerializeReflection(ShaderInfo* psReflection); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/offline/timer.cpp b/Code/Tools/HLSLCrossCompiler/offline/timer.cpp new file mode 100644 index 0000000000..c707e1bfa8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/timer.cpp @@ -0,0 +1,40 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "timer.h" + +void InitTimer(Timer_t* psTimer) +{ +#if defined(_WIN32) + QueryPerformanceFrequency(&psTimer->frequency); +#endif +} + +void ResetTimer(Timer_t* psTimer) +{ +#if defined(_WIN32) + QueryPerformanceCounter(&psTimer->startCount); +#else + gettimeofday(&psTimer->startCount, 0); +#endif +} + +/* Returns time in micro seconds */ +double ReadTimer(Timer_t* psTimer) +{ + double startTimeInMicroSec, endTimeInMicroSec; + +#if defined(_WIN32) + const double freq = (1000000.0 / psTimer->frequency.QuadPart); + QueryPerformanceCounter(&psTimer->endCount); + startTimeInMicroSec = psTimer->startCount.QuadPart * freq; + endTimeInMicroSec = psTimer->endCount.QuadPart * freq; +#else + gettimeofday(&psTimer->endCount, 0); + startTimeInMicroSec = (psTimer->startCount.tv_sec * 1000000.0) + psTimer->startCount.tv_usec; + endTimeInMicroSec = (psTimer->endCount.tv_sec * 1000000.0) + psTimer->endCount.tv_usec; +#endif + + return endTimeInMicroSec - startTimeInMicroSec; +} + diff --git a/Code/Tools/HLSLCrossCompiler/offline/timer.h b/Code/Tools/HLSLCrossCompiler/offline/timer.h new file mode 100644 index 0000000000..3f4ea333fd --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/offline/timer.h @@ -0,0 +1,29 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TIMER_H +#define TIMER_H + +#ifdef _WIN32 +#include <Windows.h> +#else +#include <sys/time.h> +#endif + +typedef struct +{ +#ifdef _WIN32 + LARGE_INTEGER frequency; + LARGE_INTEGER startCount; + LARGE_INTEGER endCount; +#else + struct timeval startCount; + struct timeval endCount; +#endif +} Timer_t; + +void InitTimer(Timer_t* psTimer); +void ResetTimer(Timer_t* psTimer); +double ReadTimer(Timer_t* psTimer); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c b/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c new file mode 100644 index 0000000000..7b339ba93e --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/amazon_changes.c @@ -0,0 +1,219 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toGLSLInstruction.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/languages.h" +#include "bstrlib.h" +#include "stdio.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "amazon_changes.h" + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wpointer-sign" +#endif + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +// These are .c files, so no C++ or C++11 for us :( +#define MAX_VARIABLE_LENGTH 16 + +// This struct is used to keep track of each valid occurance of xxxBitsToxxx(variable) and store all relevant information for fixing that instance +typedef struct ShaderCastLocation +{ + char tempVariableName[MAX_VARIABLE_LENGTH]; + char replacementVariableName[MAX_VARIABLE_LENGTH]; + unsigned int castType; + + // Since we have no stl, here's our list + struct ShaderCastLocation* next; +} ShaderCastLocation; + +// Structure used to prebuild the list of all functions that need to be replaced. +typedef struct ShaderCastType +{ + const char* functionName; + unsigned int castType; + const char* variableTypeName; // String for the variable type used when declaring a temporary variable to replace the source temp vector +} ShaderCastType; + +enum ShaderCasts +{ + CAST_UINTBITSTOFLOAT, + CAST_INTBITSTOFLOAT, + CAST_FLOATBITSTOUINT, + CAST_FLOATBITSTOINT, + CAST_NUMCASTS +}; + +// NOTICE: Order is important here because intBitsToFloat is a substring of uintBitsToFloat, so do not change the ordering here! +static const ShaderCastType s_castFunctions[CAST_NUMCASTS] = +{ + { "uintBitsToFloat", CAST_UINTBITSTOFLOAT, "uvec4" }, + { "intBitsToFloat", CAST_INTBITSTOFLOAT, "ivec4" }, + { "floatBitsToUint", CAST_FLOATBITSTOUINT, "vec4" }, + { "floatBitsToInt", CAST_FLOATBITSTOINT, "vec4" } +}; + +int IsValidUseCase( char* variableStart, char* outVariableName, ShaderCastLocation* foundShaderCastsHead, int currentType ) +{ + // Cases we have to replace (this is very strict in definition): + // 1) floatBitsToInt(Temp2) + // 2) floatBitsToInt(Temp2.x) + // 3) floatBitsToInt(Temp[0]) + // 4) floatBitsToInt(Temp[0].x) + // Cases we do not have to replace: + // 1) floatBitsToInt(vec4(Temp2)) + // 2) floatBitsToInt(Output0.x != 0.0f ? 1.0f : 0.0f) + // 3) Any other version that evaluates an expression within the () + if ( strncmp(variableStart, "Temp", 4) != 0 ) + return 0; + + unsigned int lengthOfVariable = 4; // Start at 4 for temp + + while ( 1 ) + { + char val = *(variableStart + lengthOfVariable); + + // If alphanumeric or [] (array), we have a valid variable name + if ( isalnum( val ) || (val == '[') || (val == ']') ) + { + lengthOfVariable++; + } + else if ( (val == ')') || (val == '.') ) + { + // Found end of variable + break; + } + else + { + // Found something unexpected, so abort + return 0; + } + } + + ASSERT( lengthOfVariable < MAX_VARIABLE_LENGTH ); + + // Now ensure that no duplicates of this declaration already exist + ShaderCastLocation* currentLink = foundShaderCastsHead; + while ( currentLink ) + { + // If we have the same type and the same name + if ( (currentType == currentLink->castType) && (strncmp(variableStart, currentLink->tempVariableName, lengthOfVariable) == 0) ) + return 0; // Do not add because an entry already exists for this variable and this cast function + + // Hmm...I guess this scenario is possible, but it has not shown up in any shaders. + // The only time we could ever hit this is if the same line casts a float to both an int and uint in separate calls + // Seems highly unlikely, so let's just assert for now and fix it if we have to. + if ( strncmp(variableStart, currentLink->tempVariableName, lengthOfVariable) == 0 ) + { + // TODO: Implement this case where we cast the same variable to multiple types on the same line of GLSL + ASSERT(0); + } + + currentLink = currentLink->next; + } + + // We found a unique instance, so store it + strncpy( outVariableName, variableStart, lengthOfVariable ); + return 1; +} + +void ModifyLineForQualcommReinterpretCastBug( HLSLCrossCompilerContext* psContext, bstring* originalString, bstring* overloadString ) +{ + unsigned int numFoundCasts = 0; + + ShaderCastLocation* foundShaderCastsHead = NULL; + ShaderCastLocation* currentShaderCasts = NULL; + + // Find all occurances of the *BitsTo* functions + // Note that this would be cleaner, but 'intBitsToFloat' is a substring of 'uintBitsToFloat' so parsing order is important here. + char* parsingString = bdataofs(*overloadString, 0); + while ( parsingString ) + { + char* result = NULL; + + for ( int index=0; index<CAST_NUMCASTS; ++index ) + { + result = strstr( parsingString, s_castFunctions[index].functionName ); + if ( result != NULL ) + { + // Now determine if this is a case that requires a workaround + char* variableStart = result + strlen( s_castFunctions[index].functionName ) + 1; // Add the function name + first parenthesis + char tempVariableName[MAX_VARIABLE_LENGTH]; + memset( tempVariableName, 0, MAX_VARIABLE_LENGTH ); + + // Now the next word must be Temp, or this is not a valid case + if ( IsValidUseCase( variableStart, tempVariableName, foundShaderCastsHead, index ) ) + { + // Now store the information about this cast. Allocate a new link in the list. + if ( !foundShaderCastsHead ) + { + foundShaderCastsHead = (ShaderCastLocation*)hlslcc_malloc( sizeof(ShaderCastLocation) ); + memset( foundShaderCastsHead, 0x0, sizeof(ShaderCastLocation) ); + currentShaderCasts = foundShaderCastsHead; + } + else + { + ASSERT( !currentShaderCasts->next ); + currentShaderCasts->next = (ShaderCastLocation*)hlslcc_malloc( sizeof(ShaderCastLocation) ); + memset( currentShaderCasts->next, 0x0, sizeof(ShaderCastLocation) ); + currentShaderCasts = currentShaderCasts->next; + } + + currentShaderCasts->castType = index; + strcpy( currentShaderCasts->tempVariableName, tempVariableName ); + + numFoundCasts++; + } + result += strlen( s_castFunctions[index].functionName ); + + // Break out of the loop because we have to advance the search string and start over with uintBitsToFloat again due to the problem with intBitsToFloat being a substring + break; + } + } + + parsingString = result; + } + + // If we have found no casts, then append the line to the primary string + if ( numFoundCasts == 0 ) + { + bconcat( *originalString, *overloadString ); + return; + } + + // Now we start creating our temporary variables to workaround the crash + currentShaderCasts = foundShaderCastsHead; + + // NOTE: We want a count of all variables processed for this entire shader. This could be fancier... + static unsigned int currentVariableIndex = 0; + + while ( currentShaderCasts ) + { + // Generate new variable name + sprintf( currentShaderCasts->replacementVariableName, "LYTemp%i", currentVariableIndex ); + + // Write out the new variable name declaration and initialize it + AddIndentation( psContext ); + bformata( *originalString, "%s %s=%s;\n", s_castFunctions[currentShaderCasts->castType].variableTypeName, currentShaderCasts->replacementVariableName, currentShaderCasts->tempVariableName ); + + // Now replace all instances of the variable in question with the new variable name. + // Note: We can't do a breplace on the temp variable name because the variable can still be legally used without a reinterpret cast in that line. + // Do a full replace on the xxBitsToxx(TempVar) here + bstring tempVarName = bformat( "%s(%s)", s_castFunctions[currentShaderCasts->castType].functionName, currentShaderCasts->tempVariableName ); + bstring replacementVarName = bformat( "%s(%s)", s_castFunctions[currentShaderCasts->castType].functionName, currentShaderCasts->replacementVariableName ); + bfindreplace( *overloadString, tempVarName, replacementVarName, 0 ); + + // Cleanup bstrings allocated from bformat + bdestroy( tempVarName ); + bdestroy( replacementVarName ); + + currentVariableIndex++; + currentShaderCasts = currentShaderCasts->next; + } + + // Now append our modified string to the full shader file + bconcat( *originalString, *overloadString ); +} diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c new file mode 100644 index 0000000000..3f24fa3341 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.c @@ -0,0 +1,20 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bsafe.c + * + * This is an optional module that can be used to help enforce a safety + * standard based on pervasive usage of bstrlib. This file is not necessarily + * portable, however, it has been tested to work correctly with Intel's C/C++ + * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "bsafe.h" diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h new file mode 100644 index 0000000000..3a647a6ac8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bsafe.h @@ -0,0 +1,45 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bsafe.h + * + * This is an optional module that can be used to help enforce a safety + * standard based on pervasive usage of bstrlib. This file is not necessarily + * portable, however, it has been tested to work correctly with Intel's C/C++ + * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. + */ + +#ifndef BSTRLIB_BSAFE_INCLUDE +#define BSTRLIB_BSAFE_INCLUDE + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__GNUC__) && !defined(__clang__) +#if !defined (__GNUC__) && (!defined(_MSC_VER) || (_MSC_VER <= 1310)) +/* This is caught in the linker, so its not necessary for gcc. */ +extern char * (gets) (char * buf); +#endif + +extern char * (strncpy) (char *dst, const char *src, size_t n); +extern char * (strncat) (char *dst, const char *src, size_t n); +extern char * (strtok) (char *s1, const char *s2); +extern char * (strdup) (const char *s); + +#undef strcpy +#undef strcat +#define strcpy(a,b) bsafe_strcpy(a,b) +#define strcat(a,b) bsafe_strcat(a,b) +#endif +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c new file mode 100644 index 0000000000..2dc7b04840 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.c @@ -0,0 +1,1134 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstraux.c + * + * This file is not necessarily part of the core bstring library itself, but + * is just an auxilliary module which includes miscellaneous or trivial + * functions. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include "bstrlib.h" +#include "bstraux.h" + +/* bstring bTail (bstring b, int n) + * + * Return with a string of the last n characters of b. + */ +bstring bTail (bstring b, int n) { + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; + if (n >= b->slen) return bstrcpy (b); + return bmidstr (b, b->slen - n, n); +} + +/* bstring bHead (bstring b, int n) + * + * Return with a string of the first n characters of b. + */ +bstring bHead (bstring b, int n) { + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; + if (n >= b->slen) return bstrcpy (b); + return bmidstr (b, 0, n); +} + +/* int bFill (bstring a, char c, int len) + * + * Fill a given bstring with the character in parameter c, for a length n. + */ +int bFill (bstring b, char c, int len) { + if (b == NULL || len < 0 || (b->mlen < b->slen && b->mlen > 0)) return -__LINE__; + b->slen = 0; + return bsetstr (b, len, NULL, c); +} + +/* int bReplicate (bstring b, int n) + * + * Replicate the contents of b end to end n times and replace it in b. + */ +int bReplicate (bstring b, int n) { + return bpattern (b, n * b->slen); +} + +/* int bReverse (bstring b) + * + * Reverse the contents of b in place. + */ +int bReverse (bstring b) { +int i, n, m; +unsigned char t; + + if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; + n = b->slen; + if (2 <= n) { + m = ((unsigned)n) >> 1; + n--; + for (i=0; i < m; i++) { + t = b->data[n - i]; + b->data[n - i] = b->data[i]; + b->data[i] = t; + } + } + return 0; +} + +/* int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) + * + * Insert a repeated sequence of a given character into the string at + * position pos for a length len. + */ +int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) { + if (b == NULL || b->slen < 0 || b->mlen < b->slen || pos < 0 || len <= 0) return -__LINE__; + + if (pos > b->slen + && 0 > bsetstr (b, pos, NULL, fill)) return -__LINE__; + + if (0 > balloc (b, b->slen + len)) return -__LINE__; + if (pos < b->slen) memmove (b->data + pos + len, b->data + pos, b->slen - pos); + memset (b->data + pos, c, len); + b->slen += len; + b->data[b->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bJustifyLeft (bstring b, int space) + * + * Left justify a string. + */ +int bJustifyLeft (bstring b, int space) { +int j, i, s, t; +unsigned char c = (unsigned char) space; + + if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; + if (space != (int) c) return BSTR_OK; + + for (s=j=i=0; i < b->slen; i++) { + t = s; + s = c != (b->data[j] = b->data[i]); + j += (t|s); + } + if (j > 0 && b->data[j-1] == c) j--; + + b->data[j] = (unsigned char) '\0'; + b->slen = j; + return BSTR_OK; +} + +/* int bJustifyRight (bstring b, int width, int space) + * + * Right justify a string to within a given width. + */ +int bJustifyRight (bstring b, int width, int space) { +int ret; + if (width <= 0) return -__LINE__; + if (0 > (ret = bJustifyLeft (b, space))) return ret; + if (b->slen <= width) + return bInsertChrs (b, 0, width - b->slen, (unsigned char) space, (unsigned char) space); + return BSTR_OK; +} + +/* int bJustifyCenter (bstring b, int width, int space) + * + * Center a string's non-white space characters to within a given width by + * inserting whitespaces at the beginning. + */ +int bJustifyCenter (bstring b, int width, int space) { +int ret; + if (width <= 0) return -__LINE__; + if (0 > (ret = bJustifyLeft (b, space))) return ret; + if (b->slen <= width) + return bInsertChrs (b, 0, (width - b->slen + 1) >> 1, (unsigned char) space, (unsigned char) space); + return BSTR_OK; +} + +/* int bJustifyMargin (bstring b, int width, int space) + * + * Stretch a string to flush against left and right margins by evenly + * distributing additional white space between words. If the line is too + * long to be margin justified, it is left justified. + */ +int bJustifyMargin (bstring b, int width, int space) { +struct bstrList * sl; +int i, l, c; + + if (b == NULL || b->slen < 0 || b->mlen == 0 || b->mlen < b->slen) return -__LINE__; + if (NULL == (sl = bsplit (b, (unsigned char) space))) return -__LINE__; + for (l=c=i=0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + c ++; + l += sl->entry[i]->slen; + } + } + + if (l + c >= width || c < 2) { + bstrListDestroy (sl); + return bJustifyLeft (b, space); + } + + b->slen = 0; + for (i=0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + if (b->slen > 0) { + int s = (width - l + (c / 2)) / c; + bInsertChrs (b, b->slen, s, (unsigned char) space, (unsigned char) space); + l += s; + } + bconcat (b, sl->entry[i]); + c--; + if (c <= 0) break; + } + } + + bstrListDestroy (sl); + return BSTR_OK; +} + +static size_t readNothing (void *buff, size_t elsize, size_t nelem, void *parm) { + buff = buff; + elsize = elsize; + nelem = nelem; + parm = parm; + return 0; /* Immediately indicate EOF. */ +} + +/* struct bStream * bsFromBstr (const_bstring b); + * + * Create a bStream whose contents are a copy of the bstring passed in. + * This allows the use of all the bStream APIs with bstrings. + */ +struct bStream * bsFromBstr (const_bstring b) { +struct bStream * s = bsopen ((bNread) readNothing, NULL); + bsunread (s, b); /* Push the bstring data into the empty bStream. */ + return s; +} + +static size_t readRef (void *buff, size_t elsize, size_t nelem, void *parm) { +struct tagbstring * t = (struct tagbstring *) parm; +size_t tsz = elsize * nelem; + + if (tsz > (size_t) t->slen) tsz = (size_t) t->slen; + if (tsz > 0) { + memcpy (buff, t->data, tsz); + t->slen -= (int) tsz; + t->data += tsz; + return tsz / elsize; + } + return 0; +} + +/* The "by reference" version of the above function. This function puts + * a number of restrictions on the call site (the passed in struct + * tagbstring *will* be modified by this function, and the source data + * must remain alive and constant for the lifetime of the bStream). + * Hence it is not presented as an extern. + */ +static struct bStream * bsFromBstrRef (struct tagbstring * t) { + if (!t) return NULL; + return bsopen ((bNread) readRef, t); +} + +/* char * bStr2NetStr (const_bstring b) + * + * Convert a bstring to a netstring. See + * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * Note: 1) The value returned should be freed with a call to bcstrfree() at + * the point when it will no longer be referenced to avoid a memory + * leak. + * 2) If the returned value is non-NULL, then it also '\0' terminated + * in the character position one past the "," terminator. + */ +char * bStr2NetStr (const_bstring b) { +char strnum[sizeof (b->slen) * 3 + 1]; +bstring s; +unsigned char * buff; + + if (b == NULL || b->data == NULL || b->slen < 0) return NULL; + sprintf (strnum, "%d:", b->slen); + if (NULL == (s = bfromcstr (strnum)) + || bconcat (s, b) == BSTR_ERR || bconchar (s, (char) ',') == BSTR_ERR) { + bdestroy (s); + return NULL; + } + buff = s->data; + bcstrfree ((char *) s); + return (char *) buff; +} + +/* bstring bNetStr2Bstr (const char * buf) + * + * Convert a netstring to a bstring. See + * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * Note that the terminating "," *must* be present, however a following '\0' + * is *not* required. + */ +bstring bNetStr2Bstr (const char * buff) { +int i, x; +bstring b; + if (buff == NULL) return NULL; + x = 0; + for (i=0; buff[i] != ':'; i++) { + unsigned int v = buff[i] - '0'; + if (v > 9 || x > ((INT_MAX - (signed int)v) / 10)) return NULL; + x = (x * 10) + v; + } + + /* This thing has to be properly terminated */ + if (buff[i + 1 + x] != ',') return NULL; + + if (NULL == (b = bfromcstr (""))) return NULL; + if (balloc (b, x + 1) != BSTR_OK) { + bdestroy (b); + return NULL; + } + memcpy (b->data, buff + i + 1, x); + b->data[x] = (unsigned char) '\0'; + b->slen = x; + return b; +} + +static char b64ETable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* bstring bBase64Encode (const_bstring b) + * + * Generate a base64 encoding. See: RFC1341 + */ +bstring bBase64Encode (const_bstring b) { +int i, c0, c1, c2, c3; +bstring out; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + out = bfromcstr (""); + for (i=0; i + 2 < b->slen; i += 3) { + if (i && ((i % 57) == 0)) { + if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { + bdestroy (out); + return NULL; + } + } + c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | + (b->data[i+1] >> 4)) & 0x3F; + c2 = ((b->data[i+1] << 2) | + (b->data[i+2] >> 6)) & 0x3F; + c3 = b->data[i+2] & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, b64ETable[c2]) < 0 || + bconchar (out, b64ETable[c3]) < 0) { + bdestroy (out); + return NULL; + } + } + + if (i && ((i % 57) == 0)) { + if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { + bdestroy (out); + return NULL; + } + } + + switch (i + 2 - b->slen) { + case 0: c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | + (b->data[i+1] >> 4)) & 0x3F; + c2 = (b->data[i+1] << 2) & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, b64ETable[c2]) < 0 || + bconchar (out, (char) '=') < 0) { + bdestroy (out); + return NULL; + } + break; + case 1: c0 = b->data[i] >> 2; + c1 = (b->data[i] << 4) & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, (char) '=') < 0 || + bconchar (out, (char) '=') < 0) { + bdestroy (out); + return NULL; + } + break; + case 2: break; + } + + return out; +} + +#define B64_PAD (-2) +#define B64_ERR (-1) + +static int base64DecodeSymbol (unsigned char alpha) { + if ((alpha >= 'A') && (alpha <= 'Z')) return (int)(alpha - 'A'); + else if ((alpha >= 'a') && (alpha <= 'z')) + return 26 + (int)(alpha - 'a'); + else if ((alpha >= '0') && (alpha <= '9')) + return 52 + (int)(alpha - '0'); + else if (alpha == '+') return 62; + else if (alpha == '/') return 63; + else if (alpha == '=') return B64_PAD; + else return B64_ERR; +} + +/* bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) + * + * Decode a base64 block of data. All MIME headers are assumed to have been + * removed. See: RFC1341 + */ +bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) { +int i, v; +unsigned char c0, c1, c2; +bstring out; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + if (boolTruncError) *boolTruncError = 0; + out = bfromcstr (""); + i = 0; + for (;;) { + do { + if (i >= b->slen) return out; + if (b->data[i] == '=') { /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c0 = (unsigned char) (v << 2); + do { + if (i >= b->slen || b->data[i] == '=') { /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c0 |= (unsigned char) (v >> 4); + c1 = (unsigned char) (v << 4); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (b->data[i] == '=') { + i++; + if (i >= b->slen || b->data[i] != '=' || bconchar (out, c0) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); /* Missing "=" at the end. */ + return NULL; + } + return out; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c1 |= (unsigned char) (v >> 2); + c2 = (unsigned char) (v << 6); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (b->data[i] == '=') { + if (bconchar (out, c0) < 0 || bconchar (out, c1) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (boolTruncError) *boolTruncError = 0; + return out; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c2 |= (unsigned char) (v); + if (bconchar (out, c0) < 0 || + bconchar (out, c1) < 0 || + bconchar (out, c2) < 0) { + if (boolTruncError) { + *boolTruncError = -1; + return out; + } + bdestroy (out); + return NULL; + } + } +} + +#define UU_DECODE_BYTE(b) (((b) == (signed int)'`') ? 0 : (b) - (signed int)' ') + +struct bUuInOut { + bstring src, dst; + int * badlines; +}; + +#define UU_MAX_LINELEN 45 + +static int bUuDecLine (void * parm, int ofs, int len) { +struct bUuInOut * io = (struct bUuInOut *) parm; +bstring s = io->src; +bstring t = io->dst; +int i, llen, otlen, ret, c0, c1, c2, c3, d0, d1, d2, d3; + + if (len == 0) return 0; + llen = UU_DECODE_BYTE (s->data[ofs]); + ret = 0; + + otlen = t->slen; + + if (((unsigned) llen) > UU_MAX_LINELEN) { ret = -__LINE__; + goto bl; + } + + llen += t->slen; + + for (i=1; i < s->slen && t->slen < llen;i += 4) { + unsigned char outoctet[3]; + c0 = UU_DECODE_BYTE (d0 = (int) bchare (s, i+ofs+0, ' ' - 1)); + c1 = UU_DECODE_BYTE (d1 = (int) bchare (s, i+ofs+1, ' ' - 1)); + c2 = UU_DECODE_BYTE (d2 = (int) bchare (s, i+ofs+2, ' ' - 1)); + c3 = UU_DECODE_BYTE (d3 = (int) bchare (s, i+ofs+3, ' ' - 1)); + + if (((unsigned) (c0|c1) >= 0x40)) { if (!ret) ret = -__LINE__; + if (d0 > 0x60 || (d0 < (' ' - 1) && !isspace (d0)) || + d1 > 0x60 || (d1 < (' ' - 1) && !isspace (d1))) { + t->slen = otlen; + goto bl; + } + c0 = c1 = 0; + } + outoctet[0] = (unsigned char) ((c0 << 2) | ((unsigned) c1 >> 4)); + if (t->slen+1 >= llen) { + if (0 > bconchar (t, (char) outoctet[0])) return -__LINE__; + break; + } + if ((unsigned) c2 >= 0x40) { if (!ret) ret = -__LINE__; + if (d2 > 0x60 || (d2 < (' ' - 1) && !isspace (d2))) { + t->slen = otlen; + goto bl; + } + c2 = 0; + } + outoctet[1] = (unsigned char) ((c1 << 4) | ((unsigned) c2 >> 2)); + if (t->slen+2 >= llen) { + if (0 > bcatblk (t, outoctet, 2)) return -__LINE__; + break; + } + if ((unsigned) c3 >= 0x40) { if (!ret) ret = -__LINE__; + if (d3 > 0x60 || (d3 < (' ' - 1) && !isspace (d3))) { + t->slen = otlen; + goto bl; + } + c3 = 0; + } + outoctet[2] = (unsigned char) ((c2 << 6) | ((unsigned) c3)); + if (0 > bcatblk (t, outoctet, 3)) return -__LINE__; + } + if (t->slen < llen) { if (0 == ret) ret = -__LINE__; + t->slen = otlen; + } + bl:; + if (ret && io->badlines) { + (*io->badlines)++; + return 0; + } + return ret; +} + +/* bstring bUuDecodeEx (const_bstring src, int * badlines) + * + * Performs a UUDecode of a block of data. If there are errors in the + * decoding, they are counted up and returned in "badlines", if badlines is + * not NULL. It is assumed that the "begin" and "end" lines have already + * been stripped off. The potential security problem of writing the + * filename in the begin line is something that is beyond the scope of a + * portable library. + */ + +#ifdef _MSC_VER +#pragma warning(disable:4204) +#endif + +bstring bUuDecodeEx (const_bstring src, int * badlines) { +struct tagbstring t; +struct bStream * s; +struct bStream * d; +bstring b; + + if (!src) return NULL; + t = *src; /* Short lifetime alias to header of src */ + s = bsFromBstrRef (&t); /* t is undefined after this */ + if (!s) return NULL; + d = bsUuDecode (s, badlines); + b = bfromcstralloc (256, ""); + if (NULL == b || 0 > bsread (b, d, INT_MAX)) { + bdestroy (b); + bsclose (d); + bsclose (s); + return NULL; + } + return b; +} + +struct bsUuCtx { + struct bUuInOut io; + struct bStream * sInp; +}; + +static size_t bsUuDecodePart (void *buff, size_t elsize, size_t nelem, void *parm) { +static struct tagbstring eol = bsStatic ("\r\n"); +struct bsUuCtx * luuCtx = (struct bsUuCtx *) parm; +size_t tsz; +int l, lret; + + if (NULL == buff || NULL == parm) return 0; + tsz = elsize * nelem; + + CheckInternalBuffer:; + /* If internal buffer has sufficient data, just output it */ + if (((size_t) luuCtx->io.dst->slen) > tsz) { + memcpy (buff, luuCtx->io.dst->data, tsz); + bdelete (luuCtx->io.dst, 0, (int) tsz); + return nelem; + } + + DecodeMore:; + if (0 <= (l = binchr (luuCtx->io.src, 0, &eol))) { + int ol = 0; + struct tagbstring t; + bstring s = luuCtx->io.src; + luuCtx->io.src = &t; + + do { + if (l > ol) { + bmid2tbstr (t, s, ol, l - ol); + lret = bUuDecLine (&luuCtx->io, 0, t.slen); + if (0 > lret) { + luuCtx->io.src = s; + goto Done; + } + } + ol = l + 1; + if (((size_t) luuCtx->io.dst->slen) > tsz) break; + l = binchr (s, ol, &eol); + } while (BSTR_ERR != l); + bdelete (s, 0, ol); + luuCtx->io.src = s; + goto CheckInternalBuffer; + } + + if (BSTR_ERR != bsreada (luuCtx->io.src, luuCtx->sInp, bsbufflength (luuCtx->sInp, BSTR_BS_BUFF_LENGTH_GET))) { + goto DecodeMore; + } + + bUuDecLine (&luuCtx->io, 0, luuCtx->io.src->slen); + + Done:; + /* Output any lingering data that has been translated */ + if (((size_t) luuCtx->io.dst->slen) > 0) { + if (((size_t) luuCtx->io.dst->slen) > tsz) goto CheckInternalBuffer; + memcpy (buff, luuCtx->io.dst->data, luuCtx->io.dst->slen); + tsz = luuCtx->io.dst->slen / elsize; + luuCtx->io.dst->slen = 0; + if (tsz > 0) return tsz; + } + + /* Deallocate once EOF becomes triggered */ + bdestroy (luuCtx->io.dst); + bdestroy (luuCtx->io.src); + free (luuCtx); + return 0; +} + +/* bStream * bsUuDecode (struct bStream * sInp, int * badlines) + * + * Creates a bStream which performs the UUDecode of an an input stream. If + * there are errors in the decoding, they are counted up and returned in + * "badlines", if badlines is not NULL. It is assumed that the "begin" and + * "end" lines have already been stripped off. The potential security + * problem of writing the filename in the begin line is something that is + * beyond the scope of a portable library. + */ + +struct bStream * bsUuDecode (struct bStream * sInp, int * badlines) { +struct bsUuCtx * luuCtx = (struct bsUuCtx *) malloc (sizeof (struct bsUuCtx)); +struct bStream * sOut; + + if (NULL == luuCtx) return NULL; + + luuCtx->io.src = bfromcstr (""); + luuCtx->io.dst = bfromcstr (""); + if (NULL == luuCtx->io.dst || NULL == luuCtx->io.src) { + CleanUpFailureToAllocate:; + bdestroy (luuCtx->io.dst); + bdestroy (luuCtx->io.src); + free (luuCtx); + return NULL; + } + luuCtx->io.badlines = badlines; + if (badlines) *badlines = 0; + + luuCtx->sInp = sInp; + + sOut = bsopen ((bNread) bsUuDecodePart, luuCtx); + if (NULL == sOut) goto CleanUpFailureToAllocate; + return sOut; +} + +#define UU_ENCODE_BYTE(b) (char) (((b) == 0) ? '`' : ((b) + ' ')) + +/* bstring bUuEncode (const_bstring src) + * + * Performs a UUEncode of a block of data. The "begin" and "end" lines are + * not appended. + */ +bstring bUuEncode (const_bstring src) { +bstring out; +int i, j, jm; +unsigned int c0, c1, c2; + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + for (i=0; i < src->slen; i += UU_MAX_LINELEN) { + if ((jm = i + UU_MAX_LINELEN) > src->slen) jm = src->slen; + if (bconchar (out, UU_ENCODE_BYTE (jm - i)) < 0) { + bstrFree (out); + break; + } + for (j = i; j < jm; j += 3) { + c0 = (unsigned int) bchar (src, j ); + c1 = (unsigned int) bchar (src, j + 1); + c2 = (unsigned int) bchar (src, j + 2); + if (bconchar (out, UU_ENCODE_BYTE ( (c0 & 0xFC) >> 2)) < 0 || + bconchar (out, UU_ENCODE_BYTE (((c0 & 0x03) << 4) | ((c1 & 0xF0) >> 4))) < 0 || + bconchar (out, UU_ENCODE_BYTE (((c1 & 0x0F) << 2) | ((c2 & 0xC0) >> 6))) < 0 || + bconchar (out, UU_ENCODE_BYTE ( (c2 & 0x3F))) < 0) { + bstrFree (out); + goto End; + } + } + if (bconchar (out, (char) '\r') < 0 || bconchar (out, (char) '\n') < 0) { + bstrFree (out); + break; + } + } + End:; + return out; +} + +/* bstring bYEncode (const_bstring src) + * + * Performs a YEncode of a block of data. No header or tail info is + * appended. See: http://www.yenc.org/whatis.htm and + * http://www.yenc.org/yenc-draft.1.3.txt + */ +bstring bYEncode (const_bstring src) { +int i; +bstring out; +unsigned char c; + + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + for (i=0; i < src->slen; i++) { + c = (unsigned char)(src->data[i] + 42); + if (c == '=' || c == '\0' || c == '\r' || c == '\n') { + if (0 > bconchar (out, (char) '=')) { + bdestroy (out); + return NULL; + } + c += (unsigned char) 64; + } + if (0 > bconchar (out, c)) { + bdestroy (out); + return NULL; + } + } + return out; +} + +/* bstring bYDecode (const_bstring src) + * + * Performs a YDecode of a block of data. See: + * http://www.yenc.org/whatis.htm and http://www.yenc.org/yenc-draft.1.3.txt + */ +#define MAX_OB_LEN (64) + +bstring bYDecode (const_bstring src) { +int i; +bstring out; +unsigned char c; +unsigned char octetbuff[MAX_OB_LEN]; +int obl; + + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + + obl = 0; + + for (i=0; i < src->slen; i++) { + if ('=' == (c = src->data[i])) { /* The = escape mode */ + i++; + if (i >= src->slen) { + bdestroy (out); + return NULL; + } + c = (unsigned char) (src->data[i] - 64); + } else { + if ('\0' == c) { + bdestroy (out); + return NULL; + } + + /* Extraneous CR/LFs are to be ignored. */ + if (c == '\r' || c == '\n') continue; + } + + octetbuff[obl] = (unsigned char) ((int) c - 42); + obl++; + + if (obl >= MAX_OB_LEN) { + if (0 > bcatblk (out, octetbuff, obl)) { + bdestroy (out); + return NULL; + } + obl = 0; + } + } + + if (0 > bcatblk (out, octetbuff, obl)) { + bdestroy (out); + out = NULL; + } + return out; +} + +/* bstring bStrfTime (const char * fmt, const struct tm * timeptr) + * + * Takes a format string that is compatible with strftime and a struct tm + * pointer, formats the time according to the format string and outputs + * the bstring as a result. Note that if there is an early generation of a + * '\0' character, the bstring will be truncated to this end point. + */ +bstring bStrfTime (const char * fmt, const struct tm * timeptr) { +#if defined (__TURBOC__) && !defined (__BORLANDC__) +static struct tagbstring ns = bsStatic ("bStrfTime Not supported"); + fmt = fmt; + timeptr = timeptr; + return &ns; +#else +bstring buff; +int n; +size_t r; + + if (fmt == NULL) return NULL; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "strftime" call on increasing + potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < 16) n = 16; + buff = bfromcstralloc (n+2, ""); + + for (;;) { + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return NULL; + } + + r = strftime ((char *) buff->data, n + 1, fmt, timeptr); + + if (r > 0) { + buff->slen = (int) r; + break; + } + + n += n; + } + + return buff; +#endif +} + +/* int bSetCstrChar (bstring a, int pos, char c) + * + * Sets the character at position pos to the character c in the bstring a. + * If the character c is NUL ('\0') then the string is truncated at this + * point. Note: this does not enable any other '\0' character in the bstring + * as terminator indicator for the string. pos must be in the position + * between 0 and b->slen inclusive, otherwise BSTR_ERR will be returned. + */ +int bSetCstrChar (bstring b, int pos, char c) { + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) + return BSTR_ERR; + if (pos < 0 || pos > b->slen) return BSTR_ERR; + + if (pos == b->slen) { + if ('\0' != c) return bconchar (b, c); + return 0; + } + + b->data[pos] = (unsigned char) c; + if ('\0' == c) b->slen = pos; + + return 0; +} + +/* int bSetChar (bstring b, int pos, char c) + * + * Sets the character at position pos to the character c in the bstring a. + * The string is not truncated if the character c is NUL ('\0'). pos must + * be in the position between 0 and b->slen inclusive, otherwise BSTR_ERR + * will be returned. + */ +int bSetChar (bstring b, int pos, char c) { + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) + return BSTR_ERR; + if (pos < 0 || pos > b->slen) return BSTR_ERR; + + if (pos == b->slen) { + return bconchar (b, c); + } + + b->data[pos] = (unsigned char) c; + return 0; +} + +#define INIT_SECURE_INPUT_LENGTH (256) + +/* bstring bSecureInput (int maxlen, int termchar, + * bNgetc vgetchar, void * vgcCtx) + * + * Read input from an abstracted input interface, for a length of at most + * maxlen characters. If maxlen <= 0, then there is no length limit put + * on the input. The result is terminated early if vgetchar() return EOF + * or the user specified value termchar. + * + */ +bstring bSecureInput (int maxlen, int termchar, bNgetc vgetchar, void * vgcCtx) { +int i, m, c; +bstring b, t; + + if (!vgetchar) return NULL; + + b = bfromcstralloc (INIT_SECURE_INPUT_LENGTH, ""); + if ((c = UCHAR_MAX + 1) == termchar) c++; + + for (i=0; ; i++) { + if (termchar == c || (maxlen > 0 && i >= maxlen)) c = EOF; + else c = vgetchar (vgcCtx); + + if (EOF == c) break; + + if (i+1 >= b->mlen) { + + /* Double size, but deal with unusual case of numeric + overflows */ + + if ((m = b->mlen << 1) <= b->mlen && + (m = b->mlen + 1024) <= b->mlen && + (m = b->mlen + 16) <= b->mlen && + (m = b->mlen + 1) <= b->mlen) t = NULL; + else t = bfromcstralloc (m, ""); + + if (t) memcpy (t->data, b->data, i); + bSecureDestroy (b); /* Cleanse previous buffer */ + b = t; + if (!b) return b; + } + + b->data[i] = (unsigned char) c; + } + + b->slen = i; + b->data[i] = (unsigned char) '\0'; + return b; +} + +#define BWS_BUFF_SZ (1024) + +struct bwriteStream { + bstring buff; /* Buffer for underwrites */ + void * parm; /* The stream handle for core stream */ + bNwrite writeFn; /* fwrite work-a-like fnptr for core stream */ + int isEOF; /* track stream's EOF state */ + int minBuffSz; +}; + +/* struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) + * + * Wrap a given open stream (described by a fwrite work-a-like function + * pointer and stream handle) into an open bwriteStream suitable for write + * streaming functions. + */ +struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) { +struct bwriteStream * ws; + + if (NULL == writeFn) return NULL; + ws = (struct bwriteStream *) malloc (sizeof (struct bwriteStream)); + if (ws) { + if (NULL == (ws->buff = bfromcstr (""))) { + free (ws); + ws = NULL; + } else { + ws->parm = parm; + ws->writeFn = writeFn; + ws->isEOF = 0; + ws->minBuffSz = BWS_BUFF_SZ; + } + } + return ws; +} + +#define internal_bwswriteout(ws,b) { \ + if ((b)->slen > 0) { \ + if (1 != (ws->writeFn ((b)->data, (b)->slen, 1, ws->parm))) { \ + ws->isEOF = 1; \ + return BSTR_ERR; \ + } \ + } \ +} + +/* int bwsWriteFlush (struct bwriteStream * ws) + * + * Force any pending data to be written to the core stream. + */ +int bwsWriteFlush (struct bwriteStream * ws) { + if (NULL == ws || ws->isEOF || 0 >= ws->minBuffSz || + NULL == ws->writeFn || NULL == ws->buff) return BSTR_ERR; + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + return 0; +} + +/* int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) + * + * Send a bstring to a bwriteStream. If the stream is at EOF BSTR_ERR is + * returned. Note that there is no deterministic way to determine the exact + * cut off point where the core stream stopped accepting data. + */ +int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) { +struct tagbstring t; +int l; + + if (NULL == ws || NULL == b || NULL == ws->buff || + ws->isEOF || 0 >= ws->minBuffSz || NULL == ws->writeFn) + return BSTR_ERR; + + /* Buffer prepacking optimization */ + if (b->slen > 0 && ws->buff->mlen - ws->buff->slen > b->slen) { + static struct tagbstring empty = bsStatic (""); + if (0 > bconcat (ws->buff, b)) return BSTR_ERR; + return bwsWriteBstr (ws, &empty); + } + + if (0 > (l = ws->minBuffSz - ws->buff->slen)) { + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + l = ws->minBuffSz; + } + + if (b->slen < l) return bconcat (ws->buff, b); + + if (0 > bcatblk (ws->buff, b->data, l)) return BSTR_ERR; + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + + bmid2tbstr (t, (bstring) b, l, b->slen); + + if (t.slen >= ws->minBuffSz) { + internal_bwswriteout (ws, &t); + return 0; + } + + return bassign (ws->buff, &t); +} + +/* int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) + * + * Send a block of data a bwriteStream. If the stream is at EOF BSTR_ERR is + * returned. + */ +int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) { +struct tagbstring t; + if (NULL == blk || len < 0) return BSTR_ERR; + blk2tbstr (t, blk, len); + return bwsWriteBstr (ws, &t); +} + +/* int bwsIsEOF (const struct bwriteStream * ws) + * + * Returns 0 if the stream is currently writable, 1 if the core stream has + * responded by not accepting the previous attempted write. + */ +int bwsIsEOF (const struct bwriteStream * ws) { + if (NULL == ws || NULL == ws->buff || 0 > ws->minBuffSz || + NULL == ws->writeFn) return BSTR_ERR; + return ws->isEOF; +} + +/* int bwsBuffLength (struct bwriteStream * ws, int sz) + * + * Set the length of the buffer used by the bwsStream. If sz is zero, the + * length is not set. This function returns with the previous length. + */ +int bwsBuffLength (struct bwriteStream * ws, int sz) { +int oldSz; + if (ws == NULL || sz < 0) return BSTR_ERR; + oldSz = ws->minBuffSz; + if (sz > 0) ws->minBuffSz = sz; + return oldSz; +} + +/* void * bwsClose (struct bwriteStream * s) + * + * Close the bwriteStream, and return the handle to the stream that was + * originally used to open the given stream. Note that even if the stream + * is at EOF it still needs to be closed with a call to bwsClose. + */ +void * bwsClose (struct bwriteStream * ws) { +void * parm; + if (NULL == ws || NULL == ws->buff || 0 >= ws->minBuffSz || + NULL == ws->writeFn) return NULL; + bwsWriteFlush (ws); + parm = ws->parm; + ws->parm = NULL; + ws->minBuffSz = -1; + ws->writeFn = NULL; + bstrFree (ws->buff); + free (ws); + return parm; +} + diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h new file mode 100644 index 0000000000..e10c6e1a68 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstraux.h @@ -0,0 +1,113 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstraux.h + * + * This file is not a necessary part of the core bstring library itself, but + * is just an auxilliary module which includes miscellaneous or trivial + * functions. + */ + +#ifndef BSTRAUX_INCLUDE +#define BSTRAUX_INCLUDE + +#include <time.h> +#include "bstrlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Safety mechanisms */ +#define bstrDeclare(b) bstring (b) = NULL; +#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }} + +/* Backward compatibilty with previous versions of Bstrlib */ +#define bAssign(a,b) ((bassign)((a), (b))) +#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) +#define bStrchr(b,c) ((bstrchr)((b), (c))) +#define bStrchrFast(b,c) ((bstrchr)((b), (c))) +#define bCatCstr(b,s) ((bcatcstr)((b), (s))) +#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) +#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1) +#define bTrunc(b,n) ((btrunc)((b), (n))) +#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos))) +#define bUppercase(b) ((btoupper)(b)) +#define bLowercase(b) ((btolower)(b)) +#define bCaselessCmp(a,b) ((bstricmp)((a), (b))) +#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n))) +#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL)) +#define bUuDecode(b) (bUuDecodeEx ((b), NULL)) + +/* Unusual functions */ +extern struct bStream * bsFromBstr (const_bstring b); +extern bstring bTail (bstring b, int n); +extern bstring bHead (bstring b, int n); +extern int bSetCstrChar (bstring a, int pos, char c); +extern int bSetChar (bstring b, int pos, char c); +extern int bFill (bstring a, char c, int len); +extern int bReplicate (bstring b, int n); +extern int bReverse (bstring b); +extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill); +extern bstring bStrfTime (const char * fmt, const struct tm * timeptr); +#define bAscTime(t) (bStrfTime ("%c\n", (t))) +#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL) + +/* Spacing formatting */ +extern int bJustifyLeft (bstring b, int space); +extern int bJustifyRight (bstring b, int width, int space); +extern int bJustifyMargin (bstring b, int width, int space); +extern int bJustifyCenter (bstring b, int width, int space); + +/* Esoteric standards specific functions */ +extern char * bStr2NetStr (const_bstring b); +extern bstring bNetStr2Bstr (const char * buf); +extern bstring bBase64Encode (const_bstring b); +extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError); +extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines); +extern bstring bUuDecodeEx (const_bstring src, int * badlines); +extern bstring bUuEncode (const_bstring src); +extern bstring bYEncode (const_bstring src); +extern bstring bYDecode (const_bstring src); + +/* Writable stream */ +typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm); + +struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm); +int bwsWriteBstr (struct bwriteStream * stream, const_bstring b); +int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len); +int bwsWriteFlush (struct bwriteStream * stream); +int bwsIsEOF (const struct bwriteStream * stream); +int bwsBuffLength (struct bwriteStream * stream, int sz); +void * bwsClose (struct bwriteStream * stream); + +/* Security functions */ +#define bSecureDestroy(b) { \ +bstring bstr__tmp = (b); \ + if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \ + (void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \ + bdestroy (bstr__tmp); \ + } \ +} +#define bSecureWriteProtect(t) { \ + if ((t).mlen >= 0) { \ + if ((t).mlen > (t).slen)) { \ + (void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \ + } \ + (t).mlen = -1; \ + } \ +} +extern bstring bSecureInput (int maxlen, int termchar, + bNgetc vgetchar, void * vgcCtx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c new file mode 100644 index 0000000000..7c233454ba --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.c @@ -0,0 +1,2976 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstrlib.c + * + * This file is the core module for implementing the bstring functions. + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "bstrlib.h" +#include "../internal_includes/hlslcc_malloc.h" + +/* Optionally include a mechanism for debugging memory */ + +#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) +#include "memdbg.h" +#endif + +#ifndef bstr__alloc +#define bstr__alloc(x) malloc (x) +#endif + +#ifndef bstr__free +#define bstr__free(p) free (p) +#endif + +#ifndef bstr__realloc +#define bstr__realloc(p,x) realloc ((p), (x)) +#endif + +#ifndef bstr__memcpy +#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) +#endif + +#ifndef bstr__memmove +#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) +#endif + +#ifndef bstr__memset +#define bstr__memset(d,c,l) memset ((d), (c), (l)) +#endif + +#ifndef bstr__memcmp +#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) +#endif + +#ifndef bstr__memchr +#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) +#endif + +/* Just a length safe wrapper for memmove. */ + +#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } + +/* Compute the snapped size for a given requested size. By snapping to powers + of 2 like this, repeated reallocations are avoided. */ +static int snapUpSize (int i) { + if (i < 8) { + i = 8; + } else { + unsigned int j; + j = (unsigned int) i; + + j |= (j >> 1); + j |= (j >> 2); + j |= (j >> 4); + j |= (j >> 8); /* Ok, since int >= 16 bits */ +#if (UINT_MAX != 0xffff) + j |= (j >> 16); /* For 32 bit int systems */ +#if (UINT_MAX > 0xffffffffUL) + j |= (j >> 32); /* For 64 bit int systems */ +#endif +#endif + /* Least power of two greater than i */ + j++; + if ((int) j >= i) i = (int) j; + } + return i; +} + +/* int balloc (bstring b, int len) + * + * Increase the size of the memory backing the bstring b to at least len. + */ +int balloc (bstring b, int olen) { + int len; + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || + b->mlen < b->slen || olen <= 0) { + return BSTR_ERR; + } + + if (olen >= b->mlen) { + unsigned char * x; + + if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; + + /* Assume probability of a non-moving realloc is 0.125 */ + if (7 * b->mlen < 8 * b->slen) { + + /* If slen is close to mlen in size then use realloc to reduce + the memory defragmentation */ + + reallocStrategy:; + + x = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (x == NULL) { + + /* Since we failed, try allocating the tighest possible + allocation */ + + if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { + return BSTR_ERR; + } + } + } else { + + /* If slen is not close to mlen then avoid the penalty of copying + the extra bytes that are allocated, but not considered part of + the string */ + + if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { + + /* Perhaps there is no available memory for the two + allocations to be in memory at once */ + + goto reallocStrategy; + + } else { + if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); + bstr__free (b->data); + } + } + b->data = x; + b->mlen = len; + b->data[b->slen] = (unsigned char) '\0'; + } + + return BSTR_OK; +} + +/* int ballocmin (bstring b, int len) + * + * Set the size of the memory backing the bstring b to len or b->slen+1, + * whichever is larger. Note that repeated use of this function can degrade + * performance. + */ +int ballocmin (bstring b, int len) { + unsigned char * s; + + if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || + b->mlen < b->slen || len <= 0) { + return BSTR_ERR; + } + + if (len < b->slen + 1) len = b->slen + 1; + + if (len != b->mlen) { + s = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (NULL == s) return BSTR_ERR; + s[b->slen] = (unsigned char) '\0'; + b->data = s; + b->mlen = len; + } + + return BSTR_OK; +} + +/* bstring bfromcstr (const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. + */ +bstring bfromcstr (const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; + b->slen = (int) j; + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring bfromcstralloc (int mlen, const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. The memory buffer backing the string is at least len + * characters in length. + */ +bstring bfromcstralloc (int mlen, const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = (int) j; + if (i < mlen) i = mlen; + + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring blk2bstr (const void * blk, int len) + * + * Create a bstring which contains the content of the block blk of length + * len. + */ +bstring blk2bstr (const void * blk, int len) { +bstring b; +int i; + + if (blk == NULL || len < 0) return NULL; + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = len; + + i = len + (2 - (len != 0)); + i = snapUpSize (i); + + b->mlen = i; + + b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); + b->data[len] = (unsigned char) '\0'; + + return b; +} + +/* char * bstr2cstr (const_bstring s, char z) + * + * Create a '\0' terminated char * buffer which is equal to the contents of + * the bstring s, except that any contained '\0' characters are converted + * to the character in z. This returned value should be freed with a + * bcstrfree () call, by the calling application. + */ +char * bstr2cstr (const_bstring b, char z) { +int i, l; +char * r; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + l = b->slen; + r = (char *) bstr__alloc ((size_t) (l + 1)); + if (r == NULL) return r; + + for (i=0; i < l; i ++) { + r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); + } + + r[l] = (unsigned char) '\0'; + + return r; +} + +/* int bcstrfree (char * s) + * + * Frees a C-string generated by bstr2cstr (). This is normally unnecessary + * since it just wraps a call to bstr__free (), however, if bstr__alloc () + * and bstr__free () have been redefined as a macros within the bstrlib + * module (via defining them in memdbg.h after defining + * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std + * library functions, then this allows a correct way of freeing the memory + * that allows higher level code to be independent from these macro + * redefinitions. + */ +int bcstrfree (char * s) { + if (s) { + bstr__free (s); + return BSTR_OK; + } + return BSTR_ERR; +} + +/* int bconcat (bstring b0, const_bstring b1) + * + * Concatenate the bstring b1 to the bstring b0. + */ +int bconcat (bstring b0, const_bstring b1) { +int len, d; +bstring aux = (bstring) b1; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; + + d = b0->slen; + len = b1->slen; + if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; + + if (b0->mlen <= d + len + 1) { + ptrdiff_t pd = b1->data - b0->data; + if (0 <= pd && pd < b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + if (balloc (b0, d + len + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + } + + bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); + b0->data[d + len] = (unsigned char) '\0'; + b0->slen = d + len; + if (aux != b1) bdestroy (aux); + return BSTR_OK; +} + +/* int bconchar (bstring b, char c) +/ * + * Concatenate the single character c to the bstring b. + */ +int bconchar (bstring b, char c) { +int d; + + if (b == NULL) return BSTR_ERR; + d = b->slen; + if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + b->data[d] = (unsigned char) c; + b->data[d + 1] = (unsigned char) '\0'; + b->slen++; + return BSTR_OK; +} + +/* int bcatcstr (bstring b, const char * s) + * + * Concatenate a char * string to a bstring. + */ +int bcatcstr (bstring b, const char * s) { +char * d; +int i, l; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL) return BSTR_ERR; + + /* Optimistically concatenate directly */ + l = b->mlen - b->slen; + d = (char *) &b->data[b->slen]; + for (i=0; i < l; i++) { + if ((*d++ = *s++) == '\0') { + b->slen += i; + return BSTR_OK; + } + } + b->slen += i; + + /* Need to explicitely resize and concatenate tail */ + return bcatblk (b, (const void *) s, (int) strlen (s)); +} + +/* int bcatblk (bstring b, const void * s, int len) + * + * Concatenate a fixed length buffer to a bstring. + */ +int bcatblk (bstring b, const void * s, int len) { +int nl; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; + + if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ + if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; + + bBlockCopy (&b->data[b->slen], s, (size_t) len); + b->slen = nl; + b->data[nl] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bstrcpy (const_bstring b) + * + * Create a copy of the bstring b. + */ +bstring bstrcpy (const_bstring b) { +bstring b0; +int i,j; + + /* Attempted to copy an invalid string? */ + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b0 == NULL) { + /* Unable to allocate memory for string header */ + return NULL; + } + + i = b->slen; + j = snapUpSize (i + 1); + + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + j = i + 1; + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + /* Unable to allocate memory for string data */ + bstr__free (b0); + return NULL; + } + } + + b0->mlen = j; + b0->slen = i; + + if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); + b0->data[b0->slen] = (unsigned char) '\0'; + + return b0; +} + +/* int bassign (bstring a, const_bstring b) + * + * Overwrite the string a with the contents of string b. + */ +int bassign (bstring a, const_bstring b) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + if (b->slen != 0) { + if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data, b->slen); + } else { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + } + a->data[b->slen] = (unsigned char) '\0'; + a->slen = b->slen; + return BSTR_OK; +} + +/* int bassignmidstr (bstring a, const_bstring b, int left, int len) + * + * Overwrite the string a with the middle of contents of string b + * starting from position left and running for a length len. left and + * len are clamped to the ends of b as with the function bmidstr. + */ +int bassignmidstr (bstring a, const_bstring b, int left, int len) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + + if (len > 0) { + if (balloc (a, len) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data + left, len); + a->slen = len; + } else { + a->slen = 0; + } + a->data[a->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bassigncstr (bstring a, const char * str) + * + * Overwrite the string a with the contents of char * string str. Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned however a may be partially overwritten. + */ +int bassigncstr (bstring a, const char * str) { +int i; +size_t len; + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == str) + return BSTR_ERR; + + for (i=0; i < a->mlen; i++) { + if ('\0' == (a->data[i] = str[i])) { + a->slen = i; + return BSTR_OK; + } + } + + a->slen = i; + len = strlen (str + i); + if (len > INT_MAX || i + len + 1 > INT_MAX || + 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; + bBlockCopy (a->data + i, str + i, (size_t) len + 1); + a->slen += (int) len; + return BSTR_OK; +} + +/* int bassignblk (bstring a, const void * s, int len) + * + * Overwrite the string a with the contents of the block (s, len). Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned and a is not overwritten. + */ +int bassignblk (bstring a, const void * s, int len) { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) + return BSTR_ERR; + if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; + bBlockCopy (a->data, s, (size_t) len); + a->data[len] = (unsigned char) '\0'; + a->slen = len; + return BSTR_OK; +} + +/* int btrunc (bstring b, int n) + * + * Truncate the bstring to at most n characters. + */ +int btrunc (bstring b, int n) { + if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + if (b->slen > n) { + b->slen = n; + b->data[n] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +#define upcase(c) (toupper ((unsigned char) c)) +#define downcase(c) (tolower ((unsigned char) c)) +#define wspace(c) (isspace ((unsigned char) c)) + +/* int btoupper (bstring b) + * + * Convert contents of bstring to upper case. + */ +int btoupper (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) upcase (b->data[i]); + } + return BSTR_OK; +} + +/* int btolower (bstring b) + * + * Convert contents of bstring to lower case. + */ +int btolower (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) downcase (b->data[i]); + } + return BSTR_OK; +} + +/* int bstricmp (const_bstring b0, const_bstring b1) + * + * Compare two strings without differentiating between case. The return + * value is the difference of the values of the characters where the two + * strings first differ after lower case transformation, otherwise 0 is + * returned indicating that the strings are equal. If the lengths are + * different, then a difference from 0 is given, but if the first extra + * character is '\0', then it is taken to be the value UCHAR_MAX+1. + */ +int bstricmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; + if ((n = b0->slen) > b1->slen) n = b1->slen; + else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = (char) downcase (b0->data[i]) + - (char) downcase (b1->data[i]); + if (0 != v) return v; + } + + if (b0->slen > n) { + v = (char) downcase (b0->data[n]); + if (v) return v; + return UCHAR_MAX + 1; + } + if (b1->slen > n) { + v = - (char) downcase (b1->data[n]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); + } + return BSTR_OK; +} + +/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) + * + * Compare two strings without differentiating between case for at most n + * characters. If the position where the two strings first differ is + * before the nth position, the return value is the difference of the values + * of the characters, otherwise 0 is returned. If the lengths are different + * and less than n characters, then a difference from 0 is given, but if the + * first extra character is '\0', then it is taken to be the value + * UCHAR_MAX+1. + */ +int bstrnicmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = (char) downcase (b0->data[i]); + v -= (char) downcase (b1->data[i]); + if (v != 0) return b0->data[i] - b1->data[i]; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) { + v = (char) downcase (b0->data[m]); + if (v) return v; + return UCHAR_MAX + 1; + } + + v = - (char) downcase (b1->data[m]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); +} + +/* int biseqcaseless (const_bstring b0, const_bstring b1) + * + * Compare two strings for equality without differentiating between case. + * If the strings differ other than in case, 0 is returned, if the strings + * are the same, 1 is returned, if there is an error, -1 is returned. If + * the length of the strings are different, this function is O(1). '\0' + * termination characters are not treated in any special way. + */ +int biseqcaseless (const_bstring b0, const_bstring b1) { +int i, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + for (i=0, n=b0->slen; i < n; i++) { + if (b0->data[i] != b1->data[i]) { + unsigned char c = (unsigned char) downcase (b0->data[i]); + if (c != (unsigned char) downcase (b1->data[i])) return 0; + } + } + return 1; +} + +/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len + * without differentiating between case for equality. If the beginning of b0 + * differs from the memory block other than in case (or if b0 is too short), + * 0 is returned, if the strings are the same, 1 is returned, if there is an + * error, -1 is returned. '\0' characters are not treated in any special + * way. + */ +int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) { + if (downcase (b0->data[i]) != + downcase (((const unsigned char *) blk)[i])) return 0; + } + } + return 1; +} + +/* + * int bltrimws (bstring b) + * + * Delete whitespace contiguous from the left end of the string. + */ +int bltrimws (bstring b) { +int i, len; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (len = b->slen, i = 0; i < len; i++) { + if (!wspace (b->data[i])) { + return bdelete (b, 0, i); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int brtrimws (bstring b) + * + * Delete whitespace contiguous from the right end of the string. + */ +int brtrimws (bstring b) { +int i; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + return BSTR_OK; + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int btrimws (bstring b) + * + * Delete whitespace contiguous from both ends of the string. + */ +int btrimws (bstring b) { +int i, j; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + for (j = 0; wspace (b->data[j]); j++) {} + return bdelete (b, 0, j); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* int biseq (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If the strings differ, 0 is returned, if + * the strings are the same, 1 is returned, if there is an error, -1 is + * returned. If the length of the strings are different, this function is + * O(1). '\0' termination characters are not treated in any special way. + */ +int biseq (const_bstring b0, const_bstring b1) { + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + return !bstr__memcmp (b0->data, b1->data, b0->slen); +} + +/* int bisstemeqblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len for + * equality. If the beginning of b0 differs from the memory block (or if b0 + * is too short), 0 is returned, if the strings are the same, 1 is returned, + * if there is an error, -1 is returned. '\0' characters are not treated in + * any special way. + */ +int bisstemeqblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; + } + return 1; +} + +/* int biseqcstr (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical with the bstring b with no '\0' + * characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal when comparing them in the same format after converting one or the + * other. If the strings are equal 1 is returned, if they are unequal 0 is + * returned and if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstr (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int biseqcstrcaseless (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical except for case with the bstring b with + * no '\0' characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal ignoring case when comparing them in the same format after + * converting one or the other. If the strings are equal, except for case, + * 1 is returned, if they are unequal regardless of case 0 is returned and + * if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstrcaseless (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || + (b->data[i] != (unsigned char) s[i] && + downcase (b->data[i]) != (unsigned char) downcase (s[i]))) + return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int bstrcmp (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, + * otherwise a value less than or greater than zero, indicating that the + * string pointed to by b0 is lexicographically less than or greater than + * the string pointed to by b1 is returned. If the the string lengths are + * unequal but the characters up until the length of the shorter are equal + * then a value less than, or greater than zero, indicating that the string + * pointed to by b0 is shorter or longer than the string pointed to by b1 is + * returned. 0 is returned if and only if the two strings are the same. If + * the length of the strings are different, this function is O(n). Like its + * standard C library counter part strcmp, the comparison does not proceed + * past any '\0' termination characters encountered. + */ +int bstrcmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + n = b0->slen; if (n > b1->slen) n = b1->slen; + if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) + return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + + if (b0->slen > n) return 1; + if (b1->slen > n) return -1; + return BSTR_OK; +} + +/* int bstrncmp (const_bstring b0, const_bstring b1, int n) + * + * Compare the string b0 and b1 for at most n characters. If there is an + * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and + * b1 were first truncated to at most n characters then bstrcmp was called + * with these new strings are paremeters. If the length of the strings are + * different, this function is O(n). Like its standard C library counter + * part strcmp, the comparison does not proceed past any '\0' termination + * characters encountered. + */ +int bstrncmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) return 1; + return -1; +} + +/* bstring bmidstr (const_bstring b, int left, int len) + * + * Create a bstring which is the substring of b starting from position left + * and running for a length len (clamped by the end of the bstring b.) If + * b is detectably invalid, then NULL is returned. The section described + * by (left, len) is clamped to the boundaries of b. + */ +bstring bmidstr (const_bstring b, int left, int len) { + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (len <= 0) return bfromcstr (""); + return blk2bstr (b->data + left, len); +} + +/* int bdelete (bstring b, int pos, int len) + * + * Removes characters from pos to pos+len-1 inclusive and shifts the tail of + * the bstring starting from pos+len to pos. len must be positive for this + * call to have any effect. The section of the string described by (pos, + * len) is clamped to boundaries of the bstring b. + */ +int bdelete (bstring b, int pos, int len) { + /* Clamp to left side of bstring */ + if (pos < 0) { + len += pos; + pos = 0; + } + + if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || + b->mlen < b->slen || b->mlen <= 0) + return BSTR_ERR; + if (len > 0 && pos < b->slen) { + if (pos + len >= b->slen) { + b->slen = pos; + } else { + bBlockCopy ((char *) (b->data + pos), + (char *) (b->data + pos + len), + b->slen - (pos+len)); + b->slen -= len; + } + b->data[b->slen] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +/* int bdestroy (bstring b) + * + * Free up the bstring. Note that if b is detectably invalid or not writable + * then no action is performed and BSTR_ERR is returned. Like a freed memory + * allocation, dereferences, writes or any other action on b after it has + * been bdestroyed is undefined. + */ +int bdestroy (bstring b) { + if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || + b->data == NULL) + return BSTR_ERR; + + bstr__free (b->data); + + /* In case there is any stale usage, there is one more chance to + notice this error. */ + + b->slen = -1; + b->mlen = -__LINE__; + b->data = NULL; + + bstr__free (b); + return BSTR_OK; +} + +/* int binstr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstr (const_bstring b1, int pos, const_bstring b2) { +int j, ii, ll, lf; +unsigned char * d0; +unsigned char c0; +register unsigned char * d1; +register unsigned char c1; +register int i; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* No space to find such a string? */ + if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return 0; + + i = pos; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + /* Peel off the b2->slen == 1 case */ + c0 = d0[0]; + if (1 == ll) { + for (;i < lf; i++) if (c0 == d1[i]) return i; + return BSTR_ERR; + } + + c1 = c0; + j = 0; + lf = b1->slen - 1; + + ii = -1; + if (i < lf) do { + /* Unrolled current character test */ + if (c1 != d1[i]) { + if (c1 != d1[1+i]) { + i += 2; + continue; + } + i++; + } + + /* Take note if this is the start of a potential match */ + if (0 == j) ii = i; + + /* Shift the test character down by one */ + j++; + i++; + + /* If this isn't past the last character continue */ + if (j < ll) { + c1 = d0[j]; + continue; + } + + N0:; + + /* If no characters mismatched, then we matched */ + if (i == ii+j) return ii; + + /* Shift back to the beginning */ + i -= j; + j = 0; + c1 = c0; + } while (i < lf); + + /* Deal with last case if unrolling caused a misalignment */ + if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; + + return BSTR_ERR; +} + +/* int binstrr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstrr (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j]) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l, ll; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + l = b1->slen - b2->slen + 1; + + /* No space to find such a string? */ + if (l <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return BSTR_OK; + + i = pos; + j = 0; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= ll) return i; + } else { + i ++; + if (i >= l) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + + +/* int bstrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b forwards from the position pos + * (inclusive). + */ +int bstrchrp (const_bstring b, int c, int pos) { +unsigned char * p; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); + if (p) return (int) (p - b->data); + return BSTR_ERR; +} + +/* int bstrrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b backwards from the position pos in string + * (inclusive). + */ +int bstrrchrp (const_bstring b, int c, int pos) { +int i; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + for (i=pos; i >= 0; i--) { + if (b->data[i] == (unsigned char) c) return i; + } + return BSTR_ERR; +} + +#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) +#define LONG_LOG_BITS_QTY (3) +#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) +#define LONG_TYPE unsigned char + +#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) +struct charField { LONG_TYPE content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) +#define setInCharField(cf,idx) { \ + unsigned int c = (unsigned int) (idx); \ + (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ +} + +#else + +#define CFCLEN (1 << CHAR_BIT) +struct charField { unsigned char content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) +#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 + +#endif + +/* Convert a bstring to charField */ +static int buildCharField (struct charField * cf, const_bstring b) { +int i; + if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; + memset ((void *) cf->content, 0, sizeof (struct charField)); + for (i=0; i < b->slen; i++) { + setInCharField (cf, b->data[i]); + } + return BSTR_OK; +} + +static void invertCharField (struct charField * cf) { +int i; + for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; +} + +/* Inner engine for binchr */ +static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { +int i; + for (i=pos; i < len; i++) { + unsigned char c = (unsigned char) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * one of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int binchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* Inner engine for binchrr */ +static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { +int i; + for (i=pos; i >= 0; i--) { + unsigned int c = (unsigned int) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which one of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int binchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bninchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * none of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int bninchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* int bninchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which none of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int bninchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) + * + * Overwrite the string b0 starting at position pos with the string b1. If + * the position pos is past the end of b0, then the character "fill" is + * appended as necessary to make up the gap between the end of b0 and pos. + * If b1 is NULL, it behaves as if it were a 0-length string. + */ +int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { +int d, newlen; +ptrdiff_t pd; +bstring aux = (bstring) b1; + + if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || + b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; + if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; + + d = pos; + + /* Aliasing case */ + if (NULL != aux) { + if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + d += aux->slen; + } + + /* Increase memory size if necessary */ + if (balloc (b0, d + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + + newlen = b0->slen; + + /* Fill in "fill" character as necessary */ + if (pos > newlen) { + bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); + newlen = pos; + } + + /* Copy b1 to position pos in b0. */ + if (aux != NULL) { + bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); + if (aux != b1) bdestroy (aux); + } + + /* Indicate the potentially increased size of b0 */ + if (d > newlen) newlen = d; + + b0->slen = newlen; + b0->data[newlen] = (unsigned char) '\0'; + + return BSTR_OK; +} + +/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) + * + * Inserts the string b2 into b1 at position pos. If the position pos is + * past the end of b1, then the character "fill" is appended as necessary to + * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert + * does not allow b2 to be NULL. + */ +int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { +int d, l; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || + b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + /* Compute the two possible end pointers */ + d = b1->slen + aux->slen; + l = pos + aux->slen; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b1, l + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); + b1->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b1, d + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bBlockCopy (b1->data + l, b1->data + pos, d - l); + b1->slen = d; + } + bBlockCopy (b1->data + pos, aux->data, aux->slen); + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* int breplace (bstring b1, int pos, int len, bstring b2, + * unsigned char fill) + * + * Replace a section of a string from pos for a length len with the string b2. + * fill is used is pos > b1->slen. + */ +int breplace (bstring b1, int pos, int len, const_bstring b2, + unsigned char fill) { +int pl, ret; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || + b2 == NULL || b1->data == NULL || b2->data == NULL || + b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || + b1->mlen <= 0) return BSTR_ERR; + + /* Straddles the end? */ + if (pl >= b1->slen) { + if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; + if (pos + b2->slen < b1->slen) { + b1->slen = pos + b2->slen; + b1->data[b1->slen] = (unsigned char) '\0'; + } + return ret; + } + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + if (aux->slen > len) { + if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + } + + if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); + bstr__memcpy (b1->data + pos, aux->data, aux->slen); + b1->slen += aux->slen - len; + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* + * findreplaceengine is used to implement bfindreplace and + * bfindreplacecaseless. It works by breaking the three cases of + * expansion, reduction and replacement, and solving each of these + * in the most efficient way possible. + */ + +typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); + +#define INITIAL_STATIC_FIND_INDEX_COUNT 32 + +static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { +int i, ret, slen, mlen, delta, acc; +int * d; +int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */ +ptrdiff_t pd; +bstring auxf = (bstring) find; +bstring auxr = (bstring) repl; + + if (b == NULL || b->data == NULL || find == NULL || + find->data == NULL || repl == NULL || repl->data == NULL || + pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || + b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; + if (pos > b->slen - find->slen) return BSTR_OK; + + /* Alias with find string */ + pd = (ptrdiff_t) (find->data - b->data); + if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; + } + + /* Alias with repl string */ + pd = (ptrdiff_t) (repl->data - b->data); + if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxr = bstrcpy (repl))) { + if (auxf != find) bdestroy (auxf); + return BSTR_ERR; + } + } + + delta = auxf->slen - auxr->slen; + + /* in-place replacement since find and replace strings are of equal + length */ + if (delta == 0) { + while ((pos = instr (b, pos, auxf)) >= 0) { + bstr__memcpy (b->data + pos, auxr->data, auxr->slen); + pos += auxf->slen; + } + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* shrinking replacement since auxf->slen > auxr->slen */ + if (delta > 0) { + acc = 0; + + while ((i = instr (b, pos, auxf)) >= 0) { + if (acc && i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + if (auxr->slen) + bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); + acc += delta; + pos = i + auxf->slen; + } + + if (acc) { + i = b->slen; + if (i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + b->slen -= acc; + b->data[b->slen] = (unsigned char) '\0'; + } + + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* expanding replacement since find->slen < repl->slen. Its a lot + more complicated. This works by first finding all the matches and + storing them to a growable array, then doing at most one resize of + the destination bstring and then performing the direct memory transfers + of the string segment pieces to form the final result. The growable + array of matches uses a deferred doubling reallocing strategy. What + this means is that it starts as a reasonably fixed sized auto array in + the hopes that many if not most cases will never need to grow this + array. But it switches as soon as the bounds of the array will be + exceeded. An extra find result is always appended to this array that + corresponds to the end of the destination string, so slen is checked + against mlen - 1 rather than mlen before resizing. + */ + + mlen = INITIAL_STATIC_FIND_INDEX_COUNT; + d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ + acc = slen = 0; + + while ((pos = instr (b, pos, auxf)) >= 0) { + if (slen >= mlen - 1) { + int sl, *t; + + mlen += mlen; + sl = sizeof (int *) * mlen; + if (static_d == d) d = NULL; /* static_d cannot be realloced */ + if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { + ret = BSTR_ERR; + goto done; + } + if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); + d = t; + } + d[slen] = pos; + slen++; + acc -= delta; + pos += auxf->slen; + if (pos < 0 || acc < 0) { + ret = BSTR_ERR; + goto done; + } + } + + /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ + d[slen] = b->slen; + + if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { + b->slen += acc; + for (i = slen-1; i >= 0; i--) { + int s, l; + s = d[i] + auxf->slen; + l = d[i+1] - s; /* d[slen] may be accessed here. */ + if (l) { + bstr__memmove (b->data + s + acc, b->data + s, l); + } + if (auxr->slen) { + bstr__memmove (b->data + s + acc - auxr->slen, + auxr->data, auxr->slen); + } + acc += delta; + } + b->data[b->slen] = (unsigned char) '\0'; + } + + done:; + if (static_d == d) d = NULL; + bstr__free (d); + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return ret; +} + +/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string with a replace string after a + * given point in a bstring. + */ +int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstr); +} + +/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string, ignoring case, with a replace + * string after a given point in a bstring. + */ +int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstrcaseless); +} + +/* int binsertch (bstring b, int pos, int len, unsigned char fill) + * + * Inserts the character fill repeatedly into b at position pos for a + * length len. If the position pos is past the end of b, then the + * character "fill" is appended as necessary to make up the gap between the + * end of b and the position pos + len. + */ +int binsertch (bstring b, int pos, int len, unsigned char fill) { +int d, l, i; + + if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || len < 0) return BSTR_ERR; + + /* Compute the two possible end pointers */ + d = b->slen + len; + l = pos + len; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; + pos = b->slen; + b->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; + for (i = d - 1; i >= l; i--) { + b->data[i] = b->data[i - len]; + } + b->slen = d; + } + + for (i=pos; i < l; i++) b->data[i] = fill; + b->data[b->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bpattern (bstring b, int len) + * + * Replicate the bstring, b in place, end to end repeatedly until it + * surpasses len characters, then chop the result to exactly len characters. + * This function operates in-place. The function will return with BSTR_ERR + * if b is NULL or of length 0, otherwise BSTR_OK is returned. + */ +int bpattern (bstring b, int len) { +int i, d; + + d = blength (b); + if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; + if (len > 0) { + if (d == 1) return bsetstr (b, len, NULL, b->data[0]); + for (i = d; i < len; i++) b->data[i] = b->data[i - d]; + } + b->data[len] = (unsigned char) '\0'; + b->slen = len; + return BSTR_OK; +} + +#define BS_BUFF_SZ (1024) + +/* int breada (bstring b, bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to concatenate to the + * bstring b the entire contents of file-like source data in a roughly + * efficient way. + */ +int breada (bstring b, bNread readPtr, void * parm) { +int i, l, n; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; + + i = b->slen; + for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { + if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; + l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); + i += l; + b->slen = i; + if (i < n) break; + } + + b->data[i] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bread (bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to create a bstring + * filled with the entire contents of file-like source data in a roughly + * efficient way. + */ +bstring bread (bNread readPtr, void * parm) { +bstring buff; + + if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { + bdestroy (buff); + return NULL; + } + return buff; +} + +/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result in b. If there is an empty partial + * result, 1 is returned. If no characters are read, or there is some other + * detectable error, BSTR_ERR is returned. + */ +int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = 0; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result concatentated to b. If there is + * an empty partial result, 1 is returned. If no characters are read, or + * there is some other detectable error, BSTR_ERR is returned. + */ +int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = b->slen; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* bstring bgets (bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated into a bstring. + * The stream read is terminated by the passed in terminator function. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * result obtained thus far is returned. If no characters are read, or + * there is some other detectable error, NULL is returned. + */ +bstring bgets (bNgetc getcPtr, void * parm, char terminator) { +bstring buff; + + if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { + bdestroy (buff); + buff = NULL; + } + return buff; +} + +struct bStream { + bstring buff; /* Buffer for over-reads */ + void * parm; /* The stream handle for core stream */ + bNread readFnPtr; /* fread compatible fnptr for core stream */ + int isEOF; /* track file's EOF state */ + int maxBuffSz; +}; + +/* struct bStream * bsopen (bNread readPtr, void * parm) + * + * Wrap a given open stream (described by a fread compatible function + * pointer and stream handle) into an open bStream suitable for the bstring + * library streaming functions. + */ +struct bStream * bsopen (bNread readPtr, void * parm) { +struct bStream * s; + + if (readPtr == NULL) return NULL; + s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); + if (s == NULL) return NULL; + s->parm = parm; + s->buff = bfromcstr (""); + s->readFnPtr = readPtr; + s->maxBuffSz = BS_BUFF_SZ; + s->isEOF = 0; + return s; +} + +/* int bsbufflength (struct bStream * s, int sz) + * + * Set the length of the buffer used by the bStream. If sz is zero, the + * length is not set. This function returns with the previous length. + */ +int bsbufflength (struct bStream * s, int sz) { +int oldSz; + if (s == NULL || sz < 0) return BSTR_ERR; + oldSz = s->maxBuffSz; + if (sz > 0) s->maxBuffSz = sz; + return oldSz; +} + +int bseof (const struct bStream * s) { + if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; + return s->isEOF && (s->buff->slen == 0); +} + +/* void * bsclose (struct bStream * s) + * + * Close the bStream, and return the handle to the stream that was originally + * used to open the given stream. + */ +void * bsclose (struct bStream * s) { +void * parm; + if (s == NULL) return NULL; + s->readFnPtr = NULL; + if (s->buff) bdestroy (s->buff); + s->buff = NULL; + parm = s->parm; + s->parm = NULL; + s->isEOF = 1; + bstr__free (s); + return parm; +} + +/* int bsreadlna (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadlna (bstring r, struct bStream * s, char terminator) { +int i, l, ret, rlo; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || + r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + /* First check if the current buffer holds the terminator */ + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { +int i, l, ret, rlo; +unsigned char * b; +struct tagbstring x; +struct charField cf; + + if (s == NULL || s->buff == NULL || r == NULL || term == NULL || + term->data == NULL || r->mlen <= 0 || r->slen < 0 || + r->mlen < r->slen) return BSTR_ERR; + if (term->slen == 1) return bsreadlna (r, s, term->data[0]); + if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; + + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) s->buff->data; + x.data = b; + + /* First check if the current buffer holds the terminator */ + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreada (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsreada (bstring r, struct bStream * s, int n) { +int l, ret, orslen; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; + + n += r->slen; + if (n <= 0) return BSTR_ERR; + + l = s->buff->slen; + + orslen = r->slen; + + if (0 == l) { + if (s->isEOF) return BSTR_ERR; + if (r->mlen > n) { + l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); + if (0 >= l || l > n - r->slen) { + s->isEOF = 1; + return BSTR_ERR; + } + r->slen += l; + r->data[r->slen] = (unsigned char) '\0'; + return 0; + } + } + + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + do { + if (l + r->slen >= n) { + x.slen = n - r->slen; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); + return BSTR_ERR & -(r->slen == orslen); + } + + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) break; + + l = n - r->slen; + if (l > s->maxBuffSz) l = s->maxBuffSz; + + l = (int) s->readFnPtr (b, 1, l, s->parm); + + } while (l > 0); + if (l < 0) l = 0; + if (l == 0) s->isEOF = 1; + s->buff->slen = l; + return BSTR_ERR & -(r->slen == orslen); +} + +/* int bsreadln (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadln (bstring r, struct bStream * s, char terminator) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) + return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlna (r, s, terminator); +} + +/* int bsreadlns (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlns (bstring r, struct bStream * s, const_bstring term) { + if (s == NULL || s->buff == NULL || r == NULL || term == NULL + || term->data == NULL || r->mlen <= 0) return BSTR_ERR; + if (term->slen == 1) return bsreadln (r, s, term->data[0]); + if (term->slen < 1) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlnsa (r, s, term); +} + +/* int bsread (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsread (bstring r, struct bStream * s, int n) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || n <= 0) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreada (r, s, n); +} + +/* int bsunread (struct bStream * s, const_bstring b) + * + * Insert a bstring into the bStream at the current position. These + * characters will be read prior to those that actually come from the core + * stream. + */ +int bsunread (struct bStream * s, const_bstring b) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return binsert (s->buff, 0, b, (unsigned char) '?'); +} + +/* int bspeek (bstring r, const struct bStream * s) + * + * Return the currently buffered characters from the bStream that will be + * read prior to reads from the core stream. + */ +int bspeek (bstring r, const struct bStream * s) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return bassign (r, s->buff); +} + +/* bstring bjoin (const struct bstrList * bl, const_bstring sep); + * + * Join the entries of a bstrList into one bstring by sequentially + * concatenating them with the sep string in between. If there is an error + * NULL is returned, otherwise a bstring with the correct result is returned. + */ +bstring bjoin (const struct bstrList * bl, const_bstring sep) { +bstring b; +int i, c, v; + + if (bl == NULL || bl->qty < 0) return NULL; + if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; + + for (i = 0, c = 1; i < bl->qty; i++) { + v = bl->entry[i]->slen; + if (v < 0) return NULL; /* Invalid input */ + c += v; + if (c < 0) return NULL; /* Wrap around ?? */ + } + + if (sep != NULL) c += (bl->qty - 1) * sep->slen; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; /* Out of memory */ + b->data = (unsigned char *) bstr__alloc (c); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + b->mlen = c; + b->slen = c-1; + + for (i = 0, c = 0; i < bl->qty; i++) { + if (i > 0 && sep != NULL) { + bstr__memcpy (b->data + c, sep->data, sep->slen); + c += sep->slen; + } + v = bl->entry[i]->slen; + bstr__memcpy (b->data + c, bl->entry[i]->data, v); + c += v; + } + b->data[c] = (unsigned char) '\0'; + return b; +} + +#define BSSSC_BUFF_LEN (256) + +/* int bssplitscb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by any of the characters in splitStr. An empty splitStr causes + * the whole stream to be iterated once. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +struct charField chrs; +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; + if ((ret = cb (parm, 0, buff)) > 0) + ret = 0; + } else { + buildCharField (&chrs, splitStr); + ret = p = i = 0; + for (;;) { + if (i >= buff->slen) { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (i >= buff->slen) { + if (0 < (ret = cb (parm, p, buff))) ret = 0; + break; + } + } + if (testInCharField (&chrs, buff->data[i])) { + struct tagbstring t; + unsigned char c; + + blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); + if ((ret = bsunread (s, &t)) < 0) break; + buff->slen = i; + c = buff->data[i]; + buff->data[i] = (unsigned char) '\0'; + if ((ret = cb (parm, p, buff)) < 0) break; + buff->data[i] = c; + buff->slen = 0; + p += i + 1; + i = -1; + } + i++; + } + } + + bdestroy (buff); + return ret; +} + +/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by the entire substring splitStr. An empty splitStr causes + * each character of the stream to be iterated. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { + if ((ret = cb (parm, 0, buff)) < 0) { + bdestroy (buff); + return ret; + } + buff->slen = 0; + } + return BSTR_OK; + } else { + ret = p = i = 0; + for (i=p=0;;) { + if ((ret = binstr (buff, 0, splitStr)) >= 0) { + struct tagbstring t; + blk2tbstr (t, buff->data, ret); + i = ret + splitStr->slen; + if ((ret = cb (parm, p, &t)) < 0) break; + p += i; + bdelete (buff, 0, i); + } else { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (bseof (s)) { + if ((ret = cb (parm, p, buff)) > 0) ret = 0; + break; + } + } + } + } + + bdestroy (buff); + return ret; +} + +/* int bstrListCreate (void) + * + * Create a bstrList. + */ +struct bstrList * bstrListCreate (void) { +struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (sl) { + sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); + if (!sl->entry) { + bstr__free (sl); + sl = NULL; + } else { + sl->qty = 0; + sl->mlen = 1; + } + } + return sl; +} + +/* int bstrListDestroy (struct bstrList * sl) + * + * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. + */ +int bstrListDestroy (struct bstrList * sl) { +int i; + if (sl == NULL || sl->qty < 0) return BSTR_ERR; + for (i=0; i < sl->qty; i++) { + if (sl->entry[i]) { + bdestroy (sl->entry[i]); + sl->entry[i] = NULL; + } + } + sl->qty = -1; + sl->mlen = -1; + bstr__free (sl->entry); + sl->entry = NULL; + bstr__free (sl); + return BSTR_OK; +} + +/* int bstrListAlloc (struct bstrList * sl, int msz) + * + * Ensure that there is memory for at least msz number of entries for the + * list. + */ +int bstrListAlloc (struct bstrList * sl, int msz) { +bstring * l; +int smsz; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (sl->mlen >= msz) return BSTR_OK; + smsz = snapUpSize (msz); + nsz = ((size_t) smsz) * sizeof (bstring); + if (nsz < (size_t) smsz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) { + smsz = msz; + nsz = ((size_t) smsz) * sizeof (bstring); + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + } + sl->mlen = smsz; + sl->entry = l; + return BSTR_OK; +} + +/* int bstrListAllocMin (struct bstrList * sl, int msz) + * + * Try to allocate the minimum amount of memory for the list to include at + * least msz entries or sl->qty whichever is greater. + */ +int bstrListAllocMin (struct bstrList * sl, int msz) { +bstring * l; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (msz < sl->qty) msz = sl->qty; + if (sl->mlen == msz) return BSTR_OK; + nsz = ((size_t) msz) * sizeof (bstring); + if (nsz < (size_t) msz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + sl->mlen = msz; + sl->entry = l; + return BSTR_OK; +} + +/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * character in splitChar. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitcb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitcb will continue in an undefined manner. + */ +int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) + return BSTR_ERR; + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (str->data[i] == splitChar) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by any + * of the characters in splitStr. An empty splitStr causes the whole str to + * be iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitscb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +struct charField chrs; +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + if (splitStr->slen == 0) { + if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; + return ret; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + buildCharField (&chrs, splitStr); + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (testInCharField (&chrs, str->data[i])) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * substring splitStr. An empty splitStr causes the whole str to be + * iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitstrcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (0 == splitStr->slen) { + for (i=pos; i < str->slen; i++) { + if ((ret = cb (parm, i, 1)) < 0) return ret; + } + return BSTR_OK; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + for (i=p=pos; i <= str->slen - splitStr->slen; i++) { + if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { + if ((ret = cb (parm, p, i - p)) < 0) return ret; + i += splitStr->slen; + p = i; + } + } + if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; + return BSTR_OK; +} + +struct genBstrList { + bstring b; + struct bstrList * bl; +}; + +static int bscb (void * parm, int ofs, int len) { +struct genBstrList * g = (struct genBstrList *) parm; + if (g->bl->qty >= g->bl->mlen) { + int mlen = g->bl->mlen * 2; + bstring * tbl; + + while (g->bl->qty >= mlen) { + if (mlen < g->bl->mlen) return BSTR_ERR; + mlen += mlen; + } + + tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); + if (tbl == NULL) return BSTR_ERR; + + g->bl->entry = tbl; + g->bl->mlen = mlen; + } + + g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); + g->bl->qty++; + return BSTR_OK; +} + +/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) + * + * Create an array of sequential substrings from str divided by the character + * splitChar. + */ +struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) + * + * Create an array of sequential substrings from str divided by the entire + * substring splitStr. + */ +struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplits (const_bstring str, bstring splitStr) + * + * Create an array of sequential substrings from str divided by any of the + * characters in splitStr. An empty splitStr causes a single entry bstrList + * containing a copy of str to be returned. + */ +struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if ( str == NULL || str->slen < 0 || str->data == NULL || + splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) + return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + g.b = (bstring) str; + g.bl->qty = 0; + + if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +#if defined (__TURBOC__) && !defined (__BORLANDC__) +# ifndef BSTRLIB_NOVSNP +# define BSTRLIB_NOVSNP +# endif +#endif + +/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ +#if defined(__WATCOMC__) || defined(_MSC_VER) +#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} +#else +#ifdef BSTRLIB_NOVSNP +/* This is just a hack. If you are using a system without a vsnprintf, it is + not recommended that bformat be used at all. */ +#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} +#define START_VSNBUFF (256) +#else + +#if defined(__GNUC__) && !defined(__clang__) +/* Something is making gcc complain about this prototype not being here, so + I've just gone ahead and put it in. */ +extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); +#endif + +#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} +#endif +#endif + +#if !defined (BSTRLIB_NOVSNP) + +#ifndef START_VSNBUFF +#define START_VSNBUFF (16) +#endif + +/* On IRIX vsnprintf returns n-1 when the operation would overflow the target + buffer, WATCOM and MSVC both return -1, while C99 requires that the + returned value be exactly what the length would be if the buffer would be + large enough. This leads to the idea that if the return value is larger + than n, then changing n to the return value will reduce the number of + iterations required. */ + +/* int bformata (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it appends the results to + * a bstring which contains what would have been output. Note that if there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bformata (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bconcat (b, buff); + bdestroy (buff); + return r; +} + +/* int bassignformat (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it outputs the results to + * the bstring parameter b. Note that if there is an early generation of a + * '\0' character, the bstring will be truncated to this end point. + */ +int bassignformat (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bassign (b, buff); + bdestroy (buff); + return r; +} + +/* bstring bformat (const char * fmt, ...) + * + * Takes the same parameters as printf (), but rather than outputting results + * to stdio, it forms a bstring which contains what would have been output. + * Note that if there is an early generation of a '\0' character, the + * bstring will be truncated to this end point. + */ +bstring bformat (const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (fmt == NULL) return NULL; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return NULL; + } + } + + return buff; +} + +/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) + * + * The bvcformata function formats data under control of the format control + * string fmt and attempts to append the result to b. The fmt parameter is + * the same as that of the printf function. The variable argument list is + * replaced with arglist, which has been initialized by the va_start macro. + * The size of the appended output is upper bounded by count. If the + * required output exceeds count, the string b is not augmented with any + * contents and a value below BSTR_ERR is returned. If a value below -count + * is returned then it is recommended that the negative of this value be + * used as an update to the count in a subsequent pass. On other errors, + * such as running out of memory, parameter errors or numeric wrap around + * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully + * generated and appended to b. + * + * Note: There is no sanity checking of arglist, and this function is + * destructive of the contents of b from the b->slen point onward. If there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bvcformata (bstring b, int count, const char * fmt, va_list arg) { +int n, r, l; + + if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL + || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + if (count > (n = b->slen + count) + 2) return BSTR_ERR; + if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; + + exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); + + /* Did the operation complete successfully within bounds? */ + for (l = b->slen; l <= n; l++) { + if ('\0' == b->data[l]) { + b->slen = l; + return BSTR_OK; + } + } + + /* Abort, since the buffer was not large enough. The return value + tries to help set what the retry length should be. */ + + b->data[b->slen] = '\0'; + if (r > count + 1) { /* Does r specify a particular target length? */ + n = r; + } else { + n = count + count; /* If not, just double the size of count */ + if (count > n) n = INT_MAX; + } + n = -n; + + if (n > BSTR_ERR-1) n = BSTR_ERR-1; + return n; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h new file mode 100644 index 0000000000..edf8c00fc6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.h @@ -0,0 +1,305 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstrlib.h + * + * This file is the header file for the core module for implementing the + * bstring functions. + */ + +#ifndef BSTRLIB_INCLUDE +#define BSTRLIB_INCLUDE + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> + +#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) +# if defined (__TURBOC__) && !defined (__BORLANDC__) +# define BSTRLIB_NOVSNP +# endif +#endif + +#define BSTR_ERR (-1) +#define BSTR_OK (0) +#define BSTR_BS_BUFF_LENGTH_GET (0) + +typedef struct tagbstring * bstring; +typedef const struct tagbstring * const_bstring; + +/* Copy functions */ +#define cstr2bstr bfromcstr +extern bstring bfromcstr (const char * str); +extern bstring bfromcstralloc (int mlen, const char * str); +extern bstring blk2bstr (const void * blk, int len); +extern char * bstr2cstr (const_bstring s, char z); +extern int bcstrfree (char * s); +extern bstring bstrcpy (const_bstring b1); +extern int bassign (bstring a, const_bstring b); +extern int bassignmidstr (bstring a, const_bstring b, int left, int len); +extern int bassigncstr (bstring a, const char * str); +extern int bassignblk (bstring a, const void * s, int len); + +/* Destroy function */ +extern int bdestroy (bstring b); + +/* Space allocation hinting functions */ +extern int balloc (bstring s, int len); +extern int ballocmin (bstring b, int len); + +/* Substring extraction */ +extern bstring bmidstr (const_bstring b, int left, int len); + +/* Various standard manipulations */ +extern int bconcat (bstring b0, const_bstring b1); +extern int bconchar (bstring b0, char c); +extern int bcatcstr (bstring b, const char * s); +extern int bcatblk (bstring b, const void * s, int len); +extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); +extern int binsertch (bstring s1, int pos, int len, unsigned char fill); +extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); +extern int bdelete (bstring s1, int pos, int len); +extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); +extern int btrunc (bstring b, int n); + +/* Scan/search functions */ +extern int bstricmp (const_bstring b0, const_bstring b1); +extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); +extern int biseqcaseless (const_bstring b0, const_bstring b1); +extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); +extern int biseq (const_bstring b0, const_bstring b1); +extern int bisstemeqblk (const_bstring b0, const void * blk, int len); +extern int biseqcstr (const_bstring b, const char * s); +extern int biseqcstrcaseless (const_bstring b, const char * s); +extern int bstrcmp (const_bstring b0, const_bstring b1); +extern int bstrncmp (const_bstring b0, const_bstring b1, int n); +extern int binstr (const_bstring s1, int pos, const_bstring s2); +extern int binstrr (const_bstring s1, int pos, const_bstring s2); +extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int bstrchrp (const_bstring b, int c, int pos); +extern int bstrrchrp (const_bstring b, int c, int pos); +#define bstrchr(b,c) bstrchrp ((b), (c), 0) +#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) +extern int binchr (const_bstring b0, int pos, const_bstring b1); +extern int binchrr (const_bstring b0, int pos, const_bstring b1); +extern int bninchr (const_bstring b0, int pos, const_bstring b1); +extern int bninchrr (const_bstring b0, int pos, const_bstring b1); +extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); +extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); + +/* List of string container functions */ +struct bstrList { + int qty, mlen; + bstring * entry; +}; +extern struct bstrList * bstrListCreate (void); +extern int bstrListDestroy (struct bstrList * sl); +extern int bstrListAlloc (struct bstrList * sl, int msz); +extern int bstrListAllocMin (struct bstrList * sl, int msz); + +/* String split and join functions */ +extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); +extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); +extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); +extern bstring bjoin (const struct bstrList * bl, const_bstring sep); +extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + +/* Miscellaneous functions */ +extern int bpattern (bstring b, int len); +extern int btoupper (bstring b); +extern int btolower (bstring b); +extern int bltrimws (bstring b); +extern int brtrimws (bstring b); +extern int btrimws (bstring b); + +/* <*>printf format functions */ +#if !defined (BSTRLIB_NOVSNP) +extern bstring bformat (const char * fmt, ...); +extern int bformata (bstring b, const char * fmt, ...); +extern int bassignformat (bstring b, const char * fmt, ...); +extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); + +#define bvformata(ret, b, fmt, lastarg) { \ +bstring bstrtmp_b = (b); \ +const char * bstrtmp_fmt = (fmt); \ +int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ + for (;;) { \ + va_list bstrtmp_arglist; \ + va_start (bstrtmp_arglist, lastarg); \ + bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ + va_end (bstrtmp_arglist); \ + if (bstrtmp_r >= 0) { /* Everything went ok */ \ + bstrtmp_r = BSTR_OK; \ + break; \ + } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ + bstrtmp_r = BSTR_ERR; \ + break; \ + } \ + bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ + } \ + ret = bstrtmp_r; \ +} + +#endif + +typedef int (*bNgetc) (void *parm); +typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); + +/* Input functions */ +extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); +extern bstring bread (bNread readPtr, void * parm); +extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int breada (bstring b, bNread readPtr, void * parm); + +/* Stream functions */ +extern struct bStream * bsopen (bNread readPtr, void * parm); +extern void * bsclose (struct bStream * s); +extern int bsbufflength (struct bStream * s, int sz); +extern int bsreadln (bstring b, struct bStream * s, char terminator); +extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); +extern int bsread (bstring b, struct bStream * s, int n); +extern int bsreadlna (bstring b, struct bStream * s, char terminator); +extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); +extern int bsreada (bstring b, struct bStream * s, int n); +extern int bsunread (struct bStream * s, const_bstring b); +extern int bspeek (bstring r, const struct bStream * s); +extern int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bseof (const struct bStream * s); + +struct tagbstring { + int mlen; + int slen; + unsigned char * data; +}; + +/* Accessor macros */ +#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) +#define blength(b) (blengthe ((b), 0)) +#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) +#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) +#define bdatae(b, e) (bdataofse (b, 0, e)) +#define bdata(b) (bdataofs (b, 0)) +#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) +#define bchar(b, p) bchare ((b), (p), '\0') + +/* Static constant string initialization macro */ +#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} +#if defined(_MSC_VER) +/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ +# define bsStatic(q) bsStaticMlen(q,-32) +#endif +#ifndef bsStatic +# define bsStatic(q) bsStaticMlen(q,-__LINE__) +#endif + +/* Static constant block parameter pair */ +#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) + +/* Reference building macros */ +#define cstr2tbstr btfromcstr +#define btfromcstr(t,s) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ + (t).mlen = -1; \ +} +#define blk2tbstr(t,s,l) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = l; \ + (t).mlen = -1; \ +} +#define btfromblk(t,s,l) blk2tbstr(t,s,l) +#define bmid2tbstr(t,b,p,l) { \ + const_bstring bstrtmp_s = (b); \ + if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ + int bstrtmp_left = (p); \ + int bstrtmp_len = (l); \ + if (bstrtmp_left < 0) { \ + bstrtmp_len += bstrtmp_left; \ + bstrtmp_left = 0; \ + } \ + if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ + bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ + if (bstrtmp_len <= 0) { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } else { \ + (t).data = bstrtmp_s->data + bstrtmp_left; \ + (t).slen = bstrtmp_len; \ + } \ + } else { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } \ + (t).mlen = -__LINE__; \ +} +#define btfromblkltrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l); \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} +#define btfromblkrtrimws(t,s,l) { \ + int bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_len >= 0; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s; \ + (t).slen = bstrtmp_len + 1; \ + (t).mlen = -__LINE__; \ +} +#define btfromblktrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} + +/* Write protection macros */ +#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } +#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } +#define biswriteprotected(t) ((t).mlen <= 0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt new file mode 100644 index 0000000000..8ebb188853 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/bstrlib.txt @@ -0,0 +1,3201 @@ +Better String library +--------------------- + +by Paul Hsieh + +The bstring library is an attempt to provide improved string processing +functionality to the C and C++ language. At the heart of the bstring library +(Bstrlib for short) is the management of "bstring"s which are a significant +improvement over '\0' terminated char buffers. + +=============================================================================== + +Motivation +---------- + +The standard C string library has serious problems: + + 1) Its use of '\0' to denote the end of the string means knowing a + string's length is O(n) when it could be O(1). + 2) It imposes an interpretation for the character value '\0'. + 3) gets() always exposes the application to a buffer overflow. + 4) strtok() modifies the string its parsing and thus may not be usable in + programs which are re-entrant or multithreaded. + 5) fgets has the unusual semantic of ignoring '\0's that occur before + '\n's are consumed. + 6) There is no memory management, and actions performed such as strcpy, + strcat and sprintf are common places for buffer overflows. + 7) strncpy() doesn't '\0' terminate the destination in some cases. + 8) Passing NULL to C library string functions causes an undefined NULL + pointer access. + 9) Parameter aliasing (overlapping, or self-referencing parameters) + within most C library functions has undefined behavior. + 10) Many C library string function calls take integer parameters with + restricted legal ranges. Parameters passed outside these ranges are + not typically detected and cause undefined behavior. + +So the desire is to create an alternative string library that does not suffer +from the above problems and adds in the following functionality: + + 1) Incorporate string functionality seen from other languages. + a) MID$() - from BASIC + b) split()/join() - from Python + c) string/char x n - from Perl + 2) Implement analogs to functions that combine stream IO and char buffers + without creating a dependency on stream IO functionality. + 3) Implement the basic text editor-style functions insert, delete, find, + and replace. + 4) Implement reference based sub-string access (as a generalization of + pointer arithmetic.) + 5) Implement runtime write protection for strings. + +There is also a desire to avoid "API-bloat". So functionality that can be +implemented trivially in other functionality is omitted. So there is no +left$() or right$() or reverse() or anything like that as part of the core +functionality. + +Explaining Bstrings +------------------- + +A bstring is basically a header which wraps a pointer to a char buffer. Lets +start with the declaration of a struct tagbstring: + + struct tagbstring { + int mlen; + int slen; + unsigned char * data; + }; + +This definition is considered exposed, not opaque (though it is neither +necessary nor recommended that low level maintenance of bstrings be performed +whenever the abstract interfaces are sufficient). The mlen field (usually) +describes a lower bound for the memory allocated for the data field. The +slen field describes the exact length for the bstring. The data field is a +single contiguous buffer of unsigned chars. Note that the existence of a '\0' +character in the unsigned char buffer pointed to by the data field does not +necessarily denote the end of the bstring. + +To be a well formed modifiable bstring the mlen field must be at least the +length of the slen field, and slen must be non-negative. Furthermore, the +data field must point to a valid buffer in which access to the first mlen +characters has been acquired. So the minimal check for correctness is: + + (slen >= 0 && mlen >= slen && data != NULL) + +bstrings returned by bstring functions can be assumed to be either NULL or +satisfy the above property. (When bstrings are only readable, the mlen >= +slen restriction is not required; this is discussed later in this section.) +A bstring itself is just a pointer to a struct tagbstring: + + typedef struct tagbstring * bstring; + +Note that use of the prefix "tag" in struct tagbstring is required to work +around the inconsistency between C and C++'s struct namespace usage. This +definition is also considered exposed. + +Bstrlib basically manages bstrings allocated as a header and an associated +data-buffer. Since the implementation is exposed, they can also be +constructed manually. Functions which mutate bstrings assume that the header +and data buffer have been malloced; the bstring library may perform free() or +realloc() on both the header and data buffer of any bstring parameter. +Functions which return bstring's create new bstrings. The string memory is +freed by a bdestroy() call (or using the bstrFree macro). + +The following related typedef is also provided: + + typedef const struct tagbstring * const_bstring; + +which is also considered exposed. These are directly bstring compatible (no +casting required) but are just used for parameters which are meant to be +non-mutable. So in general, bstring parameters which are read as input but +not meant to be modified will be declared as const_bstring, and bstring +parameters which may be modified will be declared as bstring. This convention +is recommended for user written functions as well. + +Since bstrings maintain interoperability with C library char-buffer style +strings, all functions which modify, update or create bstrings also append a +'\0' character into the position slen + 1. This trailing '\0' character is +not required for bstrings input to the bstring functions; this is provided +solely as a convenience for interoperability with standard C char-buffer +functionality. + +Analogs for the ANSI C string library functions have been created when they +are necessary, but have also been left out when they are not. In particular +there are no functions analogous to fwrite, or puts just for the purposes of +bstring. The ->data member of any string is exposed, and therefore can be +used just as easily as char buffers for C functions which read strings. + +For those that wish to hand construct bstrings, the following should be kept +in mind: + + 1) While bstrlib can accept constructed bstrings without terminating + '\0' characters, the rest of the C language string library will not + function properly on such non-terminated strings. This is obvious + but must be kept in mind. + 2) If it is intended that a constructed bstring be written to by the + bstring library functions then the data portion should be allocated + by the malloc function and the slen and mlen fields should be entered + properly. The struct tagbstring header is not reallocated, and only + freed by bdestroy. + 3) Writing arbitrary '\0' characters at various places in the string + will not modify its length as perceived by the bstring library + functions. In fact, '\0' is a legitimate non-terminating character + for a bstring to contain. + 4) For read only parameters, bstring functions do not check the mlen. + I.e., the minimal correctness requirements are reduced to: + + (slen >= 0 && data != NULL) + +Better pointer arithmetic +------------------------- + +One built-in feature of '\0' terminated char * strings, is that its very easy +and fast to obtain a reference to the tail of any string using pointer +arithmetic. Bstrlib does one better by providing a way to get a reference to +any substring of a bstring (or any other length delimited block of memory.) +So rather than just having pointer arithmetic, with bstrlib one essentially +has segment arithmetic. This is achieved using the macro blk2tbstr() which +builds a reference to a block of memory and the macro bmid2tbstr() which +builds a reference to a segment of a bstring. Bstrlib also includes +functions for direct consumption of memory blocks into bstrings, namely +bcatblk () and blk2bstr (). + +One scenario where this can be extremely useful is when string contains many +substrings which one would like to pass as read-only reference parameters to +some string consuming function without the need to allocate entire new +containers for the string data. More concretely, imagine parsing a command +line string whose parameters are space delimited. This can only be done for +tails of the string with '\0' terminated char * strings. + +Improved NULL semantics and error handling +------------------------------------------ + +Unless otherwise noted, if a NULL pointer is passed as a bstring or any other +detectably illegal parameter, the called function will return with an error +indicator (either NULL or BSTR_ERR) rather than simply performing a NULL +pointer access, or having undefined behavior. + +To illustrate the value of this, consider the following example: + + strcpy (p = malloc (13 * sizeof (char)), "Hello,"); + strcat (p, " World"); + +This is not correct because malloc may return NULL (due to an out of memory +condition), and the behaviour of strcpy is undefined if either of its +parameters are NULL. However: + + bstrcat (p = bfromcstr ("Hello,"), q = bfromcstr (" World")); + bdestroy (q); + +is well defined, because if either p or q are assigned NULL (indicating a +failure to allocate memory) both bstrcat and bdestroy will recognize it and +perform no detrimental action. + +Note that it is not necessary to check any of the members of a returned +bstring for internal correctness (in particular the data member does not need +to be checked against NULL when the header is non-NULL), since this is +assured by the bstring library itself. + +bStreams +-------- + +In addition to the bgets and bread functions, bstrlib can abstract streams +with a high performance read only stream called a bStream. In general, the +idea is to open a core stream (with something like fopen) then pass its +handle as well as a bNread function pointer (like fread) to the bsopen +function which will return a handle to an open bStream. Then the functions +bsread, bsreadln or bsreadlns can be called to read portions of the stream. +Finally, the bsclose function is called to close the bStream -- it will +return a handle to the original (core) stream. So bStreams, essentially, +wrap other streams. + +The bStreams have two main advantages over the bgets and bread (as well as +fgets/ungetc) paradigms: + +1) Improved functionality via the bunread function which allows a stream to + unread characters, giving the bStream stack-like functionality if so + desired. +2) A very high performance bsreadln function. The C library function fgets() + (and the bgets function) can typically be written as a loop on top of + fgetc(), thus paying all of the overhead costs of calling fgetc on a per + character basis. bsreadln will read blocks at a time, thus amortizing the + overhead of fread calls over many characters at once. + +However, clearly bStreams are suboptimal or unusable for certain kinds of +streams (stdin) or certain usage patterns (a few spotty, or non-sequential +reads from a slow stream.) For those situations, using bgets will be more +appropriate. + +The semantics of bStreams allows practical construction of layerable data +streams. What this means is that by writing a bNread compatible function on +top of a bStream, one can construct a new bStream on top of it. This can be +useful for writing multi-pass parsers that don't actually read the entire +input more than once and don't require the use of intermediate storage. + +Aliasing +-------- + +Aliasing occurs when a function is given two parameters which point to data +structures which overlap in the memory they occupy. While this does not +disturb read only functions, for many libraries this can make functions that +write to these memory locations malfunction. This is a common problem of the +C standard library and especially the string functions in the C standard +library. + +The C standard string library is entirely char by char oriented (as is +bstring) which makes conforming implementations alias safe for some +scenarios. However no actual detection of aliasing is typically performed, +so it is easy to find cases where the aliasing will cause anomolous or +undesirable behaviour (consider: strcat (p, p).) The C99 standard includes +the "restrict" pointer modifier which allows the compiler to document and +assume a no-alias condition on usage. However, only the most trivial cases +can be caught (if at all) by the compiler at compile time, and thus there is +no actual enforcement of non-aliasing. + +Bstrlib, by contrast, permits aliasing and is completely aliasing safe, in +the C99 sense of aliasing. That is to say, under the assumption that +pointers of incompatible types from distinct objects can never alias, bstrlib +is completely aliasing safe. (In practice this means that the data buffer +portion of any bstring and header of any bstring are assumed to never alias.) +With the exception of the reference building macros, the library behaves as +if all read-only parameters are first copied and replaced by temporary +non-aliased parameters before any writing to any output bstring is performed +(though actual copying is extremely rarely ever done.) + +Besides being a useful safety feature, bstring searching/comparison +functions can improve to O(1) execution when aliasing is detected. + +Note that aliasing detection and handling code in Bstrlib is generally +extremely cheap. There is almost never any appreciable performance penalty +for using aliased parameters. + +Reenterancy +----------- + +Nearly every function in Bstrlib is a leaf function, and is completely +reenterable with the exception of writing to common bstrings. The split +functions which use a callback mechanism requires only that the source string +not be destroyed by the callback function unless the callback function returns +with an error status (note that Bstrlib functions which return an error do +not modify the string in any way.) The string can in fact be modified by the +callback and the behaviour is deterministic. See the documentation of the +various split functions for more details. + +Undefined scenarios +------------------- + +One of the basic important premises for Bstrlib is to not to increase the +propogation of undefined situations from parameters that are otherwise legal +in of themselves. In particular, except for extremely marginal cases, usages +of bstrings that use the bstring library functions alone cannot lead to any +undefined action. But due to C/C++ language and library limitations, there +is no way to define a non-trivial library that is completely without +undefined operations. All such possible undefined operations are described +below: + +1) bstrings or struct tagbstrings that are not explicitely initialized cannot + be passed as a parameter to any bstring function. +2) The members of the NULL bstring cannot be accessed directly. (Though all + APIs and macros detect the NULL bstring.) +3) A bstring whose data member has not been obtained from a malloc or + compatible call and which is write accessible passed as a writable + parameter will lead to undefined results. (i.e., do not writeAllow any + constructed bstrings unless the data portion has been obtained from the + heap.) +4) If the headers of two strings alias but are not identical (which can only + happen via a defective manual construction), then passing them to a + bstring function in which one is writable is not defined. +5) If the mlen member is larger than the actual accessible length of the data + member for a writable bstring, or if the slen member is larger than the + readable length of the data member for a readable bstring, then the + corresponding bstring operations are undefined. +6) Any bstring definition whose header or accessible data portion has been + assigned to inaccessible or otherwise illegal memory clearly cannot be + acted upon by the bstring library in any way. +7) Destroying the source of an incremental split from within the callback + and not returning with a negative value (indicating that it should abort) + will lead to undefined behaviour. (Though *modifying* or adjusting the + state of the source data, even if those modification fail within the + bstrlib API, has well defined behavior.) +8) Modifying a bstring which is write protected by direct access has + undefined behavior. + +While this may seem like a long list, with the exception of invalid uses of +the writeAllow macro, and source destruction during an iterative split +without an accompanying abort, no usage of the bstring API alone can cause +any undefined scenario to occurr. I.e., the policy of restricting usage of +bstrings to the bstring API can significantly reduce the risk of runtime +errors (in practice it should eliminate them) related to string manipulation +due to undefined action. + +C++ wrapper +----------- + +A C++ wrapper has been created to enable bstring functionality for C++ in the +most natural (for C++ programers) way possible. The mandate for the C++ +wrapper is different from the base C bstring library. Since the C++ language +has far more abstracting capabilities, the CBString structure is considered +fully abstracted -- i.e., hand generated CBStrings are not supported (though +conversion from a struct tagbstring is allowed) and all detectable errors are +manifest as thrown exceptions. + +- The C++ class definitions are all under the namespace Bstrlib. bstrwrap.h + enables this namespace (with a using namespace Bstrlib; directive at the + end) unless the macro BSTRLIB_DONT_ASSUME_NAMESPACE has been defined before + it is included. + +- Erroneous accesses results in an exception being thrown. The exception + parameter is of type "struct CBStringException" which is derived from + std::exception if STL is used. A verbose description of the error message + can be obtained from the what() method. + +- CBString is a C++ structure derived from a struct tagbstring. An address + of a CBString cast to a bstring must not be passed to bdestroy. The bstring + C API has been made C++ safe and can be used directly in a C++ project. + +- It includes constructors which can take a char, '\0' terminated char + buffer, tagbstring, (char, repeat-value), a length delimited buffer or a + CBStringList to initialize it. + +- Concatenation is performed with the + and += operators. Comparisons are + done with the ==, !=, <, >, <= and >= operators. Note that == and != use + the biseq call, while <, >, <= and >= use bstrcmp. + +- CBString's can be directly cast to const character buffers. + +- CBString's can be directly cast to double, float, int or unsigned int so + long as the CBString are decimal representations of those types (otherwise + an exception will be thrown). Converting the other way should be done with + the format(a) method(s). + +- CBString contains the length, character and [] accessor methods. The + character and [] accessors are aliases of each other. If the bounds for + the string are exceeded, an exception is thrown. To avoid the overhead for + this check, first cast the CBString to a (const char *) and use [] to + dereference the array as normal. Note that the character and [] accessor + methods allows both reading and writing of individual characters. + +- The methods: format, formata, find, reversefind, findcaseless, + reversefindcaseless, midstr, insert, insertchrs, replace, findreplace, + findreplacecaseless, remove, findchr, nfindchr, alloc, toupper, tolower, + gets, read are analogous to the functions that can be found in the C API. + +- The caselessEqual and caselessCmp methods are analogous to biseqcaseless + and bstricmp functions respectively. + +- Note that just like the bformat function, the format and formata methods do + not automatically cast CBStrings into char * strings for "%s"-type + substitutions: + + CBString w("world"); + CBString h("Hello"); + CBString hw; + + /* The casts are necessary */ + hw.format ("%s, %s", (const char *)h, (const char *)w); + +- The methods trunc and repeat have been added instead of using pattern. + +- ltrim, rtrim and trim methods have been added. These remove characters + from a given character string set (defaulting to the whitespace characters) + from either the left, right or both ends of the CBString, respectively. + +- The method setsubstr is also analogous in functionality to bsetstr, except + that it cannot be passed NULL. Instead the method fill and the fill-style + constructor have been supplied to enable this functionality. + +- The writeprotect(), writeallow() and iswriteprotected() methods are + analogous to the bwriteprotect(), bwriteallow() and biswriteprotected() + macros in the C API. Write protection semantics in CBString are stronger + than with the C API in that indexed character assignment is checked for + write protection. However, unlike with the C API, a write protected + CBString can be destroyed by the destructor. + +- CBStream is a C++ structure which wraps a struct bStream (its not derived + from it, since destruction is slightly different). It is constructed by + passing in a bNread function pointer and a stream parameter cast to void *. + This structure includes methods for detecting eof, setting the buffer + length, reading the whole stream or reading entries line by line or block + by block, an unread function, and a peek function. + +- If STL is available, the CBStringList structure is derived from a vector of + CBString with various split methods. The split method has been overloaded + to accept either a character or CBString as the second parameter (when the + split parameter is a CBString any character in that CBString is used as a + seperator). The splitstr method takes a CBString as a substring seperator. + Joins can be performed via a CBString constructor which takes a + CBStringList as a parameter, or just using the CBString::join() method. + +- If there is proper support for std::iostreams, then the >> and << operators + and the getline() function have been added (with semantics the same as + those for std::string). + +Multithreading +-------------- + +A mutable bstring is kind of analogous to a small (two entry) linked list +allocated by malloc, with all aliasing completely under programmer control. +I.e., manipulation of one bstring will never affect any other distinct +bstring unless explicitely constructed to do so by the programmer via hand +construction or via building a reference. Bstrlib also does not use any +static or global storage, so there are no hidden unremovable race conditions. +Bstrings are also clearly not inherently thread local. So just like +char *'s, bstrings can be passed around from thread to thread and shared and +so on, so long as modifications to a bstring correspond to some kind of +exclusive access lock as should be expected (or if the bstring is read-only, +which can be enforced by bstring write protection) for any sort of shared +object in a multithreaded environment. + +Bsafe module +------------ + +For convenience, a bsafe module has been included. The idea is that if this +module is included, inadvertant usage of the most dangerous C functions will +be overridden and lead to an immediate run time abort. Of course, it should +be emphasized that usage of this module is completely optional. The +intention is essentially to provide an option for creating project safety +rules which can be enforced mechanically rather than socially. This is +useful for larger, or open development projects where its more difficult to +enforce social rules or "coding conventions". + +Problems not solved +------------------- + +Bstrlib is written for the C and C++ languages, which have inherent weaknesses +that cannot be easily solved: + +1. Memory leaks: Forgetting to call bdestroy on a bstring that is about to be + unreferenced, just as forgetting to call free on a heap buffer that is + about to be dereferenced. Though bstrlib itself is leak free. +2. Read before write usage: In C, declaring an auto bstring does not + automatically fill it with legal/valid contents. This problem has been + somewhat mitigated in C++. (The bstrDeclare and bstrFree macros from + bstraux can be used to help mitigate this problem.) + +Other problems not addressed: + +3. Built-in mutex usage to automatically avoid all bstring internal race + conditions in multitasking environments: The problem with trying to + implement such things at this low a level is that it is typically more + efficient to use locks in higher level primitives. There is also no + platform independent way to implement locks or mutexes. +4. Unicode/widecharacter support. + +Note that except for spotty support of wide characters, the default C +standard library does not address any of these problems either. + +Configurable compilation options +-------------------------------- + +All configuration options are meant solely for the purpose of compiler +compatibility. Configuration options are not meant to change the semantics +or capabilities of the library, except where it is unavoidable. + +Since some C++ compilers don't include the Standard Template Library and some +have the options of disabling exception handling, a number of macros can be +used to conditionally compile support for each of this: + +BSTRLIB_CAN_USE_STL + + - defining this will enable the used of the Standard Template Library. + Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. + +BSTRLIB_CANNOT_USE_STL + + - defining this will disable the use of the Standard Template Library. + Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. + +BSTRLIB_CAN_USE_IOSTREAM + + - defining this will enable the used of streams from class std. Defining + BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. + +BSTRLIB_CANNOT_USE_IOSTREAM + + - defining this will disable the use of streams from class std. Defining + BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. + +BSTRLIB_THROWS_EXCEPTIONS + + - defining this will enable the exception handling within bstring. + Defining BSTRLIB_THROWS_EXCEPTIONS overrides the + BSTRLIB_DOESNT_THROWS_EXCEPTIONS macro. + +BSTRLIB_DOESNT_THROW_EXCEPTIONS + + - defining this will disable the exception handling within bstring. + Defining BSTRLIB_THROWS_EXCEPTIONS overrides the + BSTRLIB_DOESNT_THROW_EXCEPTIONS macro. + +Note that these macros must be defined consistently throughout all modules +that use CBStrings including bstrwrap.cpp. + +Some older C compilers do not support functions such as vsnprintf. This is +handled by the following macro variables: + +BSTRLIB_NOVSNP + + - defining this indicates that the compiler does not support vsnprintf. + This will cause bformat and bformata to not be declared. Note that + for some compilers, such as Turbo C, this is set automatically. + Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. + +BSTRLIB_VSNP_OK + + - defining this will disable the autodetection of compilers the do not + support of compilers that do not support vsnprintf. + Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. + +Semantic compilation options +---------------------------- + +Bstrlib comes with very few compilation options for changing the semantics of +of the library. These are described below. + +BSTRLIB_DONT_ASSUME_NAMESPACE + + - Defining this before including bstrwrap.h will disable the automatic + enabling of the Bstrlib namespace for the C++ declarations. + +BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR + + - Defining this will make the CBString destructor non-virtual. + +BSTRLIB_MEMORY_DEBUG + + - Defining this will cause the bstrlib modules bstrlib.c and bstrwrap.cpp + to invoke a #include "memdbg.h". memdbg.h has to be supplied by the user. + +Note that these macros must be defined consistently throughout all modules +that use bstrings or CBStrings including bstrlib.c, bstraux.c and +bstrwrap.cpp. + +=============================================================================== + +Files +----- + +bstrlib.c - C implementaion of bstring functions. +bstrlib.h - C header file for bstring functions. +bstraux.c - C example that implements trivial additional functions. +bstraux.h - C header for bstraux.c +bstest.c - C unit/regression test for bstrlib.c + +bstrwrap.cpp - C++ implementation of CBString. +bstrwrap.h - C++ header file for CBString. +test.cpp - C++ unit/regression test for bstrwrap.cpp + +bsafe.c - C runtime stubs to abort usage of unsafe C functions. +bsafe.h - C header file for bsafe.c functions. + +C projects need only include bstrlib.h and compile/link bstrlib.c to use the +bstring library. C++ projects need to additionally include bstrwrap.h and +compile/link bstrwrap.cpp. For both, there may be a need to make choices +about feature configuration as described in the "Configurable compilation +options" in the section above. + +Other files that are included in this archive are: + +license.txt - The 3 clause BSD license for Bstrlib +gpl.txt - The GPL version 2 +security.txt - A security statement useful for auditting Bstrlib +porting.txt - A guide to porting Bstrlib +bstrlib.txt - This file + +=============================================================================== + +The functions +------------- + + extern bstring bfromcstr (const char * str); + + Take a standard C library style '\0' terminated char buffer and generate + a bstring with the same contents as the char buffer. If an error occurs + NULL is returned. + + So for example: + + bstring b = bfromcstr ("Hello"); + if (!b) { + fprintf (stderr, "Out of memory"); + } else { + puts ((char *) b->data); + } + + .......................................................................... + + extern bstring bfromcstralloc (int mlen, const char * str); + + Create a bstring which contains the contents of the '\0' terminated + char * buffer str. The memory buffer backing the bstring is at least + mlen characters in length. If an error occurs NULL is returned. + + So for example: + + bstring b = bfromcstralloc (64, someCstr); + if (b) b->data[63] = 'x'; + + The idea is that this will set the 64th character of b to 'x' if it is at + least 64 characters long otherwise do nothing. And we know this is well + defined so long as b was successfully created, since it will have been + allocated with at least 64 characters. + + .......................................................................... + + extern bstring blk2bstr (const void * blk, int len); + + Create a bstring whose contents are described by the contiguous buffer + pointing to by blk with a length of len bytes. Note that this function + creates a copy of the data in blk, rather than simply referencing it. + Compare with the blk2tbstr macro. If an error occurs NULL is returned. + + .......................................................................... + + extern char * bstr2cstr (const_bstring s, char z); + + Create a '\0' terminated char buffer which contains the contents of the + bstring s, except that any contained '\0' characters are converted to the + character in z. This returned value should be freed with bcstrfree(), by + the caller. If an error occurs NULL is returned. + + .......................................................................... + + extern int bcstrfree (char * s); + + Frees a C-string generated by bstr2cstr (). This is normally unnecessary + since it just wraps a call to free (), however, if malloc () and free () + have been redefined as a macros within the bstrlib module (via macros in + the memdbg.h backdoor) with some difference in behaviour from the std + library functions, then this allows a correct way of freeing the memory + that allows higher level code to be independent from these macro + redefinitions. + + .......................................................................... + + extern bstring bstrcpy (const_bstring b1); + + Make a copy of the passed in bstring. The copied bstring is returned if + there is no error, otherwise NULL is returned. + + .......................................................................... + + extern int bassign (bstring a, const_bstring b); + + Overwrite the bstring a with the contents of bstring b. Note that the + bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + int bassigncstr (bstring a, const char * str); + + Overwrite the string a with the contents of char * string str. Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a may be partially overwritten. + + .......................................................................... + + int bassignblk (bstring a, const void * s, int len); + + Overwrite the string a with the contents of the block (s, len). Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + extern int bassignmidstr (bstring a, const_bstring b, int left, int len); + + Overwrite the bstring a with the middle of contents of bstring b + starting from position left and running for a length len. left and + len are clamped to the ends of b as with the function bmidstr. Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + extern bstring bmidstr (const_bstring b, int left, int len); + + Create a bstring which is the substring of b starting from position left + and running for a length len (clamped by the end of the bstring b.) If + there was no error, the value of this constructed bstring is returned + otherwise NULL is returned. + + .......................................................................... + + extern int bdelete (bstring s1, int pos, int len); + + Removes characters from pos to pos+len-1 and shifts the tail of the + bstring starting from pos+len to pos. len must be positive for this call + to have any effect. The section of the bstring described by (pos, len) + is clamped to boundaries of the bstring b. The value BSTR_OK is returned + if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int bconcat (bstring b0, const_bstring b1); + + Concatenate the bstring b1 to the end of bstring b0. The value BSTR_OK + is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bconchar (bstring b, char c); + + Concatenate the character c to the end of bstring b. The value BSTR_OK + is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bcatcstr (bstring b, const char * s); + + Concatenate the char * string s to the end of bstring b. The value + BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bcatblk (bstring b, const void * s, int len); + + Concatenate a fixed length buffer (s, len) to the end of bstring b. The + value BSTR_OK is returned if the operation is successful, otherwise + BSTR_ERR is returned. + + .......................................................................... + + extern int biseq (const_bstring b0, const_bstring b1); + + Compare the bstring b0 and b1 for equality. If the bstrings differ, 0 + is returned, if the bstrings are the same, 1 is returned, if there is an + error, -1 is returned. If the length of the bstrings are different, this + function has O(1) complexity. Contained '\0' characters are not treated + as a termination character. + + Note that the semantics of biseq are not completely compatible with + bstrcmp because of its different treatment of the '\0' character. + + .......................................................................... + + extern int bisstemeqblk (const_bstring b, const void * blk, int len); + + Compare beginning of bstring b0 with a block of memory of length len for + equality. If the beginning of b0 differs from the memory block (or if b0 + is too short), 0 is returned, if the bstrings are the same, 1 is returned, + if there is an error, -1 is returned. + + .......................................................................... + + extern int biseqcaseless (const_bstring b0, const_bstring b1); + + Compare two bstrings for equality without differentiating between case. + If the bstrings differ other than in case, 0 is returned, if the bstrings + are the same, 1 is returned, if there is an error, -1 is returned. If + the length of the bstrings are different, this function is O(1). '\0' + termination characters are not treated in any special way. + + .......................................................................... + + extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); + + Compare beginning of bstring b0 with a block of memory of length len + without differentiating between case for equality. If the beginning of b0 + differs from the memory block other than in case (or if b0 is too short), + 0 is returned, if the bstrings are the same, 1 is returned, if there is an + error, -1 is returned. + + .......................................................................... + + extern int biseqcstr (const_bstring b, const char *s); + + Compare the bstring b and char * bstring s. The C string s must be '\0' + terminated at exactly the length of the bstring b, and the contents + between the two must be identical with the bstring b with no '\0' + characters for the two contents to be considered equal. This is + equivalent to the condition that their current contents will be always be + equal when comparing them in the same format after converting one or the + other. If they are equal 1 is returned, if they are unequal 0 is + returned and if there is a detectable error BSTR_ERR is returned. + + .......................................................................... + + extern int biseqcstrcaseless (const_bstring b, const char *s); + + Compare the bstring b and char * string s. The C string s must be '\0' + terminated at exactly the length of the bstring b, and the contents + between the two must be identical except for case with the bstring b with + no '\0' characters for the two contents to be considered equal. This is + equivalent to the condition that their current contents will be always be + equal ignoring case when comparing them in the same format after + converting one or the other. If they are equal, except for case, 1 is + returned, if they are unequal regardless of case 0 is returned and if + there is a detectable error BSTR_ERR is returned. + + .......................................................................... + + extern int bstrcmp (const_bstring b0, const_bstring b1); + + Compare the bstrings b0 and b1 for ordering. If there is an error, + SHRT_MIN is returned, otherwise a value less than or greater than zero, + indicating that the bstring pointed to by b0 is lexicographically less + than or greater than the bstring pointed to by b1 is returned. If the + bstring lengths are unequal but the characters up until the length of the + shorter are equal then a value less than, or greater than zero, + indicating that the bstring pointed to by b0 is shorter or longer than the + bstring pointed to by b1 is returned. 0 is returned if and only if the + two bstrings are the same. If the length of the bstrings are different, + this function is O(n). Like its standard C library counter part, the + comparison does not proceed past any '\0' termination characters + encountered. + + The seemingly odd error return value, merely provides slightly more + granularity than the undefined situation given in the C library function + strcmp. The function otherwise behaves very much like strcmp(). + + Note that the semantics of bstrcmp are not completely compatible with + biseq because of its different treatment of the '\0' termination + character. + + .......................................................................... + + extern int bstrncmp (const_bstring b0, const_bstring b1, int n); + + Compare the bstrings b0 and b1 for ordering for at most n characters. If + there is an error, SHRT_MIN is returned, otherwise a value is returned as + if b0 and b1 were first truncated to at most n characters then bstrcmp + was called with these new bstrings are paremeters. If the length of the + bstrings are different, this function is O(n). Like its standard C + library counter part, the comparison does not proceed past any '\0' + termination characters encountered. + + The seemingly odd error return value, merely provides slightly more + granularity than the undefined situation given in the C library function + strncmp. The function otherwise behaves very much like strncmp(). + + .......................................................................... + + extern int bstricmp (const_bstring b0, const_bstring b1); + + Compare two bstrings without differentiating between case. The return + value is the difference of the values of the characters where the two + bstrings first differ, otherwise 0 is returned indicating that the + bstrings are equal. If the lengths are different, then a difference from + 0 is given, but if the first extra character is '\0', then it is taken to + be the value UCHAR_MAX+1. + + .......................................................................... + + extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); + + Compare two bstrings without differentiating between case for at most n + characters. If the position where the two bstrings first differ is + before the nth position, the return value is the difference of the values + of the characters, otherwise 0 is returned. If the lengths are different + and less than n characters, then a difference from 0 is given, but if the + first extra character is '\0', then it is taken to be the value + UCHAR_MAX+1. + + .......................................................................... + + extern int bdestroy (bstring b); + + Deallocate the bstring passed. Passing NULL in as a parameter will have + no effect. Note that both the header and the data portion of the bstring + will be freed. No other bstring function which modifies one of its + parameters will free or reallocate the header. Because of this, in + general, bdestroy cannot be called on any declared struct tagbstring even + if it is not write protected. A bstring which is write protected cannot + be destroyed via the bdestroy call. Any attempt to do so will result in + no action taken, and BSTR_ERR will be returned. + + Note to C++ users: Passing in a CBString cast to a bstring will lead to + undefined behavior (free will be called on the header, rather than the + CBString destructor.) Instead just use the ordinary C++ language + facilities to dealloc a CBString. + + .......................................................................... + + extern int binstr (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + forward (increasing) direction. If it is found then it returns with the + first position after pos where it is found, otherwise it returns BSTR_ERR. + The algorithm used is brute force; O(m*n). + + .......................................................................... + + extern int binstrr (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + backward (decreasing) direction. If it is found then it returns with the + first position after pos where it is found, otherwise return BSTR_ERR. + Note that the current position at pos is tested as well -- so to be + disjoint from a previous forward search it is recommended that the + position be backed up (decremented) by one position. The algorithm used + is brute force; O(m*n). + + .......................................................................... + + extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + forward (increasing) direction but without regard to case. If it is + found then it returns with the first position after pos where it is + found, otherwise it returns BSTR_ERR. The algorithm used is brute force; + O(m*n). + + .......................................................................... + + extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + backward (decreasing) direction but without regard to case. If it is + found then it returns with the first position after pos where it is + found, otherwise return BSTR_ERR. Note that the current position at pos + is tested as well -- so to be disjoint from a previous forward search it + is recommended that the position be backed up (decremented) by one + position. The algorithm used is brute force; O(m*n). + + .......................................................................... + + extern int binchr (const_bstring b0, int pos, const_bstring b1); + + Search for the first position in b0 starting from pos or after, in which + one of the characters in b1 is found. This function has an execution + time of O(b0->slen + b1->slen). If such a position does not exist in b0, + then BSTR_ERR is returned. + + .......................................................................... + + extern int binchrr (const_bstring b0, int pos, const_bstring b1); + + Search for the last position in b0 no greater than pos, in which one of + the characters in b1 is found. This function has an execution time + of O(b0->slen + b1->slen). If such a position does not exist in b0, + then BSTR_ERR is returned. + + .......................................................................... + + extern int bninchr (const_bstring b0, int pos, const_bstring b1); + + Search for the first position in b0 starting from pos or after, in which + none of the characters in b1 is found and return it. This function has + an execution time of O(b0->slen + b1->slen). If such a position does + not exist in b0, then BSTR_ERR is returned. + + .......................................................................... + + extern int bninchrr (const_bstring b0, int pos, const_bstring b1); + + Search for the last position in b0 no greater than pos, in which none of + the characters in b1 is found and return it. This function has an + execution time of O(b0->slen + b1->slen). If such a position does not + exist in b0, then BSTR_ERR is returned. + + .......................................................................... + + extern int bstrchr (const_bstring b, int c); + + Search for the character c in the bstring b forwards from the start of + the bstring. Returns the position of the found character or BSTR_ERR if + it is not found. + + NOTE: This has been implemented as a macro on top of bstrchrp (). + + .......................................................................... + + extern int bstrrchr (const_bstring b, int c); + + Search for the character c in the bstring b backwards from the end of the + bstring. Returns the position of the found character or BSTR_ERR if it is + not found. + + NOTE: This has been implemented as a macro on top of bstrrchrp (). + + .......................................................................... + + extern int bstrchrp (const_bstring b, int c, int pos); + + Search for the character c in b forwards from the position pos + (inclusive). Returns the position of the found character or BSTR_ERR if + it is not found. + + .......................................................................... + + extern int bstrrchrp (const_bstring b, int c, int pos); + + Search for the character c in b backwards from the position pos in bstring + (inclusive). Returns the position of the found character or BSTR_ERR if + it is not found. + + .......................................................................... + + extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); + + Overwrite the bstring b0 starting at position pos with the bstring b1. If + the position pos is past the end of b0, then the character "fill" is + appended as necessary to make up the gap between the end of b0 and pos. + If b1 is NULL, it behaves as if it were a 0-length bstring. The value + BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); + + Inserts the bstring s2 into s1 at position pos. If the position pos is + past the end of s1, then the character "fill" is appended as necessary to + make up the gap between the end of s1 and pos. The value BSTR_OK is + returned if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int binsertch (bstring s1, int pos, int len, unsigned char fill); + + Inserts the character fill repeatedly into s1 at position pos for a + length len. If the position pos is past the end of s1, then the + character "fill" is appended as necessary to make up the gap between the + end of s1 and the position pos + len (exclusive). The value BSTR_OK is + returned if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int breplace (bstring b1, int pos, int len, const_bstring b2, + unsigned char fill); + + Replace a section of a bstring from pos for a length len with the bstring + b2. If the position pos is past the end of b1 then the character "fill" + is appended as necessary to make up the gap between the end of b1 and + pos. + + .......................................................................... + + extern int bfindreplace (bstring b, const_bstring find, + const_bstring replace, int position); + + Replace all occurrences of the find substring with a replace bstring + after a given position in the bstring b. The find bstring must have a + length > 0 otherwise BSTR_ERR is returned. This function does not + perform recursive per character replacement; that is to say successive + searches resume at the position after the last replace. + + So for example: + + bfindreplace (a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"), + a2 = bfromcstr("aa"), 0); + + Should result in changing a0 to "aaaabaaAb". + + This function performs exactly (b->slen - position) bstring comparisons, + and data movement is bounded above by character volume equivalent to size + of the output bstring. + + .......................................................................... + + extern int bfindreplacecaseless (bstring b, const_bstring find, + const_bstring replace, int position); + + Replace all occurrences of the find substring, ignoring case, with a + replace bstring after a given position in the bstring b. The find bstring + must have a length > 0 otherwise BSTR_ERR is returned. This function + does not perform recursive per character replacement; that is to say + successive searches resume at the position after the last replace. + + So for example: + + bfindreplacecaseless (a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"), + a2 = bfromcstr("aa"), 0); + + Should result in changing a0 to "aaaabaaaab". + + This function performs exactly (b->slen - position) bstring comparisons, + and data movement is bounded above by character volume equivalent to size + of the output bstring. + + .......................................................................... + + extern int balloc (bstring b, int length); + + Increase the allocated memory backing the data buffer for the bstring b + to a length of at least length. If the memory backing the bstring b is + already large enough, not action is performed. This has no effect on the + bstring b that is visible to the bstring API. Usually this function will + only be used when a minimum buffer size is required coupled with a direct + access to the ->data member of the bstring structure. + + Be warned that like any other bstring function, the bstring must be well + defined upon entry to this function. I.e., doing something like: + + b->slen *= 2; /* ?? Most likely incorrect */ + balloc (b, b->slen); + + is invalid, and should be implemented as: + + int t; + if (BSTR_OK == balloc (b, t = (b->slen * 2))) b->slen = t; + + This function will return with BSTR_ERR if b is not detected as a valid + bstring or length is not greater than 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int ballocmin (bstring b, int length); + + Change the amount of memory backing the bstring b to at least length. + This operation will never truncate the bstring data including the + extra terminating '\0' and thus will not decrease the length to less than + b->slen + 1. Note that repeated use of this function may cause + performance problems (realloc may be called on the bstring more than + the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b + is not detected as a valid bstring or length is not greater than 0, + otherwise BSTR_OK is returned. + + So for example: + + if (BSTR_OK == ballocmin (b, 64)) b->data[63] = 'x'; + + The idea is that this will set the 64th character of b to 'x' if it is at + least 64 characters long otherwise do nothing. And we know this is well + defined so long as the ballocmin call was successfully, since it will + ensure that b has been allocated with at least 64 characters. + + .......................................................................... + + int btrunc (bstring b, int n); + + Truncate the bstring to at most n characters. This function will return + with BSTR_ERR if b is not detected as a valid bstring or n is less than + 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bpattern (bstring b, int len); + + Replicate the starting bstring, b, end to end repeatedly until it + surpasses len characters, then chop the result to exactly len characters. + This function operates in-place. This function will return with BSTR_ERR + if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int btoupper (bstring b); + + Convert contents of bstring to upper case. This function will return with + BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int btolower (bstring b); + + Convert contents of bstring to lower case. This function will return with + BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bltrimws (bstring b); + + Delete whitespace contiguous from the left end of the bstring. This + function will return with BSTR_ERR if b is NULL or of length 0, otherwise + BSTR_OK is returned. + + .......................................................................... + + extern int brtrimws (bstring b); + + Delete whitespace contiguous from the right end of the bstring. This + function will return with BSTR_ERR if b is NULL or of length 0, otherwise + BSTR_OK is returned. + + .......................................................................... + + extern int btrimws (bstring b); + + Delete whitespace contiguous from both ends of the bstring. This function + will return with BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK + is returned. + + .......................................................................... + + extern int bstrListCreate (void); + + Create an empty struct bstrList. The struct bstrList output structure is + declared as follows: + + struct bstrList { + int qty, mlen; + bstring * entry; + }; + + The entry field actually is an array with qty number entries. The mlen + record counts the maximum number of bstring's for which there is memory + in the entry record. + + The Bstrlib API does *NOT* include a comprehensive set of functions for + full management of struct bstrList in an abstracted way. The reason for + this is because aliasing semantics of the list are best left to the user + of this function, and performance varies wildly depending on the + assumptions made. For a complete list of bstring data type it is + recommended that the C++ public std::vector<CBString> be used, since its + semantics are usage are more standard. + + .......................................................................... + + extern int bstrListDestroy (struct bstrList * sl); + + Destroy a struct bstrList structure that was returned by the bsplit + function. Note that this will destroy each bstring in the ->entry array + as well. See bstrListCreate() above for structure of struct bstrList. + + .......................................................................... + + extern int bstrListAlloc (struct bstrList * sl, int msz); + + Ensure that there is memory for at least msz number of entries for the + list. + + .......................................................................... + + extern int bstrListAllocMin (struct bstrList * sl, int msz); + + Try to allocate the minimum amount of memory for the list to include at + least msz entries or sl->qty whichever is greater. + + .......................................................................... + + extern struct bstrList * bsplit (bstring str, unsigned char splitChar); + + Create an array of sequential substrings from str divided by the + character splitChar. Successive occurrences of the splitChar will be + divided by empty bstring entries, following the semantics from the Python + programming language. To reclaim the memory from this output structure, + bstrListDestroy () should be called. See bstrListCreate() above for + structure of struct bstrList. + + .......................................................................... + + extern struct bstrList * bsplits (bstring str, const_bstring splitStr); + + Create an array of sequential substrings from str divided by any + character contained in splitStr. An empty splitStr causes a single entry + bstrList containing a copy of str to be returned. See bstrListCreate() + above for structure of struct bstrList. + + .......................................................................... + + extern struct bstrList * bsplitstr (bstring str, const_bstring splitStr); + + Create an array of sequential substrings from str divided by the entire + substring splitStr. An empty splitStr causes a single entry bstrList + containing a copy of str to be returned. See bstrListCreate() above for + structure of struct bstrList. + + .......................................................................... + + extern bstring bjoin (const struct bstrList * bl, const_bstring sep); + + Join the entries of a bstrList into one bstring by sequentially + concatenating them with the sep bstring in between. If sep is NULL, it + is treated as if it were the empty bstring. Note that: + + bjoin (l = bsplit (b, s->data[0]), s); + + should result in a copy of b, if s->slen is 1. If there is an error NULL + is returned, otherwise a bstring with the correct result is returned. + See bstrListCreate() above for structure of struct bstrList. + + .......................................................................... + + extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by the character splitChar. The parm passed to + bsplitcb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitcb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitcb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitcb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplit that is + abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by any of the characters in splitStr. An empty + splitStr causes the whole str to be iterated once. The parm passed to + bsplitcb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitscb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitscb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitscb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplits that + is abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by the entire substring splitStr. An empty splitStr + causes each character of str to be iterated. The parm passed to bsplitcb + is passed on to cb. If the function cb returns a value < 0, then further + iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitstrcb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitstrcb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitscb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplitstr that + is abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern bstring bformat (const char * fmt, ...); + + Takes the same parameters as printf (), but rather than outputting + results to stdio, it forms a bstring which contains what would have been + output. Note that if there is an early generation of a '\0' character, + the bstring will be truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + b0 = bformat ("Hello, %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bformat function is not present. + + .......................................................................... + + extern int bformata (bstring b, const char * fmt, ...); + + In addition to the initial output buffer b, bformata takes the same + parameters as printf (), but rather than outputting results to stdio, it + appends the results to the initial bstring parameter. Note that if + there is an early generation of a '\0' character, the bstring will be + truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bformata function is not present. + + .......................................................................... + + extern int bassignformat (bstring b, const char * fmt, ...); + + After the first parameter, it takes the same parameters as printf (), but + rather than outputting results to stdio, it outputs the results to + the bstring parameter b. Note that if there is an early generation of a + '\0' character, the bstring will be truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bassignformat function is not present. + + .......................................................................... + + extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); + + The bvcformata function formats data under control of the format control + string fmt and attempts to append the result to b. The fmt parameter is + the same as that of the printf function. The variable argument list is + replaced with arglist, which has been initialized by the va_start macro. + The size of the output is upper bounded by count. If the required output + exceeds count, the string b is not augmented with any contents and a value + below BSTR_ERR is returned. If a value below -count is returned then it + is recommended that the negative of this value be used as an update to the + count in a subsequent pass. On other errors, such as running out of + memory, parameter errors or numeric wrap around BSTR_ERR is returned. + BSTR_OK is returned when the output is successfully generated and + appended to b. + + Note: There is no sanity checking of arglist, and this function is + destructive of the contents of b from the b->slen point onward. If there + is an early generation of a '\0' character, the bstring will be truncated + to this end point. + + Although this function is part of the external API for Bstrlib, the + interface and semantics (length limitations, and unusual return codes) + are fairly atypical. The real purpose for this function is to provide an + engine for the bvformata macro. + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bvcformata function is not present. + + .......................................................................... + + extern bstring bread (bNread readPtr, void * parm); + typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, + void *parm); + + Read an entire stream into a bstring, verbatum. The readPtr function + pointer is compatible with fread sematics, except that it need not obtain + the stream data from a file. The intention is that parm would contain + the stream data context/state required (similar to the role of the FILE* + I/O stream parameter of fread.) + + Abstracting the block read function allows for block devices other than + file streams to be read if desired. Note that there is an ANSI + compatibility issue if "fread" is used directly; see the ANSI issues + section below. + + .......................................................................... + + extern int breada (bstring b, bNread readPtr, void * parm); + + Read an entire stream and append it to a bstring, verbatum. Behaves + like bread, except that it appends it results to the bstring b. + BSTR_ERR is returned on error, otherwise 0 is returned. + + .......................................................................... + + extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); + typedef int (* bNgetc) (void * parm); + + Read a bstring from a stream. As many bytes as is necessary are read + until the terminator is consumed or no more characters are available from + the stream. If read from the stream, the terminator character will be + appended to the end of the returned bstring. The getcPtr function must + have the same semantics as the fgetc C library function (i.e., returning + an integer whose value is negative when there are no more characters + available, otherwise the value of the next available unsigned character + from the stream.) The intention is that parm would contain the stream + data context/state required (similar to the role of the FILE* I/O stream + parameter of fgets.) If no characters are read, or there is some other + detectable error, NULL is returned. + + bgets will never call the getcPtr function more often than necessary to + construct its output (including a single call, if required, to determine + that the stream contains no more characters.) + + Abstracting the character stream function and terminator character allows + for different stream devices and string formats other than '\n' + terminated lines in a file if desired (consider \032 terminated email + messages, in a UNIX mailbox for example.) + + For files, this function can be used analogously as fgets as follows: + + fp = fopen ( ... ); + if (fp) b = bgets ((bNgetc) fgetc, fp, '\n'); + + (Note that only one terminator character can be used, and that '\0' is + not assumed to terminate the stream in addition to the terminator + character. This is consistent with the semantics of fgets.) + + .......................................................................... + + extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); + + Read from a stream and concatenate to a bstring. Behaves like bgets, + except that it appends it results to the bstring b. The value 1 is + returned if no characters are read before a negative result is returned + from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned + in other normal cases. + + .......................................................................... + + extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); + + Read from a stream and concatenate to a bstring. Behaves like bgets, + except that it assigns the results to the bstring b. The value 1 is + returned if no characters are read before a negative result is returned + from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned + in other normal cases. + + .......................................................................... + + extern struct bStream * bsopen (bNread readPtr, void * parm); + + Wrap a given open stream (described by a fread compatible function + pointer and stream handle) into an open bStream suitable for the bstring + library streaming functions. + + .......................................................................... + + extern void * bsclose (struct bStream * s); + + Close the bStream, and return the handle to the stream that was + originally used to open the given stream. If s is NULL or detectably + invalid, NULL will be returned. + + .......................................................................... + + extern int bsbufflength (struct bStream * s, int sz); + + Set the length of the buffer used by the bStream. If sz is the macro + BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not set. If s is + NULL or sz is negative, the function will return with BSTR_ERR, otherwise + this function returns with the previous length. + + .......................................................................... + + extern int bsreadln (bstring r, struct bStream * s, char terminator); + + Read a bstring terminated by the terminator character or the end of the + stream from the bStream (s) and return it into the parameter r. The + matched terminator, if found, appears at the end of the line read. If + the stream has been exhausted of all available data, before any can be + read, BSTR_ERR is returned. This function may read additional characters + into the stream buffer from the core stream that are not returned, but + will be retained for subsequent read operations. When reading from high + speed streams, this function can perform significantly faster than bgets. + + .......................................................................... + + extern int bsreadlna (bstring r, struct bStream * s, char terminator); + + Read a bstring terminated by the terminator character or the end of the + stream from the bStream (s) and concatenate it to the parameter r. The + matched terminator, if found, appears at the end of the line read. If + the stream has been exhausted of all available data, before any can be + read, BSTR_ERR is returned. This function may read additional characters + into the stream buffer from the core stream that are not returned, but + will be retained for subsequent read operations. When reading from high + speed streams, this function can perform significantly faster than bgets. + + .......................................................................... + + extern int bsreadlns (bstring r, struct bStream * s, bstring terminators); + + Read a bstring terminated by any character in the terminators bstring or + the end of the stream from the bStream (s) and return it into the + parameter r. This function may read additional characters from the core + stream that are not returned, but will be retained for subsequent read + operations. + + .......................................................................... + + extern int bsreadlnsa (bstring r, struct bStream * s, bstring terminators); + + Read a bstring terminated by any character in the terminators bstring or + the end of the stream from the bStream (s) and concatenate it to the + parameter r. If the stream has been exhausted of all available data, + before any can be read, BSTR_ERR is returned. This function may read + additional characters from the core stream that are not returned, but + will be retained for subsequent read operations. + + .......................................................................... + + extern int bsread (bstring r, struct bStream * s, int n); + + Read a bstring of length n (or, if it is fewer, as many bytes as is + remaining) from the bStream. This function will read the minimum + required number of additional characters from the core stream. When the + stream is at the end of the file BSTR_ERR is returned, otherwise BSTR_OK + is returned. + + .......................................................................... + + extern int bsreada (bstring r, struct bStream * s, int n); + + Read a bstring of length n (or, if it is fewer, as many bytes as is + remaining) from the bStream and concatenate it to the parameter r. This + function will read the minimum required number of additional characters + from the core stream. When the stream is at the end of the file BSTR_ERR + is returned, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bsunread (struct bStream * s, const_bstring b); + + Insert a bstring into the bStream at the current position. These + characters will be read prior to those that actually come from the core + stream. + + .......................................................................... + + extern int bspeek (bstring r, const struct bStream * s); + + Return the number of currently buffered characters from the bStream that + will be read prior to reads from the core stream, and append it to the + the parameter r. + + .......................................................................... + + extern int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); + + Iterate the set of disjoint sequential substrings over the stream s + divided by any character from the bstring splitStr. The parm passed to + bssplitscb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this return value is returned by + bssplitscb. + + Note: At the point of calling the cb function, the bStream pointer is + pointed exactly at the position right after having read the split + character. The cb function can act on the stream by causing the bStream + pointer to move, and bssplitscb will continue by starting the next split + at the position of the pointer after the return from cb. + + However, if the cb causes the bStream s to be destroyed then the cb must + return with a negative value, otherwise bssplitscb will continue in an + undefined manner. + + This function is provided as way to incrementally parse through a file + or other generic stream that in total size may otherwise exceed the + practical or desired memory available. As with the other split callback + based functions this is abortable and does not impose additional memory + allocation. + + .......................................................................... + + extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); + + Iterate the set of disjoint sequential substrings over the stream s + divided by the entire substring splitStr. The parm passed to + bssplitstrcb is passed on to cb. If the function cb returns a + value < 0, then further iterating is halted and this return value is + returned by bssplitstrcb. + + Note: At the point of calling the cb function, the bStream pointer is + pointed exactly at the position right after having read the split + character. The cb function can act on the stream by causing the bStream + pointer to move, and bssplitstrcb will continue by starting the next + split at the position of the pointer after the return from cb. + + However, if the cb causes the bStream s to be destroyed then the cb must + return with a negative value, otherwise bssplitscb will continue in an + undefined manner. + + This function is provided as way to incrementally parse through a file + or other generic stream that in total size may otherwise exceed the + practical or desired memory available. As with the other split callback + based functions this is abortable and does not impose additional memory + allocation. + + .......................................................................... + + extern int bseof (const struct bStream * s); + + Return the defacto "EOF" (end of file) state of a stream (1 if the + bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or + detectably erroneous.) When the readPtr callback returns a value <= 0 + the stream reaches its "EOF" state. Note that bunread with non-empty + content will essentially turn off this state, and the stream will not be + in its "EOF" state so long as its possible to read more data out of it. + + Also note that the semantics of bseof() are slightly different from + something like feof(). I.e., reaching the end of the stream does not + necessarily guarantee that bseof() will return with a value indicating + that this has happened. bseof() will only return indicating that it has + reached the "EOF" and an attempt has been made to read past the end of + the bStream. + +The macros +---------- + + The macros described below are shown in a prototype form indicating their + intended usage. Note that the parameters passed to these macros will be + referenced multiple times. As with all macros, programmer care is + required to guard against unintended side effects. + + int blengthe (const_bstring b, int err); + + Returns the length of the bstring. If the bstring is NULL err is + returned. + + .......................................................................... + + int blength (const_bstring b); + + Returns the length of the bstring. If the bstring is NULL, the length + returned is 0. + + .......................................................................... + + int bchare (const_bstring b, int p, int c); + + Returns the p'th character of the bstring b. If the position p refers to + a position that does not exist in the bstring or the bstring is NULL, + then c is returned. + + .......................................................................... + + char bchar (const_bstring b, int p); + + Returns the p'th character of the bstring b. If the position p refers to + a position that does not exist in the bstring or the bstring is NULL, + then '\0' is returned. + + .......................................................................... + + char * bdatae (bstring b, char * err); + + Returns the char * data portion of the bstring b. If b is NULL, err is + returned. + + .......................................................................... + + char * bdata (bstring b); + + Returns the char * data portion of the bstring b. If b is NULL, NULL is + returned. + + .......................................................................... + + char * bdataofse (bstring b, int ofs, char * err); + + Returns the char * data portion of the bstring b offset by ofs. If b is + NULL, err is returned. + + .......................................................................... + + char * bdataofs (bstring b, int ofs); + + Returns the char * data portion of the bstring b offset by ofs. If b is + NULL, NULL is returned. + + .......................................................................... + + struct tagbstring var = bsStatic ("..."); + + The bsStatic macro allows for static declarations of literal string + constants as struct tagbstring structures. The resulting tagbstring does + not need to be freed or destroyed. Note that this macro is only well + defined for string literal arguments. For more general string pointers, + use the btfromcstr macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + <void * blk, int len> <- bsStaticBlkParms ("...") + + The bsStaticBlkParms macro emits a pair of comma seperated parameters + corresponding to the block parameters for the block functions in Bstrlib + (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk.) + Note that this macro is only well defined for string literal arguments. + + Examples: + + bstring b = blk2bstr (bsStaticBlkParms ("Fast init. ")); + bcatblk (b, bsStaticBlkParms ("No frills fast concatenation.")); + + These are faster than using bfromcstr() and bcatcstr() respectively + because the length of the inline string is known as a compile time + constant. Also note that seperate struct tagbstring declarations for + holding the output of a bsStatic() macro are not required. + + .......................................................................... + + void btfromcstr (struct tagbstring& t, const char * s); + + Fill in the tagbstring t with the '\0' terminated char buffer s. This + action is purely reference oriented; no memory management is done. The + data member is just assigned s, and slen is assigned the strlen of s. + The s parameter is accessed exactly once in this macro. + + The resulting struct tagbstring is initially write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoke the + bwriteallow on this struct tagbstring to make it writeable (though this + requires that s be obtained from a function compatible with malloc.) + + .......................................................................... + + void btfromblk (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len. This + action is purely reference oriented; no memory management is done. The + data member of t is just assigned s, and slen is assigned len. Note that + the buffer is not appended with a '\0' character. The s and len + parameters are accessed exactly once each in this macro. + + The resulting struct tagbstring is initially write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoke the + bwriteallow on this struct tagbstring to make it writeable (though this + requires that s be obtained from a function compatible with malloc.) + + .......................................................................... + + void btfromblkltrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been left trimmed. This action is purely reference oriented; no + memory management is done. The data member of t is just assigned to a + pointer inside the buffer s. Note that the buffer is not appended with a + '\0' character. The s and len parameters are accessed exactly once each + in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void btfromblkrtrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been right trimmed. This action is purely reference oriented; no + memory management is done. The data member of t is just assigned to a + pointer inside the buffer s. Note that the buffer is not appended with a + '\0' character. The s and len parameters are accessed exactly once each + in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void btfromblktrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been left and right trimmed. This action is purely reference + oriented; no memory management is done. The data member of t is just + assigned to a pointer inside the buffer s. Note that the buffer is not + appended with a '\0' character. The s and len parameters are accessed + exactly once each in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void bmid2tbstr (struct tagbstring& t, bstring b, int pos, int len); + + Fill the tagbstring t with the substring from b, starting from position + pos with a length len. The segment is clamped by the boundaries of + the bstring b. This action is purely reference oriented; no memory + management is done. Note that the buffer is not appended with a '\0' + character. Note that the t parameter to this macro may be accessed + multiple times. Note that the contents of t will become undefined + if the contents of b change or are destroyed. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoking the + bwriteallow macro on this struct tagbstring will have no effect. + + .......................................................................... + + void bvformata (int& ret, bstring b, const char * format, lastarg); + + Append the bstring b with printf like formatting with the format control + string, and the arguments taken from the ... list of arguments after + lastarg passed to the containing function. If the containing function + does not have ... parameters or lastarg is not the last named parameter + before the ... then the results are undefined. If successful, the + results are appended to b and BSTR_OK is assigned to ret. Otherwise + BSTR_ERR is assigned to ret. + + Example: + + void dbgerror (FILE * fp, const char * fmt, ...) { + int ret; + bstring b; + bvformata (ret, b = bfromcstr ("DBG: "), fmt, fmt); + if (BSTR_OK == ret) fputs ((char *) bdata (b), fp); + bdestroy (b); + } + + Note that if the BSTRLIB_NOVSNP macro was set when bstrlib had been + compiled the bvformata macro will not link properly. If the + BSTRLIB_NOVSNP macro has been set, the bvformata macro will not be + available. + + .......................................................................... + + void bwriteprotect (struct tagbstring& t); + + Disallow bstring from being written to via the bstrlib API. Attempts to + write to the resulting tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. + + Note: bstrings which are write protected cannot be destroyed via bdestroy. + + Note to C++ users: Setting a CBString as write protected will not prevent + it from being destroyed by the destructor. + + .......................................................................... + + void bwriteallow (struct tagbstring& t); + + Allow bstring to be written to via the bstrlib API. Note that such an + action makes the bstring both writable and destroyable. If the bstring is + not legitimately writable (as is the case for struct tagbstrings + initialized with a bsStatic value), the results of this are undefined. + + Note that invoking the bwriteallow macro may increase the number of + reallocs by one more than necessary for every call to bwriteallow + interleaved with any bstring API which writes to this bstring. + + .......................................................................... + + int biswriteprotected (struct tagbstring& t); + + Returns 1 if the bstring is write protected, otherwise 0 is returned. + +=============================================================================== + +The bstest module +----------------- + +The bstest module is just a unit test for the bstrlib module. For correct +implementations of bstrlib, it should execute with 0 failures being reported. +This test should be utilized if modifications/customizations to bstrlib have +been performed. It tests each core bstrlib function with bstrings of every +mode (read-only, NULL, static and mutable) and ensures that the expected +semantics are observed (including results that should indicate an error). It +also tests for aliasing support. Passing bstest is a necessary but not a +sufficient condition for ensuring the correctness of the bstrlib module. + + +The test module +--------------- + +The test module is just a unit test for the bstrwrap module. For correct +implementations of bstrwrap, it should execute with 0 failures being +reported. This test should be utilized if modifications/customizations to +bstrwrap have been performed. It tests each core bstrwrap function with +CBStrings write protected or not and ensures that the expected semantics are +observed (including expected exceptions.) Note that exceptions cannot be +disabled to run this test. Passing test is a necessary but not a sufficient +condition for ensuring the correctness of the bstrwrap module. + +=============================================================================== + +Using Bstring and CBString as an alternative to the C library +------------------------------------------------------------- + +First let us give a table of C library functions and the alternative bstring +functions and CBString methods that should be used instead of them. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +gets bgets ::gets +strcpy bassign = operator +strncpy bassignmidstr ::midstr +strcat bconcat += operator +strncat bconcat + btrunc += operator + ::trunc +strtok bsplit, bsplits ::split +sprintf b(assign)format ::format +snprintf b(assign)format + btrunc ::format + ::trunc +vsprintf bvformata bvformata + +vsnprintf bvformata + btrunc bvformata + btrunc +vfprintf bvformata + fputs use bvformata + fputs +strcmp biseq, bstrcmp comparison operators. +strncmp bstrncmp, memcmp bstrncmp, memcmp +strlen ->slen, blength ::length +strdup bstrcpy constructor +strset bpattern ::fill +strstr binstr ::find +strpbrk binchr ::findchr +stricmp bstricmp cast & use bstricmp +strlwr btolower cast & use btolower +strupr btoupper cast & use btoupper +strrev bReverse (aux module) cast & use bReverse +strchr bstrchr cast & use bstrchr +strspnp use strspn use strspn +ungetc bsunread bsunread + +The top 9 C functions listed here are troublesome in that they impose memory +management in the calling function. The Bstring and CBstring interfaces have +built-in memory management, so there is far less code with far less potential +for buffer overrun problems. strtok can only be reliably called as a "leaf" +calculation, since it (quite bizarrely) maintains hidden internal state. And +gets is well known to be broken no matter what. The Bstrlib alternatives do +not suffer from those sorts of problems. + +The substitute for strncat can be performed with higher performance by using +the blk2tbstr macro to create a presized second operand for bconcat. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +strspn strspn acceptable strspn acceptable +strcspn strcspn acceptable strcspn acceptable +strnset strnset acceptable strnset acceptable +printf printf acceptable printf acceptable +puts puts acceptable puts acceptable +fprintf fprintf acceptable fprintf acceptable +fputs fputs acceptable fputs acceptable +memcmp memcmp acceptable memcmp acceptable + +Remember that Bstring (and CBstring) functions will automatically append the +'\0' character to the character data buffer. So by simply accessing the data +buffer directly, ordinary C string library functions can be called directly +on them. Note that bstrcmp is not the same as memcmp in exactly the same way +that strcmp is not the same as memcmp. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +fread balloc + fread ::alloc + fread +fgets balloc + fgets ::alloc + fgets + +These are odd ones because of the exact sizing of the buffer required. The +Bstring and CBString alternatives requires that the buffers are forced to +hold at least the prescribed length, then just use fread or fgets directly. +However, typically the automatic memory management of Bstring and CBstring +will make the typical use of fgets and fread to read specifically sized +strings unnecessary. + +Implementation Choices +---------------------- + +Overhead: +......... + +The bstring library has more overhead versus straight char buffers for most +functions. This overhead is essentially just the memory management and +string header allocation. This overhead usually only shows up for small +string manipulations. The performance loss has to be considered in +light of the following: + +1) What would be the performance loss of trying to write this management + code in one's own application? +2) Since the bstring library source code is given, a sufficiently powerful + modern inlining globally optimizing compiler can remove function call + overhead. + +Since the data type is exposed, a developer can replace any unsatisfactory +function with their own inline implementation. And that is besides the main +point of what the better string library is mainly meant to provide. Any +overhead lost has to be compared against the value of the safe abstraction +for coupling memory management and string functionality. + +Performance of the C interface: +............................... + +The algorithms used have performance advantages versus the analogous C +library functions. For example: + +1. bfromcstr/blk2str/bstrcpy versus strcpy/strdup. By using memmove instead + of strcpy, the break condition of the copy loop is based on an independent + counter (that should be allocated in a register) rather than having to + check the results of the load. Modern out-of-order executing CPUs can + parallelize the final branch mis-predict penality with the loading of the + source string. Some CPUs will also tend to have better built-in hardware + support for counted memory moves than load-compare-store. (This is a + minor, but non-zero gain.) +2. biseq versus strcmp. If the strings are unequal in length, bsiseq will + return in O(1) time. If the strings are aliased, or have aliased data + buffers, biseq will return in O(1) time. strcmp will always be O(k), + where k is the length of the common prefix or the whole string if they are + identical. +3. ->slen versus strlen. ->slen is obviously always O(1), while strlen is + always O(n) where n is the length of the string. +4. bconcat versus strcat. Both rely on precomputing the length of the + destination string argument, which will favor the bstring library. On + iterated concatenations the performance difference can be enormous. +5. bsreadln versus fgets. The bsreadln function reads large blocks at a time + from the given stream, then parses out lines from the buffers directly. + Some C libraries will implement fgets as a loop over single fgetc calls. + Testing indicates that the bsreadln approach can be several times faster + for fast stream devices (such as a file that has been entirely cached.) +6. bsplits/bsplitscb versus strspn. Accelerators for the set of match + characters are generated only once. +7. binstr versus strstr. The binstr implementation unrolls the loops to + help reduce loop overhead. This will matter if the target string is + long and source string is not found very early in the target string. + With strstr, while it is possible to unroll the source contents, it is + not possible to do so with the destination contents in a way that is + effective because every destination character must be tested against + '\0' before proceeding to the next character. +8. bReverse versus strrev. The C function must find the end of the string + first before swaping character pairs. +9. bstrrchr versus no comparable C function. Its not hard to write some C + code to search for a character from the end going backwards. But there + is no way to do this without computing the length of the string with + strlen. + +Practical testing indicates that in general Bstrlib is never signifcantly +slower than the C library for common operations, while very often having a +performance advantage that ranges from significant to massive. Even for +functions like b(n)inchr versus str(c)spn() (where, in theory, there is no +advantage for the Bstrlib architecture) the performance of Bstrlib is vastly +superior to most tested C library implementations. + +Some of Bstrlib's extra functionality also lead to inevitable performance +advantages over typical C solutions. For example, using the blk2tbstr macro, +one can (in O(1) time) generate an internal substring by reference while not +disturbing the original string. If disturbing the original string is not an +option, typically, a comparable char * solution would have to make a copy of +the substring to provide similar functionality. Another example is reverse +character set scanning -- the str(c)spn functions only scan in a forward +direction which can complicate some parsing algorithms. + +Where high performance char * based algorithms are available, Bstrlib can +still leverage them by accessing the ->data field on bstrings. So +realistically Bstrlib can never be significantly slower than any standard +'\0' terminated char * based solutions. + +Performance of the C++ interface: +................................. + +The C++ interface has been designed with an emphasis on abstraction and safety +first. However, since it is substantially a wrapper for the C bstring +functions, for longer strings the performance comments described in the +"Performance of the C interface" section above still apply. Note that the +(CBString *) type can be directly cast to a (bstring) type, and passed as +parameters to the C functions (though a CBString must never be passed to +bdestroy.) + +Probably the most controversial choice is performing full bounds checking on +the [] operator. This decision was made because 1) the fast alternative of +not bounds checking is still available by first casting the CBString to a +(const char *) buffer or to a (struct tagbstring) then derefencing .data and +2) because the lack of bounds checking is seen as one of the main weaknesses +of C/C++ versus other languages. This check being done on every access leads +to individual character extraction being actually slower than other languages +in this one respect (other language's compilers will normally dedicate more +resources on hoisting or removing bounds checking as necessary) but otherwise +bring C++ up to the level of other languages in terms of functionality. + +It is common for other C++ libraries to leverage the abstractions provided by +C++ to use reference counting and "copy on write" policies. While these +techniques can speed up some scenarios, they impose a problem with respect to +thread safety. bstrings and CBStrings can be properly protected with +"per-object" mutexes, meaning that two bstrlib calls can be made and execute +simultaneously, so long as the bstrings and CBstrings are distinct. With a +reference count and alias before copy on write policy, global mutexes are +required that prevent multiple calls to the strings library to execute +simultaneously regardless of whether or not the strings represent the same +string. + +One interesting trade off in CBString is that the default constructor is not +trivial. I.e., it always prepares a ready to use memory buffer. The purpose +is to ensure that there is a uniform internal composition for any functioning +CBString that is compatible with bstrings. It also means that the other +methods in the class are not forced to perform "late initialization" checks. +In the end it means that construction of CBStrings are slower than other +comparable C++ string classes. Initial testing, however, indicates that +CBString outperforms std::string and MFC's CString, for example, in all other +operations. So to work around this weakness it is recommended that CBString +declarations be pushed outside of inner loops. + +Practical testing indicates that with the exception of the caveats given +above (constructors and safe index character manipulations) the C++ API for +Bstrlib generally outperforms popular standard C++ string classes. Amongst +the standard libraries and compilers, the quality of concatenation operations +varies wildly and very little care has gone into search functions. Bstrlib +dominates those performance benchmarks. + +Memory management: +.................. + +The bstring functions which write and modify bstrings will automatically +reallocate the backing memory for the char buffer whenever it is required to +grow. The algorithm for resizing chosen is to snap up to sizes that are a +power of two which are sufficient to hold the intended new size. Memory +reallocation is not performed when the required size of the buffer is +decreased. This behavior can be relied on, and is necessary to make the +behaviour of balloc deterministic. This trades off additional memory usage +for decreasing the frequency for required reallocations: + +1. For any bstring whose size never exceeds n, its buffer is not ever + reallocated more than log_2(n) times for its lifetime. +2. For any bstring whose size never exceeds n, its buffer is never more than + 2*(n+1) in length. (The extra characters beyond 2*n are to allow for the + implicit '\0' which is always added by the bstring modifying functions.) + +Decreasing the buffer size when the string decreases in size would violate 1) +above and in real world case lead to pathological heap thrashing. Similarly, +allocating more tightly than "least power of 2 greater than necessary" would +lead to a violation of 1) and have the same potential for heap thrashing. + +Property 2) needs emphasizing. Although the memory allocated is always a +power of 2, for a bstring that grows linearly in size, its buffer memory also +grows linearly, not exponentially. The reason is that the amount of extra +space increases with each reallocation, which decreases the frequency of +future reallocations. + +Obviously, given that bstring writing functions may reallocate the data +buffer backing the target bstring, one should not attempt to cache the data +buffer address and use it after such bstring functions have been called. +This includes making reference struct tagbstrings which alias to a writable +bstring. + +balloc or bfromcstralloc can be used to preallocate the minimum amount of +space used for a given bstring. This will reduce even further the number of +times the data portion is reallocated. If the length of the string is never +more than one less than the memory length then there will be no further +reallocations. + +Note that invoking the bwriteallow macro may increase the number of reallocs +by one more than necessary for every call to bwriteallow interleaved with any +bstring API which writes to this bstring. + +The library does not use any mechanism for automatic clean up for the C API. +Thus explicit clean up via calls to bdestroy() are required to avoid memory +leaks. + +Constant and static tagbstrings: +................................ + +A struct tagbstring can be write protected from any bstrlib function using +the bwriteprotect macro. A write protected struct tagbstring can then be +reset to being writable via the bwriteallow macro. There is, of course, no +protection from attempts to directly access the bstring members. Modifying a +bstring which is write protected by direct access has undefined behavior. + +static struct tagbstrings can be declared via the bsStatic macro. They are +considered permanently unwritable. Such struct tagbstrings's are declared +such that attempts to write to it are not well defined. Invoking either +bwriteallow or bwriteprotect on static struct tagbstrings has no effect. + +struct tagbstring's initialized via btfromcstr or blk2tbstr are protected by +default but can be made writeable via the bwriteallow macro. If bwriteallow +is called on such struct tagbstring's, it is the programmer's responsibility +to ensure that: + +1) the buffer supplied was allocated from the heap. +2) bdestroy is not called on this tagbstring (unless the header itself has + also been allocated from the heap.) +3) free is called on the buffer to reclaim its memory. + +bwriteallow and bwriteprotect can be invoked on ordinary bstrings (they have +to be dereferenced with the (*) operator to get the levels of indirection +correct) to give them write protection. + +Buffer declaration: +................... + +The memory buffer is actually declared "unsigned char *" instead of "char *". +The reason for this is to trigger compiler warnings whenever uncasted char +buffers are assigned to the data portion of a bstring. This will draw more +diligent programmers into taking a second look at the code where they +have carelessly left off the typically required cast. (Research from +AT&T/Lucent indicates that additional programmer eyeballs is one of the most +effective mechanisms at ferreting out bugs.) + +Function pointers: +.................. + +The bgets, bread and bStream functions use function pointers to obtain +strings from data streams. The function pointer declarations have been +specifically chosen to be compatible with the fgetc and fread functions. +While this may seem to be a convoluted way of implementing fgets and fread +style functionality, it has been specifically designed this way to ensure +that there is no dependency on a single narrowly defined set of device +interfaces, such as just stream I/O. In the embedded world, its quite +possible to have environments where such interfaces may not exist in the +standard C library form. Furthermore, the generalization that this opens up +allows for more sophisticated uses for these functions (performing an fgets +like function on a socket, for example.) By using function pointers, it also +allows such abstract stream interfaces to be created using the bstring library +itself while not creating a circular dependency. + +Use of int's for sizes: +....................... + +This is just a recognition that 16bit platforms with requirements for strings +that are larger than 64K and 32bit+ platforms with requirements for strings +that are larger than 4GB are pretty marginal. The main focus is for 32bit +platforms, and emerging 64bit platforms with reasonable < 4GB string +requirements. Using ints allows for negative values which has meaning +internally to bstrlib. + +Semantic consideration: +....................... + +Certain care needs to be taken when copying and aliasing bstrings. A bstring +is essentially a pointer type which points to a multipart abstract data +structure. Thus usage, and lifetime of bstrings have semantics that follow +these considerations. For example: + + bstring a, b; + struct tagbstring t; + + a = bfromcstr("Hello"); /* Create new bstring and copy "Hello" into it. */ + b = a; /* Alias b to the contents of a. */ + t = *a; /* Create a current instance pseudo-alias of a. */ + bconcat (a, b); /* Double a and b, t is now undefined. */ + bdestroy (a); /* Destroy the contents of both a and b. */ + +Variables of type bstring are really just references that point to real +bstring objects. The equal operator (=) creates aliases, and the asterisk +dereference operator (*) creates a kind of alias to the current instance (which +is generally not useful for any purpose.) Using bstrcpy() is the correct way +of creating duplicate instances. The ampersand operator (&) is useful for +creating aliases to struct tagbstrings (remembering that constructed struct +tagbstrings are not writable by default.) + +CBStrings use complete copy semantics for the equal operator (=), and thus do +not have these sorts of issues. + +Debugging: +.......... + +Bstrings have a simple, exposed definition and construction, and the library +itself is open source. So most debugging is going to be fairly straight- +forward. But the memory for bstrings come from the heap, which can often be +corrupted indirectly, and it might not be obvious what has happened even from +direct examination of the contents in a debugger or a core dump. There are +some tools such as Purify, Insure++ and Electric Fence which can help solve +such problems, however another common approach is to directly instrument the +calls to malloc, realloc, calloc, free, memcpy, memmove and/or other calls +by overriding them with macro definitions. + +Although the user could hack on the Bstrlib sources directly as necessary to +perform such an instrumentation, Bstrlib comes with a built-in mechanism for +doing this. By defining the macro BSTRLIB_MEMORY_DEBUG and providing an +include file named memdbg.h this will force the core Bstrlib modules to +attempt to include this file. In such a file, macros could be defined which +overrides Bstrlib's useage of the C standard library. + +Rather than calling malloc, realloc, free, memcpy or memmove directly, Bstrlib +emits the macros bstr__alloc, bstr__realloc, bstr__free, bstr__memcpy and +bstr__memmove in their place respectively. By default these macros are simply +assigned to be equivalent to their corresponding C standard library function +call. However, if they are given earlier macro definitions (via the back +door include file) they will not be given their default definition. In this +way Bstrlib's interface to the standard library can be changed but without +having to directly redefine or link standard library symbols (both of which +are not strictly ANSI C compliant.) + +An example definition might include: + + #define bstr__alloc(sz) X_malloc ((sz), __LINE__, __FILE__) + +which might help contextualize heap entries in a debugging environment. + +The NULL parameter and sanity checking of bstrings is part of the Bstrlib +API, and thus Bstrlib itself does not present any different modes which would +correspond to "Debug" or "Release" modes. Bstrlib always contains mechanisms +which one might think of as debugging features, but retains the performance +and small memory footprint one would normally associate with release mode +code. + +Integration Microsoft's Visual Studio debugger: +............................................... + +Microsoft's Visual Studio debugger has a capability of customizable mouse +float over data type descriptions. This is accomplished by editting the +AUTOEXP.DAT file to include the following: + + ; new for CBString + tagbstring =slen=<slen> mlen=<mlen> <data,st> + Bstrlib::CBStringList =count=<size()> + +In Visual C++ 6.0 this file is located in the directory: + + C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin + +and in Visual Studio .NET 2003 its located here: + + C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger + +This will improve the ability of debugging with Bstrlib under Visual Studio. + +Security +-------- + +Bstrlib does not come with explicit security features outside of its fairly +comprehensive error detection, coupled with its strict semantic support. +That is to say that certain common security problems, such as buffer overrun, +constant overwrite, arbitrary truncation etc, are far less likely to happen +inadvertently. Where it does help, Bstrlib maximizes its advantage by +providing developers a simple adoption path that lets them leave less secure +string mechanisms behind. The library will not leave developers wanting, so +they will be less likely to add new code using a less secure string library +to add functionality that might be missing from Bstrlib. + +That said there are a number of security ideas not addressed by Bstrlib: + +1. Race condition exploitation (i.e., verifying a string's contents, then +raising the privilege level and execute it as a shell command as two +non-atomic steps) is well beyond the scope of what Bstrlib can provide. It +should be noted that MFC's built-in string mutex actually does not solve this +problem either -- it just removes immediate data corruption as a possible +outcome of such exploit attempts (it can be argued that this is worse, since +it will leave no trace of the exploitation). In general race conditions have +to be dealt with by careful design and implementation; it cannot be assisted +by a string library. + +2. Any kind of access control or security attributes to prevent usage in +dangerous interfaces such as system(). Perl includes a "trust" attribute +which can be endowed upon strings that are intended to be passed to such +dangerous interfaces. However, Perl's solution reflects its own limitations +-- notably that it is not a strongly typed language. In the example code for +Bstrlib, there is a module called taint.cpp. It demonstrates how to write a +simple wrapper class for managing "untainted" or trusted strings using the +type system to prevent questionable mixing of ordinary untrusted strings with +untainted ones then passing them to dangerous interfaces. In this way the +security correctness of the code reduces to auditing the direct usages of +dangerous interfaces or promotions of tainted strings to untainted ones. + +3. Encryption of string contents is way beyond the scope of Bstrlib. +Maintaining encrypted string contents in the futile hopes of thwarting things +like using system-level debuggers to examine sensitive string data is likely +to be a wasted effort (imagine a debugger that runs at a higher level than a +virtual processor where the application runs). For more standard encryption +usages, since the bstring contents are simply binary blocks of data, this +should pose no problem for usage with other standard encryption libraries. + +Compatibility +------------- + +The Better String Library is known to compile and function correctly with the +following compilers: + + - Microsoft Visual C++ + - Watcom C/C++ + - Intel's C/C++ compiler (Windows) + - The GNU C/C++ compiler (cygwin and Linux on PPC64) + - Borland C + - Turbo C + +Setting of configuration options should be unnecessary for these compilers +(unless exceptions are being disabled or STLport has been added to WATCOM +C/C++). Bstrlib has been developed with an emphasis on portability. As such +porting it to other compilers should be straight forward. This package +includes a porting guide (called porting.txt) which explains what issues may +exist for porting Bstrlib to different compilers and environments. + +ANSI issues +----------- + +1. The function pointer types bNgetc and bNread have prototypes which are very +similar to, but not exactly the same as fgetc and fread respectively. +Basically the FILE * parameter is replaced by void *. The purpose of this +was to allow one to create other functions with fgetc and fread like +semantics without being tied to ANSI C's file streaming mechanism. I.e., one +could very easily adapt it to sockets, or simply reading a block of memory, +or procedurally generated strings (for fractal generation, for example.) + +The problem is that invoking the functions (bNgetc)fgetc and (bNread)fread is +not technically legal in ANSI C. The reason being that the compiler is only +able to coerce the function pointers themselves into the target type, however +are unable to perform any cast (implicit or otherwise) on the parameters +passed once invoked. I.e., if internally void * and FILE * need some kind of +mechanical coercion, the compiler will not properly perform this conversion +and thus lead to undefined behavior. + +Apparently a platform from Data General called "Eclipse" and another from +Tandem called "NonStop" have a different representation for pointers to bytes +and pointers to words, for example, where coercion via casting is necessary. +(Actual confirmation of the existence of such machines is hard to come by, so +it is prudent to be skeptical about this information.) However, this is not +an issue for any known contemporary platforms. One may conclude that such +platforms are effectively apocryphal even if they do exist. + +To correctly work around this problem to the satisfaction of the ANSI +limitations, one needs to create wrapper functions for fgets and/or +fread with the prototypes of bNgetc and/or bNread respectively which performs +no other action other than to explicitely cast the void * parameter to a +FILE *, and simply pass the remaining parameters straight to the function +pointer call. + +The wrappers themselves are trivial: + + size_t freadWrap (void * buff, size_t esz, size_t eqty, void * parm) { + return fread (buff, esz, eqty, (FILE *) parm); + } + + int fgetcWrap (void * parm) { + return fgetc ((FILE *) parm); + } + +These have not been supplied in bstrlib or bstraux to prevent unnecessary +linking with file I/O functions. + +2. vsnprintf is not available on all compilers. Because of this, the bformat +and bformata functions (and format and formata methods) are not guaranteed to +work properly. For those compilers that don't have vsnprintf, the +BSTRLIB_NOVSNP macro should be set before compiling bstrlib, and the format +functions/method will be disabled. + +The more recent ANSI C standards have specified the required inclusion of a +vsnprintf function. + +3. The bstrlib function names are not unique in the first 6 characters. This +is only an issue for older C compiler environments which do not store more +than 6 characters for function names. + +4. The bsafe module defines macros and function names which are part of the +C library. This simply overrides the definition as expected on all platforms +tested, however it is not sanctioned by the ANSI standard. This module is +clearly optional and should be omitted on platforms which disallow its +undefined semantics. + +In practice the real issue is that some compilers in some modes of operation +can/will inline these standard library functions on a module by module basis +as they appear in each. The linker will thus have no opportunity to override +the implementation of these functions for those cases. This can lead to +inconsistent behaviour of the bsafe module on different platforms and +compilers. + +=============================================================================== + +Comparison with Microsoft's CString class +----------------------------------------- + +Although developed independently, CBStrings have very similar functionality to +Microsoft's CString class. However, the bstring library has significant +advantages over CString: + +1. Bstrlib is a C-library as well as a C++ library (using the C++ wrapper). + + - Thus it is compatible with more programming environments and + available to a wider population of programmers. + +2. The internal structure of a bstring is considered exposed. + + - A single contiguous block of data can be cut into read-only pieces by + simply creating headers, without allocating additional memory to create + reference copies of each of these sub-strings. + - In this way, using bstrings in a totally abstracted way becomes a choice + rather than an imposition. Further this choice can be made differently + at different layers of applications that use it. + +3. Static declaration support precludes the need for constructor + invocation. + + - Allows for static declarations of constant strings that has no + additional constructor overhead. + +4. Bstrlib is not attached to another library. + + - Bstrlib is designed to be easily plugged into any other library + collection, without dependencies on other libraries or paradigms (such + as "MFC".) + +The bstring library also comes with a few additional functions that are not +available in the CString class: + + - bsetstr + - bsplit + - bread + - breplace (this is different from CString::Replace()) + - Writable indexed characters (for example a[i]='x') + +Interestingly, although Microsoft did implement mid$(), left$() and right$() +functional analogues (these are functions from GWBASIC) they seem to have +forgotten that mid$() could be also used to write into the middle of a string. +This functionality exists in Bstrlib with the bsetstr() and breplace() +functions. + +Among the disadvantages of Bstrlib is that there is no special support for +localization or wide characters. Such things are considered beyond the scope +of what bstrings are trying to deliver. CString essentially supports the +older UCS-2 version of Unicode via widechar_t as an application-wide compile +time switch. + +CString's also use built-in mechanisms for ensuring thread safety under all +situations. While this makes writing thread safe code that much easier, this +built-in safety feature has a price -- the inner loops of each CString method +runs in its own critical section (grabbing and releasing a light weight mutex +on every operation.) The usual way to decrease the impact of a critical +section performance penalty is to amortize more operations per critical +section. But since the implementation of CStrings is fixed as a one critical +section per-operation cost, there is no way to leverage this common +performance enhancing idea. + +The search facilities in Bstrlib are comparable to those in MFC's CString +class, though it is missing locale specific collation. But because Bstrlib +is interoperable with C's char buffers, it will allow programmers to write +their own string searching mechanism (such as Boyer-Moore), or be able to +choose from a variety of available existing string searching libraries (such +as those for regular expressions) without difficulty. + +Microsoft used a very non-ANSI conforming trick in its implementation to +allow printf() to use the "%s" specifier to output a CString correctly. This +can be convenient, but it is inherently not portable. CBString requires an +explicit cast, while bstring requires the data member to be dereferenced. +Microsoft's own documentation recommends casting, instead of relying on this +feature. + +Comparison with C++'s std::string +--------------------------------- + +This is the C++ language's standard STL based string class. + +1. There is no C implementation. +2. The [] operator is not bounds checked. +3. Missing a lot of useful functions like printf-like formatting. +4. Some sub-standard std::string implementations (SGI) are necessarily unsafe + to use with multithreading. +5. Limited by STL's std::iostream which in turn is limited by ifstream which + can only take input from files. (Compare to CBStream's API which can take + abstracted input.) +6. Extremely uneven performance across implementations. + +Comparison with ISO C TR 24731 proposal +--------------------------------------- + +Following the ISO C99 standard, Microsoft has proposed a group of C library +extensions which are supposedly "safer and more secure". This proposal is +expected to be adopted by the ISO C standard which follows C99. + +The proposal reveals itself to be very similar to Microsoft's "StrSafe" +library. The functions are basically the same as other standard C library +string functions except that destination parameters are paired with an +additional length parameter of type rsize_t. rsize_t is the same as size_t, +however, the range is checked to make sure its between 1 and RSIZE_MAX. Like +Bstrlib, the functions perform a "parameter check". Unlike Bstrlib, when a +parameter check fails, rather than simply outputing accumulatable error +statuses, they call a user settable global error function handler, and upon +return of control performs no (additional) detrimental action. The proposal +covers basic string functions as well as a few non-reenterable functions +(asctime, ctime, and strtok). + +1. Still based solely on char * buffers (and therefore strlen() and strcat() + is still O(n), and there are no faster streq() comparison functions.) +2. No growable string semantics. +3. Requires manual buffer length synchronization in the source code. +4. No attempt to enhance functionality of the C library. +5. Introduces a new error scenario (strings exceeding RSIZE_MAX length). + +The hope is that by exposing the buffer length requirements there will be +fewer buffer overrun errors. However, the error modes are really just +transformed, rather than removed. The real problem of buffer overflows is +that they all happen as a result of erroneous programming. So forcing +programmers to manually deal with buffer limits, will make them more aware of +the problem but doesn't remove the possibility of erroneous programming. So +a programmer that erroneously mixes up the rsize_t parameters is no better off +from a programmer that introduces potential buffer overflows through other +more typical lapses. So at best this may reduce the rate of erroneous +programming, rather than making any attempt at removing failure modes. + +The error handler can discriminate between types of failures, but does not +take into account any callsite context. So the problem is that the error is +going to be manifest in a piece of code, but there is no pointer to that +code. It would seem that passing in the call site __FILE__, __LINE__ as +parameters would be very useful, but the API clearly doesn't support such a +thing (it would increase code bloat even more than the extra length +parameter does, and would require macro tricks to implement). + +The Bstrlib C API takes the position that error handling needs to be done at +the callsite, and just tries to make it as painless as possible. Furthermore, +error modes are removed by supporting auto-growing strings and aliasing. For +capturing errors in more central code fragments, Bstrlib's C++ API uses +exception handling extensively, which is superior to the leaf-only error +handler approach. + +Comparison with Managed String Library CERT proposal +---------------------------------------------------- + +The main webpage for the managed string library: +http://www.cert.org/secure-coding/managedstring.html + +Robert Seacord at CERT has proposed a C string library that he calls the +"Managed String Library" for C. Like Bstrlib, it introduces a new type +which is called a managed string. The structure of a managed string +(string_m) is like a struct tagbstring but missing the length field. This +internal structure is considered opaque. The length is, like the C standard +library, always computed on the fly by searching for a terminating NUL on +every operation that requires it. So it suffers from every performance +problem that the C standard library suffers from. Interoperating with C +string APIs (like printf, fopen, or anything else that takes a string +parameter) requires copying to additionally allocating buffers that have to +be manually freed -- this makes this library probably slower and more +cumbersome than any other string library in existence. + +The library gives a fully populated error status as the return value of every +string function. The hope is to be able to diagnose all problems +specifically from the return code alone. Comparing this to Bstrlib, which +aways returns one consistent error message, might make it seem that Bstrlib +would be harder to debug; but this is not true. With Bstrlib, if an error +occurs there is always enough information from just knowing there was an error +and examining the parameters to deduce exactly what kind of error has +happened. The managed string library thus gives up nested function calls +while achieving little benefit, while Bstrlib does not. + +One interesting feature that "managed strings" has is the idea of data +sanitization via character set whitelisting. That is to say, a globally +definable filter that makes any attempt to put invalid characters into strings +lead to an error and not modify the string. The author gives the following +example: + + // create valid char set + if (retValue = strcreate_m(&str1, "abc") ) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + if (retValue = setcharset(str1)) { + fprintf( + stderr, + "Error %d from setcharset().\n", + retValue + ); + } + if (retValue = strcreate_m(&str1, "aabbccabc")) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + // create string with invalid char set + if (retValue = strcreate_m(&str1, "abbccdabc")) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + +Which we can compare with a more Bstrlib way of doing things: + + bstring bCreateWithFilter (const char * cstr, const_bstring filter) { + bstring b = bfromcstr (cstr); + if (BSTR_ERR != bninchr (b, filter) && NULL != b) { + fprintf (stderr, "Filter violation.\n"); + bdestroy (b); + b = NULL; + } + return b; + } + + struct tagbstring charFilter = bsStatic ("abc"); + bstring str1 = bCreateWithFilter ("aabbccabc", &charFilter); + bstring str2 = bCreateWithFilter ("aabbccdabc", &charFilter); + +The first thing we should notice is that with the Bstrlib approach you can +have different filters for different strings if necessary. Furthermore, +selecting a charset filter in the Managed String Library is uni-contextual. +That is to say, there can only be one such filter active for the entire +program, which means its usage is not well defined for intermediate library +usage (a library that uses it will interfere with user code that uses it, and +vice versa.) It is also likely to be poorly defined in multi-threading +environments. + +There is also a question as to whether the data sanitization filter is checked +on every operation, or just on creation operations. Since the charset can be +set arbitrarily at run time, it might be set *after* some managed strings have +been created. This would seem to imply that all functions should run this +additional check every time if there is an attempt to enforce this. This +would make things tremendously slow. On the other hand, if it is assumed that +only creates and other operations that take char *'s as input need be checked +because the charset was only supposed to be called once at and before any +other managed string was created, then one can see that its easy to cover +Bstrlib with equivalent functionality via a few wrapper calls such as the +example given above. + +And finally we have to question the value of sanitation in the first place. +For example, for httpd servers, there is generally a requirement that the +URLs parsed have some form that avoids undesirable translation to local file +system filenames or resources. The problem is that the way URLs can be +encoded, it must be completely parsed and translated to know if it is using +certain invalid character combinations. That is to say, merely filtering +each character one at a time is not necessarily the right way to ensure that +a string has safe contents. + +In the article that describes this proposal, it is claimed that it fairly +closely approximates the existing C API semantics. On this point we should +compare this "closeness" with Bstrlib: + + Bstrlib Managed String Library + ------- ---------------------- + +Pointer arithmetic Segment arithmetic N/A + +Use in C Std lib ->data, or bdata{e} getstr_m(x,*) ... free(x) + +String literals bsStatic, bsStaticBlk strcreate_m() + +Transparency Complete None + +Its pretty clear that the semantic mapping from C strings to Bstrlib is fairly +straightforward, and that in general semantic capabilities are the same or +superior in Bstrlib. On the other hand the Managed String Library is either +missing semantics or changes things fairly significantly. + +Comparison with Annexia's c2lib library +--------------------------------------- + +This library is available at: +http://www.annexia.org/freeware/c2lib + +1. Still based solely on char * buffers (and therefore strlen() and strcat() + is still O(n), and there are no faster streq() comparison functions.) + Their suggestion that alternatives which wrap the string data type (such as + bstring does) imposes a difficulty in interoperating with the C langauge's + ordinary C string library is not founded. +2. Introduction of memory (and vector?) abstractions imposes a learning + curve, and some kind of memory usage policy that is outside of the strings + themselves (and therefore must be maintained by the developer.) +3. The API is massive, and filled with all sorts of trivial (pjoin) and + controvertial (pmatch -- regular expression are not sufficiently + standardized, and there is a very large difference in performance between + compiled and non-compiled, REs) functions. Bstrlib takes a decidely + minimal approach -- none of the functionality in c2lib is difficult or + challenging to implement on top of Bstrlib (except the regex stuff, which + is going to be difficult, and controvertial no matter what.) +4. Understanding why c2lib is the way it is pretty much requires a working + knowledge of Perl. bstrlib requires only knowledge of the C string library + while providing just a very select few worthwhile extras. +5. It is attached to a lot of cruft like a matrix math library (that doesn't + include any functions for getting the determinant, eigenvectors, + eigenvalues, the matrix inverse, test for singularity, test for + orthogonality, a grahm schmit orthogonlization, LU decomposition ... I + mean why bother?) + +Convincing a development house to use c2lib is likely quite difficult. It +introduces too much, while not being part of any kind of standards body. The +code must therefore be trusted, or maintained by those that use it. While +bstring offers nothing more on this front, since its so much smaller, covers +far less in terms of scope, and will typically improve string performance, +the barrier to usage should be much smaller. + +Comparison with stralloc/qmail +------------------------------ + +More information about this library can be found here: +http://www.canonical.org/~kragen/stralloc.html or here: +http://cr.yp.to/lib/stralloc.html + +1. Library is very very minimal. A little too minimal. +2. Untargetted source parameters are not declared const. +3. Slightly different expected emphasis (like _cats function which takes an + ordinary C string char buffer as a parameter.) Its clear that the + remainder of the C string library is still required to perform more + useful string operations. + +The struct declaration for their string header is essentially the same as that +for bstring. But its clear that this was a quickly written hack whose goals +are clearly a subset of what Bstrlib supplies. For anyone who is served by +stralloc, Bstrlib is complete substitute that just adds more functionality. + +stralloc actually uses the interesting policy that a NULL data pointer +indicates an empty string. In this way, non-static empty strings can be +declared without construction. This advantage is minimal, since static empty +bstrings can be declared inline without construction, and if the string needs +to be written to it should be constructed from an empty string (or its first +initializer) in any event. + +wxString class +-------------- + +This is the string class used in the wxWindows project. A description of +wxString can be found here: +http://www.wxwindows.org/manuals/2.4.2/wx368.htm#wxstring + +This C++ library is similar to CBString. However, it is littered with +trivial functions (IsAscii, UpperCase, RemoveLast etc.) + +1. There is no C implementation. +2. The memory management strategy is to allocate a bounded fixed amount of + additional space on each resize, meaning that it does not have the + log_2(n) property that Bstrlib has (it will thrash very easily, cause + massive fragmentation in common heap implementations, and can easily be a + common source of performance problems). +3. The library uses a "copy on write" strategy, meaning that it has to deal + with multithreading problems. + +Vstr +---- + +This is a highly orthogonal C string library with an emphasis on +networking/realtime programming. It can be found here: +http://www.and.org/vstr/ + +1. The convoluted internal structure does not contain a '\0' char * compatible + buffer, so interoperability with the C library a non-starter. +2. The API and implementation is very large (owing to its orthogonality) and + can lead to difficulty in understanding its exact functionality. +3. An obvious dependency on gnu tools (confusing make configure step) +4. Uses a reference counting system, meaning that it is not likely to be + thread safe. + +The implementation has an extreme emphasis on performance for nontrivial +actions (adds, inserts and deletes are all constant or roughly O(#operations) +time) following the "zero copy" principle. This trades off performance of +trivial functions (character access, char buffer access/coersion, alias +detection) which becomes significantly slower, as well as incremental +accumulative costs for its searching/parsing functions. Whether or not Vstr +wins any particular performance benchmark will depend a lot on the benchmark, +but it should handily win on some, while losing dreadfully on others. + +The learning curve for Vstr is very steep, and it doesn't come with any +obvious way to build for Windows or other platforms without gnu tools. At +least one mechanism (the iterator) introduces a new undefined scenario +(writing to a Vstr while iterating through it.) Vstr has a very large +footprint, and is very ambitious in its total functionality. Vstr has no C++ +API. + +Vstr usage requires context initialization via vstr_init() which must be run +in a thread-local context. Given the totally reference based architecture +this means that sharing Vstrings across threads is not well defined, or at +least not safe from race conditions. This API is clearly geared to the older +standard of fork() style multitasking in UNIX, and is not safely transportable +to modern shared memory multithreading available in Linux and Windows. There +is no portable external solution making the library thread safe (since it +requires a mutex around each Vstr context -- not each string.) + +In the documentation for this library, a big deal is made of its self hosted +s(n)printf-like function. This is an issue for older compilers that don't +include vsnprintf(), but also an issue because Vstr has a slow conversion to +'\0' terminated char * mechanism. That is to say, using "%s" to format data +that originates from Vstr would be slow without some sort of native function +to do so. Bstrlib sidesteps the issue by relying on what snprintf-like +functionality does exist and having a high performance conversion to a char * +compatible string so that "%s" can be used directly. + +Str Library +----------- + +This is a fairly extensive string library, that includes full unicode support +and targetted at the goal of out performing MFC and STL. The architecture, +similarly to MFC's CStrings, is a copy on write reference counting mechanism. + +http://www.utilitycode.com/str/default.aspx + +1. Commercial. +2. C++ only. + +This library, like Vstr, uses a ref counting system. There is only so deeply +I can analyze it, since I don't have a license for it. However, performance +improvements over MFC's and STL, doesn't seem like a sufficient reason to +move your source base to it. For example, in the future, Microsoft may +improve the performance CString. + +It should be pointed out that performance testing of Bstrlib has indicated +that its relative performance advantage versus MFC's CString and STL's +std::string is at least as high as that for the Str library. + +libmib astrings +--------------- + +A handful of functional extensions to the C library that add dynamic string +functionality. +http://www.mibsoftware.com/libmib/astring/ + +This package basically references strings through char ** pointers and assumes +they are pointing to the top of an allocated heap entry (or NULL, in which +case memory will be newly allocated from the heap.) So its still up to user +to mix and match the older C string functions with these functions whenever +pointer arithmetic is used (i.e., there is no leveraging of the type system +to assert semantic differences between references and base strings as Bstrlib +does since no new types are introduced.) Unlike Bstrlib, exact string length +meta data is not stored, thus requiring a strlen() call on *every* string +writing operation. The library is very small, covering only a handful of C's +functions. + +While this is better than nothing, it is clearly slower than even the +standard C library, less safe and less functional than Bstrlib. + +To explain the advantage of using libmib, their website shows an example of +how dangerous C code: + + char buf[256]; + char *pszExtraPath = ";/usr/local/bin"; + + strcpy(buf,getenv("PATH")); /* oops! could overrun! */ + strcat(buf,pszExtraPath); /* Could overrun as well! */ + + printf("Checking...%s\n",buf); /* Some printfs overrun too! */ + +is avoided using libmib: + + char *pasz = 0; /* Must initialize to 0 */ + char *paszOut = 0; + char *pszExtraPath = ";/usr/local/bin"; + + if (!astrcpy(&pasz,getenv("PATH"))) /* malloc error */ exit(-1); + if (!astrcat(&pasz,pszExtraPath)) /* malloc error */ exit(-1); + + /* Finally, a "limitless" printf! we can use */ + asprintf(&paszOut,"Checking...%s\n",pasz);fputs(paszOut,stdout); + + astrfree(&pasz); /* Can use free(pasz) also. */ + astrfree(&paszOut); + +However, compare this to Bstrlib: + + bstring b, out; + + bcatcstr (b = bfromcstr (getenv ("PATH")), ";/usr/local/bin"); + out = bformat ("Checking...%s\n", bdatae (b, "<Out of memory>")); + /* if (out && b) */ fputs (bdatae (out, "<Out of memory>"), stdout); + bdestroy (b); + bdestroy (out); + +Besides being shorter, we can see that error handling can be deferred right +to the very end. Also, unlike the above two versions, if getenv() returns +with NULL, the Bstrlib version will not exhibit undefined behavior. +Initialization starts with the relevant content rather than an extra +autoinitialization step. + +libclc +------ + +An attempt to add to the standard C library with a number of common useful +functions, including additional string functions. +http://libclc.sourceforge.net/ + +1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass + the responsibility to guard against aliasing to the programmer. +2. Adds no safety or memory management whatsoever. +3. Most of the supplied string functions are completely trivial. + +The goals of libclc and Bstrlib are clearly quite different. + +fireString +---------- + +http://firestuff.org/ + +1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass + the responsibility to guard against aliasing to the programmer. +2. Mixes char * and length wrapped buffers (estr) functions, doubling the API + size, with safety limited to only half of the functions. + +Firestring was originally just a wrapper of char * functionality with extra +length parameters. However, it has been augmented with the inclusion of the +estr type which has similar functionality to stralloc. But firestring does +not nearly cover the functional scope of Bstrlib. + +Safe C String Library +--------------------- + +A library written for the purpose of increasing safety and power to C's string +handling capabilities. +http://www.zork.org/safestr/safestr.html + +1. While the safestr_* functions are safe in of themselves, interoperating + with char * string has dangerous unsafe modes of operation. +2. The architecture of safestr's causes the base pointer to change. Thus, + its not practical/safe to store a safestr in multiple locations if any + single instance can be manipulated. +3. Dependent on an additional error handling library. +4. Uses reference counting, meaning that it is either not thread safe or + slow and not portable. + +I think the idea of reallocating (and hence potentially changing) the base +pointer is a serious design flaw that is fatal to this architecture. True +safety is obtained by having automatic handling of all common scenarios +without creating implicit constraints on the user. + +Because of its automatic temporary clean up system, it cannot use "const" +semantics on input arguments. Interesting anomolies such as: + + safestr_t s, t; + s = safestr_replace (t = SAFESTR_TEMP ("This is a test"), + SAFESTR_TEMP (" "), SAFESTR_TEMP (".")); + /* t is now undefined. */ + +are possible. If one defines a function which takes a safestr_t as a +parameter, then the function would not know whether or not the safestr_t is +defined after it passes it to a safestr library function. The author +recommended method for working around this problem is to examine the +attributes of the safestr_t within the function which is to modify any of +its parameters and play games with its reference count. I think, therefore, +that the whole SAFESTR_TEMP idea is also fatally broken. + +The library implements immutability, optional non-resizability, and a "trust" +flag. This trust flag is interesting, and suggests that applying any +arbitrary sequence of safestr_* function calls on any set of trusted strings +will result in a trusted string. It seems to me, however, that if one wanted +to implement a trusted string semantic, one might do so by actually creating +a different *type* and only implement the subset of string functions that are +deemed safe (i.e., user input would be excluded, for example.) This, in +essence, would allow the compiler to enforce trust propogation at compile +time rather than run time. Non-resizability is also interesting, however, +it seems marginal (i.e., to want a string that cannot be resized, yet can be +modified and yet where a fixed sized buffer is undesirable.) + +=============================================================================== + +Examples +-------- + + Dumping a line numbered file: + + FILE * fp; + int i, ret; + struct bstrList * lines; + struct tagbstring prefix = bsStatic ("-> "); + + if (NULL != (fp = fopen ("bstrlib.txt", "rb"))) { + bstring b = bread ((bNread) fread, fp); + fclose (fp); + if (NULL != (lines = bsplit (b, '\n'))) { + for (i=0; i < lines->qty; i++) { + binsert (lines->entry[i], 0, &prefix, '?'); + printf ("%04d: %s\n", i, bdatae (lines->entry[i], "NULL")); + } + bstrListDestroy (lines); + } + bdestroy (b); + } + +For numerous other examples, see bstraux.c, bstraux.h and the example archive. + +=============================================================================== + +License +------- + +The Better String Library is available under either the 3 clause BSD license +(see the accompanying license.txt) or the Gnu Public License version 2 (see +the accompanying gpl.txt) at the option of the user. + +=============================================================================== + +Acknowledgements +---------------- + +The following individuals have made significant contributions to the design +and testing of the Better String Library: + +Bjorn Augestad +Clint Olsen +Darryl Bleau +Fabian Cenedese +Graham Wideman +Ignacio Burgueno +International Business Machines Corporation +Ira Mica +John Kortink +Manuel Woelker +Marcel van Kervinck +Michael Hsieh +Richard A. Smith +Simon Ekstrom +Wayne Scott + +=============================================================================== diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt new file mode 100644 index 0000000000..cf78a984cc --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/license.txt @@ -0,0 +1,29 @@ +Copyright (c) 2002-2008 Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of bstrlib nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt new file mode 100644 index 0000000000..11d8d13130 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/porting.txt @@ -0,0 +1,172 @@ +Better String library Porting Guide +----------------------------------- + +by Paul Hsieh + +The bstring library is an attempt to provide improved string processing +functionality to the C and C++ language. At the heart of the bstring library +is the management of "bstring"s which are a significant improvement over '\0' +terminated char buffers. See the accompanying documenation file bstrlib.txt +for more information. + +=============================================================================== + +Identifying the Compiler +------------------------ + +Bstrlib has been tested on the following compilers: + + Microsoft Visual C++ + Watcom C/C++ (32 bit flat) + Intel's C/C++ compiler (on Windows) + The GNU C/C++ compiler (on Windows/Linux on x86 and PPC64) + Borland C++ + Turbo C + +There are slight differences in these compilers which requires slight +differences in the implementation of Bstrlib. These are accomodated in the +same sources using #ifdef/#if defined() on compiler specific macros. To +port Bstrlib to a new compiler not listed above, it is recommended that the +same strategy be followed. If you are unaware of the compiler specific +identifying preprocessor macro for your compiler you might find it here: + +http://predef.sourceforge.net/precomp.html + +Note that Intel C/C++ on Windows sets the Microsoft identifier: _MSC_VER. + +16-bit vs. 32-bit vs. 64-bit Systems +------------------------------------ + +Bstrlib has been architected to deal with strings of length between 0 and +INT_MAX (inclusive). Since the values of int are never higher than size_t +there will be no issue here. Note that on most 64-bit systems int is 32-bit. + +Dependency on The C-Library +--------------------------- + +Bstrlib uses the functions memcpy, memmove, malloc, realloc, free and +vsnprintf. Many free standing C compiler implementations that have a mode in +which the C library is not available will typically not include these +functions which will make porting Bstrlib to it onerous. Bstrlib is not +designed for such bare bones compiler environments. This usually includes +compilers that target ROM environments. + +Porting Issues +-------------- + +Bstrlib has been written completely in ANSI/ISO C and ISO C++, however, there +are still a few porting issues. These are described below. + +1. The vsnprintf () function. + +Unfortunately, the earlier ANSI/ISO C standards did not include this function. +If the compiler of interest does not support this function then the +BSTRLIB_NOVSNP should be defined via something like: + + #if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) + # if defined (__TURBOC__) || defined (__COMPILERVENDORSPECIFICMACRO__) + # define BSTRLIB_NOVSNP + # endif + #endif + +which appears at the top of bstrlib.h. Note that the bformat(a) functions +will not be declared or implemented if the BSTRLIB_NOVSNP macro is set. If +the compiler has renamed vsnprintf() to some other named function, then +search for the definition of the exvsnprintf macro in bstrlib.c file and be +sure its defined appropriately: + + #if defined (__COMPILERVENDORSPECIFICMACRO__) + # define exvsnprintf(r,b,n,f,a) {r=__compiler_specific_vsnprintf(b,n,f,a);} + #else + # define exvsnprintf(r,b,n,f,a) {r=vsnprintf(b,n,f,a);} + #endif + +Take notice of the return value being captured in the variable r. It is +assumed that r exceeds n if and only if the underlying vsnprintf function has +determined what the true maximal output length would be for output if the +buffer were large enough to hold it. Non-modern implementations must output a +lesser number (the macro can and should be modified to ensure this). + +2. Weak C++ compiler. + +C++ is a much more complicated language to implement than C. This has lead +to varying quality of compiler implementations. The weaknesses isolated in +the initial ports are inclusion of the Standard Template Library, +std::iostream and exception handling. By default it is assumed that the C++ +compiler supports all of these things correctly. If your compiler does not +support one or more of these define the corresponding macro: + + BSTRLIB_CANNOT_USE_STL + BSTRLIB_CANNOT_USE_IOSTREAM + BSTRLIB_DOESNT_THROW_EXCEPTIONS + +The compiler specific detected macro should be defined at the top of +bstrwrap.h in the Configuration defines section. Note that these disabling +macros can be overrided with the associated enabling macro if a subsequent +version of the compiler gains support. (For example, its possible to rig +up STLport to provide STL support for WATCOM C/C++, so -DBSTRLIB_CAN_USE_STL +can be passed in as a compiler option.) + +3. The bsafe module, and reserved words. + +The bsafe module is in gross violation of the ANSI/ISO C standard in the +sense that it redefines what could be implemented as reserved words on a +given compiler. The typical problem is that a compiler may inline some of the +functions and thus not be properly overridden by the definitions in the bsafe +module. It is also possible that a compiler may prohibit the redefinitions in +the bsafe module. Compiler specific action will be required to deal with +these situations. + +Platform Specific Files +----------------------- + +The makefiles for the examples are basically setup of for particular +environments for each platform. In general these makefiles are not portable +and should be constructed as necessary from scratch for each platform. + +Testing a port +-------------- + +To test that a port compiles correctly do the following: + +1. Build a sample project that includes the bstrlib, bstraux, bstrwrap, and + bsafe modules. +2. Compile bstest against the bstrlib module. +3. Run bstest and ensure that 0 errors are reported. +4. Compile test against the bstrlib and bstrwrap modules. +5. Run test and ensure that 0 errors are reported. +6. Compile each of the examples (except for the "re" example, which may be + complicated and is not a real test of bstrlib and except for the mfcbench + example which is Windows specific.) +7. Run each of the examples. + +The builds must have 0 errors, and should have the absolute minimum number of +warnings (in most cases can be reduced to 0.) The result of execution should +be essentially identical on each platform. + +Performance +----------- + +Different CPU and compilers have different capabilities in terms of +performance. It is possible for Bstrlib to assume performance +characteristics that a platform doesn't have (since it was primarily +developed on just one platform). The goal of Bstrlib is to provide very good +performance on all platforms regardless of this but without resorting to +extreme measures (such as using assembly language, or non-portable intrinsics +or library extensions.) + +There are two performance benchmarks that can be found in the example/ +directory. They are: cbench.c and cppbench.cpp. These are variations and +expansions of a benchmark for another string library. They don't cover all +string functionality, but do include the most basic functions which will be +common in most string manipulation kernels. + +............................................................................... + +Feedback +-------- + +In all cases, you may email issues found to the primary author of Bstrlib at +the email address: websnarf@users.sourceforge.net + +=============================================================================== diff --git a/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt b/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt new file mode 100644 index 0000000000..9761409f56 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/cbstring/security.txt @@ -0,0 +1,221 @@ +Better String library Security Statement +---------------------------------------- + +by Paul Hsieh + +=============================================================================== + +Introduction +------------ + +The Better String library (hereafter referred to as Bstrlib) is an attempt to +provide improved string processing functionality to the C and C++ languages. +At the heart of the Bstrlib is the management of "bstring"s which are a +significant improvement over '\0' terminated char buffers. See the +accompanying documenation file bstrlib.txt for more information. + +DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Like any software, there is always a possibility of failure due to a flawed +implementation. Nevertheless a good faith effort has been made to minimize +such flaws in Bstrlib. Also, use of Bstrlib by itself will not make an +application secure or free from implementation failures. However, it is the +author's conviction that use of Bstrlib can greatly facilitate the creation +of software meeting the highest possible standards of security. + +Part of the reason why this document has been created, is for the purpose of +security auditing, or the creation of further "Statements on Security" for +software that is created that uses Bstrlib. An auditor may check the claims +below against Bstrlib, and use this as a basis for analysis of software which +uses Bstrlib. + +=============================================================================== + +Statement on Security +--------------------- + +This is a document intended to give consumers of the Better String Library +who are interested in security an idea of where the Better String Library +stands on various security issues. Any deviation observed in the actual +library itself from the descriptions below should be considered an +implementation error, not a design flaw. + +This statement is not an analytical proof of correctness or an outline of one +but rather an assertion similar to a scientific claim or hypothesis. By use, +testing and open independent examination (otherwise known as scientific +falsifiability), the credibility of the claims made below can rise to the +level of an established theory. + +Common security issues: +....................... + +1. Buffer Overflows + +The Bstrlib API allows the programmer a way to deal with strings without +having to deal with the buffers containing them. Ordinary usage of the +Bstrlib API itself makes buffer overflows impossible. + +Furthermore, the Bstrlib API has a superset of basic string functionality as +compared to the C library's char * functions, C++'s std::string class and +Microsoft's MFC based CString class. It also has abstracted mechanisms for +dealing with IO. This is important as it gives developers a way of migrating +all their code from a functionality point of view. + +2. Memory size overflow/wrap around attack + +Bstrlib is, by design, impervious to memory size overflow attacks. The +reason is it is resiliant to length overflows is that bstring lengths are +bounded above by INT_MAX, instead of ~(size_t)0. So length addition +overflows cause a wrap around of the integer value making them negative +causing balloc() to fail before an erroneous operation can occurr. Attempted +conversions of char * strings which may have lengths greater than INT_MAX are +detected and the conversion is aborted. + +It is unknown if this property holds on machines that don't represent +integers as 2s complement. It is recommended that Bstrlib be carefully +auditted by anyone using a system which is not 2s complement based. + +3. Constant string protection + +Bstrlib implements runtime enforced constant and read-only string semantics. +I.e., bstrings which are declared as constant via the bsStatic() macro cannot +be modified or deallocated directly through the Bstrlib API, and this cannot +be subverted by casting or other type coercion. This is independent of the +use of the const_bstring data type. + +The Bstrlib C API uses the type const_bstring to specify bstring parameters +whose contents do not change. Although the C language cannot enforce this, +this is nevertheless guaranteed by the implementation of the Bstrlib library +of C functions. The C++ API enforces the const attribute on CBString types +correctly. + +4. Aliased bstring support + +Bstrlib detects and supports aliased parameter management throughout the API. +The kind of aliasing that is allowed is the one where pointers of the same +basic type may be pointing to overlapping objects (this is the assumption the +ANSI C99 specification makes.) Each function behaves as if all read-only +parameters were copied to temporaries which are used in their stead before +the function is enacted (it rarely actually does this). No function in the +Bstrlib uses the "restrict" parameter attribute from the ANSI C99 +specification. + +5. Information leaking + +In bstraux.h, using the semantically equivalent macros bSecureDestroy() and +bSecureWriteProtect() in place of bdestroy() and bwriteprotect() respectively +will ensure that stale data does not linger in the heap's free space after +strings have been released back to memory. Created bstrings or CBStrings +are not linked to anything external to themselves, and thus cannot expose +deterministic data leaking. If a bstring is resized, the preimage may exist +as a copy that is released to the heap. Thus for sensitive data, the bstring +should be sufficiently presized before manipulated so that it is not resized. +bSecureInput() has been supplied in bstraux.c, which can be used to obtain +input securely without any risk of leaving any part of the input image in the +heap except for the allocated bstring that is returned. + +6. Memory leaking + +Bstrlib can be built using memdbg.h enabled via the BSTRLIB_MEMORY_DEBUG +macro. User generated definitions for malloc, realloc and free can then be +supplied which can implement special strategies for memory corruption +detection or memory leaking. Otherwise, bstrlib does not do anything out of +the ordinary to attempt to deal with the standard problem of memory leaking +(i.e., losing references to allocated memory) when programming in the C and +C++ languages. However, it does not compound the problem any more than exists +either, as it doesn't have any intrinsic inescapable leaks in it. Bstrlib +does not preclude the use of automatic garbage collection mechanisms such as +the Boehm garbage collector. + +7. Encryption + +Bstrlib does not present any built-in encryption mechanism. However, it +supports full binary contents in its data buffers, so any standard block +based encryption mechanism can make direct use of bstrings/CBStrings for +buffer management. + +8. Double freeing + +Freeing a pointer that is already free is an extremely rare, but nevertheless +a potentially ruthlessly corrupting operation (its possible to cause Win 98 to +reboot, by calling free mulitiple times on already freed data using the WATCOM +CRT.) Bstrlib invalidates the bstring header data before freeing, so that in +many cases a double free will be detected and an error will be reported +(though this behaviour is not guaranteed and should not be relied on). + +Using bstrFree pervasively (instead of bdestroy) can lead to somewhat +improved invalid free avoidance (it is completely safe whenever bstring +instances are only stored in unique variables). For example: + + struct tagbstring hw = bsStatic ("Hello, world"); + bstring cpHw = bstrcpy (&hw); + + #ifdef NOT_QUITE_AS_SAFE + bdestroy (cpHw); /* Never fail */ + bdestroy (cpHw); /* Error sometimes detected at runtime */ + bdestroy (&hw); /* Error detected at run time */ + #else + bstrFree (cpHw); /* Never fail */ + bstrFree (cpHw); /* Will do nothing */ + bstrFree (&hw); /* Will lead to a compile time error */ + #endif + +9. Resource based denial of service + +bSecureInput() has been supplied in bstraux.c. It has an optional upper limit +for input length. But unlike fgets(), it is also easily determined if the +buffer has been truncated early. In this way, a program can set an upper limit +on input sizes while still allowing for implementing context specific +truncation semantics (i.e., does the program consume but dump the extra +input, or does it consume it in later inputs?) + +10. Mixing char *'s and bstrings + +The bstring and char * representations are not identical. So there is a risk +when converting back and forth that data may lost. Essentially bstrings can +contain '\0' as a valid non-terminating character, while char * strings +cannot and in fact must use the character as a terminator. The risk of data +loss is very low, since: + + A) the simple method of only using bstrings in a char * semantically + compatible way is both easy to achieve and pervasively supported. + B) obtaining '\0' content in a string is either deliberate or indicative + of another, likely more serious problem in the code. + C) the library comes with various functions which deal with this issue + (namely: bfromcstr(), bstr2cstr (), and bSetCstrChar ()) + +Marginal security issues: +......................... + +11. 8-bit versus 9-bit portability + +Bstrlib uses CHAR_BIT and other limits.h constants to the maximum extent +possible to avoid portability problems. However, Bstrlib has not been tested +on any system that does not represent char as 8-bits. So whether or not it +works on 9-bit systems is an open question. It is recommended that Bstrlib be +carefully auditted by anyone using a system in which CHAR_BIT is not 8. + +12. EBCDIC/ASCII/UTF-8 data representation attacks. + +Bstrlib uses ctype.h functions to ensure that it remains portable to non- +ASCII systems. It also checks range to make sure it is well defined even for +data that ANSI does not define for the ctype functions. + +Obscure issues: +............... + +13. Data attributes + +There is no support for a Perl-like "taint" attribute, however, an example of +how to do this using C++'s type system is given as an example. + diff --git a/Code/Tools/HLSLCrossCompiler/src/decode.c b/Code/Tools/HLSLCrossCompiler/src/decode.c new file mode 100644 index 0000000000..0af6423971 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/decode.c @@ -0,0 +1,1845 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/decode.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/reflect.h" +#include "internal_includes/structs.h" +#include "internal_includes/tokens.h" +#include "stdio.h" +#include "stdlib.h" + +enum +{ + FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C') +}; // DirectX byte code +enum +{ + FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R') +}; // Shader model 4 code +enum +{ + FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X') +}; // Shader model 5 code +enum +{ + FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F') +}; // Resource definition (e.g. constant buffers) +enum +{ + FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N') +}; // Input signature +enum +{ + FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E') +}; // Interface (for dynamic linking) +enum +{ + FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N') +}; // Output signature + +enum +{ + FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1') +}; // Input signature with Stream and MinPrecision +enum +{ + FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1') +}; // Output signature with Stream and MinPrecision +enum +{ + FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5') +}; // Output signature with Stream + +typedef struct DXBCContainerHeaderTAG +{ + unsigned fourcc; + uint32_t unk[4]; + uint32_t one; + uint32_t totalSize; + uint32_t chunkCount; +} DXBCContainerHeader; + +typedef struct DXBCChunkHeaderTAG +{ + unsigned fourcc; + unsigned size; +} DXBCChunkHeader; + +#ifdef _DEBUG +static uint64_t operandID = 0; +static uint64_t instructionID = 0; +#endif + +#if defined(_WIN32) +#define osSprintf(dest, size, src) sprintf_s(dest, size, src) +#else +#define osSprintf(dest, size, src) sprintf(dest, src) +#endif + +void DecodeNameToken(const uint32_t* pui32NameToken, Operand* psOperand) +{ + const size_t MAX_BUFFER_SIZE = sizeof(psOperand->pszSpecialName); + psOperand->eSpecialName = DecodeOperandSpecialName(*pui32NameToken); + switch (psOperand->eSpecialName) + { + case NAME_UNDEFINED: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "undefined"); + break; + } + case NAME_POSITION: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "position"); + break; + } + case NAME_CLIP_DISTANCE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "clipDistance"); + break; + } + case NAME_CULL_DISTANCE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "cullDistance"); + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "renderTargetArrayIndex"); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "viewportArrayIndex"); + break; + } + case NAME_VERTEX_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "vertexID"); + break; + } + case NAME_PRIMITIVE_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "primitiveID"); + break; + } + case NAME_INSTANCE_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "instanceID"); + break; + } + case NAME_IS_FRONT_FACE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "isFrontFace"); + break; + } + case NAME_SAMPLE_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "sampleIndex"); + break; + } + // For the quadrilateral domain, there are 6 factors (4 sides, 2 inner). + case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: + case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: + + // For the triangular domain, there are 4 factors (3 sides, 1 inner) + case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_INSIDE_TESSFACTOR: + + // For the isoline domain, there are 2 factors (detail and density). + case NAME_FINAL_LINE_DETAIL_TESSFACTOR: + case NAME_FINAL_LINE_DENSITY_TESSFACTOR: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "tessFactor"); + break; + } + default: + { + ASSERT(0); + break; + } + } + + return; +} + +uint32_t DecodeOperand(const uint32_t* pui32Tokens, Operand* psOperand) +{ + int i; + uint32_t ui32NumTokens = 1; + OPERAND_NUM_COMPONENTS eNumComponents; + +#ifdef _DEBUG + psOperand->id = operandID++; +#endif + + // Some defaults + psOperand->iWriteMaskEnabled = 1; + psOperand->iGSInput = 0; + psOperand->aeDataType[0] = SVT_FLOAT; + psOperand->aeDataType[1] = SVT_FLOAT; + psOperand->aeDataType[2] = SVT_FLOAT; + psOperand->aeDataType[3] = SVT_FLOAT; + + psOperand->iExtended = DecodeIsOperandExtended(*pui32Tokens); + + psOperand->eModifier = OPERAND_MODIFIER_NONE; + psOperand->psSubOperand[0] = 0; + psOperand->psSubOperand[1] = 0; + psOperand->psSubOperand[2] = 0; + + psOperand->eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; + + /* Check if this instruction is extended. If it is, + * we need to print the information first */ + if (psOperand->iExtended) + { + /* OperandToken1 is the second token */ + ui32NumTokens++; + + if (DecodeExtendedOperandType(pui32Tokens[1]) == EXTENDED_OPERAND_MODIFIER) + { + psOperand->eModifier = DecodeExtendedOperandModifier(pui32Tokens[1]); + psOperand->eMinPrecision = DecodeOperandMinPrecision(pui32Tokens[1]); + } + } + + psOperand->iIndexDims = DecodeOperandIndexDimension(*pui32Tokens); + psOperand->eType = DecodeOperandType(*pui32Tokens); + + psOperand->ui32RegisterNumber = 0; + + eNumComponents = DecodeOperandNumComponents(*pui32Tokens); + + switch (eNumComponents) + { + case OPERAND_1_COMPONENT: + { + psOperand->iNumComponents = 1; + break; + } + case OPERAND_4_COMPONENT: + { + psOperand->iNumComponents = 4; + break; + } + default: + { + psOperand->iNumComponents = 0; + break; + } + } + + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) + { + psOperand->eSelMode = DecodeOperand4CompSelMode(*pui32Tokens); + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + psOperand->ui32CompMask = DecodeOperand4CompMask(*pui32Tokens); + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + psOperand->ui32Swizzle = DecodeOperand4CompSwizzle(*pui32Tokens); + + if (psOperand->ui32Swizzle != NO_SWIZZLE) + { + psOperand->aui32Swizzle[0] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 0); + psOperand->aui32Swizzle[1] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 1); + psOperand->aui32Swizzle[2] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 2); + psOperand->aui32Swizzle[3] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 3); + } + else + { + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; + psOperand->aui32Swizzle[1] = OPERAND_4_COMPONENT_Y; + psOperand->aui32Swizzle[2] = OPERAND_4_COMPONENT_Z; + psOperand->aui32Swizzle[3] = OPERAND_4_COMPONENT_W; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psOperand->aui32Swizzle[0] = DecodeOperand4CompSel1(*pui32Tokens); + } + } + + // Set externally to this function based on the instruction opcode. + psOperand->iIntegerImmediate = 0; + + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) + { + for (i = 0; i < psOperand->iNumComponents; ++i) + { + psOperand->afImmediates[i] = *((float*)(&pui32Tokens[ui32NumTokens])); + ui32NumTokens++; + } + } + else if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + for (i = 0; i < psOperand->iNumComponents; ++i) + { + psOperand->adImmediates[i] = *((double*)(&pui32Tokens[ui32NumTokens])); + ui32NumTokens += 2; + } + } + + if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) + { + psOperand->ui32RegisterNumber = -1; + psOperand->ui32CompMask = -1; + } + + for (i = 0; i < psOperand->iIndexDims; ++i) + { + OPERAND_INDEX_REPRESENTATION eRep = DecodeOperandIndexRepresentation(i, *pui32Tokens); + + psOperand->eIndexRep[i] = eRep; + + psOperand->aui32ArraySizes[i] = 0; + psOperand->ui32RegisterNumber = 0; + + switch (eRep) + { + case OPERAND_INDEX_IMMEDIATE32: + { + psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); + psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; + break; + } + case OPERAND_INDEX_RELATIVE: + { + psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); + DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); + + ui32NumTokens++; + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); + psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; + + ui32NumTokens++; + + psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); + DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); + + ui32NumTokens++; + break; + } + default: + { + ASSERT(0); + break; + } + } + + ui32NumTokens++; + } + + psOperand->pszSpecialName[0] = '\0'; + + return ui32NumTokens; +} + +const uint32_t* DecodeDeclaration(Shader* psShader, const uint32_t* pui32Token, Declaration* psDecl) +{ + uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); + const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); + const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); + uint32_t ui32OperandOffset = 1; + + if (eOpcode < NUM_OPCODES && eOpcode >= 0) + { + psShader->aiOpcodeUsed[eOpcode] = 1; + } + + psDecl->eOpcode = eOpcode; + + psDecl->ui32TexReturnType = SVT_FLOAT; + + if (bExtended) + { + ui32OperandOffset = 2; + } + + switch (eOpcode) + { + case OPCODE_DCL_RESOURCE: // DCL* opcodes have + { + ResourceBinding* psBinding = 0; + psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && + GetResourceFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) + { + psDecl->ui32TexReturnType = psBinding->ui32ReturnType; + } + break; + } + case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. + { + psDecl->value.eCBAccessPattern = DecodeConstantBufferAccessPattern(*pui32Token); + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_SAMPLER: + { + break; + } + case OPCODE_DCL_INDEX_RANGE: + { + psDecl->ui32NumOperands = 1; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + psDecl->value.ui32IndexRange = pui32Token[ui32OperandOffset]; + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) + { + uint32_t i; + const uint32_t indexRange = psDecl->value.ui32IndexRange; + const uint32_t reg = psDecl->asOperands[0].ui32RegisterNumber; + + psShader->aIndexedInput[reg] = indexRange; + psShader->aIndexedInputParents[reg] = reg; + + //-1 means don't declare this input because it falls in + // the range of an already declared array. + for (i = reg + 1; i < reg + indexRange; ++i) + { + psShader->aIndexedInput[i] = -1; + psShader->aIndexedInputParents[i] = reg; + } + } + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) + { + psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.ui32IndexRange; + } + break; + } + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + { + psDecl->value.eOutputPrimitiveTopology = DecodeGSOutputPrimitiveTopology(*pui32Token); + break; + } + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + { + psDecl->value.eInputPrimitive = DecodeGSInputPrimitive(*pui32Token); + break; + } + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + psDecl->value.ui32MaxOutputVertexCount = pui32Token[1]; + break; + } + case OPCODE_DCL_TESS_PARTITIONING: + { + psDecl->value.eTessPartitioning = DecodeTessPartitioning(*pui32Token); + break; + } + case OPCODE_DCL_TESS_DOMAIN: + { + psDecl->value.eTessDomain = DecodeTessDomain(*pui32Token); + break; + } + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + { + psDecl->value.eTessOutPrim = DecodeTessOutPrim(*pui32Token); + break; + } + case OPCODE_DCL_THREAD_GROUP: + { + psDecl->value.aui32WorkGroupSize[0] = pui32Token[1]; + psDecl->value.aui32WorkGroupSize[1] = pui32Token[2]; + psDecl->value.aui32WorkGroupSize[2] = pui32Token[3]; + break; + } + case OPCODE_DCL_INPUT: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_SIV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + if (psShader->eShaderType == PIXEL_SHADER) + { + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + } + break; + } + case OPCODE_DCL_INPUT_PS: + { + psDecl->ui32NumOperands = 1; + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_PS_SGV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_PS_SIV: + { + psDecl->ui32NumOperands = 1; + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_OUTPUT: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_OUTPUT_SGV: + { + break; + } + case OPCODE_DCL_OUTPUT_SIV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_TEMPS: + { + psDecl->value.ui32NumTemps = *(pui32Token + ui32OperandOffset); + break; + } + case OPCODE_DCL_INDEXABLE_TEMP: + { + psDecl->sIdxTemp.ui32RegIndex = *(pui32Token + ui32OperandOffset); + psDecl->sIdxTemp.ui32RegCount = *(pui32Token + ui32OperandOffset + 1); + psDecl->sIdxTemp.ui32RegComponentSize = *(pui32Token + ui32OperandOffset + 2); + break; + } + case OPCODE_DCL_GLOBAL_FLAGS: + { + psDecl->value.ui32GlobalFlags = DecodeGlobalFlags(*pui32Token); + break; + } + case OPCODE_DCL_INTERFACE: + { + uint32_t func = 0, numClassesImplementingThisInterface, arrayLen, interfaceID; + interfaceID = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + psDecl->ui32TableLength = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + + numClassesImplementingThisInterface = DecodeInterfaceTableLength(*(pui32Token + ui32OperandOffset)); + arrayLen = DecodeInterfaceArrayLength(*(pui32Token + ui32OperandOffset)); + + ui32OperandOffset++; + + psDecl->value.interface.ui32InterfaceID = interfaceID; + psDecl->value.interface.ui32NumFuncTables = numClassesImplementingThisInterface; + psDecl->value.interface.ui32ArraySize = arrayLen; + + psShader->funcPointer[interfaceID].ui32NumBodiesPerTable = psDecl->ui32TableLength; + + for (; func < numClassesImplementingThisInterface; ++func) + { + uint32_t ui32FuncTable = *(pui32Token + ui32OperandOffset); + psShader->aui32FuncTableToFuncPointer[ui32FuncTable] = interfaceID; + + psShader->funcPointer[interfaceID].aui32FuncTables[func] = ui32FuncTable; + ui32OperandOffset++; + } + + break; + } + case OPCODE_DCL_FUNCTION_BODY: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_FUNCTION_TABLE: + { + uint32_t ui32Func; + const uint32_t ui32FuncTableID = pui32Token[ui32OperandOffset++]; + const uint32_t ui32NumFuncsInTable = pui32Token[ui32OperandOffset++]; + + for (ui32Func = 0; ui32Func < ui32NumFuncsInTable; ++ui32Func) + { + const uint32_t ui32FuncBodyID = pui32Token[ui32OperandOffset++]; + + psShader->aui32FuncBodyToFuncTable[ui32FuncBodyID] = ui32FuncTableID; + + psShader->funcTable[ui32FuncTableID].aui32FuncBodies[ui32Func] = ui32FuncBodyID; + } + + // OpcodeToken0 is followed by a DWORD that represents the function table + // identifier and another DWORD (TableLength) that gives the number of + // functions in the table. + // + // This is followed by TableLength DWORDs which are function body indices. + // + + break; + } + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_HS_DECLS: + { + break; + } + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + { + psDecl->value.ui32MaxOutputVertexCount = DecodeOutputControlPointCount(*pui32Token); + break; + } + case OPCODE_HS_JOIN_PHASE: + case OPCODE_HS_FORK_PHASE: + case OPCODE_HS_CONTROL_POINT_PHASE: + { + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + ASSERT(psShader->ui32ForkPhaseCount != 0); // Check for wrapping when we decrement. + psDecl->value.aui32HullPhaseInstanceInfo[0] = psShader->ui32ForkPhaseCount - 1; + psDecl->value.aui32HullPhaseInstanceInfo[1] = pui32Token[1]; + break; + } + case OPCODE_CUSTOMDATA: + { + ui32TokenLength = pui32Token[1]; + { + const uint32_t ui32NumVec4 = (ui32TokenLength - 2) / 4; + uint32_t uIdx = 0; + + ICBVec4 const* pVec4Array = (void*)(pui32Token + 2); + + // The buffer will contain at least one value, but not more than 4096 scalars/1024 vec4's. + ASSERT(ui32NumVec4 < MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE); + + /* must be a multiple of 4 */ + ASSERT(((ui32TokenLength - 2) % 4) == 0); + + for (uIdx = 0; uIdx < ui32NumVec4; uIdx++) + { + psDecl->asImmediateConstBuffer[uIdx] = pVec4Array[uIdx]; + } + + psDecl->ui32NumOperands = ui32NumVec4; + } + break; + } + case OPCODE_DCL_HS_MAX_TESSFACTOR: + { + psDecl->value.fMaxTessFactor = *((float*)&pui32Token[1]); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + { + psDecl->ui32NumOperands = 2; + psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + psDecl->sUAV.Type = DecodeResourceReturnType(0, pui32Token[ui32OperandOffset]); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + { + + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + // This should be a RTYPE_UAV_RWBYTEADDRESS buffer. It is memory backed by + // a shader storage buffer whose is unknown at compile time. + psDecl->sUAV.ui32BufferSize = 0; + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + { + ResourceBinding* psBinding = NULL; + ConstantBuffer* psBuffer = NULL; + + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding); + + GetConstantBufferFromBindingPoint(RGROUP_UAV, psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); + psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; + switch (psBinding->eType) + { + case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: + case RTYPE_UAV_APPEND_STRUCTURED: + case RTYPE_UAV_CONSUME_STRUCTURED: + psDecl->sUAV.bCounter = 1; + break; + default: + break; + } + break; + } + case OPCODE_DCL_RESOURCE_STRUCTURED: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_RESOURCE_RAW: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + { + + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = 0; + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + psDecl->sTGSM.ui32Stride = pui32Token[ui32OperandOffset++]; + psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + { + + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = 0; + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + psDecl->sTGSM.ui32Stride = 4; + psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++] / 4; + break; + } + case OPCODE_DCL_STREAM: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_GS_INSTANCE_COUNT: + { + psDecl->ui32NumOperands = 0; + psDecl->value.ui32GSInstanceCount = pui32Token[1]; + break; + } + default: + { + // Reached end of declarations + return 0; + } + } + + UpdateDeclarationReferences(psShader, psDecl); + + return pui32Token + ui32TokenLength; +} + +const uint32_t* DecodeInstruction(const uint32_t* pui32Token, Instruction* psInst, Shader* psShader) +{ + uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); + const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); + const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); + uint32_t ui32OperandOffset = 1; + +#ifdef _DEBUG + psInst->id = instructionID++; +#endif + + psInst->eOpcode = eOpcode; + + psInst->bSaturate = DecodeInstructionSaturate(*pui32Token); + + psInst->bAddressOffset = 0; + + psInst->ui32FirstSrc = 1; + + if (bExtended) + { + do + { + const uint32_t ui32ExtOpcodeToken = pui32Token[ui32OperandOffset]; + const EXTENDED_OPCODE_TYPE eExtType = DecodeExtendedOpcodeType(ui32ExtOpcodeToken); + + if (eExtType == EXTENDED_OPCODE_SAMPLE_CONTROLS) + { + psInst->bAddressOffset = 1; + + psInst->iUAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_U, ui32ExtOpcodeToken); + psInst->iVAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_V, ui32ExtOpcodeToken); + psInst->iWAddrOffset = DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_W, ui32ExtOpcodeToken); + } + else if (eExtType == EXTENDED_OPCODE_RESOURCE_RETURN_TYPE) + { + psInst->xType = DecodeExtendedResourceReturnType(0, ui32ExtOpcodeToken); + psInst->yType = DecodeExtendedResourceReturnType(1, ui32ExtOpcodeToken); + psInst->zType = DecodeExtendedResourceReturnType(2, ui32ExtOpcodeToken); + psInst->wType = DecodeExtendedResourceReturnType(3, ui32ExtOpcodeToken); + } + else if (eExtType == EXTENDED_OPCODE_RESOURCE_DIM) + { + psInst->eResDim = DecodeExtendedResourceDimension(ui32ExtOpcodeToken); + } + + ui32OperandOffset++; + } while (DecodeIsOpcodeExtended(pui32Token[ui32OperandOffset - 1])); + } + + if (eOpcode < NUM_OPCODES && eOpcode >= 0) + { + psShader->aiOpcodeUsed[eOpcode] = 1; + } + + switch (eOpcode) + { + // no operands + case OPCODE_CUT: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_RET: + case OPCODE_LOOP: + case OPCODE_ENDLOOP: + case OPCODE_BREAK: + case OPCODE_ELSE: + case OPCODE_ENDIF: + case OPCODE_CONTINUE: + case OPCODE_DEFAULT: + case OPCODE_ENDSWITCH: + case OPCODE_NOP: + case OPCODE_HS_CONTROL_POINT_PHASE: + case OPCODE_HS_FORK_PHASE: + case OPCODE_HS_JOIN_PHASE: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + break; + } + case OPCODE_SYNC: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + psInst->ui32SyncFlags = DecodeSyncFlags(*pui32Token); + break; + } + + // 1 operand + case OPCODE_EMIT_STREAM: + case OPCODE_CUT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + case OPCODE_CASE: + case OPCODE_SWITCH: + case OPCODE_LABEL: + { + psInst->ui32NumOperands = 1; + psInst->ui32FirstSrc = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + + // if(eOpcode == OPCODE_CASE) + // { + // psInst->asOperands[0].iIntegerImmediate = 1; + // } + break; + } + + case OPCODE_INTERFACE_CALL: + { + psInst->ui32NumOperands = 1; + psInst->ui32FirstSrc = 0; + psInst->ui32FuncIndexWithinInterface = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + + break; + } + + /* Floating point instruction decodes */ + + // Instructions with two operands go here + case OPCODE_MOV: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + + // Mov with an integer dest. If src is an immediate then it must be encoded as an integer. + if (psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_SINT_16 || psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_UINT_16) + { + psInst->asOperands[1].iIntegerImmediate = 1; + } + break; + } + case OPCODE_LOG: + case OPCODE_RSQ: + case OPCODE_EXP: + case OPCODE_SQRT: + case OPCODE_ROUND_PI: + case OPCODE_ROUND_NI: + case OPCODE_ROUND_Z: + case OPCODE_ROUND_NE: + case OPCODE_FRC: + case OPCODE_FTOU: + case OPCODE_FTOI: + case OPCODE_UTOF: + case OPCODE_ITOF: + case OPCODE_INEG: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + case OPCODE_DMOV: + case OPCODE_DTOF: + case OPCODE_FTOD: + case OPCODE_DRCP: + case OPCODE_COUNTBITS: + case OPCODE_FIRSTBIT_HI: + case OPCODE_FIRSTBIT_LO: + case OPCODE_FIRSTBIT_SHI: + case OPCODE_BFREV: + case OPCODE_F32TOF16: + case OPCODE_F16TOF32: + case OPCODE_RCP: + case OPCODE_DERIV_RTX: + case OPCODE_DERIV_RTY: + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_NOT: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + + // Instructions with three operands go here + case OPCODE_SINCOS: + { + psInst->ui32FirstSrc = 2; + // Intentional fall-through + } + case OPCODE_IMIN: + case OPCODE_UMIN: + case OPCODE_MIN: + case OPCODE_IMAX: + case OPCODE_UMAX: + case OPCODE_MAX: + case OPCODE_MUL: + case OPCODE_DIV: + case OPCODE_ADD: + case OPCODE_DP2: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_NE: + case OPCODE_OR: + case OPCODE_XOR: + case OPCODE_LT: + case OPCODE_IEQ: + case OPCODE_IADD: + case OPCODE_AND: + case OPCODE_GE: + case OPCODE_IGE: + case OPCODE_EQ: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_LD: + case OPCODE_ILT: + case OPCODE_INE: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_IMIN: + case OPCODE_DADD: + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DDIV: + { + psInst->ui32NumOperands = 3; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + case OPCODE_UGE: + case OPCODE_ULT: + case OPCODE_USHR: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_UMIN: + { + psInst->ui32NumOperands = 3; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + // Instructions with four operands go here + case OPCODE_MAD: + case OPCODE_MOVC: + case OPCODE_IMAD: + case OPCODE_UDIV: + case OPCODE_LOD: + case OPCODE_SAMPLE: + case OPCODE_GATHER4: + case OPCODE_LD_MS: + case OPCODE_UBFE: + case OPCODE_IBFE: + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_DMOVC: + case OPCODE_DFMA: + case OPCODE_IMUL: + { + psInst->ui32NumOperands = 4; + + if (eOpcode == OPCODE_IMUL || eOpcode == OPCODE_UDIV) + { + psInst->ui32FirstSrc = 2; + } + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + + break; + } + case OPCODE_UADDC: + case OPCODE_USUBB: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + { + psInst->ui32NumOperands = 4; + + if (eOpcode == OPCODE_IMUL) + { + psInst->ui32FirstSrc = 2; + } + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + + break; + } + case OPCODE_GATHER4_PO: + case OPCODE_SAMPLE_L: + case OPCODE_BFI: + case OPCODE_SWAPC: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + psInst->ui32NumOperands = 5; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + + break; + } + case OPCODE_GATHER4_C: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_B: + { + psInst->ui32NumOperands = 5; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + break; + } + case OPCODE_GATHER4_PO_C: + case OPCODE_SAMPLE_D: + { + psInst->ui32NumOperands = 6; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[5]); + break; + } + case OPCODE_IF: + case OPCODE_BREAKC: + case OPCODE_CONTINUEC: + case OPCODE_RETC: + case OPCODE_DISCARD: + { + psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); + psInst->ui32NumOperands = 1; + psInst->ui32FirstSrc = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + break; + } + case OPCODE_CALLC: + { + psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); + psInst->ui32NumOperands = 2; + psInst->ui32FirstSrc = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + case OPCODE_CUSTOMDATA: + { + psInst->ui32NumOperands = 0; + ui32TokenLength = pui32Token[1]; + break; + } + case OPCODE_EVAL_CENTROID: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_SNAPPED: + case OPCODE_STORE_UAV_TYPED: + case OPCODE_LD_UAV_TYPED: + case OPCODE_LD_RAW: + case OPCODE_STORE_RAW: + { + psInst->ui32NumOperands = 3; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + case OPCODE_STORE_STRUCTURED: + case OPCODE_LD_STRUCTURED: + { + psInst->ui32NumOperands = 4; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + break; + } + case OPCODE_RESINFO: + { + psInst->ui32NumOperands = 3; + + psInst->eResInfoReturnType = DecodeResInfoReturnType(pui32Token[0]); + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + case OPCODE_MSAD: + default: + { + ASSERT(0); + break; + } + } + + UpdateInstructionReferences(psShader, psInst); + + return pui32Token + ui32TokenLength; +} + +void BindTextureToSampler(Shader* psShader, uint32_t ui32TextureRegister, uint32_t ui32SamplerRegister, uint32_t bCompare) +{ + uint32_t ui32Sampler, ui32TextureUnit, bLoad; + ASSERT(ui32TextureRegister < (1 << 10)); + ASSERT(ui32SamplerRegister < (1 << 10)); + + if (psShader->sInfo.ui32NumSamplers >= MAX_RESOURCE_BINDINGS) + { + ASSERT(0); + return; + } + + ui32TextureUnit = ui32TextureRegister; + for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) + { + if (psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureBindPoint == ui32TextureRegister) + { + if (psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10SamplerBindPoint == ui32SamplerRegister) + break; + ui32TextureUnit = MAX_RESOURCE_BINDINGS; // Texture is used by two or more samplers - assign to an available texture unit later + } + } + + // MAX_RESOURCE_BINDINGS means no sampler object (used for texture load) + bLoad = ui32SamplerRegister == MAX_RESOURCE_BINDINGS; + + if (bCompare) + psShader->sInfo.asSamplers[ui32Sampler].sMask.bCompareSample = 1; + else if (!bLoad) + psShader->sInfo.asSamplers[ui32Sampler].sMask.bNormalSample = 1; + else + { + psShader->sInfo.asSamplers[ui32Sampler].sMask.bNormalSample = 0; + psShader->sInfo.asSamplers[ui32Sampler].sMask.bCompareSample = 0; + } + + if (ui32Sampler == psShader->sInfo.ui32NumSamplers) + { + psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureBindPoint = ui32TextureRegister; + psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10SamplerBindPoint = ui32SamplerRegister; + psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit = ui32TextureUnit; + ++psShader->sInfo.ui32NumSamplers; + } +} + +void RegisterUniformBuffer(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) +{ + uint32_t ui32UniformBuffer = psShader->sInfo.ui32NumUniformBuffers; + psShader->sInfo.asUniformBuffers[ui32UniformBuffer].ui32BindPoint = ui32BindPoint; + psShader->sInfo.asUniformBuffers[ui32UniformBuffer].eGroup = eGroup; + ++psShader->sInfo.ui32NumUniformBuffers; +} + +void RegisterStorageBuffer(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) +{ + uint32_t ui32StorageBuffer = psShader->sInfo.ui32NumStorageBuffers; + psShader->sInfo.asStorageBuffers[ui32StorageBuffer].ui32BindPoint = ui32BindPoint; + psShader->sInfo.asStorageBuffers[ui32StorageBuffer].eGroup = eGroup; + ++psShader->sInfo.ui32NumStorageBuffers; +} + +void RegisterImage(Shader* psShader, ResourceGroup eGroup, uint32_t ui32BindPoint) +{ + uint32_t ui32Image = psShader->sInfo.ui32NumImages; + psShader->sInfo.asImages[ui32Image].ui32BindPoint = ui32BindPoint; + psShader->sInfo.asImages[ui32Image].eGroup = eGroup; + ++psShader->sInfo.ui32NumImages; +} + +void AssignRemainingSamplers(Shader* psShader) +{ + uint32_t ui32Sampler; + uint32_t aui32TextureUnitsUsed[(MAX_RESOURCE_BINDINGS + 31) / 32]; + uint32_t ui32MinAvailUnit; + + memset((void*)aui32TextureUnitsUsed, 0, sizeof(aui32TextureUnitsUsed)); + for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) + { + uint32_t ui32Unit = psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit; + if (ui32Unit < MAX_RESOURCE_BINDINGS) + aui32TextureUnitsUsed[ui32Unit / 32] |= 1 << (ui32Unit % 32); + } + + ui32MinAvailUnit = 0; + for (ui32Sampler = 0; ui32Sampler < psShader->sInfo.ui32NumSamplers; ++ui32Sampler) + { + uint32_t ui32Unit = psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit; + if (ui32Unit == MAX_RESOURCE_BINDINGS) + { + uint32_t ui32Mask, ui32AvailUnit; + uint32_t ui32WordIndex = ui32MinAvailUnit / 32; + uint32_t ui32BitIndex = ui32MinAvailUnit % 32; + + while (ui32WordIndex < sizeof(aui32TextureUnitsUsed)) + { + if (aui32TextureUnitsUsed[ui32WordIndex] != ~0L) + break; + ++ui32WordIndex; + ui32BitIndex = 0; + } + if (ui32WordIndex == sizeof(aui32TextureUnitsUsed)) + { + ASSERT(0); // Not enough resource bindings + break; + } + + ui32Mask = aui32TextureUnitsUsed[ui32WordIndex]; + while (ui32BitIndex < 32) + { + if ((ui32Mask & (1 << ui32BitIndex)) == 0) + break; + ++ui32BitIndex; + } + if (ui32BitIndex == 32) + { + ASSERT(0); + break; + } + + ui32AvailUnit = 32 * ui32WordIndex + ui32BitIndex; + aui32TextureUnitsUsed[ui32WordIndex] |= (1 << ui32BitIndex); + + psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit = ui32AvailUnit; + ui32MinAvailUnit = ui32AvailUnit + 1; + + ASSERT(psShader->sInfo.asSamplers[ui32Sampler].sMask.ui10TextureUnit < MAX_RESOURCE_BINDINGS); + } + } +} + +void UpdateDeclarationReferences(Shader* psShader, Declaration* psDecl) +{ + switch (psDecl->eOpcode) + { + case OPCODE_DCL_CONSTANT_BUFFER: + RegisterUniformBuffer(psShader, RGROUP_CBUFFER, psDecl->asOperands[0].aui32ArraySizes[0]); + break; + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + RegisterImage(psShader, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber); + break; + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + RegisterStorageBuffer(psShader, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber); + break; + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + RegisterStorageBuffer(psShader, RGROUP_UAV, psDecl->asOperands[0].aui32ArraySizes[0]); + break; + case OPCODE_DCL_RESOURCE_RAW: + RegisterStorageBuffer(psShader, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber); + break; + case OPCODE_DCL_RESOURCE_STRUCTURED: + RegisterStorageBuffer(psShader, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber); + break; + } +} + +void UpdateInstructionReferences(Shader* psShader, Instruction* psInst) +{ + uint32_t ui32Operand; + const uint32_t ui32NumOperands = psInst->ui32NumOperands; + for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) + { + Operand* psOperand = &psInst->asOperands[ui32Operand]; + if (psOperand->eType == OPERAND_TYPE_INPUT || psOperand->eType == OPERAND_TYPE_INPUT_CONTROL_POINT) + { + if (psOperand->iIndexDims == INDEX_2D) + { + if (psOperand->aui32ArraySizes[1] != 0) // gl_in[].gl_Position + { + psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; + } + } + else + { + psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; + } + } + } + + switch (psInst->eOpcode) + { + case OPCODE_SWAPC: + psShader->bUseTempCopy = 1; + break; + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_D: + case OPCODE_SAMPLE_B: + case OPCODE_GATHER4: + BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); + break; + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_C: + case OPCODE_GATHER4_C: + BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); + break; + case OPCODE_GATHER4_PO: + BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0); + break; + case OPCODE_GATHER4_PO_C: + BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 1); + break; + case OPCODE_LD: + case OPCODE_LD_MS: + // MAX_RESOURCE_BINDINGS means no sampler object + BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, MAX_RESOURCE_BINDINGS, 0); + break; + } +} + +const uint32_t* DecodeHullShaderJoinPhase(const uint32_t* pui32Tokens, Shader* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + + Instruction* psInst; + + // Declarations + Declaration* psDecl; + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + psShader->psHSJoinPhaseDecl = psDecl; + psShader->ui32HSJoinDeclCount = 0; + + while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + psShader->ui32HSJoinDeclCount++; + psDecl++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + // Instructions + psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); + psShader->psHSJoinPhaseInstr = psInst; + psShader->ui32HSJoinInstrCount = 0; + + while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) + { + const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); + +#ifdef _DEBUG + if (nextInstr == pui32CurrentToken) + { + ASSERT(0); + break; + } +#endif + + pui32CurrentToken = nextInstr; + psShader->ui32HSJoinInstrCount++; + + psInst++; + } + + return pui32CurrentToken; +} + +const uint32_t* DecodeHullShaderForkPhase(const uint32_t* pui32Tokens, Shader* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + const uint32_t ui32ForkPhaseIndex = psShader->ui32ForkPhaseCount; + + Instruction* psInst; + + // Declarations + Declaration* psDecl; + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + + ASSERT(ui32ForkPhaseIndex < MAX_FORK_PHASES); + + psShader->ui32ForkPhaseCount++; + + psShader->apsHSForkPhaseDecl[ui32ForkPhaseIndex] = psDecl; + psShader->aui32HSForkDeclCount[ui32ForkPhaseIndex] = 0; + + while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + psShader->aui32HSForkDeclCount[ui32ForkPhaseIndex]++; + psDecl++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + // Instructions + psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); + psShader->apsHSForkPhaseInstr[ui32ForkPhaseIndex] = psInst; + psShader->aui32HSForkInstrCount[ui32ForkPhaseIndex] = 0; + + while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) + { + const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); + +#ifdef _DEBUG + if (nextInstr == pui32CurrentToken) + { + ASSERT(0); + break; + } +#endif + + pui32CurrentToken = nextInstr; + + if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) + { + pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + + psShader->aui32HSForkInstrCount[ui32ForkPhaseIndex]++; + psInst++; + } + + return pui32CurrentToken; +} + +const uint32_t* DecodeHullShaderControlPointPhase(const uint32_t* pui32Tokens, Shader* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + + Instruction* psInst; + + // TODO one block of memory for instructions and declarions to reduce memory usage and number of allocs. + // hlscc_malloc max(sizeof(declaration), sizeof(instruction) * shader length; or sizeof(DeclInst) - unifying both structs. + + // Declarations + Declaration* psDecl; + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + psShader->psHSControlPointPhaseDecl = psDecl; + psShader->ui32HSControlPointDeclCount = 0; + + while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + psShader->ui32HSControlPointDeclCount++; + psDecl++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + // Instructions + psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); + psShader->psHSControlPointPhaseInstr = psInst; + psShader->ui32HSControlPointInstrCount = 0; + + while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) + { + const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); + +#ifdef _DEBUG + if (nextInstr == pui32CurrentToken) + { + ASSERT(0); + break; + } +#endif + + pui32CurrentToken = nextInstr; + + if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) + { + pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + if (psInst->eOpcode == OPCODE_HS_JOIN_PHASE) + { + pui32CurrentToken = DecodeHullShaderJoinPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + psInst++; + psShader->ui32HSControlPointInstrCount++; + } + + return pui32CurrentToken; +} + +const uint32_t* DecodeHullShader(const uint32_t* pui32Tokens, Shader* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + Declaration* psDecl; + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + psShader->psHSDecl = psDecl; + psShader->ui32HSDeclCount = 0; + + while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + + if (psDecl->eOpcode == OPCODE_HS_CONTROL_POINT_PHASE) + { + pui32CurrentToken = DecodeHullShaderControlPointPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + if (psDecl->eOpcode == OPCODE_HS_FORK_PHASE) + { + pui32CurrentToken = DecodeHullShaderForkPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + if (psDecl->eOpcode == OPCODE_HS_JOIN_PHASE) + { + pui32CurrentToken = DecodeHullShaderJoinPhase(pui32CurrentToken, psShader); + return pui32CurrentToken; + } + + psDecl++; + psShader->ui32HSDeclCount++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + return pui32CurrentToken; +} + +void Decode(const uint32_t* pui32Tokens, Shader* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = pui32Tokens[1]; + Instruction* psInst; + Declaration* psDecl; + + psShader->ui32MajorVersion = DecodeProgramMajorVersion(*pui32CurrentToken); + psShader->ui32MinorVersion = DecodeProgramMinorVersion(*pui32CurrentToken); + psShader->eShaderType = DecodeShaderType(*pui32CurrentToken); + + pui32CurrentToken++; // Move to shader length + psShader->ui32ShaderLength = ui32ShaderLength; + pui32CurrentToken++; // Move to after shader length (usually a declaration) + + psShader->pui32FirstToken = pui32Tokens; + +#ifdef _DEBUG + operandID = 0; + instructionID = 0; +#endif + + if (psShader->eShaderType == HULL_SHADER) + { + pui32CurrentToken = DecodeHullShader(pui32CurrentToken, psShader); + return; + } + + // Using ui32ShaderLength as the instruction count + // will allocate more than enough memory. Avoids having to + // traverse the entire shader just to get the real instruction count. + psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); + psShader->psInst = psInst; + psShader->ui32InstCount = 0; + + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + psShader->psDecl = psDecl; + psShader->ui32DeclCount = 0; + + while (1) // Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + psShader->ui32DeclCount++; + psDecl++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) + { + const uint32_t* nextInstr = DecodeInstruction(pui32CurrentToken, psInst, psShader); + +#ifdef _DEBUG + if (nextInstr == pui32CurrentToken) + { + ASSERT(0); + break; + } +#endif + + pui32CurrentToken = nextInstr; + psShader->ui32InstCount++; + psInst++; + } + + AssignRemainingSamplers(psShader); +} + +Shader* DecodeDXBC(uint32_t* data) +{ + Shader* psShader; + DXBCContainerHeader* header = (DXBCContainerHeader*)data; + uint32_t i; + uint32_t chunkCount; + uint32_t* chunkOffsets; + ReflectionChunks refChunks; + uint32_t* shaderChunk = 0; + + if (header->fourcc != FOURCC_DXBC) + { + // Could be SM1/2/3. If the shader type token + // looks valid then we continue + uint32_t type = DecodeShaderTypeDX9(data[0]); + + if (type != INVALID_SHADER) + { + return DecodeDX9BC(data); + } + return 0; + } + + refChunks.pui32Inputs = NULL; + refChunks.pui32Interfaces = NULL; + refChunks.pui32Outputs = NULL; + refChunks.pui32Resources = NULL; + refChunks.pui32Inputs11 = NULL; + refChunks.pui32Outputs11 = NULL; + refChunks.pui32OutputsWithStreams = NULL; + + chunkOffsets = (uint32_t*)(header + 1); + + chunkCount = header->chunkCount; + + for (i = 0; i < chunkCount; ++i) + { + uint32_t offset = chunkOffsets[i]; + + DXBCChunkHeader* chunk = (DXBCChunkHeader*)((char*)data + offset); + + switch (chunk->fourcc) + { + case FOURCC_ISGN: + { + refChunks.pui32Inputs = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_ISG1: + { + refChunks.pui32Inputs11 = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_RDEF: + { + refChunks.pui32Resources = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_IFCE: + { + refChunks.pui32Interfaces = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSGN: + { + refChunks.pui32Outputs = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSG1: + { + refChunks.pui32Outputs11 = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSG5: + { + refChunks.pui32OutputsWithStreams = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_SHDR: + case FOURCC_SHEX: + { + shaderChunk = (uint32_t*)(chunk + 1); + break; + } + default: + { + break; + } + } + } + + if (shaderChunk) + { + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + + psShader = hlslcc_calloc(1, sizeof(Shader)); + + ui32MajorVersion = DecodeProgramMajorVersion(*shaderChunk); + ui32MinorVersion = DecodeProgramMinorVersion(*shaderChunk); + + LoadShaderInfo(ui32MajorVersion, ui32MinorVersion, &refChunks, &psShader->sInfo); + + Decode(shaderChunk, psShader); + + return psShader; + } + + return 0; +} diff --git a/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c b/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c new file mode 100644 index 0000000000..68f4dd6225 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/decodeDX9.c @@ -0,0 +1,1113 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/debug.h" +#include "internal_includes/decode.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/reflect.h" +#include "internal_includes/structs.h" +#include "internal_includes/tokens.h" +#include "stdio.h" +#include "stdlib.h" + +enum +{ + FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B') +}; // Constant table + +#ifdef _DEBUG +static uint64_t dx9operandID = 0; +static uint64_t dx9instructionID = 0; +#endif + +static uint32_t aui32ImmediateConst[256]; +static uint32_t ui32MaxTemp = 0; + +uint32_t DX9_DECODE_OPERAND_IS_SRC = 0x1; +uint32_t DX9_DECODE_OPERAND_IS_DEST = 0x2; +uint32_t DX9_DECODE_OPERAND_IS_DECL = 0x4; + +uint32_t DX9_DECODE_OPERAND_IS_CONST = 0x8; +uint32_t DX9_DECODE_OPERAND_IS_ICONST = 0x10; +uint32_t DX9_DECODE_OPERAND_IS_BCONST = 0x20; + +#define MAX_INPUTS 64 + +static DECLUSAGE_DX9 aeInputUsage[MAX_INPUTS]; +static uint32_t aui32InputUsageIndex[MAX_INPUTS]; + +static void DecodeOperandDX9(const Shader* psShader, const uint32_t ui32Token, const uint32_t ui32Token1, uint32_t ui32Flags, Operand* psOperand) +{ + const uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token); + const uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token); + const uint32_t bRelativeAddr = DecodeOperandIsRelativeAddressModeDX9(ui32Token); + + const uint32_t ui32WriteMask = DecodeDestWriteMaskDX9(ui32Token); + const uint32_t ui32Swizzle = DecodeOperandSwizzleDX9(ui32Token); + + SHADER_VARIABLE_TYPE ConstType; + + psOperand->ui32RegisterNumber = ui32RegNum; + + psOperand->iNumComponents = 4; + +#ifdef _DEBUG + psOperand->id = dx9operandID++; +#endif + + psOperand->iWriteMaskEnabled = 0; + psOperand->iGSInput = 0; + psOperand->iExtended = 0; + psOperand->psSubOperand[0] = 0; + psOperand->psSubOperand[1] = 0; + psOperand->psSubOperand[2] = 0; + + psOperand->iIndexDims = INDEX_0D; + + psOperand->iIntegerImmediate = 0; + + psOperand->pszSpecialName[0] = '\0'; + + psOperand->eModifier = OPERAND_MODIFIER_NONE; + if (ui32Flags & DX9_DECODE_OPERAND_IS_SRC) + { + uint32_t ui32Modifier = DecodeSrcModifierDX9(ui32Token); + + switch (ui32Modifier) + { + case SRCMOD_DX9_NONE: + { + break; + } + case SRCMOD_DX9_NEG: + { + psOperand->eModifier = OPERAND_MODIFIER_NEG; + break; + } + case SRCMOD_DX9_ABS: + { + psOperand->eModifier = OPERAND_MODIFIER_ABS; + break; + } + case SRCMOD_DX9_ABSNEG: + { + psOperand->eModifier = OPERAND_MODIFIER_ABSNEG; + break; + } + default: + { + ASSERT(0); + break; + } + } + } + + if ((ui32Flags & DX9_DECODE_OPERAND_IS_DECL) == 0) + { + if (ui32Flags & DX9_DECODE_OPERAND_IS_DEST) + { + if (ui32WriteMask != DX9_WRITEMASK_ALL) + { + psOperand->iWriteMaskEnabled = 1; + psOperand->eSelMode = OPERAND_4_COMPONENT_MASK_MODE; + + if (ui32WriteMask & DX9_WRITEMASK_0) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_X; + } + if (ui32WriteMask & DX9_WRITEMASK_1) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Y; + } + if (ui32WriteMask & DX9_WRITEMASK_2) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Z; + } + if (ui32WriteMask & DX9_WRITEMASK_3) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_W; + } + } + } + else if (ui32Swizzle != NO_SWIZZLE_DX9) + { + uint32_t component; + + psOperand->iWriteMaskEnabled = 1; + psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE; + + psOperand->ui32Swizzle = 1; + + /* Add the swizzle */ + if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(0)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(1)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Y; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(2)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Z; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(3)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_W; + } + else + { + for (component = 0; component < 4; component++) + { + uint32_t ui32CompSwiz = ui32Swizzle & (3 << (DX9_SWIZZLE_SHIFT + (component * 2))); + ui32CompSwiz >>= (DX9_SWIZZLE_SHIFT + (component * 2)); + + if (ui32CompSwiz == 0) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_X; + } + else if (ui32CompSwiz == 1) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Y; + } + else if (ui32CompSwiz == 2) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Z; + } + else + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_W; + } + } + } + } + + if (bRelativeAddr) + { + psOperand->psSubOperand[0] = hlslcc_malloc(sizeof(Operand)); + DecodeOperandDX9(psShader, ui32Token1, 0, ui32Flags, psOperand->psSubOperand[0]); + + psOperand->iIndexDims = INDEX_1D; + + psOperand->eIndexRep[0] = OPERAND_INDEX_RELATIVE; + + psOperand->aui32ArraySizes[0] = 0; + } + } + + if (ui32RegType == OPERAND_TYPE_DX9_CONSTBOOL) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; + ConstType = SVT_BOOL; + } + else if (ui32RegType == OPERAND_TYPE_DX9_CONSTINT) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; + ConstType = SVT_INT; + } + else if (ui32RegType == OPERAND_TYPE_DX9_CONST) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; + ConstType = SVT_FLOAT; + } + + switch (ui32RegType) + { + case OPERAND_TYPE_DX9_TEMP: + { + psOperand->eType = OPERAND_TYPE_TEMP; + + if (ui32MaxTemp < ui32RegNum + 1) + { + ui32MaxTemp = ui32RegNum + 1; + } + break; + } + case OPERAND_TYPE_DX9_INPUT: + { + psOperand->eType = OPERAND_TYPE_INPUT; + + ASSERT(ui32RegNum < MAX_INPUTS); + + if (psShader->eShaderType == PIXEL_SHADER) + { + if (aeInputUsage[ui32RegNum] == DECLUSAGE_TEXCOORD) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + psOperand->ui32RegisterNumber = aui32InputUsageIndex[ui32RegNum]; + } + else + // 0 = base colour, 1 = offset colour. + if (ui32RegNum == 0) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; + } + else + { + ASSERT(ui32RegNum == 1); + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; + } + } + break; + } + // Same value as OPERAND_TYPE_DX9_TEXCRDOUT + // OPERAND_TYPE_DX9_TEXCRDOUT is the pre-SM3 equivalent + case OPERAND_TYPE_DX9_OUTPUT: + { + psOperand->eType = OPERAND_TYPE_OUTPUT; + + if (psShader->eShaderType == VERTEX_SHADER) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + } + break; + } + case OPERAND_TYPE_DX9_RASTOUT: + { + // RegNum: + // 0=POSIION + // 1=FOG + // 2=POINTSIZE + psOperand->eType = OPERAND_TYPE_OUTPUT; + switch (ui32RegNum) + { + case 0: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_POSITION; + break; + } + case 1: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_FOG; + break; + } + case 2: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_POINTSIZE; + psOperand->iNumComponents = 1; + break; + } + } + break; + } + case OPERAND_TYPE_DX9_ATTROUT: + { + ASSERT(psShader->eShaderType == VERTEX_SHADER); + + psOperand->eType = OPERAND_TYPE_OUTPUT; + + // 0 = base colour, 1 = offset colour. + if (ui32RegNum == 0) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; + } + else + { + ASSERT(ui32RegNum == 1); + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; + } + + break; + } + case OPERAND_TYPE_DX9_COLOROUT: + { + ASSERT(psShader->eShaderType == PIXEL_SHADER); + psOperand->eType = OPERAND_TYPE_OUTPUT; + break; + } + case OPERAND_TYPE_DX9_CONSTBOOL: + case OPERAND_TYPE_DX9_CONSTINT: + case OPERAND_TYPE_DX9_CONST: + { + // c# = constant float + // i# = constant int + // b# = constant bool + + // c0 might be an immediate while i0 is in the constant buffer + if (aui32ImmediateConst[ui32RegNum] & ui32Flags) + { + if (ConstType != SVT_FLOAT) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; + } + else + { + psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONST; + } + } + else + { + psOperand->eType = OPERAND_TYPE_CONSTANT_BUFFER; + psOperand->aui32ArraySizes[1] = psOperand->ui32RegisterNumber; + } + break; + } + case OPERAND_TYPE_DX9_ADDR: + { + // Vertex shader: address register (only have one of these) + // Pixel shader: texture coordinate register (a few of these) + if (psShader->eShaderType == PIXEL_SHADER) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + } + else + { + psOperand->eType = OPERAND_TYPE_SPECIAL_ADDRESS; + } + break; + } + case OPERAND_TYPE_DX9_SAMPLER: + { + psOperand->eType = OPERAND_TYPE_RESOURCE; + break; + } + case OPERAND_TYPE_DX9_LOOP: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_LOOPCOUNTER; + break; + } + default: + { + ASSERT(0); + break; + } + } +} + +static void DeclareNumTemps(Shader* psShader, const uint32_t ui32NumTemps, Declaration* psDecl) +{ + (void)psShader; + + psDecl->eOpcode = OPCODE_DCL_TEMPS; + psDecl->value.ui32NumTemps = ui32NumTemps; +} + +static void SetupRegisterUsage(const Shader* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1) +{ + (void)psShader; + + DECLUSAGE_DX9 eUsage = DecodeUsageDX9(ui32Token0); + uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0); + uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token1); + uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); + + if (ui32RegType == OPERAND_TYPE_DX9_INPUT) + { + ASSERT(ui32RegNum < MAX_INPUTS); + aeInputUsage[ui32RegNum] = eUsage; + aui32InputUsageIndex[ui32RegNum] = ui32UsageIndex; + } +} + +// Declaring one constant from a constant buffer will cause all constants in the buffer decalared. +// In dx9 there is only one constant buffer per shader. +static void DeclareConstantBuffer(const Shader* psShader, Declaration* psDecl) +{ + // Pick any constant register in the table. Might not start at c0 (e.g. when register(cX) is used). + uint32_t ui32RegNum = psShader->sInfo.psConstantBuffers->asVars[0].ui32StartOffset / 16; + OPERAND_TYPE_DX9 ui32RegType = OPERAND_TYPE_DX9_CONST; + + if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_INT) + { + ui32RegType = OPERAND_TYPE_DX9_CONSTINT; + } + else if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_BOOL) + { + ui32RegType = OPERAND_TYPE_DX9_CONSTBOOL; + } + + if (psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_INPUT; + } + else + { + psDecl->eOpcode = OPCODE_DCL_INPUT_PS; + } + psDecl->ui32NumOperands = 1; + + DecodeOperandDX9(psShader, CreateOperandTokenDX9(ui32RegNum, ui32RegType), 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); + + ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER); + + psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index + psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. +} + +static void DecodeDeclarationDX9(const Shader* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1, Declaration* psDecl) +{ + uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); + + if (psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_INPUT; + } + else + { + psDecl->eOpcode = OPCODE_DCL_INPUT_PS; + } + psDecl->ui32NumOperands = 1; + DecodeOperandDX9(psShader, ui32Token1, 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); + + if (ui32RegType == OPERAND_TYPE_DX9_SAMPLER) + { + const RESOURCE_DIMENSION eResDim = DecodeTextureTypeMaskDX9(ui32Token0); + psDecl->value.eResourceDimension = eResDim; + psDecl->eOpcode = OPCODE_DCL_RESOURCE; + } + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) + { + psDecl->eOpcode = OPCODE_DCL_OUTPUT; + + if (psDecl->asOperands[0].ui32RegisterNumber == 0 && psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_OUTPUT_SIV; + // gl_Position + psDecl->asOperands[0].eSpecialName = NAME_POSITION; + } + } + else if (psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index + psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. + } +} + +static void DefineDX9(Shader* psShader, + const uint32_t ui32RegNum, + const uint32_t ui32Flags, + const uint32_t c0, + const uint32_t c1, + const uint32_t c2, + const uint32_t c3, + Declaration* psDecl) +{ + (void)psShader; + + psDecl->eOpcode = OPCODE_SPECIAL_DCL_IMMCONST; + psDecl->ui32NumOperands = 2; + + memset(&psDecl->asOperands[0], 0, sizeof(Operand)); + psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONST; + + psDecl->asOperands[0].ui32RegisterNumber = ui32RegNum; + + if (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) + { + psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; + } + + aui32ImmediateConst[ui32RegNum] |= ui32Flags; + + memset(&psDecl->asOperands[1], 0, sizeof(Operand)); + psDecl->asOperands[1].eType = OPERAND_TYPE_IMMEDIATE32; + psDecl->asOperands[1].iNumComponents = 4; + psDecl->asOperands[1].iIntegerImmediate = (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) ? 1 : 0; + psDecl->asOperands[1].afImmediates[0] = *((float*)&c0); + psDecl->asOperands[1].afImmediates[1] = *((float*)&c1); + psDecl->asOperands[1].afImmediates[2] = *((float*)&c2); + psDecl->asOperands[1].afImmediates[3] = *((float*)&c3); +} + +static void CreateD3D10Instruction(Shader* psShader, + Instruction* psInst, + const OPCODE_TYPE eType, + const uint32_t bHasDest, + const uint32_t ui32SrcCount, + const uint32_t* pui32Tokens) +{ + uint32_t ui32Src; + uint32_t ui32Offset = 1; + + memset(psInst, 0, sizeof(Instruction)); + +#ifdef _DEBUG + psInst->id = dx9instructionID++; +#endif + + psInst->eOpcode = eType; + psInst->ui32NumOperands = ui32SrcCount; + + if (bHasDest) + { + ++psInst->ui32NumOperands; + + DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_DEST, &psInst->asOperands[0]); + + if (DecodeDestModifierDX9(pui32Tokens[ui32Offset]) & DESTMOD_DX9_SATURATE) + { + psInst->bSaturate = 1; + } + + ui32Offset++; + psInst->ui32FirstSrc = 1; + } + + for (ui32Src = 0; ui32Src < ui32SrcCount; ++ui32Src) + { + DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_SRC, &psInst->asOperands[bHasDest + ui32Src]); + + ui32Offset++; + } +} + +Shader* DecodeDX9BC(const uint32_t* pui32Tokens) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + uint32_t ui32NumInstructions = 0; + uint32_t ui32NumDeclarations = 0; + Instruction* psInst; + Declaration* psDecl; + uint32_t decl, inst; + uint32_t bDeclareConstantTable = 0; + Shader* psShader = hlslcc_calloc(1, sizeof(Shader)); + + memset(aui32ImmediateConst, 0, 256); + + psShader->ui32MajorVersion = DecodeProgramMajorVersionDX9(*pui32CurrentToken); + psShader->ui32MinorVersion = DecodeProgramMinorVersionDX9(*pui32CurrentToken); + psShader->eShaderType = DecodeShaderTypeDX9(*pui32CurrentToken); + + pui32CurrentToken++; + + // Work out how many instructions and declarations we need to allocate memory for. + while (1) + { + OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); + uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); + + if (eOpcode == OPCODE_DX9_END) + { + // SM4+ always end with RET. + // Insert a RET instruction on END to + // replicate this behaviour. + ++ui32NumInstructions; + break; + } + else if (eOpcode == OPCODE_DX9_COMMENT) + { + ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); + if (pui32CurrentToken[1] == FOURCC_CTAB) + { + LoadD3D9ConstantTable((char*)(&pui32CurrentToken[2]), &psShader->sInfo); + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + if (psShader->sInfo.psConstantBuffers[0].ui32NumVars) + { + ++ui32NumDeclarations; + bDeclareConstantTable = 1; + } + } + } + else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) + { + ++ui32NumDeclarations; + } + else if (eOpcode == OPCODE_DX9_DCL) + { + const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); + uint32_t ignoreDCL = 0; + + // Inputs and outputs are declared in AddVersionDependentCode + if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) + { + ignoreDCL = 1; + } + if (!ignoreDCL) + { + ++ui32NumDeclarations; + } + } + else + { + switch (eOpcode) + { + case OPCODE_DX9_NRM: + { + // Emulate with dp4 and rsq + ui32NumInstructions += 2; + break; + } + default: + { + ++ui32NumInstructions; + break; + } + } + } + + pui32CurrentToken += ui32InstLen + 1; + } + + psInst = hlslcc_malloc(sizeof(Instruction) * ui32NumInstructions); + psShader->psInst = psInst; + psShader->ui32InstCount = ui32NumInstructions; + + if (psShader->eShaderType == VERTEX_SHADER) + { + // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not + ui32NumDeclarations++; + } + + // For declaring temps. + ui32NumDeclarations++; + + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32NumDeclarations); + psShader->psDecl = psDecl; + psShader->ui32DeclCount = ui32NumDeclarations; + + pui32CurrentToken = pui32Tokens + 1; + + inst = 0; + decl = 0; + while (1) + { + OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); + uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); + + if (eOpcode == OPCODE_DX9_END) + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); + inst++; + break; + } + else if (eOpcode == OPCODE_DX9_COMMENT) + { + ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); + } + else if (eOpcode == OPCODE_DX9_DCL) + { + const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); + uint32_t ignoreDCL = 0; + // Inputs and outputs are declared in AddVersionDependentCode + if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) + { + ignoreDCL = 1; + } + + SetupRegisterUsage(psShader, pui32CurrentToken[1], pui32CurrentToken[2]); + + if (!ignoreDCL) + { + DecodeDeclarationDX9(psShader, pui32CurrentToken[1], pui32CurrentToken[2], &psDecl[decl]); + decl++; + } + } + else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) + { + const uint32_t ui32Const0 = *(pui32CurrentToken + 2); + const uint32_t ui32Const1 = *(pui32CurrentToken + 3); + const uint32_t ui32Const2 = *(pui32CurrentToken + 4); + const uint32_t ui32Const3 = *(pui32CurrentToken + 5); + uint32_t ui32Flags = 0; + + if (eOpcode == OPCODE_DX9_DEF) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; + } + else if (eOpcode == OPCODE_DX9_DEFI) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; + } + else + { + ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; + } + + DefineDX9(psShader, DecodeOperandRegisterNumberDX9(pui32CurrentToken[1]), ui32Flags, ui32Const0, ui32Const1, ui32Const2, ui32Const3, &psDecl[decl]); + decl++; + } + else + { + switch (eOpcode) + { + case OPCODE_DX9_MOV: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOV, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_LIT: + { + /*Dest.x = 1 + Dest.y = (Src0.x > 0) ? Src0.x : 0 + Dest.z = (Src0.x > 0 && Src0.y > 0) ? pow(Src0.y, Src0.w) : 0 + Dest.w = 1 + */ + ASSERT(0); + break; + } + case OPCODE_DX9_ADD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SUB: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); + ASSERT(psInst[inst].asOperands[2].eModifier == OPERAND_MODIFIER_NONE); + psInst[inst].asOperands[2].eModifier = OPERAND_MODIFIER_NEG; + break; + } + case OPCODE_DX9_MAD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAD, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_MUL: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MUL, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_RCP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RCP, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_RSQ: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP3: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP3, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP4: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_MIN: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MIN, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_MAX: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAX, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SLT: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LT, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SGE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_GE, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_EXP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_EXP, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_LOG: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOG, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_NRM: + { + // Convert NRM RESULT, SRCA into: + // dp4 RESULT, SRCA, SRCA + // rsq RESULT, RESULT + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 1, pui32CurrentToken); + memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); + ++inst; + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 0, 0, pui32CurrentToken); + memcpy(&psInst[inst].asOperands[0], &psInst[inst - 1].asOperands[0], sizeof(Operand)); + break; + } + case OPCODE_DX9_SINCOS: + { + // Before SM3, SINCOS has 2 extra constant sources -D3DSINCOSCONST1 and D3DSINCOSCONST2. + // Ignore them. + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SINCOS, 1, 1, pui32CurrentToken); + // Pre-SM4: + // If the write mask is .x: dest.x = cos( V ) + // If the write mask is .y: dest.y = sin( V ) + // If the write mask is .xy: + // dest.x = cos( V ) + // dest.y = sin( V ) + + // SM4+ + // destSin destCos Angle + + psInst[inst].ui32NumOperands = 3; + + // Set the angle + memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); + + // Set the cosine dest + memcpy(&psInst[inst].asOperands[1], &psInst[inst].asOperands[0], sizeof(Operand)); + + // Set write masks + psInst[inst].asOperands[0].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_Y; + if (psInst[inst].asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + // Need cosine + } + else + { + psInst[inst].asOperands[0].eType = OPERAND_TYPE_NULL; + } + psInst[inst].asOperands[1].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_X; + if (psInst[inst].asOperands[1].ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + // Need sine + } + else + { + psInst[inst].asOperands[1].eType = OPERAND_TYPE_NULL; + } + + break; + } + case OPCODE_DX9_FRC: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_FRC, 1, 1, pui32CurrentToken); + break; + } + + case OPCODE_DX9_MOVA: + { + // MOVA preforms RoundToNearest on the src data. + // The only rounding functions available in all GLSL version are ceil and floor. + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ROUND_NI, 1, 1, pui32CurrentToken); + break; + } + + case OPCODE_DX9_TEX: + { + // texld r0, t0, s0 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE, 1, 2, pui32CurrentToken); + psInst[inst].asOperands[2].ui32RegisterNumber = 0; + + break; + } + case OPCODE_DX9_TEXLDL: + { + // texld r0, t0, s0 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_L, 1, 2, pui32CurrentToken); + psInst[inst].asOperands[2].ui32RegisterNumber = 0; + + // Lod comes from fourth coordinate of address. + memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[1], sizeof(Operand)); + + psInst[inst].ui32NumOperands = 5; + + break; + } + + case OPCODE_DX9_IF: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 1, pui32CurrentToken); + psInst[inst].eDX9TestType = D3DSPC_BOOLEAN; + break; + } + + case OPCODE_DX9_IFC: + { + const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 2, pui32CurrentToken); + psInst[inst].eDX9TestType = eCmpOp; + break; + } + case OPCODE_DX9_ELSE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ELSE, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_CMP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOVC, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_REP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_REP, 0, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDREP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDREP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_BREAKC: + { + const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAKC, 0, 2, pui32CurrentToken); + psInst[inst].eDX9TestType = eCmpOp; + break; + } + + case OPCODE_DX9_DSX: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTX, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_DSY: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTY, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_TEXKILL: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DISCARD, 1, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_TEXLDD: + { + // texldd, dst, src0, src1, src2, src3 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler, XGradient, YGradient + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_D, 1, 4, pui32CurrentToken); + psInst[inst].asOperands[2].ui32RegisterNumber = 0; + break; + } + case OPCODE_DX9_LRP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LRP, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP2ADD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP2ADD, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_POW: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_POW, 1, 2, pui32CurrentToken); + break; + } + + case OPCODE_DX9_DST: + case OPCODE_DX9_M4x4: + case OPCODE_DX9_M4x3: + case OPCODE_DX9_M3x4: + case OPCODE_DX9_M3x3: + case OPCODE_DX9_M3x2: + case OPCODE_DX9_CALL: + case OPCODE_DX9_CALLNZ: + case OPCODE_DX9_LABEL: + + case OPCODE_DX9_CRS: + case OPCODE_DX9_SGN: + case OPCODE_DX9_ABS: + + case OPCODE_DX9_TEXCOORD: + case OPCODE_DX9_TEXBEM: + case OPCODE_DX9_TEXBEML: + case OPCODE_DX9_TEXREG2AR: + case OPCODE_DX9_TEXREG2GB: + case OPCODE_DX9_TEXM3x2PAD: + case OPCODE_DX9_TEXM3x2TEX: + case OPCODE_DX9_TEXM3x3PAD: + case OPCODE_DX9_TEXM3x3TEX: + case OPCODE_DX9_TEXM3x3SPEC: + case OPCODE_DX9_TEXM3x3VSPEC: + case OPCODE_DX9_EXPP: + case OPCODE_DX9_LOGP: + case OPCODE_DX9_CND: + case OPCODE_DX9_TEXREG2RGB: + case OPCODE_DX9_TEXDP3TEX: + case OPCODE_DX9_TEXM3x2DEPTH: + case OPCODE_DX9_TEXDP3: + case OPCODE_DX9_TEXM3x3: + case OPCODE_DX9_TEXDEPTH: + case OPCODE_DX9_BEM: + case OPCODE_DX9_SETP: + case OPCODE_DX9_BREAKP: + { + ASSERT(0); + break; + } + case OPCODE_DX9_NOP: + case OPCODE_DX9_PHASE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_NOP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_LOOP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOOP, 0, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_RET: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDLOOP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDLOOP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDIF: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDIF, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_BREAK: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAK, 0, 0, pui32CurrentToken); + break; + } + default: + { + ASSERT(0); + break; + } + } + + UpdateInstructionReferences(psShader, &psInst[inst]); + + inst++; + } + + pui32CurrentToken += ui32InstLen + 1; + } + + DeclareNumTemps(psShader, ui32MaxTemp, &psDecl[decl]); + ++decl; + + if (psShader->eShaderType == VERTEX_SHADER) + { + // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not + if (bDeclareConstantTable) + { + DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl + 1]); + } + else + { + DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl]); + } + } + + if (bDeclareConstantTable) + { + DeclareConstantBuffer(psShader, &psDecl[decl]); + } + + return psShader; +} diff --git a/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c b/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c new file mode 100644 index 0000000000..22abd1a5e2 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/hlslccToolkit.c @@ -0,0 +1,167 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +#include "internal_includes/hlslccToolkit.h" +#include "internal_includes/debug.h" +#include "internal_includes/languages.h" + +bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src) +{ + if (src == dest) + return true; + + if ((dest == SVT_FLOAT || dest == SVT_FLOAT10 || dest == SVT_FLOAT16) && + (src == SVT_FLOAT || src == SVT_FLOAT10 || src == SVT_FLOAT16)) + return true; + + if ((dest == SVT_INT || dest == SVT_INT12 || dest == SVT_INT16) && + (src == SVT_INT || src == SVT_INT12 || src == SVT_INT16)) + return true; + + if ((dest == SVT_UINT || dest == SVT_UINT16) && + (src == SVT_UINT || src == SVT_UINT16)) + return true; + + return false; +} + +const char * GetConstructorForTypeGLSL(HLSLCrossCompilerContext* psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision) +{ + const bool usePrecision = useGLSLPrecision && HavePrecisionQualifers(psContext->psShader->eTargetLanguage); + + static const char * const uintTypes[] = { " ", "uint", "uvec2", "uvec3", "uvec4" }; + static const char * const uint16Types[] = { " ", "mediump uint", "mediump uvec2", "mediump uvec3", "mediump uvec4" }; + static const char * const intTypes[] = { " ", "int", "ivec2", "ivec3", "ivec4" }; + static const char * const int16Types[] = { " ", "mediump int", "mediump ivec2", "mediump ivec3", "mediump ivec4" }; + static const char * const int12Types[] = { " ", "lowp int", "lowp ivec2", "lowp ivec3", "lowp ivec4" }; + static const char * const floatTypes[] = { " ", "float", "vec2", "vec3", "vec4" }; + static const char * const float16Types[] = { " ", "mediump float", "mediump vec2", "mediump vec3", "mediump vec4" }; + static const char * const float10Types[] = { " ", "lowp float", "lowp vec2", "lowp vec3", "lowp vec4" }; + static const char * const boolTypes[] = { " ", "bool", "bvec2", "bvec3", "bvec4" }; + + ASSERT(components >= 1 && components <= 4); + + switch (eType) + { + case SVT_UINT: + return uintTypes[components]; + case SVT_UINT16: + return usePrecision ? uint16Types[components] : uintTypes[components]; + case SVT_INT: + return intTypes[components]; + case SVT_INT16: + return usePrecision ? int16Types[components] : intTypes[components]; + case SVT_INT12: + return usePrecision ? int12Types[components] : intTypes[components]; + case SVT_FLOAT: + return floatTypes[components]; + case SVT_FLOAT16: + return usePrecision ? float16Types[components] : floatTypes[components]; + case SVT_FLOAT10: + return usePrecision ? float10Types[components] : floatTypes[components]; + case SVT_BOOL: + return boolTypes[components]; + default: + ASSERT(0); + return ""; + } +} + +SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags) +{ + if (typeflags & TO_FLAG_INTEGER) + return SVT_INT; + if (typeflags & TO_FLAG_UNSIGNED_INTEGER) + return SVT_UINT; + return SVT_FLOAT; +} + +uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType) +{ + if (eType == SVT_FLOAT16 || eType == SVT_FLOAT10 || eType == SVT_FLOAT) + { + return TO_FLAG_FLOAT; + } + if (eType == SVT_UINT || eType == SVT_UINT16) + { + return TO_FLAG_UNSIGNED_INTEGER; + } + else if (eType == SVT_INT || eType == SVT_INT16 || eType == SVT_INT12) + { + return TO_FLAG_INTEGER; + } + else + { + return TO_FLAG_NONE; + } +} + +bool CanDoDirectCast(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) +{ + // uint<->int<->bool conversions possible + if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL || src == SVT_INT12 || src == SVT_INT16 || src == SVT_UINT16) && + (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL || dest == SVT_INT12 || dest == SVT_INT16 || dest == SVT_UINT16)) + return true; + + // float<->double possible + if ((src == SVT_FLOAT || src == SVT_DOUBLE || src == SVT_FLOAT16 || src == SVT_FLOAT10) && + (dest == SVT_FLOAT || dest == SVT_DOUBLE || dest == SVT_FLOAT16 || dest == SVT_FLOAT10)) + return true; + + return false; +} + +const char* GetBitcastOp(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) +{ + static const char* intToFloat = "intBitsToFloat"; + static const char* uintToFloat = "uintBitsToFloat"; + static const char* floatToInt = "floatBitsToInt"; + static const char* floatToUint = "floatBitsToUint"; + + if ((to == SVT_FLOAT || to == SVT_FLOAT16 || to == SVT_FLOAT10) && from == SVT_INT) + return intToFloat; + else if ((to == SVT_FLOAT || to == SVT_FLOAT16 || to == SVT_FLOAT10) && from == SVT_UINT) + return uintToFloat; + else if (to == SVT_INT && (from == SVT_FLOAT || from == SVT_FLOAT16 || from == SVT_FLOAT10)) + return floatToInt; + else if (to == SVT_UINT && (from == SVT_FLOAT || from == SVT_FLOAT16 || from == SVT_FLOAT10)) + return floatToUint; + + ASSERT(0); + return ""; +} + +bool IsGmemReservedSlot(FRAMEBUFFER_FETCH_TYPE typeMask, const uint32_t regNumber) +{ + if (((typeMask & FBF_ARM_COLOR) && regNumber == GMEM_ARM_COLOR_SLOT) || + ((typeMask & FBF_ARM_DEPTH) && regNumber == GMEM_ARM_DEPTH_SLOT) || + ((typeMask & FBF_ARM_STENCIL) && regNumber == GMEM_ARM_STENCIL_SLOT) || + ((typeMask & FBF_EXT_COLOR) && regNumber >= GMEM_FLOAT_START_SLOT)) + { + return true; + } + + return false; +} + +const char * GetAuxArgumentName(const SHADER_VARIABLE_TYPE varType) +{ + switch (varType) + { + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + return "uArg"; + case SVT_INT: + case SVT_INT16: + case SVT_INT12: + return "iArg"; + case SVT_FLOAT: + case SVT_FLOAT16: + case SVT_FLOAT10: + return "fArg"; + case SVT_BOOL: + return "bArg"; + default: + ASSERT(0); + return ""; + } +} \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h new file mode 100644 index 0000000000..5b071709bc --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/debug.h @@ -0,0 +1,21 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef DEBUG_H_ +#define DEBUG_H_ + +#ifdef _DEBUG +#include "assert.h" +#define ASSERT(expr) CustomAssert(expr) +static void CustomAssert(int expression) +{ + if(!expression) + { + assert(0); + } +} +#else +#define ASSERT(expr) +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h new file mode 100644 index 0000000000..d8102683a8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/decode.h @@ -0,0 +1,21 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef DECODE_H +#define DECODE_H + +#include "internal_includes/structs.h" + +Shader* DecodeDXBC(uint32_t* data); + +//You don't need to call this directly because DecodeDXBC +//will call DecodeDX9BC if the shader looks +//like it is SM1/2/3. +Shader* DecodeDX9BC(const uint32_t* pui32Tokens); + +void UpdateDeclarationReferences(Shader* psShader, Declaration* psDeclaration); +void UpdateInstructionReferences(Shader* psShader, Instruction* psInstruction); + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h new file mode 100644 index 0000000000..d0875613a4 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslccToolkit.h @@ -0,0 +1,35 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +#ifndef HLSLCC_TOOLKIT_DECLARATION_H +#define HLSLCC_TOOLKIT_DECLARATION_H + +#include "hlslcc.h" +#include "bstrlib.h" +#include "internal_includes/structs.h" + +#include <stdbool.h> + +// Check if "src" type can be assigned directly to the "dest" type. +bool DoAssignmentDataTypesMatch(SHADER_VARIABLE_TYPE dest, SHADER_VARIABLE_TYPE src); + +// Returns the constructor needed depending on the type, the number of components and the use of precision qualifier. +const char * GetConstructorForTypeGLSL(HLSLCrossCompilerContext* psContext, const SHADER_VARIABLE_TYPE eType, const int components, bool useGLSLPrecision); + +// Transform from a variable type to a shader variable flag. +uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType); + +// Transform from a shader variable flag to a shader variable type. +SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags); + +// Check if the "src" type can be casted using a constructor to the "dest" type (without bitcasting). +bool CanDoDirectCast(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest); + +// Returns the bitcast operation needed to assign the "src" type to the "dest" type +const char* GetBitcastOp(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest); + +// Check if the register number is part of the ones we used for signaling GMEM input +bool IsGmemReservedSlot(FRAMEBUFFER_FETCH_TYPE type, const uint32_t regNumber); + +// Return the name of an auxiliary variable used to save intermediate values to bypass driver issues +const char * GetAuxArgumentName(const SHADER_VARIABLE_TYPE varType); + +#endif \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c new file mode 100644 index 0000000000..0f1c8d62e6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.c @@ -0,0 +1,16 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifdef _WIN32 +#include <malloc.h> +#else +#include <stdlib.h> +#endif +#include <AzCore/PlatformDef.h> + +AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free/calloc/realloc are not static +void* (*hlslcc_malloc)(size_t size) = malloc; +void* (*hlslcc_calloc)(size_t num,size_t size) = calloc; +void (*hlslcc_free)(void *p) = free; +void* (*hlslcc_realloc)(void *p,size_t size) = realloc; +AZ_POP_DISABLE_WARNING diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h new file mode 100644 index 0000000000..533050e17b --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/hlslcc_malloc.h @@ -0,0 +1,15 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef __HLSCC_MALLOC_H +#define __HLSCC_MALLOC_H + +extern void* (*hlslcc_malloc)(size_t size); +extern void* (* hlslcc_calloc)(size_t num, size_t size); +extern void (* hlslcc_free)(void* p); +extern void* (* hlslcc_realloc)(void* p, size_t size); + +#define bstr__alloc hlslcc_malloc +#define bstr__free hlslcc_free +#define bstr__realloc hlslcc_realloc +#endif \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h new file mode 100644 index 0000000000..dd9562379a --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/languages.h @@ -0,0 +1,242 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef LANGUAGES_H +#define LANGUAGES_H + +#include "hlslcc.h" + +static int InOutSupported(const GLLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 0; + } + return 1; +} + +static int WriteToFragData(const GLLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 1; + } + return 0; +} + +static int ShaderBitEncodingSupported(const GLLang eLang) +{ + if( eLang != LANG_ES_300 && + eLang != LANG_ES_310 && + eLang < LANG_330) + { + return 0; + } + return 1; +} + +static int HaveOverloadedTextureFuncs(const GLLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 0; + } + return 1; +} + +//Only enable for ES. +//Not present in 120, ignored in other desktop languages. +static int HavePrecisionQualifers(const GLLang eLang) +{ + if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310) + { + return 1; + } + return 0; +} + +//Only on vertex inputs and pixel outputs. +static int HaveLimitedInOutLocationQualifier(const GLLang eLang) +{ + if(eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveInOutLocationQualifier(const GLLang eLang,const struct GlExtensions *extensions) +{ + if(eLang >= LANG_410 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_attrib_location)) + { + return 1; + } + return 0; +} + +//layout(binding = X) uniform {uniformA; uniformB;} +//layout(location = X) uniform uniform_name; +static int HaveUniformBindingsAndLocations(const GLLang eLang,const struct GlExtensions *extensions) +{ + if(eLang >= LANG_430 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_uniform_location)) + { + return 1; + } + return 0; +} + +static int DualSourceBlendSupported(const GLLang eLang) +{ + if(eLang >= LANG_330) + { + return 1; + } + return 0; +} + +static int SubroutinesSupported(const GLLang eLang) +{ + if(eLang >= LANG_400) + { + return 1; + } + return 0; +} + +//Before 430, flat/smooth/centroid/noperspective must match +//between fragment and its previous stage. +//HLSL bytecode only tells us the interpolation in pixel shader. +static int PixelInterpDependency(const GLLang eLang) +{ + if(eLang < LANG_430) + { + return 1; + } + return 0; +} + +static int HaveUVec(const GLLang eLang) +{ + switch(eLang) + { + case LANG_ES_100: + case LANG_120: + return 0; + default: + break; + } + return 1; +} + +static int HaveGather(const GLLang eLang) +{ + if(eLang >= LANG_400 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveGatherNonConstOffset(const GLLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + + +static int HaveQueryLod(const GLLang eLang) +{ + if(eLang >= LANG_400) + { + return 1; + } + return 0; +} + +static int HaveQueryLevels(const GLLang eLang) +{ + if(eLang >= LANG_430) + { + return 1; + } + return 0; +} + + +static int HaveAtomicCounter(const GLLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveAtomicMem(const GLLang eLang) +{ + if(eLang >= LANG_430) + { + return 1; + } + return 0; +} + +static int HaveCompute(const GLLang eLang) +{ + if(eLang >= LANG_430 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveImageLoadStore(const GLLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int EmulateDepthClamp(const GLLang eLang) +{ + if (eLang >= LANG_ES_300 && eLang < LANG_120) //Requires gl_FragDepth available in fragment shader + { + return 1; + } + return 0; +} + +static int HaveNoperspectiveInterpolation(const GLLang eLang) +{ + if (eLang >= LANG_330) + { + return 1; + } + return 0; +} + +static int EarlyDepthTestSupported(const GLLang eLang) +{ + if ((eLang > LANG_410) || (eLang == LANG_ES_310)) + { + return 1; + } + return 0; +} + +static int StorageBlockBindingSupported(const GLLang eLang) +{ + if (eLang >= LANG_430) + { + return 1; + } + return 0; +} + + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h new file mode 100644 index 0000000000..bea00aafc4 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/reflect.h @@ -0,0 +1,42 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef REFLECT_H +#define REFLECT_H + +#include "hlslcc.h" + +ResourceGroup ResourceTypeToResourceGroup(ResourceType); + +int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding); + +void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf); + +int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); + +int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); +int GetOutputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32Stream, const uint32_t ui32CompMask, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); + +int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); + +int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, const uint32_t* pui32Swizzle, ConstantBuffer* psCBuf, ShaderVarType** ppsShaderVar, int32_t* pi32Index, int32_t* pi32Rebase); + +typedef struct +{ + uint32_t* pui32Inputs; + uint32_t* pui32Outputs; + uint32_t* pui32Resources; + uint32_t* pui32Interfaces; + uint32_t* pui32Inputs11; + uint32_t* pui32Outputs11; + uint32_t* pui32OutputsWithStreams; +} ReflectionChunks; + +void LoadShaderInfo(const uint32_t ui32MajorVersion, const uint32_t ui32MinorVersion, const ReflectionChunks* psChunks, ShaderInfo* psInfo); + +void LoadD3D9ConstantTable(const char* data, ShaderInfo* psInfo); + +void FreeShaderInfo(ShaderInfo* psShaderInfo); + +#endif + diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h new file mode 100644 index 0000000000..7bddbed4da --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/shaderLimits.h @@ -0,0 +1,36 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HLSLCC_SHADER_LIMITS_H +#define HLSLCC_SHADER_LIMITS_H + +static enum +{ + MAX_SHADER_VEC4_OUTPUT = 512 +}; +static enum +{ + MAX_SHADER_VEC4_INPUT = 512 +}; +static enum +{ + MAX_TEXTURES = 128 +}; +static enum +{ + MAX_FORK_PHASES = 2 +}; +static enum +{ + MAX_FUNCTION_BODIES = 1024 +}; +static enum +{ + MAX_CLASS_TYPES = 1024 +}; +static enum +{ + MAX_FUNCTION_POINTERS = 128 +}; + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h new file mode 100644 index 0000000000..a9e7fd92b7 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/structs.h @@ -0,0 +1,374 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef STRUCTS_H +#define STRUCTS_H + +#include "hlslcc.h" +#include "bstrlib.h" + +#include "internal_includes/tokens.h" +#include "internal_includes/reflect.h" + +enum +{ + MAX_SUB_OPERANDS = 3 +}; + +typedef struct Operand_TAG +{ + int iExtended; + OPERAND_TYPE eType; + OPERAND_MODIFIER eModifier; + OPERAND_MIN_PRECISION eMinPrecision; + int iIndexDims; + int indexRepresentation[4]; + int writeMask; + int iGSInput; + int iWriteMaskEnabled; + + int iNumComponents; + + OPERAND_4_COMPONENT_SELECTION_MODE eSelMode; + uint32_t ui32CompMask; + uint32_t ui32Swizzle; + uint32_t aui32Swizzle[4]; + + uint32_t aui32ArraySizes[3]; + uint32_t ui32RegisterNumber; + //If eType is OPERAND_TYPE_IMMEDIATE32 + float afImmediates[4]; + //If eType is OPERAND_TYPE_IMMEDIATE64 + double adImmediates[4]; + + int iIntegerImmediate; + + SPECIAL_NAME eSpecialName; + char pszSpecialName[64]; + + OPERAND_INDEX_REPRESENTATION eIndexRep[3]; + + struct Operand_TAG* psSubOperand[MAX_SUB_OPERANDS]; + + //One type for each component. + SHADER_VARIABLE_TYPE aeDataType[4]; + +#ifdef _DEBUG + uint64_t id; +#endif +} Operand; + +typedef struct Instruction_TAG +{ + OPCODE_TYPE eOpcode; + INSTRUCTION_TEST_BOOLEAN eBooleanTestType; + COMPARISON_DX9 eDX9TestType; + uint32_t ui32SyncFlags; + uint32_t ui32NumOperands; + uint32_t ui32FirstSrc; + Operand asOperands[6]; + uint32_t bSaturate; + uint32_t ui32FuncIndexWithinInterface; + RESINFO_RETURN_TYPE eResInfoReturnType; + + int bAddressOffset; + int iUAddrOffset; + int iVAddrOffset; + int iWAddrOffset; + RESOURCE_RETURN_TYPE xType, yType, zType, wType; + RESOURCE_DIMENSION eResDim; + +#ifdef _DEBUG + uint64_t id; +#endif +} Instruction; + +enum +{ + MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE = 1024 +}; + +typedef struct ICBVec4_TAG +{ + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; +} ICBVec4; + +typedef struct Declaration_TAG +{ + OPCODE_TYPE eOpcode; + + uint32_t ui32NumOperands; + + Operand asOperands[2]; + + ICBVec4 asImmediateConstBuffer[MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE]; + //The declaration can set one of these + //values depending on the opcode. + union + { + uint32_t ui32GlobalFlags; + uint32_t ui32NumTemps; + RESOURCE_DIMENSION eResourceDimension; + CONSTANT_BUFFER_ACCESS_PATTERN eCBAccessPattern; + INTERPOLATION_MODE eInterpolation; + PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology; + PRIMITIVE eInputPrimitive; + uint32_t ui32MaxOutputVertexCount; + TESSELLATOR_DOMAIN eTessDomain; + TESSELLATOR_PARTITIONING eTessPartitioning; + TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; + uint32_t aui32WorkGroupSize[3]; + //Fork phase index followed by the instance count. + uint32_t aui32HullPhaseInstanceInfo[2]; + float fMaxTessFactor; + uint32_t ui32IndexRange; + uint32_t ui32GSInstanceCount; + + struct Interface_TAG + { + uint32_t ui32InterfaceID; + uint32_t ui32NumFuncTables; + uint32_t ui32ArraySize; + } interface; + } value; + + struct UAV_TAG + { + uint32_t ui32GloballyCoherentAccess; + uint32_t ui32BufferSize; + uint8_t bCounter; + RESOURCE_RETURN_TYPE Type; + } sUAV; + + struct TGSM_TAG + { + uint32_t ui32Stride; + uint32_t ui32Count; + } sTGSM; + + struct IndexableTemp_TAG + { + uint32_t ui32RegIndex; + uint32_t ui32RegCount; + uint32_t ui32RegComponentSize; + } sIdxTemp; + + uint32_t ui32TableLength; + + uint32_t ui32TexReturnType; +} Declaration; + +enum +{ + MAX_TEMP_VEC4 = 512 +}; + +enum +{ + MAX_GROUPSHARED = 8 +}; + +enum +{ + MAX_DX9_IMMCONST = 256 +}; + +typedef struct Shader_TAG +{ + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + SHADER_TYPE eShaderType; + + GLLang eTargetLanguage; + const struct GlExtensions *extensions; + + int fp64; + + //DWORDs in program code, including version and length tokens. + uint32_t ui32ShaderLength; + + uint32_t ui32DeclCount; + Declaration* psDecl; + + //Instruction* functions;//non-main subroutines + + uint32_t aui32FuncTableToFuncPointer[MAX_FUNCTION_TABLES];//FIXME dynamic alloc + uint32_t aui32FuncBodyToFuncTable[MAX_FUNCTION_BODIES]; + + struct + { + uint32_t aui32FuncBodies[MAX_FUNCTION_BODIES]; + }funcTable[MAX_FUNCTION_TABLES]; + + struct + { + uint32_t aui32FuncTables[MAX_FUNCTION_TABLES]; + uint32_t ui32NumBodiesPerTable; + }funcPointer[MAX_FUNCTION_POINTERS]; + + uint32_t ui32NextClassFuncName[MAX_CLASS_TYPES]; + + uint32_t ui32InstCount; + Instruction* psInst; + + const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream. + + //Hull shader declarations and instructions. + //psDecl, psInst are null for hull shaders. + uint32_t ui32HSDeclCount; + Declaration* psHSDecl; + + uint32_t ui32HSControlPointDeclCount; + Declaration* psHSControlPointPhaseDecl; + + uint32_t ui32HSControlPointInstrCount; + Instruction* psHSControlPointPhaseInstr; + + uint32_t ui32ForkPhaseCount; + + uint32_t aui32HSForkDeclCount[MAX_FORK_PHASES]; + Declaration* apsHSForkPhaseDecl[MAX_FORK_PHASES]; + + uint32_t aui32HSForkInstrCount[MAX_FORK_PHASES]; + Instruction* apsHSForkPhaseInstr[MAX_FORK_PHASES]; + + uint32_t ui32HSJoinDeclCount; + Declaration* psHSJoinPhaseDecl; + + uint32_t ui32HSJoinInstrCount; + Instruction* psHSJoinPhaseInstr; + + ShaderInfo sInfo; + + int abScalarInput[MAX_SHADER_VEC4_INPUT]; + + int aIndexedOutput[MAX_SHADER_VEC4_OUTPUT]; + + int aIndexedInput[MAX_SHADER_VEC4_INPUT]; + int aIndexedInputParents[MAX_SHADER_VEC4_INPUT]; + + RESOURCE_DIMENSION aeResourceDims[MAX_TEXTURES]; + + int aiInputDeclaredSize[MAX_SHADER_VEC4_INPUT]; + + int aiOutputDeclared[MAX_SHADER_VEC4_OUTPUT]; + + //Does not track built-in inputs. + int abInputReferencedByInstruction[MAX_SHADER_VEC4_INPUT]; + + int aiOpcodeUsed[NUM_OPCODES]; + + uint32_t ui32CurrentVertexOutputStream; + + uint32_t ui32NumDx9ImmConst; + uint32_t aui32Dx9ImmConstArrayRemap[MAX_DX9_IMMCONST]; + + ShaderVarType sGroupSharedVarType[MAX_GROUPSHARED]; + + SHADER_VARIABLE_TYPE aeCommonTempVecType[MAX_TEMP_VEC4]; + uint32_t bUseTempCopy; + FRAMEBUFFER_FETCH_TYPE eGmemType; +} Shader; + +/* CONFETTI NOTE: DAVID SROUR + * The following is super sketchy, but at the moment, + * there is no way to figure out the type of a resource + * since HLSL has only register sets for the following: + * bool, int4, float4, sampler. + * THIS CODE IS DUPLICATED FROM HLSLcc METAL. + * IF ANYTHING CHANGES, BOTH TRANSLATORS SHOULD HAVE THE CHANGE. + * TODO: CONSOLIDATE THE 2 HLSLcc PROJECTS. + */ +enum +{ + GMEM_FLOAT4_START_SLOT = 120 +}; +enum +{ + GMEM_FLOAT3_START_SLOT = 112 +}; +enum +{ + GMEM_FLOAT2_START_SLOT = 104 +}; +enum +{ + GMEM_FLOAT_START_SLOT = 96 +}; + +enum +{ + GMEM_ARM_COLOR_SLOT = 93, + GMEM_ARM_DEPTH_SLOT = 94, + GMEM_ARM_STENCIL_SLOT = 95 +}; + +/* CONFETTI NOTE: DAVID SROUR + * Following is the reserved slot for PLS extension (https://www.khronos.org/registry/gles/extensions/EXT/EXT_shader_pixel_local_storage.txt). + * It will get picked up when a RWStructuredBuffer resource is defined at the following reserved slot. + * Note that only one PLS struct can be present at a time otherwise the behavior is undefined. + * + * Types in the struct and their output conversion (each output variable will always be 4 bytes): + * float2 -> rg16f + * float3 -> r11f_g11f_b10f + * float4 -> rgba8 + * uint -> r32ui + * int2 -> rg16i + * int4 -> rgba8i + */ +enum +{ + GMEM_PLS_RO_SLOT = 60 +}; // READ-ONLY +enum +{ + GMEM_PLS_WO_SLOT = 61 +}; // WRITE-ONLY +enum +{ + GMEM_PLS_RW_SLOT = 62 +}; // READ/WRITE + +static const uint32_t MAIN_PHASE = 0; +static const uint32_t HS_FORK_PHASE = 1; +static const uint32_t HS_CTRL_POINT_PHASE = 2; +static const uint32_t HS_JOIN_PHASE = 3; +enum +{ + NUM_PHASES = 4 +}; + +enum +{ + MAX_COLOR_MRT = 8 +}; + +enum +{ + INPUT_RENDERTARGET = 1 << 0, + OUTPUT_RENDERTARGET = 1 << 1 +}; + +typedef struct HLSLCrossCompilerContext_TAG +{ + bstring glsl; + bstring earlyMain;//Code to be inserted at the start of main() + bstring postShaderCode[NUM_PHASES];//End of main or before emit() + bstring debugHeader; + + bstring* currentGLSLString;//either glsl or earlyMain + + int havePostShaderCode[NUM_PHASES]; + uint32_t currentPhase; + + uint32_t rendertargetUse[MAX_COLOR_MRT]; + + int indent; + unsigned int flags; + Shader* psShader; +} HLSLCrossCompilerContext; + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h new file mode 100644 index 0000000000..337a771e19 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLDeclaration.h @@ -0,0 +1,19 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_DECLARATION_H +#define TO_GLSL_DECLARATION_H + +#include "internal_includes/structs.h" + +void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); + +char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); +char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand, int* stream); + +//Hull shaders have multiple phases. +//Each phase has its own temps. +//Convert to global temps for GLSL. +void ConsolidateHullTempVars(Shader* psShader); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h new file mode 100644 index 0000000000..bf6795d931 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLInstruction.h @@ -0,0 +1,18 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_INSTRUCTION_H +#define TO_GLSL_INSTRUCTION_H + +#include "internal_includes/structs.h" + +void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst); + +//For each MOV temp, immediate; check to see if the next instruction +//using that temp has an integer opcode. If so then the immediate value +//is flaged as having an integer encoding. +void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext); + +void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h new file mode 100644 index 0000000000..56487ea69b --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toGLSLOperand.h @@ -0,0 +1,46 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_OPERAND_H +#define TO_GLSL_OPERAND_H + +#include "internal_includes/structs.h" + +void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); + +int GetMaxComponentFromComponentMask(const Operand* psOperand); +void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); +void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); +void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle); +void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); + +uint32_t GetNumSwizzleElements(const Operand* psOperand); +void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); +int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +uint32_t IsSwizzleReplacated(const Operand* psOperand); + +void TextureName(bstring output, Shader* psShader, const uint32_t ui32TextureRegister, const uint32_t ui32SamplerRegister, const int bCompare); +void UAVName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber); +void UniformBufferName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber); + +void ConvertToTextureName(bstring output, Shader* psShader, const char* szName, const char* szSamplerName, const int bCompare); +void ConvertToUAVName(bstring output, Shader* psShader, const char* szOriginalUAVName); +void ConvertToUniformBufferName(bstring output, Shader* psShader, const char* szConstantBufferName); + +void ShaderVarName(bstring output, Shader* psShader, const char* OriginalName); +void ShaderVarFullName(bstring output, Shader* psShader, const ShaderVarType* psShaderVar); + +uint32_t ConvertOperandSwizzleToComponentMask(const Operand* psOperand); +//Non-zero means the components overlap +int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB); + +SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand); + + +// NOTE: CODE DUPLICATION FROM HLSLcc METAL //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void TranslateGmemOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements); +uint32_t GetGmemInputResourceSlot(uint32_t const slotIn); +uint32_t GetGmemInputResourceNumElements(uint32_t const slotIn); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h new file mode 100644 index 0000000000..724723bf49 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALDeclaration.h @@ -0,0 +1,16 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_DECLARATION_H +#define TO_METAL_DECLARATION_H + +#include "internal_includes/structs.h" + +void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); + +char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); +char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); + +const char* GetMangleSuffixMETAL(const SHADER_TYPE eShaderType); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h new file mode 100644 index 0000000000..eb29e74685 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALInstruction.h @@ -0,0 +1,18 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_INSTRUCTION_H +#define TO_METAL_INSTRUCTION_H + +#include "internal_includes/structs.h" + +void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst); + +//For each MOV temp, immediate; check to see if the next instruction +//using that temp has an integer opcode. If so then the immediate value +//is flaged as having an integer encoding. +void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext); + +void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h new file mode 100644 index 0000000000..d4bcbcbc73 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/toMETALOperand.h @@ -0,0 +1,38 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_OPERAND_H +#define TO_METAL_OPERAND_H + +#include "internal_includes/structs.h" + +#define TO_FLAG_NONE 0x0 +#define TO_FLAG_INTEGER 0x1 +#define TO_FLAG_NAME_ONLY 0x2 +#define TO_FLAG_DECLARATION_NAME 0x4 +#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. +#define TO_FLAG_UNSIGNED_INTEGER 0x10 +#define TO_FLAG_DOUBLE 0x20 +#define TO_FLAG_FLOAT 0x40 + +void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); + +int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand); +void TranslateOperandMETALIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); +void TranslateOperandMETALIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); +void TranslateVariableNameMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle); +void TranslateOperandMETALSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand); +void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count); +int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +uint32_t IsSwizzleReplacatedMETAL(const Operand* psOperand); + +void TextureNameMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32RegisterNumber, const int bZCompare); + +uint32_t ConvertOperandSwizzleToComponentMaskMETAL(const Operand* psOperand); +//Non-zero means the components overlap +int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB); + +SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h new file mode 100644 index 0000000000..635edf57be --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokens.h @@ -0,0 +1,812 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TOKENS_H +#define TOKENS_H + +#include "hlslcc.h" + +typedef enum +{ + INVALID_SHADER = -1, + PIXEL_SHADER, + VERTEX_SHADER, + GEOMETRY_SHADER, + HULL_SHADER, + DOMAIN_SHADER, + COMPUTE_SHADER, +} SHADER_TYPE; + +static SHADER_TYPE DecodeShaderType(uint32_t ui32Token) +{ + return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16); +} + +static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token) +{ + return (ui32Token & 0x000000f0) >> 4; +} + +static uint32_t DecodeProgramMinorVersion(uint32_t ui32Token) +{ + return (ui32Token & 0x0000000f); +} + +static uint32_t DecodeInstructionLength(uint32_t ui32Token) +{ + return (ui32Token & 0x7f000000) >> 24; +} + +static uint32_t DecodeIsOpcodeExtended(uint32_t ui32Token) +{ + return (ui32Token & 0x80000000) >> 31; +} + +typedef enum EXTENDED_OPCODE_TYPE +{ + EXTENDED_OPCODE_EMPTY = 0, + EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, + EXTENDED_OPCODE_RESOURCE_DIM = 2, + EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, +} EXTENDED_OPCODE_TYPE; + +static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token) +{ + return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f); +} + +typedef enum RESOURCE_RETURN_TYPE +{ + RETURN_TYPE_UNORM = 1, + RETURN_TYPE_SNORM = 2, + RETURN_TYPE_SINT = 3, + RETURN_TYPE_UINT = 4, + RETURN_TYPE_FLOAT = 5, + RETURN_TYPE_MIXED = 6, + RETURN_TYPE_DOUBLE = 7, + RETURN_TYPE_CONTINUED = 8, + RETURN_TYPE_UNUSED = 9, +} RESOURCE_RETURN_TYPE; + +static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) +{ + return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF); +} + +static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) +{ + return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF); +} + +typedef enum +{ + //For DX9 + OPCODE_POW = -6, + OPCODE_DP2ADD = -5, + OPCODE_LRP = -4, + OPCODE_ENDREP = -3, + OPCODE_REP = -2, + OPCODE_SPECIAL_DCL_IMMCONST = -1, + + OPCODE_ADD, + OPCODE_AND, + OPCODE_BREAK, + OPCODE_BREAKC, + OPCODE_CALL, + OPCODE_CALLC, + OPCODE_CASE, + OPCODE_CONTINUE, + OPCODE_CONTINUEC, + OPCODE_CUT, + OPCODE_DEFAULT, + OPCODE_DERIV_RTX, + OPCODE_DERIV_RTY, + OPCODE_DISCARD, + OPCODE_DIV, + OPCODE_DP2, + OPCODE_DP3, + OPCODE_DP4, + OPCODE_ELSE, + OPCODE_EMIT, + OPCODE_EMITTHENCUT, + OPCODE_ENDIF, + OPCODE_ENDLOOP, + OPCODE_ENDSWITCH, + OPCODE_EQ, + OPCODE_EXP, + OPCODE_FRC, + OPCODE_FTOI, + OPCODE_FTOU, + OPCODE_GE, + OPCODE_IADD, + OPCODE_IF, + OPCODE_IEQ, + OPCODE_IGE, + OPCODE_ILT, + OPCODE_IMAD, + OPCODE_IMAX, + OPCODE_IMIN, + OPCODE_IMUL, + OPCODE_INE, + OPCODE_INEG, + OPCODE_ISHL, + OPCODE_ISHR, + OPCODE_ITOF, + OPCODE_LABEL, + OPCODE_LD, + OPCODE_LD_MS, + OPCODE_LOG, + OPCODE_LOOP, + OPCODE_LT, + OPCODE_MAD, + OPCODE_MIN, + OPCODE_MAX, + OPCODE_CUSTOMDATA, + OPCODE_MOV, + OPCODE_MOVC, + OPCODE_MUL, + OPCODE_NE, + OPCODE_NOP, + OPCODE_NOT, + OPCODE_OR, + OPCODE_RESINFO, + OPCODE_RET, + OPCODE_RETC, + OPCODE_ROUND_NE, + OPCODE_ROUND_NI, + OPCODE_ROUND_PI, + OPCODE_ROUND_Z, + OPCODE_RSQ, + OPCODE_SAMPLE, + OPCODE_SAMPLE_C, + OPCODE_SAMPLE_C_LZ, + OPCODE_SAMPLE_L, + OPCODE_SAMPLE_D, + OPCODE_SAMPLE_B, + OPCODE_SQRT, + OPCODE_SWITCH, + OPCODE_SINCOS, + OPCODE_UDIV, + OPCODE_ULT, + OPCODE_UGE, + OPCODE_UMUL, + OPCODE_UMAD, + OPCODE_UMAX, + OPCODE_UMIN, + OPCODE_USHR, + OPCODE_UTOF, + OPCODE_XOR, + OPCODE_DCL_RESOURCE, // DCL* opcodes have + OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats. + OPCODE_DCL_SAMPLER, + OPCODE_DCL_INDEX_RANGE, + OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, + OPCODE_DCL_GS_INPUT_PRIMITIVE, + OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, + OPCODE_DCL_INPUT, + OPCODE_DCL_INPUT_SGV, + OPCODE_DCL_INPUT_SIV, + OPCODE_DCL_INPUT_PS, + OPCODE_DCL_INPUT_PS_SGV, + OPCODE_DCL_INPUT_PS_SIV, + OPCODE_DCL_OUTPUT, + OPCODE_DCL_OUTPUT_SGV, + OPCODE_DCL_OUTPUT_SIV, + OPCODE_DCL_TEMPS, + OPCODE_DCL_INDEXABLE_TEMP, + OPCODE_DCL_GLOBAL_FLAGS, + + // ----------------------------------------------- + + OPCODE_RESERVED_10, + + // ---------- DX 10.1 op codes--------------------- + + OPCODE_LOD, + OPCODE_GATHER4, + OPCODE_SAMPLE_POS, + OPCODE_SAMPLE_INFO, + + // ----------------------------------------------- + + // This should be 10.1's version of NUM_OPCODES + OPCODE_RESERVED_10_1, + + // ---------- DX 11 op codes--------------------- + OPCODE_HS_DECLS, // token marks beginning of HS sub-shader + OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader + OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader + OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader + + OPCODE_EMIT_STREAM, + OPCODE_CUT_STREAM, + OPCODE_EMITTHENCUT_STREAM, + OPCODE_INTERFACE_CALL, + + OPCODE_BUFINFO, + OPCODE_DERIV_RTX_COARSE, + OPCODE_DERIV_RTX_FINE, + OPCODE_DERIV_RTY_COARSE, + OPCODE_DERIV_RTY_FINE, + OPCODE_GATHER4_C, + OPCODE_GATHER4_PO, + OPCODE_GATHER4_PO_C, + OPCODE_RCP, + OPCODE_F32TOF16, + OPCODE_F16TOF32, + OPCODE_UADDC, + OPCODE_USUBB, + OPCODE_COUNTBITS, + OPCODE_FIRSTBIT_HI, + OPCODE_FIRSTBIT_LO, + OPCODE_FIRSTBIT_SHI, + OPCODE_UBFE, + OPCODE_IBFE, + OPCODE_BFI, + OPCODE_BFREV, + OPCODE_SWAPC, + + OPCODE_DCL_STREAM, + OPCODE_DCL_FUNCTION_BODY, + OPCODE_DCL_FUNCTION_TABLE, + OPCODE_DCL_INTERFACE, + + OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, + OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, + OPCODE_DCL_TESS_DOMAIN, + OPCODE_DCL_TESS_PARTITIONING, + OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, + OPCODE_DCL_HS_MAX_TESSFACTOR, + OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, + OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, + + OPCODE_DCL_THREAD_GROUP, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, + OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, + OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, + OPCODE_DCL_RESOURCE_RAW, + OPCODE_DCL_RESOURCE_STRUCTURED, + OPCODE_LD_UAV_TYPED, + OPCODE_STORE_UAV_TYPED, + OPCODE_LD_RAW, + OPCODE_STORE_RAW, + OPCODE_LD_STRUCTURED, + OPCODE_STORE_STRUCTURED, + OPCODE_ATOMIC_AND, + OPCODE_ATOMIC_OR, + OPCODE_ATOMIC_XOR, + OPCODE_ATOMIC_CMP_STORE, + OPCODE_ATOMIC_IADD, + OPCODE_ATOMIC_IMAX, + OPCODE_ATOMIC_IMIN, + OPCODE_ATOMIC_UMAX, + OPCODE_ATOMIC_UMIN, + OPCODE_IMM_ATOMIC_ALLOC, + OPCODE_IMM_ATOMIC_CONSUME, + OPCODE_IMM_ATOMIC_IADD, + OPCODE_IMM_ATOMIC_AND, + OPCODE_IMM_ATOMIC_OR, + OPCODE_IMM_ATOMIC_XOR, + OPCODE_IMM_ATOMIC_EXCH, + OPCODE_IMM_ATOMIC_CMP_EXCH, + OPCODE_IMM_ATOMIC_IMAX, + OPCODE_IMM_ATOMIC_IMIN, + OPCODE_IMM_ATOMIC_UMAX, + OPCODE_IMM_ATOMIC_UMIN, + OPCODE_SYNC, + + OPCODE_DADD, + OPCODE_DMAX, + OPCODE_DMIN, + OPCODE_DMUL, + OPCODE_DEQ, + OPCODE_DGE, + OPCODE_DLT, + OPCODE_DNE, + OPCODE_DMOV, + OPCODE_DMOVC, + OPCODE_DTOF, + OPCODE_FTOD, + + OPCODE_EVAL_SNAPPED, + OPCODE_EVAL_SAMPLE_INDEX, + OPCODE_EVAL_CENTROID, + + OPCODE_DCL_GS_INSTANCE_COUNT, + + OPCODE_ABORT, + OPCODE_DEBUG_BREAK, + + // ----------------------------------------------- + + // This marks the end of D3D11.0 opcodes + OPCODE_RESERVED_11, + + OPCODE_DDIV, + OPCODE_DFMA, + OPCODE_DRCP, + + OPCODE_MSAD, + + OPCODE_DTOI, + OPCODE_DTOU, + OPCODE_ITOD, + OPCODE_UTOD, + + // ----------------------------------------------- + + // This marks the end of D3D11.1 opcodes + OPCODE_RESERVED_11_1, + + NUM_OPCODES, + OPCODE_INVAILD = NUM_OPCODES, +} OPCODE_TYPE; + +static OPCODE_TYPE DecodeOpcodeType(uint32_t ui32Token) +{ + return (OPCODE_TYPE)(ui32Token & 0x00007ff); +} + +typedef enum +{ + INDEX_0D, + INDEX_1D, + INDEX_2D, + INDEX_3D, +} OPERAND_INDEX_DIMENSION; + +static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token) +{ + return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20); +} + +typedef enum OPERAND_TYPE +{ + OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10, + OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9, + OPERAND_TYPE_SPECIAL_TEXCOORD = -8, + OPERAND_TYPE_SPECIAL_POSITION = -7, + OPERAND_TYPE_SPECIAL_FOG = -6, + OPERAND_TYPE_SPECIAL_POINTSIZE = -5, + OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR = -4, + OPERAND_TYPE_SPECIAL_OUTBASECOLOUR = -3, + OPERAND_TYPE_SPECIAL_ADDRESS = -2, + OPERAND_TYPE_SPECIAL_IMMCONST = -1, + OPERAND_TYPE_TEMP = 0, // Temporary Register File + OPERAND_TYPE_INPUT = 1, // General Input Register File + OPERAND_TYPE_OUTPUT = 2, // General Output Register File + OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable) + OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s) + // If for example, operand token bits + // [01:00]==OPERAND_4_COMPONENT, + // this means that the operand type: + // OPERAND_TYPE_IMMEDIATE32 + // results in 4 additional 32bit + // DWORDS present for the operand. + OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO + OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state + OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture) + OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer + OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer + OPERAND_TYPE_LABEL = 10, // Label + OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID + OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth + OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations + // Below Are operands new in DX 10.1 + OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources + OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar) + // Below Are operands new in DX 11 + OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource + OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition + OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class + OPERAND_TYPE_INTERFACE = 19, // Reference to an interface + OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function + OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function + OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is + OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID + OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID + OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them) + OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them) + OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them) + OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point + OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer + OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u# + OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g# + OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID + OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID + OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group + OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input + OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value. + OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID + OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth + OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth + OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter +} OPERAND_TYPE; + +static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token) +{ + return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12); +} + +static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token) +{ + return (SPECIAL_NAME)(ui32Token & 0x0000ffff); +} + +typedef enum OPERAND_INDEX_REPRESENTATION +{ + OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD + OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs + // (HI32:LO32) + OPERAND_INDEX_RELATIVE = 2, // Extra operand + OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by + // extra operand + OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS + // (HI32:LO32) followed + // by extra operand +} OPERAND_INDEX_REPRESENTATION; + +static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token) +{ + return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3))); +} + +typedef enum OPERAND_NUM_COMPONENTS +{ + OPERAND_0_COMPONENT = 0, + OPERAND_1_COMPONENT = 1, + OPERAND_4_COMPONENT = 2, + OPERAND_N_COMPONENT = 3 // unused for now +} OPERAND_NUM_COMPONENTS; + +static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token) +{ + return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003); +} + +typedef enum OPERAND_4_COMPONENT_SELECTION_MODE +{ + OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components + OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components + OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components +} OPERAND_4_COMPONENT_SELECTION_MODE; + +static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token) +{ + return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2); +} + +#define OPERAND_4_COMPONENT_MASK_X 0x00000001 +#define OPERAND_4_COMPONENT_MASK_Y 0x00000002 +#define OPERAND_4_COMPONENT_MASK_Z 0x00000004 +#define OPERAND_4_COMPONENT_MASK_W 0x00000008 +#define OPERAND_4_COMPONENT_MASK_R OPERAND_4_COMPONENT_MASK_X +#define OPERAND_4_COMPONENT_MASK_G OPERAND_4_COMPONENT_MASK_Y +#define OPERAND_4_COMPONENT_MASK_B OPERAND_4_COMPONENT_MASK_Z +#define OPERAND_4_COMPONENT_MASK_A OPERAND_4_COMPONENT_MASK_W +#define OPERAND_4_COMPONENT_MASK_ALL 0x0000000f + +static uint32_t DecodeOperand4CompMask(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x000000f0) >> 4); +} + +static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x00000ff0) >> 4); +} + +static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x00000030) >> 4); +} + +#define OPERAND_4_COMPONENT_X 0 +#define OPERAND_4_COMPONENT_Y 1 +#define OPERAND_4_COMPONENT_Z 2 +#define OPERAND_4_COMPONENT_W 3 + +static uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/); + +static uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X<<2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6))); +static uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6))); +static uint32_t ZZZZ_SWIZZLE = (((OPERAND_4_COMPONENT_Z) | (OPERAND_4_COMPONENT_Z<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_Z << 6))); +static uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMPONENT_W<<2) | (OPERAND_4_COMPONENT_W << 4) | (OPERAND_4_COMPONENT_W << 6))); + +static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp) +{ + return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3); +} + +typedef enum RESOURCE_DIMENSION +{ + RESOURCE_DIMENSION_UNKNOWN = 0, + RESOURCE_DIMENSION_BUFFER = 1, + RESOURCE_DIMENSION_TEXTURE1D = 2, + RESOURCE_DIMENSION_TEXTURE2D = 3, + RESOURCE_DIMENSION_TEXTURE2DMS = 4, + RESOURCE_DIMENSION_TEXTURE3D = 5, + RESOURCE_DIMENSION_TEXTURECUBE = 6, + RESOURCE_DIMENSION_TEXTURE1DARRAY = 7, + RESOURCE_DIMENSION_TEXTURE2DARRAY = 8, + RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 9, + RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, + RESOURCE_DIMENSION_RAW_BUFFER = 11, + RESOURCE_DIMENSION_STRUCTURED_BUFFER = 12, +} RESOURCE_DIMENSION; + +static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token) +{ + return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11); +} + +static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token) +{ + return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6); +} + +typedef enum CONSTANT_BUFFER_ACCESS_PATTERN +{ + CONSTANT_BUFFER_ACCESS_PATTERN_IMMEDIATEINDEXED = 0, + CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED = 1 +} CONSTANT_BUFFER_ACCESS_PATTERN; + +static CONSTANT_BUFFER_ACCESS_PATTERN DecodeConstantBufferAccessPattern(uint32_t ui32Token) +{ + return (CONSTANT_BUFFER_ACCESS_PATTERN)((ui32Token & 0x00000800) >> 11); +} + +typedef enum INSTRUCTION_TEST_BOOLEAN +{ + INSTRUCTION_TEST_ZERO = 0, + INSTRUCTION_TEST_NONZERO = 1 +} INSTRUCTION_TEST_BOOLEAN; + +static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token) +{ + return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18); +} + +static uint32_t DecodeIsOperandExtended(uint32_t ui32Token) +{ + return (ui32Token & 0x80000000) >> 31; +} + +typedef enum EXTENDED_OPERAND_TYPE +{ + EXTENDED_OPERAND_EMPTY = 0, + EXTENDED_OPERAND_MODIFIER = 1, +} EXTENDED_OPERAND_TYPE; + +static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token) +{ + return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f); +} + +typedef enum OPERAND_MODIFIER +{ + OPERAND_MODIFIER_NONE = 0, + OPERAND_MODIFIER_NEG = 1, + OPERAND_MODIFIER_ABS = 2, + OPERAND_MODIFIER_ABSNEG = 3, +} OPERAND_MODIFIER; + +static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token) +{ + return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6); +} + +static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11); +static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12); +static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13); +static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14); +static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15); +static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16); +static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17); +static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18); + +static uint32_t DecodeGlobalFlags(uint32_t ui32Token) +{ + return (uint32_t)(ui32Token & 0x00fff800); +} + +static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token) +{ + return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11); +} + + +typedef enum PRIMITIVE_TOPOLOGY +{ + PRIMITIVE_TOPOLOGY_UNDEFINED = 0, + PRIMITIVE_TOPOLOGY_POINTLIST = 1, + PRIMITIVE_TOPOLOGY_LINELIST = 2, + PRIMITIVE_TOPOLOGY_LINESTRIP = 3, + PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4, + PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5, + // 6 is reserved for legacy triangle fans + // Adjacency values should be equal to (0x8 & non-adjacency): + PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10, + PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11, + PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12, + PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13, +} PRIMITIVE_TOPOLOGY; + +static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token) +{ + return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11); +} + +typedef enum PRIMITIVE +{ + PRIMITIVE_UNDEFINED = 0, + PRIMITIVE_POINT = 1, + PRIMITIVE_LINE = 2, + PRIMITIVE_TRIANGLE = 3, + // Adjacency values should be equal to (0x4 & non-adjacency): + PRIMITIVE_LINE_ADJ = 6, + PRIMITIVE_TRIANGLE_ADJ = 7, + PRIMITIVE_1_CONTROL_POINT_PATCH = 8, + PRIMITIVE_2_CONTROL_POINT_PATCH = 9, + PRIMITIVE_3_CONTROL_POINT_PATCH = 10, + PRIMITIVE_4_CONTROL_POINT_PATCH = 11, + PRIMITIVE_5_CONTROL_POINT_PATCH = 12, + PRIMITIVE_6_CONTROL_POINT_PATCH = 13, + PRIMITIVE_7_CONTROL_POINT_PATCH = 14, + PRIMITIVE_8_CONTROL_POINT_PATCH = 15, + PRIMITIVE_9_CONTROL_POINT_PATCH = 16, + PRIMITIVE_10_CONTROL_POINT_PATCH = 17, + PRIMITIVE_11_CONTROL_POINT_PATCH = 18, + PRIMITIVE_12_CONTROL_POINT_PATCH = 19, + PRIMITIVE_13_CONTROL_POINT_PATCH = 20, + PRIMITIVE_14_CONTROL_POINT_PATCH = 21, + PRIMITIVE_15_CONTROL_POINT_PATCH = 22, + PRIMITIVE_16_CONTROL_POINT_PATCH = 23, + PRIMITIVE_17_CONTROL_POINT_PATCH = 24, + PRIMITIVE_18_CONTROL_POINT_PATCH = 25, + PRIMITIVE_19_CONTROL_POINT_PATCH = 26, + PRIMITIVE_20_CONTROL_POINT_PATCH = 27, + PRIMITIVE_21_CONTROL_POINT_PATCH = 28, + PRIMITIVE_22_CONTROL_POINT_PATCH = 29, + PRIMITIVE_23_CONTROL_POINT_PATCH = 30, + PRIMITIVE_24_CONTROL_POINT_PATCH = 31, + PRIMITIVE_25_CONTROL_POINT_PATCH = 32, + PRIMITIVE_26_CONTROL_POINT_PATCH = 33, + PRIMITIVE_27_CONTROL_POINT_PATCH = 34, + PRIMITIVE_28_CONTROL_POINT_PATCH = 35, + PRIMITIVE_29_CONTROL_POINT_PATCH = 36, + PRIMITIVE_30_CONTROL_POINT_PATCH = 37, + PRIMITIVE_31_CONTROL_POINT_PATCH = 38, + PRIMITIVE_32_CONTROL_POINT_PATCH = 39, +} PRIMITIVE; + +static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token) +{ + return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11); +} + +static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token) +{ + return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11); +} + +typedef enum TESSELLATOR_DOMAIN +{ + TESSELLATOR_DOMAIN_UNDEFINED = 0, + TESSELLATOR_DOMAIN_ISOLINE = 1, + TESSELLATOR_DOMAIN_TRI = 2, + TESSELLATOR_DOMAIN_QUAD = 3 +} TESSELLATOR_DOMAIN; + +static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token) +{ + return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11); +} + +static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token) +{ + return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11); +} + +static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800; +static const uint32_t SYNC_THREAD_GROUP_SHARED_MEMORY = 0x00001000; +static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP = 0x00002000; +static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000; + +static uint32_t DecodeSyncFlags(uint32_t ui32Token) +{ + return ui32Token & 0x00007800; +} + +// The number of types that implement this interface +static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x0000ffff) >> 0); +} + +// The number of interfaces that are defined in this array. +static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0xffff0000) >> 16); +} + +typedef enum CUSTOMDATA_CLASS +{ + CUSTOMDATA_COMMENT = 0, + CUSTOMDATA_DEBUGINFO, + CUSTOMDATA_OPAQUE, + CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, + CUSTOMDATA_SHADER_MESSAGE, +} CUSTOMDATA_CLASS; + +static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token) +{ + return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11); +} + +static uint32_t DecodeInstructionSaturate(uint32_t ui32Token) +{ + return (ui32Token & 0x00002000) ? 1 : 0; +} + +typedef enum OPERAND_MIN_PRECISION +{ + OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision + // for the shader model + OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float + OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float + OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer + OPERAND_MIN_PRECISION_UINT_16 = 5, // Min 16 bit/comp. unsigned integer +} OPERAND_MIN_PRECISION; + +static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token) +{ + return (ui32Token & 0x0001C000) >> 14; +} + +static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token) +{ + return ((ui32Token & 0x0001f800) >> 11); +} + +typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD +{ + IMMEDIATE_ADDRESS_OFFSET_U = 0, + IMMEDIATE_ADDRESS_OFFSET_V = 1, + IMMEDIATE_ADDRESS_OFFSET_W = 2, +} IMMEDIATE_ADDRESS_OFFSET_COORD; + + +#define IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&3)) +#define IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<<IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord)) + +static uint32_t DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_COORD eCoord, uint32_t ui32Token) +{ + return ((((ui32Token)&IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord))>>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord)))); +} + +// UAV access scope flags +static const uint32_t GLOBALLY_COHERENT_ACCESS = 0x00010000; +static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token) +{ + return ui32Token & 0x00010000; +} + + +typedef enum RESINFO_RETURN_TYPE +{ + RESINFO_INSTRUCTION_RETURN_FLOAT = 0, + RESINFO_INSTRUCTION_RETURN_RCPFLOAT = 1, + RESINFO_INSTRUCTION_RETURN_UINT = 2 +} RESINFO_RETURN_TYPE; + +static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token) +{ + return (RESINFO_RETURN_TYPE)((ui32Token & 0x00001800) >> 11); +} + +#include "tokensDX9.h" + +#endif diff --git a/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h new file mode 100644 index 0000000000..a71afd7b59 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/internal_includes/tokensDX9.h @@ -0,0 +1,304 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "debug.h" + +static const uint32_t D3D9SHADER_TYPE_VERTEX = 0xFFFE0000; +static const uint32_t D3D9SHADER_TYPE_PIXEL = 0xFFFF0000; + +static SHADER_TYPE DecodeShaderTypeDX9(const uint32_t ui32Token) +{ + uint32_t ui32Type = ui32Token & 0xFFFF0000; + if(ui32Type == D3D9SHADER_TYPE_VERTEX) + return VERTEX_SHADER; + + if(ui32Type == D3D9SHADER_TYPE_PIXEL) + return PIXEL_SHADER; + + return INVALID_SHADER; +} + +static uint32_t DecodeProgramMajorVersionDX9(const uint32_t ui32Token) +{ + return ((ui32Token)>>8)&0xFF; +} + +static uint32_t DecodeProgramMinorVersionDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xFF; +} + +typedef enum +{ + OPCODE_DX9_NOP = 0, + OPCODE_DX9_MOV , + OPCODE_DX9_ADD , + OPCODE_DX9_SUB , + OPCODE_DX9_MAD , + OPCODE_DX9_MUL , + OPCODE_DX9_RCP , + OPCODE_DX9_RSQ , + OPCODE_DX9_DP3 , + OPCODE_DX9_DP4 , + OPCODE_DX9_MIN , + OPCODE_DX9_MAX , + OPCODE_DX9_SLT , + OPCODE_DX9_SGE , + OPCODE_DX9_EXP , + OPCODE_DX9_LOG , + OPCODE_DX9_LIT , + OPCODE_DX9_DST , + OPCODE_DX9_LRP , + OPCODE_DX9_FRC , + OPCODE_DX9_M4x4 , + OPCODE_DX9_M4x3 , + OPCODE_DX9_M3x4 , + OPCODE_DX9_M3x3 , + OPCODE_DX9_M3x2 , + OPCODE_DX9_CALL , + OPCODE_DX9_CALLNZ , + OPCODE_DX9_LOOP , + OPCODE_DX9_RET , + OPCODE_DX9_ENDLOOP , + OPCODE_DX9_LABEL , + OPCODE_DX9_DCL , + OPCODE_DX9_POW , + OPCODE_DX9_CRS , + OPCODE_DX9_SGN , + OPCODE_DX9_ABS , + OPCODE_DX9_NRM , + OPCODE_DX9_SINCOS , + OPCODE_DX9_REP , + OPCODE_DX9_ENDREP , + OPCODE_DX9_IF , + OPCODE_DX9_IFC , + OPCODE_DX9_ELSE , + OPCODE_DX9_ENDIF , + OPCODE_DX9_BREAK , + OPCODE_DX9_BREAKC , + OPCODE_DX9_MOVA , + OPCODE_DX9_DEFB , + OPCODE_DX9_DEFI , + + OPCODE_DX9_TEXCOORD = 64, + OPCODE_DX9_TEXKILL , + OPCODE_DX9_TEX , + OPCODE_DX9_TEXBEM , + OPCODE_DX9_TEXBEML , + OPCODE_DX9_TEXREG2AR , + OPCODE_DX9_TEXREG2GB , + OPCODE_DX9_TEXM3x2PAD , + OPCODE_DX9_TEXM3x2TEX , + OPCODE_DX9_TEXM3x3PAD , + OPCODE_DX9_TEXM3x3TEX , + OPCODE_DX9_RESERVED0 , + OPCODE_DX9_TEXM3x3SPEC , + OPCODE_DX9_TEXM3x3VSPEC , + OPCODE_DX9_EXPP , + OPCODE_DX9_LOGP , + OPCODE_DX9_CND , + OPCODE_DX9_DEF , + OPCODE_DX9_TEXREG2RGB , + OPCODE_DX9_TEXDP3TEX , + OPCODE_DX9_TEXM3x2DEPTH , + OPCODE_DX9_TEXDP3 , + OPCODE_DX9_TEXM3x3 , + OPCODE_DX9_TEXDEPTH , + OPCODE_DX9_CMP , + OPCODE_DX9_BEM , + OPCODE_DX9_DP2ADD , + OPCODE_DX9_DSX , + OPCODE_DX9_DSY , + OPCODE_DX9_TEXLDD , + OPCODE_DX9_SETP , + OPCODE_DX9_TEXLDL , + OPCODE_DX9_BREAKP , + + OPCODE_DX9_PHASE = 0xFFFD, + OPCODE_DX9_COMMENT = 0xFFFE, + OPCODE_DX9_END = 0xFFFF, + + OPCODE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} OPCODE_TYPE_DX9; + +static OPCODE_TYPE_DX9 DecodeOpcodeTypeDX9(const uint32_t ui32Token) +{ + return (OPCODE_TYPE_DX9)(ui32Token & 0x0000FFFF); +} + +static uint32_t DecodeInstructionLengthDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x0F000000)>>24; +} + +static uint32_t DecodeCommentLengthDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x7FFF0000)>>16; +} + +static uint32_t DecodeOperandRegisterNumberDX9(const uint32_t ui32Token) +{ + return ui32Token & 0x000007FF; +} + +typedef enum +{ + OPERAND_TYPE_DX9_TEMP = 0, // Temporary Register File + OPERAND_TYPE_DX9_INPUT = 1, // Input Register File + OPERAND_TYPE_DX9_CONST = 2, // Constant Register File + OPERAND_TYPE_DX9_ADDR = 3, // Address Register (VS) + OPERAND_TYPE_DX9_TEXTURE = 3, // Texture Register File (PS) + OPERAND_TYPE_DX9_RASTOUT = 4, // Rasterizer Register File + OPERAND_TYPE_DX9_ATTROUT = 5, // Attribute Output Register File + OPERAND_TYPE_DX9_TEXCRDOUT = 6, // Texture Coordinate Output Register File + OPERAND_TYPE_DX9_OUTPUT = 6, // Output register file for VS3.0+ + OPERAND_TYPE_DX9_CONSTINT = 7, // Constant Integer Vector Register File + OPERAND_TYPE_DX9_COLOROUT = 8, // Color Output Register File + OPERAND_TYPE_DX9_DEPTHOUT = 9, // Depth Output Register File + OPERAND_TYPE_DX9_SAMPLER = 10, // Sampler State Register File + OPERAND_TYPE_DX9_CONST2 = 11, // Constant Register File 2048 - 4095 + OPERAND_TYPE_DX9_CONST3 = 12, // Constant Register File 4096 - 6143 + OPERAND_TYPE_DX9_CONST4 = 13, // Constant Register File 6144 - 8191 + OPERAND_TYPE_DX9_CONSTBOOL = 14, // Constant Boolean register file + OPERAND_TYPE_DX9_LOOP = 15, // Loop counter register file + OPERAND_TYPE_DX9_TEMPFLOAT16 = 16, // 16-bit float temp register file + OPERAND_TYPE_DX9_MISCTYPE = 17, // Miscellaneous (single) registers. + OPERAND_TYPE_DX9_LABEL = 18, // Label + OPERAND_TYPE_DX9_PREDICATE = 19, // Predicate register + OPERAND_TYPE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} OPERAND_TYPE_DX9; + +static OPERAND_TYPE_DX9 DecodeOperandTypeDX9(const uint32_t ui32Token) +{ + return (OPERAND_TYPE_DX9)(((ui32Token & 0x70000000) >> 28) | + ((ui32Token & 0x00001800) >> 8)); +} + +static uint32_t CreateOperandTokenDX9(const uint32_t ui32RegNum, const OPERAND_TYPE_DX9 eType) +{ + uint32_t ui32Token = ui32RegNum; + ASSERT(ui32RegNum <2048); + ui32Token |= (eType <<28) & 0x70000000; + ui32Token |= (eType <<8) & 0x00001800; + return ui32Token; +} + +typedef enum { + DECLUSAGE_POSITION = 0, + DECLUSAGE_BLENDWEIGHT = 1, + DECLUSAGE_BLENDINDICES = 2, + DECLUSAGE_NORMAL = 3, + DECLUSAGE_PSIZE = 4, + DECLUSAGE_TEXCOORD = 5, + DECLUSAGE_TANGENT = 6, + DECLUSAGE_BINORMAL = 7, + DECLUSAGE_TESSFACTOR = 8, + DECLUSAGE_POSITIONT = 9, + DECLUSAGE_COLOR = 10, + DECLUSAGE_FOG = 11, + DECLUSAGE_DEPTH = 12, + DECLUSAGE_SAMPLE = 13 +} DECLUSAGE_DX9; + +static DECLUSAGE_DX9 DecodeUsageDX9(const uint32_t ui32Token) +{ + return (DECLUSAGE_DX9) (ui32Token & 0x0000000f); +} + +static uint32_t DecodeUsageIndexDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x000f0000)>>16; +} + +static uint32_t DecodeOperandIsRelativeAddressModeDX9(const uint32_t ui32Token) +{ + return ui32Token & (1<<13); +} + +static const uint32_t DX9_SWIZZLE_SHIFT = 16; +#define NO_SWIZZLE_DX9 ((0<<DX9_SWIZZLE_SHIFT)|(1<<DX9_SWIZZLE_SHIFT)|(2<<DX9_SWIZZLE_SHIFT)|(3<<DX9_SWIZZLE_SHIFT)) + +#define REPLICATE_SWIZZLE_DX9(CHANNEL) ((CHANNEL<<DX9_SWIZZLE_SHIFT)|(CHANNEL<<(DX9_SWIZZLE_SHIFT+2))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+4))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+6))) + +static uint32_t DecodeOperandSwizzleDX9(const uint32_t ui32Token) +{ + return ui32Token & 0x00FF0000; +} + +static const uint32_t DX9_WRITEMASK_0 = 0x00010000; // Component 0 (X;Red) +static const uint32_t DX9_WRITEMASK_1 = 0x00020000; // Component 1 (Y;Green) +static const uint32_t DX9_WRITEMASK_2 = 0x00040000; // Component 2 (Z;Blue) +static const uint32_t DX9_WRITEMASK_3 = 0x00080000; // Component 3 (W;Alpha) +static const uint32_t DX9_WRITEMASK_ALL = 0x000F0000; // All Components + +static uint32_t DecodeDestWriteMaskDX9(const uint32_t ui32Token) +{ + return ui32Token & DX9_WRITEMASK_ALL; +} + +static RESOURCE_DIMENSION DecodeTextureTypeMaskDX9(const uint32_t ui32Token) +{ + + switch(ui32Token & 0x78000000) + { + case 2 << 27: + return RESOURCE_DIMENSION_TEXTURE2D; + case 3 << 27: + return RESOURCE_DIMENSION_TEXTURECUBE; + case 4 << 27: + return RESOURCE_DIMENSION_TEXTURE3D; + default: + return RESOURCE_DIMENSION_UNKNOWN; + } +} + + + +static const uint32_t DESTMOD_DX9_NONE = 0; +static const uint32_t DESTMOD_DX9_SATURATE = (1 << 20); +static const uint32_t DESTMOD_DX9_PARTIALPRECISION = (2 << 20); +static const uint32_t DESTMOD_DX9_MSAMPCENTROID = (4 << 20); +static uint32_t DecodeDestModifierDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xf00000; +} + +typedef enum +{ + SRCMOD_DX9_NONE = 0 << 24, + SRCMOD_DX9_NEG = 1 << 24, + SRCMOD_DX9_BIAS = 2 << 24, + SRCMOD_DX9_BIASNEG = 3 << 24, + SRCMOD_DX9_SIGN = 4 << 24, + SRCMOD_DX9_SIGNNEG = 5 << 24, + SRCMOD_DX9_COMP = 6 << 24, + SRCMOD_DX9_X2 = 7 << 24, + SRCMOD_DX9_X2NEG = 8 << 24, + SRCMOD_DX9_DZ = 9 << 24, + SRCMOD_DX9_DW = 10 << 24, + SRCMOD_DX9_ABS = 11 << 24, + SRCMOD_DX9_ABSNEG = 12 << 24, + SRCMOD_DX9_NOT = 13 << 24, + SRCMOD_DX9_FORCE_DWORD = 0xffffffff +} SRCMOD_DX9; +static uint32_t DecodeSrcModifierDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xf000000; +} + +typedef enum +{ + D3DSPC_RESERVED0 = 0, + D3DSPC_GT = 1, + D3DSPC_EQ = 2, + D3DSPC_GE = 3, + D3DSPC_LT = 4, + D3DSPC_NE = 5, + D3DSPC_LE = 6, + D3DSPC_BOOLEAN = 7, //Make use of the RESERVED1 bit to indicate if-bool opcode. +} COMPARISON_DX9; + +static COMPARISON_DX9 DecodeComparisonDX9(const uint32_t ui32Token) +{ + return (COMPARISON_DX9)((ui32Token & (0x07<<16))>>16); +} diff --git a/Code/Tools/HLSLCrossCompiler/src/reflect.c b/Code/Tools/HLSLCrossCompiler/src/reflect.c new file mode 100644 index 0000000000..66587c0152 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/reflect.c @@ -0,0 +1,1075 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/reflect.h" +#include "internal_includes/debug.h" +#include "internal_includes/decode.h" +#include "internal_includes/hlslcc_malloc.h" +#include "bstrlib.h" +#include <stdlib.h> +#include <stdio.h> + +static void FormatVariableName(char* Name) +{ + int i; + + /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx + The uniform function parameters appear in the + constant table prepended with a dollar sign ($), + unlike the global variables. The dollar sign is + required to avoid name collisions between local + uniform inputs and global variables of the same name.*/ + + /* Leave $ThisPointer, $Element and $Globals as-is. + Otherwise remove $ character ($ is not a valid character for GLSL variable names). */ + if(Name[0] == '$') + { + if(strcmp(Name, "$Element") !=0 && + strcmp(Name, "$Globals") != 0 && + strcmp(Name, "$ThisPointer") != 0) + { + Name[0] = '_'; + } + } + + // remove "__" because it's reserved in OpenGL + for (i = 0; Name[i] != '\0'; ++i) + { + if (Name[i] == '_' && Name[i + 1] == '_') + { + Name[i + 1] = 'x'; + } + } +} + +static void ReadStringFromTokenStream(const uint32_t* tokens, char* str) +{ + char* charTokens = (char*) tokens; + char nextCharacter = *charTokens++; + int length = 0; + + //Add each individual character until + //a terminator is found. + while(nextCharacter != 0) { + + str[length++] = nextCharacter; + + if(length > MAX_REFLECT_STRING_LENGTH) + { + str[length-1] = '\0'; + return; + } + + nextCharacter = *charTokens++; + } + + str[length] = '\0'; +} + +static void ReadInputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int extended) +{ + uint32_t i; + + InOutSignature* psSignatures; + const uint32_t* pui32FirstSignatureToken = pui32Tokens; + const uint32_t ui32ElementCount = *pui32Tokens++; + /* const uint32_t ui32Key = */ *pui32Tokens++; + + psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); + psShaderInfo->psInputSignatures = psSignatures; + psShaderInfo->ui32NumInputSignatures = ui32ElementCount; + + for(i=0; i<ui32ElementCount; ++i) + { + uint32_t ui32ComponentMasks; + InOutSignature* psCurrentSignature = psSignatures + i; + uint32_t ui32SemanticNameOffset; + + psCurrentSignature->ui32Stream = 0; + psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; + + if(extended) + psCurrentSignature->ui32Stream = *pui32Tokens++; + + ui32SemanticNameOffset = *pui32Tokens++; + psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; + psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++; + psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; + psCurrentSignature->ui32Register = *pui32Tokens++; + + ui32ComponentMasks = *pui32Tokens++; + psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; + //Shows which components are read + psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; + + if(extended) + psCurrentSignature->eMinPrec = *pui32Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); + } +} + +static void ReadOutputSignatures(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo, const int minPrec, const int streams) +{ + uint32_t i; + + InOutSignature* psSignatures; + const uint32_t* pui32FirstSignatureToken = pui32Tokens; + const uint32_t ui32ElementCount = *pui32Tokens++; + /* const uint32_t ui32Key = */ *pui32Tokens++; + + psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); + psShaderInfo->psOutputSignatures = psSignatures; + psShaderInfo->ui32NumOutputSignatures = ui32ElementCount; + + for(i=0; i<ui32ElementCount; ++i) + { + uint32_t ui32ComponentMasks; + InOutSignature* psCurrentSignature = psSignatures + i; + uint32_t ui32SemanticNameOffset; + + psCurrentSignature->ui32Stream = 0; + psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; + + if(streams) + psCurrentSignature->ui32Stream = *pui32Tokens++; + + ui32SemanticNameOffset = *pui32Tokens++; + psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; + psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; + psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; + psCurrentSignature->ui32Register = *pui32Tokens++; + + ui32ComponentMasks = *pui32Tokens++; + psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; + //Shows which components are NEVER written. + psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; + + if(minPrec) + psCurrentSignature->eMinPrec = *pui32Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken+ui32SemanticNameOffset), psCurrentSignature->SemanticName); + } +} + +static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding) +{ + uint32_t ui32NameOffset = *pui32Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken+ui32NameOffset), psBinding->Name); + FormatVariableName(psBinding->Name); + + psBinding->eType = *pui32Tokens++; + psBinding->ui32ReturnType = *pui32Tokens++; + psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++; + psBinding->ui32NumSamples = *pui32Tokens++; + psBinding->ui32BindPoint = *pui32Tokens++; + psBinding->ui32BindCount = *pui32Tokens++; + psBinding->ui32Flags = *pui32Tokens++; + + return pui32Tokens; +} + +//Read D3D11_SHADER_TYPE_DESC +static void ReadShaderVariableType(const uint32_t ui32MajorVersion, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32tokens, ShaderVarType* varType) +{ + const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens; + uint16_t ui32MemberCount; + uint32_t ui32MemberOffset; + const uint32_t* pui32MemberTokens; + uint32_t i; + + varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0]; + varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1]; + varType->Rows = pui16Tokens[2]; + varType->Columns = pui16Tokens[3]; + varType->Elements = pui16Tokens[4]; + + varType->MemberCount = ui32MemberCount = pui16Tokens[5]; + varType->Members = 0; + + if(ui32MemberCount) + { + varType->Members = (ShaderVarType*)hlslcc_malloc(sizeof(ShaderVarType)*ui32MemberCount); + + ui32MemberOffset = pui32tokens[3]; + + pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberOffset); + + for(i=0; i< ui32MemberCount; ++i) + { + uint32_t ui32NameOffset = *pui32MemberTokens++; + uint32_t ui32MemberTypeOffset = *pui32MemberTokens++; + + varType->Members[i].Parent = varType; + varType->Members[i].ParentCount = varType->ParentCount + 1; + + varType->Members[i].Offset = *pui32MemberTokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), varType->Members[i].Name); + + ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken, + (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32MemberTypeOffset), &varType->Members[i]); + } + } +} + +static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo, const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32Tokens, ConstantBuffer* psBuffer) +{ + uint32_t i; + uint32_t ui32NameOffset = *pui32Tokens++; + uint32_t ui32VarCount = *pui32Tokens++; + uint32_t ui32VarOffset = *pui32Tokens++; + const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32VarOffset); + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psBuffer->Name); + FormatVariableName(psBuffer->Name); + + psBuffer->ui32NumVars = ui32VarCount; + + for(i=0; i<ui32VarCount; ++i) + { + //D3D11_SHADER_VARIABLE_DESC + ShaderVar * const psVar = &psBuffer->asVars[i]; + + uint32_t ui32TypeOffset; + uint32_t ui32DefaultValueOffset; + + ui32NameOffset = *pui32VarToken++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken+ui32NameOffset), psVar->Name); + FormatVariableName(psVar->Name); + + psVar->ui32StartOffset = *pui32VarToken++; + psVar->ui32Size = *pui32VarToken++; + psVar->ui32Flags = *pui32VarToken++; + ui32TypeOffset = *pui32VarToken++; + + strcpy(psVar->sType.Name, psVar->Name); + psVar->sType.Parent = 0; + psVar->sType.ParentCount = 0; + psVar->sType.Offset = 0; + + ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken, + (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32TypeOffset), &psVar->sType); + + ui32DefaultValueOffset = *pui32VarToken++; + + + if (psShaderInfo->ui32MajorVersion >= 5) + { + /* uint32_t StartTexture = */ *pui32VarToken++; + /* uint32_t TextureSize = */ *pui32VarToken++; + /* uint32_t StartSampler = */ *pui32VarToken++; + /* uint32_t SamplerSize = */ *pui32VarToken++; + } + + psVar->haveDefaultValue = 0; + + if(ui32DefaultValueOffset) + { + const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4; + const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken+ui32DefaultValueOffset); + + //Always a sequence of 4-bytes at the moment. + //bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes. + ASSERT(psVar->ui32Size%4 == 0); + + psVar->haveDefaultValue = 1; + + psVar->pui32DefaultValues = hlslcc_malloc(psVar->ui32Size); + + for(uint32_t j=0; j<ui32NumDefaultValues;++j) + { + psVar->pui32DefaultValues[j] = pui32DefaultValToken[j]; + } + } + } + + + { + uint32_t ui32Flags; + uint32_t ui32BufferType; + + psBuffer->ui32TotalSizeInBytes = *pui32Tokens++; + psBuffer->blob = 0; + ui32Flags = *pui32Tokens++; + ui32BufferType = *pui32Tokens++; + } + + return pui32Tokens; +} + +static void ReadResources(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) +{ + ResourceBinding* psResBindings; + ConstantBuffer* psConstantBuffers; + const uint32_t* pui32ConstantBuffers; + const uint32_t* pui32ResourceBindings; + const uint32_t* pui32FirstToken = pui32Tokens; + uint32_t i; + + const uint32_t ui32NumConstantBuffers = *pui32Tokens++; + const uint32_t ui32ConstantBufferOffset = *pui32Tokens++; + + uint32_t ui32NumResourceBindings = *pui32Tokens++; + uint32_t ui32ResourceBindingOffset = *pui32Tokens++; + /* uint32_t ui32ShaderModel = */ *pui32Tokens++; + /* uint32_t ui32CompileFlags = */ *pui32Tokens++;//D3DCompile flags? http://msdn.microsoft.com/en-us/library/gg615083(v=vs.85).aspx + + //Resources + pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset); + + psResBindings = hlslcc_malloc(sizeof(ResourceBinding)*ui32NumResourceBindings); + + psShaderInfo->ui32NumResourceBindings = ui32NumResourceBindings; + psShaderInfo->psResourceBindings = psResBindings; + + for(i=0; i < ui32NumResourceBindings; ++i) + { + pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings+i); + ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS); + } + + //Constant buffers + pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset); + + psConstantBuffers = hlslcc_malloc(sizeof(ConstantBuffer) * ui32NumConstantBuffers); + + psShaderInfo->ui32NumConstantBuffers = ui32NumConstantBuffers; + psShaderInfo->psConstantBuffers = psConstantBuffers; + + for(i=0; i < ui32NumConstantBuffers; ++i) + { + pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers+i); + } + + + //Map resource bindings to constant buffers + if(psShaderInfo->ui32NumConstantBuffers) + { + for(i=0; i < ui32NumResourceBindings; ++i) + { + ResourceGroup eRGroup; + uint32_t cbufIndex = 0; + + eRGroup = ResourceTypeToResourceGroup(psResBindings[i].eType); + + //Find the constant buffer whose name matches the resource at the given resource binding point + for(cbufIndex=0; cbufIndex < psShaderInfo->ui32NumConstantBuffers; cbufIndex++) + { + if(strcmp(psConstantBuffers[cbufIndex].Name, psResBindings[i].Name) == 0) + { + psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex; + } + } + } + } +} + +static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType) +{ + const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens; + uint32_t ui32NameOffset = *pui32Tokens; + pui16Tokens+= 2; + + psClassType->ui16ID = *pui16Tokens++; + psClassType->ui16ConstBufStride = *pui16Tokens++; + psClassType->ui16Texture = *pui16Tokens++; + psClassType->ui16Sampler = *pui16Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassType->Name); + + return pui16Tokens; +} + +static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassInstance* psClassInstance) +{ + uint32_t ui32NameOffset = *pui16Tokens++ << 16; + ui32NameOffset |= *pui16Tokens++; + + psClassInstance->ui16ID = *pui16Tokens++; + psClassInstance->ui16ConstBuf = *pui16Tokens++; + psClassInstance->ui16ConstBufOffset = *pui16Tokens++; + psClassInstance->ui16Texture = *pui16Tokens++; + psClassInstance->ui16Sampler = *pui16Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32NameOffset), psClassInstance->Name); + + return pui16Tokens; +} + + +static void ReadInterfaces(const uint32_t* pui32Tokens, ShaderInfo* psShaderInfo) +{ + uint32_t i; + uint32_t ui32StartSlot; + const uint32_t* pui32FirstInterfaceToken = pui32Tokens; + const uint32_t ui32ClassInstanceCount = *pui32Tokens++; + const uint32_t ui32ClassTypeCount = *pui32Tokens++; + const uint32_t ui32InterfaceSlotRecordCount = *pui32Tokens++; + /* const uint32_t ui32InterfaceSlotCount = */ *pui32Tokens++; + const uint32_t ui32ClassInstanceOffset = *pui32Tokens++; + const uint32_t ui32ClassTypeOffset = *pui32Tokens++; + const uint32_t ui32InterfaceSlotOffset = *pui32Tokens++; + + const uint16_t* pui16ClassTypes = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassTypeOffset); + const uint16_t* pui16ClassInstances = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassInstanceOffset); + const uint32_t* pui32InterfaceSlots = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32InterfaceSlotOffset); + + const uint32_t* pui32InterfaceSlotTokens = pui32InterfaceSlots; + + ClassType* psClassTypes; + ClassInstance* psClassInstances; + + psClassTypes = hlslcc_malloc(sizeof(ClassType) * ui32ClassTypeCount); + for(i=0; i<ui32ClassTypeCount; ++i) + { + pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes+i); + psClassTypes[i].ui16ID = (uint16_t)i; + } + + psClassInstances = hlslcc_malloc(sizeof(ClassInstance) * ui32ClassInstanceCount); + for(i=0; i<ui32ClassInstanceCount; ++i) + { + pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances+i); + } + + //Slots map function table to $ThisPointer cbuffer variable index + ui32StartSlot = 0; + for(i=0; i<ui32InterfaceSlotRecordCount;++i) + { + uint32_t k; + + const uint32_t ui32SlotSpan = *pui32InterfaceSlotTokens++; + const uint32_t ui32Count = *pui32InterfaceSlotTokens++; + const uint32_t ui32TypeIDOffset = *pui32InterfaceSlotTokens++; + const uint32_t ui32TableIDOffset = *pui32InterfaceSlotTokens++; + + const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken+ui32TypeIDOffset); + const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken+ui32TableIDOffset); + + for(k=0; k < ui32Count; ++k) + { + psShaderInfo->aui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++; + } + + ui32StartSlot += ui32SlotSpan; + } + + psShaderInfo->ui32NumClassInstances = ui32ClassInstanceCount; + psShaderInfo->psClassInstances = psClassInstances; + + psShaderInfo->ui32NumClassTypes = ui32ClassTypeCount; + psShaderInfo->psClassTypes = psClassTypes; +} + +void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf) +{ + if(psShaderInfo->ui32MajorVersion > 3) + { + *ppsConstBuf = psShaderInfo->psConstantBuffers + psShaderInfo->aui32ResourceMap[eGroup][ui32BindPoint]; + } + else + { + ASSERT(psShaderInfo->ui32NumConstantBuffers == 1); + *ppsConstBuf = psShaderInfo->psConstantBuffers; + } +} + +int GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding) +{ + uint32_t i; + const uint32_t ui32NumBindings = psShaderInfo->ui32NumResourceBindings; + ResourceBinding* psBindings = psShaderInfo->psResourceBindings; + + for(i=0; i<ui32NumBindings; ++i) + { + if(ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup) + { + if(ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount)) + { + *ppsOutBinding = psBindings + i; + return 1; + } + } + } + return 0; +} + +int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar) +{ + uint32_t i; + ConstantBuffer* psThisPointerConstBuffer = psShaderInfo->psThisPointerConstBuffer; + + const uint32_t ui32NumVars = psThisPointerConstBuffer->ui32NumVars; + + for(i=0; i<ui32NumVars; ++i) + { + if(ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset && + ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size)) + { + *ppsShaderVar = &psThisPointerConstBuffer->asVars[i]; + return 1; + } + } + return 0; +} + +int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +{ + uint32_t i; + const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; + + for(i=0; i<ui32NumVars; ++i) + { + InOutSignature* psInputSignatures = psShaderInfo->psInputSignatures; + if(ui32Register == psInputSignatures[i].ui32Register) + { + *ppsOut = psInputSignatures+i; + return 1; + } + } + return 0; +} + +int GetOutputSignatureFromRegister(const uint32_t ui32Register, const uint32_t ui32CompMask, const uint32_t ui32Stream, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +{ + uint32_t i; + const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; + + for(i=0; i<ui32NumVars; ++i) + { + InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; + if(ui32Register == psOutputSignatures[i].ui32Register && + (ui32CompMask & psOutputSignatures[i].ui32Mask) && + ui32Stream == psOutputSignatures[i].ui32Stream) + { + *ppsOut = psOutputSignatures+i; + return 1; + } + } + return 0; +} + +int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +{ + uint32_t i; + const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; + + for(i=0; i<ui32NumVars; ++i) + { + InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; + if(eSystemValueType == psOutputSignatures[i].eSystemValueType && + ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex) + { + *ppsOut = psOutputSignatures+i; + return 1; + } + } + return 0; +} + +static int IsOffsetInType(ShaderVarType* psType, uint32_t parentOffset, uint32_t offsetToFind, const uint32_t* pui32Swizzle, int32_t* pi32Index, int32_t* pi32Rebase) +{ + uint32_t thisOffset = parentOffset + psType->Offset; + uint32_t thisSize = psType->Columns * psType->Rows * 4; + + if(psType->Elements) + { + thisSize += 16 * (psType->Elements - 1); + } + + //Swizzle can point to another variable. In the example below + //cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined + //into vectors. psCBuf->ui32NumVars will be 3. + + // cbuffer cbUIUpdates + // { + // + // float g_fLifeSpan; // Offset: 0 Size: 4 + // float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused] + // float g_fRadiusMin; // Offset: 8 Size: 4 [unused] + // float g_fRadiusMax; // Offset: 12 Size: 4 [unused] + // float g_fGrowTime; // Offset: 16 Size: 4 [unused] + // float g_fStepSize; // Offset: 20 Size: 4 + // float g_fTurnRate; // Offset: 24 Size: 4 + // float g_fTurnSpeed; // Offset: 28 Size: 4 [unused] + // float g_fLeafRate; // Offset: 32 Size: 4 + // float g_fShrinkTime; // Offset: 36 Size: 4 [unused] + // uint g_uMaxFaces; // Offset: 40 Size: 4 + // + // } + + // Name Type Format Dim Slot Elements + // ------------------------------ ---------- ------- ----------- ---- -------- + // cbUIUpdates cbuffer NA NA 1 1 + + if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + offsetToFind += 4; + } + else + if(pui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + offsetToFind += 8; + } + else + if(pui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + offsetToFind += 12; + } + + if((offsetToFind >= thisOffset) && + offsetToFind < (thisOffset + thisSize)) + { + + if(psType->Class == SVC_MATRIX_ROWS || + psType->Class == SVC_MATRIX_COLUMNS) + { + //Matrices are treated as arrays of vectors. + pi32Index[0] = (offsetToFind - thisOffset) / 16; + } + //Check for array of vectors + else if(psType->Class == SVC_VECTOR && psType->Elements > 1) + { + pi32Index[0] = (offsetToFind - thisOffset) / 16; + } + else if(psType->Class == SVC_VECTOR && psType->Columns > 1) + { + //Check for vector starting at a non-vec4 offset. + + // cbuffer $Globals + // { + // + // float angle; // Offset: 0 Size: 4 + // float2 angle2; // Offset: 4 Size: 8 + // + // } + + //cb0[0].x = angle + //cb0[0].yzyy = angle2.xyxx + + //Rebase angle2 so that .y maps to .x, .z maps to .y + + pi32Rebase[0] = thisOffset % 16; + } + + return 1; + } + return 0; +} + +int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, const uint32_t* pui32Swizzle, ConstantBuffer* psCBuf, ShaderVarType** ppsShaderVar, int32_t* pi32Index, int32_t* pi32Rebase) +{ + uint32_t i; + + uint32_t ui32ByteOffset = ui32Vec4Offset * 16; + + const uint32_t ui32NumVars = psCBuf->ui32NumVars; + + for(i=0; i<ui32NumVars; ++i) + { + if(psCBuf->asVars[i].sType.Class == SVC_STRUCT) + { + uint32_t m = 0; + + for(m=0; m < psCBuf->asVars[i].sType.MemberCount; ++m) + { + ShaderVarType* psMember = psCBuf->asVars[i].sType.Members + m; + + ASSERT(psMember->Class != SVC_STRUCT); + + if(IsOffsetInType(psMember, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) + { + ppsShaderVar[0] = psMember; + return 1; + } + } + } + else + { + if(IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) + { + ppsShaderVar[0] = &psCBuf->asVars[i].sType; + return 1; + } + } + } + return 0; +} + +ResourceGroup ResourceTypeToResourceGroup(ResourceType eType) +{ + switch(eType) + { + case RTYPE_CBUFFER: + return RGROUP_CBUFFER; + + case RTYPE_SAMPLER: + return RGROUP_SAMPLER; + + case RTYPE_TEXTURE: + case RTYPE_BYTEADDRESS: + case RTYPE_STRUCTURED: + return RGROUP_TEXTURE; + + case RTYPE_UAV_RWTYPED: + case RTYPE_UAV_RWSTRUCTURED: + case RTYPE_UAV_RWBYTEADDRESS: + case RTYPE_UAV_APPEND_STRUCTURED: + case RTYPE_UAV_CONSUME_STRUCTURED: + case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: + return RGROUP_UAV; + + case RTYPE_TBUFFER: + ASSERT(0); // Need to find out which group this belongs to + return RGROUP_TEXTURE; + } + + ASSERT(0); + return RGROUP_CBUFFER; +} + +void LoadShaderInfo(const uint32_t ui32MajorVersion, const uint32_t ui32MinorVersion, const ReflectionChunks* psChunks, ShaderInfo* psInfo) +{ + uint32_t i; + const uint32_t* pui32Inputs = psChunks->pui32Inputs; + const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11; + const uint32_t* pui32Resources = psChunks->pui32Resources; + const uint32_t* pui32Interfaces = psChunks->pui32Interfaces; + const uint32_t* pui32Outputs = psChunks->pui32Outputs; + const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11; + const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams; + + psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED; + psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED; + for(i=0; i<MAX_SHADER_VEC4_INPUT;++i) + psInfo->aePixelInputInterpolation[i] = INTERPOLATION_LINEAR; + + psInfo->ui32MajorVersion = ui32MajorVersion; + psInfo->ui32MinorVersion = ui32MinorVersion; + + psInfo->ui32NumImports = 0; + psInfo->ui32NumExports = 0; + psInfo->psImports = 0; + psInfo->psExports = 0; + psInfo->ui32InputHash = 0; + psInfo->ui32SymbolsOffset = 0; + psInfo->ui32NumSamplers = 0; + + if(pui32Inputs) + ReadInputSignatures(pui32Inputs, psInfo, 0); + if(pui32Inputs11) + ReadInputSignatures(pui32Inputs11, psInfo, 1); + if(pui32Resources) + ReadResources(pui32Resources, psInfo); + if(pui32Interfaces) + ReadInterfaces(pui32Interfaces, psInfo); + if(pui32Outputs) + ReadOutputSignatures(pui32Outputs, psInfo, 0, 0); + if(pui32Outputs11) + ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1); + if(pui32OutputsWithStreams) + ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1); + + for(i=0; i<psInfo->ui32NumConstantBuffers;++i) + { + bstring cbufName = bfromcstr(&psInfo->psConstantBuffers[i].Name[0]); + bstring cbufThisPointer = bfromcstr("$ThisPointer"); + if(bstrcmp(cbufName, cbufThisPointer) == 0) + { + psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i]; + } + bdestroy(cbufName); + bdestroy(cbufThisPointer); + } + + memset(psInfo->asSamplers, 0, sizeof(psInfo->asSamplers)); +} + +void FreeShaderInfo(ShaderInfo* psShaderInfo) +{ + uint32_t uStep; + //Free any default values for constants. + uint32_t cbuf; + for(cbuf=0; cbuf<psShaderInfo->ui32NumConstantBuffers; ++cbuf) + { + ConstantBuffer* psCBuf = &psShaderInfo->psConstantBuffers[cbuf]; + uint32_t var; + for(var=0; var < psCBuf->ui32NumVars; ++var) + { + ShaderVar* psVar = &psCBuf->asVars[var]; + hlslcc_free(psVar->sType.Members); + if(psVar->haveDefaultValue) + { + hlslcc_free(psVar->pui32DefaultValues); + } + } + } + hlslcc_free(psShaderInfo->psInputSignatures); + hlslcc_free(psShaderInfo->psResourceBindings); + hlslcc_free(psShaderInfo->psConstantBuffers); + hlslcc_free(psShaderInfo->psClassTypes); + hlslcc_free(psShaderInfo->psClassInstances); + hlslcc_free(psShaderInfo->psOutputSignatures); + hlslcc_free(psShaderInfo->psImports); + hlslcc_free(psShaderInfo->psExports); + + for (uStep = 0; uStep < psShaderInfo->ui32NumTraceSteps; ++uStep) + { + hlslcc_free(psShaderInfo->psTraceSteps[uStep].psVariables); + } + hlslcc_free(psShaderInfo->psTraceSteps); + + psShaderInfo->ui32NumInputSignatures = 0; + psShaderInfo->ui32NumResourceBindings = 0; + psShaderInfo->ui32NumConstantBuffers = 0; + psShaderInfo->ui32NumClassTypes = 0; + psShaderInfo->ui32NumClassInstances = 0; + psShaderInfo->ui32NumOutputSignatures = 0; + psShaderInfo->ui32NumTraceSteps = 0; + psShaderInfo->ui32NumImports = 0; + psShaderInfo->ui32NumExports = 0; +} + +typedef struct ConstantTableD3D9_TAG +{ + uint32_t size; + uint32_t creator; + uint32_t version; + uint32_t constants; + uint32_t constantInfos; + uint32_t flags; + uint32_t target; +} ConstantTableD3D9; + +// These enums match those in d3dx9shader.h. +enum RegisterSet +{ + RS_BOOL, + RS_INT4, + RS_FLOAT4, + RS_SAMPLER, +}; + +enum TypeClass +{ + CLASS_SCALAR, + CLASS_VECTOR, + CLASS_MATRIX_ROWS, + CLASS_MATRIX_COLUMNS, + CLASS_OBJECT, + CLASS_STRUCT, +}; + +enum Type +{ + PT_VOID, + PT_BOOL, + PT_INT, + PT_FLOAT, + PT_STRING, + PT_TEXTURE, + PT_TEXTURE1D, + PT_TEXTURE2D, + PT_TEXTURE3D, + PT_TEXTURECUBE, + PT_SAMPLER, + PT_SAMPLER1D, + PT_SAMPLER2D, + PT_SAMPLER3D, + PT_SAMPLERCUBE, + PT_PIXELSHADER, + PT_VERTEXSHADER, + PT_PIXELFRAGMENT, + PT_VERTEXFRAGMENT, + PT_UNSUPPORTED, +}; +typedef struct ConstantInfoD3D9_TAG +{ + uint32_t name; + uint16_t registerSet; + uint16_t registerIndex; + uint16_t registerCount; + uint16_t reserved; + uint32_t typeInfo; + uint32_t defaultValue; +} ConstantInfoD3D9; + +typedef struct TypeInfoD3D9_TAG +{ + uint16_t typeClass; + uint16_t type; + uint16_t rows; + uint16_t columns; + uint16_t elements; + uint16_t structMembers; + uint32_t structMemberInfos; +} TypeInfoD3D9; + +typedef struct StructMemberInfoD3D9_TAG +{ + uint32_t name; + uint32_t typeInfo; +} StructMemberInfoD3D9; + +void LoadD3D9ConstantTable(const char* data, ShaderInfo* psInfo) +{ + ConstantTableD3D9* ctab; + uint32_t constNum; + ConstantInfoD3D9* cinfos; + ConstantBuffer* psConstantBuffer; + uint32_t ui32ConstantBufferSize = 0; + uint32_t numResourceBindingsNeeded = 0; + ShaderVar* var; + + ctab = (ConstantTableD3D9*)data; + + cinfos = (ConstantInfoD3D9*)(data + ctab->constantInfos); + + psInfo->ui32NumConstantBuffers++; + + //Only 1 Constant Table in d3d9 + ASSERT(psInfo->ui32NumConstantBuffers == 1); + + psConstantBuffer = hlslcc_malloc(sizeof(ConstantBuffer)); + + psInfo->psConstantBuffers = psConstantBuffer; + + psConstantBuffer->ui32NumVars = 0; + strcpy(psConstantBuffer->Name, "$Globals"); + + //Determine how many resource bindings to create + for (constNum = 0; constNum < ctab->constants; ++constNum) + { + if (cinfos[constNum].registerSet == RS_SAMPLER) + { + ++numResourceBindingsNeeded; + } + } + + psInfo->psResourceBindings = hlslcc_malloc(numResourceBindingsNeeded * sizeof(ResourceBinding)); + + var = &psConstantBuffer->asVars[0]; + + for (constNum = 0; constNum < ctab->constants; ++constNum) + { + TypeInfoD3D9* typeInfo = (TypeInfoD3D9*)(data + cinfos[constNum].typeInfo); + + if (cinfos[constNum].registerSet != RS_SAMPLER) + { + strcpy(var->Name, data + cinfos[constNum].name); + FormatVariableName(var->Name); + var->ui32Size = cinfos[constNum].registerCount * 16; + var->ui32StartOffset = cinfos[constNum].registerIndex * 16; + var->haveDefaultValue = 0; + + if (ui32ConstantBufferSize < (var->ui32Size + var->ui32StartOffset)) + { + ui32ConstantBufferSize = var->ui32Size + var->ui32StartOffset; + } + + var->sType.Rows = typeInfo->rows; + var->sType.Columns = typeInfo->columns; + var->sType.Elements = typeInfo->elements; + var->sType.MemberCount = typeInfo->structMembers; + var->sType.Members = 0; + var->sType.Offset = 0; + var->sType.Parent = 0; + var->sType.ParentCount = 0; + + switch (typeInfo->typeClass) + { + case CLASS_SCALAR: + { + var->sType.Class = SVC_SCALAR; + break; + } + case CLASS_VECTOR: + { + var->sType.Class = SVC_VECTOR; + break; + } + case CLASS_MATRIX_ROWS: + { + var->sType.Class = SVC_MATRIX_ROWS; + break; + } + case CLASS_MATRIX_COLUMNS: + { + var->sType.Class = SVC_MATRIX_COLUMNS; + break; + } + case CLASS_OBJECT: + { + var->sType.Class = SVC_OBJECT; + break; + } + case CLASS_STRUCT: + { + var->sType.Class = SVC_STRUCT; + break; + } + } + + switch (cinfos[constNum].registerSet) + { + case RS_BOOL: + { + var->sType.Type = SVT_BOOL; + break; + } + case RS_INT4: + { + var->sType.Type = SVT_INT; + break; + } + case RS_FLOAT4: + { + var->sType.Type = SVT_FLOAT; + break; + } + } + + var++; + psConstantBuffer->ui32NumVars++; + } + else + { + //Create a resource if it is sampler in order to replicate the d3d10+ + //method of separating samplers from general constants. + uint32_t ui32ResourceIndex = psInfo->ui32NumResourceBindings++; + ResourceBinding* res = &psInfo->psResourceBindings[ui32ResourceIndex]; + + strcpy(res->Name, data + cinfos[constNum].name); + FormatVariableName(res->Name); + + res->ui32BindPoint = cinfos[constNum].registerIndex; + res->ui32BindCount = cinfos[constNum].registerCount; + res->ui32Flags = 0; + res->ui32NumSamples = 1; + res->ui32ReturnType = 0; + + res->eType = RTYPE_TEXTURE; + + switch (typeInfo->type) + { + case PT_SAMPLER: + case PT_SAMPLER1D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE1D; + break; + case PT_SAMPLER2D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; + break; + case PT_SAMPLER3D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; + break; + case PT_SAMPLERCUBE: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURECUBE; + break; + } + } + } + psConstantBuffer->ui32TotalSizeInBytes = ui32ConstantBufferSize; +} diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSL.c b/Code/Tools/HLSLCrossCompiler/src/toGLSL.c new file mode 100644 index 0000000000..ff1546b703 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/toGLSL.c @@ -0,0 +1,1921 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/tokens.h" +#include "internal_includes/structs.h" +#include "internal_includes/decode.h" +#include "stdlib.h" +#include "stdio.h" +#include "bstrlib.h" +#include "internal_includes/toGLSLInstruction.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/toGLSLDeclaration.h" +#include "internal_includes/languages.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/hlslccToolkit.h" +#include "../offline/hash.h" + +#if defined(_WIN32) && !defined(PORTABLE) +#include <AzCore/PlatformDef.h> +AZ_PUSH_DISABLE_WARNING(4115, "-Wunknown-warning-option") // 4115: named type definition in parentheses +#include <d3dcompiler.h> +AZ_POP_DISABLE_WARNING +#pragma comment(lib,"d3dcompiler.lib") +#endif //defined(_WIN32) && !defined(PORTABLE) + +#ifndef GL_VERTEX_SHADER_ARB +#define GL_VERTEX_SHADER_ARB 0x8B31 +#endif +#ifndef GL_FRAGMENT_SHADER_ARB +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#endif +#ifndef GL_GEOMETRY_SHADER +#define GL_GEOMETRY_SHADER 0x8DD9 +#endif +#ifndef GL_TESS_EVALUATION_SHADER +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#endif +#ifndef GL_TESS_CONTROL_SHADER +#define GL_TESS_CONTROL_SHADER 0x8E88 +#endif +#ifndef GL_COMPUTE_SHADER +#define GL_COMPUTE_SHADER 0x91B9 +#endif + + +HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), void* (*calloc_override)(size_t, size_t), void (* free_override)(void*), void* (*realloc_override)(void*, size_t)) +{ + hlslcc_malloc = malloc_override; + hlslcc_calloc = calloc_override; + hlslcc_free = free_override; + hlslcc_realloc = realloc_override; +} + +void AddIndentation(HLSLCrossCompilerContext* psContext) +{ + int i; + int indent = psContext->indent; + bstring glsl = *psContext->currentGLSLString; + for (i = 0; i < indent; ++i) + { + bcatcstr(glsl, " "); + } +} + +uint32_t AddImport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Default) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t ui32Symbol = psContext->psShader->sInfo.ui32NumImports; + + psContext->psShader->sInfo.psImports = (Symbol*)hlslcc_realloc(psContext->psShader->sInfo.psImports, (ui32Symbol + 1) * sizeof(Symbol)); + ++psContext->psShader->sInfo.ui32NumImports; + + bformata(glsl, "#ifndef IMPORT_%d\n", ui32Symbol); + bformata(glsl, "#define IMPORT_%d %d\n", ui32Symbol, ui32Default); + bformata(glsl, "#endif\n", ui32Symbol); + + psContext->psShader->sInfo.psImports[ui32Symbol].eType = eType; + psContext->psShader->sInfo.psImports[ui32Symbol].ui32ID = ui32ID; + psContext->psShader->sInfo.psImports[ui32Symbol].ui32Value = ui32Default; + + return ui32Symbol; +} + +uint32_t AddExport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Value) +{ + uint32_t ui32Param = psContext->psShader->sInfo.ui32NumExports; + + psContext->psShader->sInfo.psExports = (Symbol*)hlslcc_realloc(psContext->psShader->sInfo.psExports, (ui32Param + 1) * sizeof(Symbol)); + ++psContext->psShader->sInfo.ui32NumExports; + + psContext->psShader->sInfo.psExports[ui32Param].eType = eType; + psContext->psShader->sInfo.psExports[ui32Param].ui32ID = ui32ID; + psContext->psShader->sInfo.psExports[ui32Param].ui32Value = ui32Value; + + return ui32Param; +} + +void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t ui32DepthClampImp; + + if (!HaveCompute(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->eShaderType == COMPUTE_SHADER) + { + bcatcstr(glsl, "#extension GL_ARB_compute_shader : enable\n"); + bcatcstr(glsl, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); + } + } + + if (!HaveAtomicMem(psContext->psShader->eTargetLanguage) || + !HaveAtomicCounter(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_ALLOC] || + psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_CONSUME] || + psContext->psShader->aiOpcodeUsed[OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED]) + { + bcatcstr(glsl, "#extension GL_ARB_shader_atomic_counters : enable\n"); + + bcatcstr(glsl, "#extension GL_ARB_shader_storage_buffer_object : enable\n"); + } + } + + if (!HaveGather(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_C]) + { + bcatcstr(glsl, "#extension GL_ARB_texture_gather : enable\n"); + } + } + + if (!HaveGatherNonConstOffset(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO]) + { + bcatcstr(glsl, "#extension GL_ARB_gpu_shader5 : enable\n"); + } + } + + if (!HaveQueryLod(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_LOD]) + { + bcatcstr(glsl, "#extension GL_ARB_texture_query_lod : enable\n"); + } + } + + if (!HaveQueryLevels(psContext->psShader->eTargetLanguage)) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_RESINFO]) + { + bcatcstr(glsl, "#extension GL_ARB_texture_query_levels : enable\n"); + } + } + + if (!HaveImageLoadStore(psContext->psShader->eTargetLanguage) && (psContext->flags & HLSLCC_FLAG_AVOID_SHADER_LOAD_STORE_EXTENSION) == 0) + { + if (psContext->psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] || + psContext->psShader->aiOpcodeUsed[OPCODE_STORE_RAW] || + psContext->psShader->aiOpcodeUsed[OPCODE_STORE_STRUCTURED]) + { + bcatcstr(glsl, "#extension GL_ARB_shader_image_load_store : enable\n"); + bcatcstr(glsl, "#extension GL_ARB_shader_bit_encoding : enable\n"); + } + else + if (psContext->psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] || + psContext->psShader->aiOpcodeUsed[OPCODE_LD_RAW] || + psContext->psShader->aiOpcodeUsed[OPCODE_LD_STRUCTURED]) + { + bcatcstr(glsl, "#extension GL_ARB_shader_image_load_store : enable\n"); + } + } + + + // #extension directive must occur before any non-preprocessor token + if (EmulateDepthClamp(psContext->psShader->eTargetLanguage) && (psContext->psShader->eShaderType == VERTEX_SHADER || psContext->psShader->eShaderType == PIXEL_SHADER)) + { + ui32DepthClampImp = AddImport(psContext, SYMBOL_EMULATE_DEPTH_CLAMP, 0, 0); + + bformata(glsl, "#if IMPORT_%d > 0\n", ui32DepthClampImp); + if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#ifdef GL_NV_shader_noperspective_interpolation\n"); + bcatcstr(glsl, "#extension GL_NV_shader_noperspective_interpolation:enable\n"); + bformata(glsl, "#endif\n"); + } + bformata(glsl, "#endif\n"); + } + + if (psContext->psShader->ui32MajorVersion <= 3) + { + bcatcstr(glsl, "int RepCounter;\n"); + bcatcstr(glsl, "int LoopCounter;\n"); + bcatcstr(glsl, "int ZeroBasedCounter;\n"); + if (psContext->psShader->eShaderType == VERTEX_SHADER) + { + uint32_t texCoord; + bcatcstr(glsl, "ivec4 Address;\n"); + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "out vec4 OffsetColour;\n"); + bcatcstr(glsl, "out vec4 BaseColour;\n"); + + bcatcstr(glsl, "out vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "out vec4 TexCoord%d;\n", texCoord); + } + } + else + { + bcatcstr(glsl, "varying vec4 OffsetColour;\n"); + bcatcstr(glsl, "varying vec4 BaseColour;\n"); + + bcatcstr(glsl, "varying vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); + } + } + } + else + { + uint32_t renderTargets, texCoord; + + bcatcstr(glsl, "varying vec4 OffsetColour;\n"); + bcatcstr(glsl, "varying vec4 BaseColour;\n"); + + bcatcstr(glsl, "varying vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); + } + + for (renderTargets = 0; renderTargets < 8; ++renderTargets) + { + bformata(glsl, "#define Output%d gl_FragData[%d]\n", renderTargets, renderTargets); + } + } + } + + + if ((psContext->flags & HLSLCC_FLAG_ORIGIN_UPPER_LEFT) + && (psContext->psShader->eTargetLanguage >= LANG_150) + && (psContext->psShader->eShaderType == PIXEL_SHADER)) + { + bcatcstr(glsl, "layout(origin_upper_left) in vec4 gl_FragCoord;\n"); + } + + if ((psContext->flags & HLSLCC_FLAG_PIXEL_CENTER_INTEGER) + && (psContext->psShader->eTargetLanguage >= LANG_150)) + { + bcatcstr(glsl, "layout(pixel_center_integer) in vec4 gl_FragCoord;\n"); + } + + /* For versions which do not support a vec1 (currently all versions) */ + bcatcstr(glsl, "struct vec1 {\n"); + if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310 || psContext->psShader->eTargetLanguage == LANG_ES_100) + { + bcatcstr(glsl, "\thighp float x;\n"); + } + else + { + bcatcstr(glsl, "\tfloat x;\n"); + } + bcatcstr(glsl, "};\n"); + + if (HaveUVec(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "struct uvec1 {\n"); + bcatcstr(glsl, "\tuint x;\n"); + bcatcstr(glsl, "};\n"); + } + + bcatcstr(glsl, "struct ivec1 {\n"); + bcatcstr(glsl, "\tint x;\n"); + bcatcstr(glsl, "};\n"); + + /* + OpenGL 4.1 API spec: + To use any built-in input or output in the gl_PerVertex block in separable + program objects, shader code must redeclare that block prior to use. + */ + if (psContext->psShader->eShaderType == VERTEX_SHADER && psContext->psShader->eTargetLanguage >= LANG_410) + { + bcatcstr(glsl, "out gl_PerVertex {\n"); + bcatcstr(glsl, "vec4 gl_Position;\n"); + bcatcstr(glsl, "float gl_PointSize;\n"); + bcatcstr(glsl, "float gl_ClipDistance[];"); + bcatcstr(glsl, "};\n"); + } + + //The fragment language has no default precision qualifier for floating point types. + if (psContext->psShader->eShaderType == PIXEL_SHADER && + psContext->psShader->eTargetLanguage == LANG_ES_100 || psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision highp float;\n"); + } + + /* There is no default precision qualifier for the following sampler types in either the vertex or fragment language: */ + if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision lowp sampler3D;\n"); + bcatcstr(glsl, "precision lowp samplerCubeShadow;\n"); + bcatcstr(glsl, "precision lowp sampler2DShadow;\n"); + bcatcstr(glsl, "precision lowp sampler2DArray;\n"); + bcatcstr(glsl, "precision lowp sampler2DArrayShadow;\n"); + bcatcstr(glsl, "precision lowp isampler2D;\n"); + bcatcstr(glsl, "precision lowp isampler3D;\n"); + bcatcstr(glsl, "precision lowp isamplerCube;\n"); + bcatcstr(glsl, "precision lowp isampler2DArray;\n"); + bcatcstr(glsl, "precision lowp usampler2D;\n"); + bcatcstr(glsl, "precision lowp usampler3D;\n"); + bcatcstr(glsl, "precision lowp usamplerCube;\n"); + bcatcstr(glsl, "precision lowp usampler2DArray;\n"); + + if (psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision lowp isampler2DMS;\n"); + bcatcstr(glsl, "precision lowp usampler2D;\n"); + bcatcstr(glsl, "precision lowp usampler3D;\n"); + bcatcstr(glsl, "precision lowp usamplerCube;\n"); + bcatcstr(glsl, "precision lowp usampler2DArray;\n"); + bcatcstr(glsl, "precision lowp usampler2DMS;\n"); + bcatcstr(glsl, "precision lowp image2D;\n"); + bcatcstr(glsl, "precision lowp image3D;\n"); + bcatcstr(glsl, "precision lowp imageCube;\n"); + bcatcstr(glsl, "precision lowp image2DArray;\n"); + bcatcstr(glsl, "precision lowp iimage2D;\n"); + bcatcstr(glsl, "precision lowp iimage3D;\n"); + bcatcstr(glsl, "precision lowp iimageCube;\n"); + bcatcstr(glsl, "precision lowp uimage2DArray;\n"); + //Only highp is valid for atomic_uint + bcatcstr(glsl, "precision highp atomic_uint;\n"); + } + } + + if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "subroutine void SubroutineType();\n"); + } + + if (EmulateDepthClamp(psContext->psShader->eTargetLanguage) && (psContext->psShader->eShaderType == VERTEX_SHADER || psContext->psShader->eShaderType == PIXEL_SHADER)) + { + char* szInOut = psContext->psShader->eShaderType == VERTEX_SHADER ? "out" : "in"; + + bformata(glsl, "#if IMPORT_%d > 0\n", ui32DepthClampImp); + if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#ifdef GL_NV_shader_noperspective_interpolation\n"); + } + bcatcstr(glsl, "#define EMULATE_DEPTH_CLAMP 1\n"); + bformata(glsl, "noperspective %s float unclampedDepth;\n", szInOut); + if (!HaveNoperspectiveInterpolation(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#else\n"); + bcatcstr(glsl, "#define EMULATE_DEPTH_CLAMP 2\n"); + bformata(glsl, "%s float unclampedZ;\n", szInOut); + bformata(glsl, "#endif\n"); + } + bformata(glsl, "#endif\n"); + + if (psContext->psShader->eShaderType == PIXEL_SHADER) + { + bcatcstr(psContext->earlyMain, "#ifdef EMULATE_DEPTH_CLAMP\n"); + bcatcstr(psContext->earlyMain, "#if EMULATE_DEPTH_CLAMP == 2\n"); + bcatcstr(psContext->earlyMain, "\tfloat unclampedDepth = gl_DepthRange.near + unclampedZ * gl_FragCoord.w;\n"); + bcatcstr(psContext->earlyMain, "#endif\n"); + bcatcstr(psContext->earlyMain, "\tgl_FragDepth = clamp(unclampedDepth, 0.0, 1.0);\n"); + bcatcstr(psContext->earlyMain, "#endif\n"); + } + } +} + +FRAMEBUFFER_FETCH_TYPE CollectGmemInfo(HLSLCrossCompilerContext* psContext) +{ + FRAMEBUFFER_FETCH_TYPE fetchType = FBF_NONE; + Shader* psShader = psContext->psShader; + memset(psContext->rendertargetUse, 0x00, sizeof(psContext->rendertargetUse)); + for (uint32_t i = 0; i < psShader->ui32DeclCount; ++i) + { + Declaration* decl = psShader->psDecl + i; + if (decl->eOpcode == OPCODE_DCL_RESOURCE) + { + if (IsGmemReservedSlot(FBF_EXT_COLOR, decl->asOperands[0].ui32RegisterNumber)) + { + int regNum = GetGmemInputResourceSlot(decl->asOperands[0].ui32RegisterNumber); + ASSERT(regNum < MAX_COLOR_MRT); + psContext->rendertargetUse[regNum] |= INPUT_RENDERTARGET; + fetchType |= FBF_EXT_COLOR; + } + else if (IsGmemReservedSlot(FBF_ARM_COLOR, decl->asOperands[0].ui32RegisterNumber)) + { + fetchType |= FBF_ARM_COLOR; + } + else if (IsGmemReservedSlot(FBF_ARM_DEPTH, decl->asOperands[0].ui32RegisterNumber)) + { + fetchType |= FBF_ARM_DEPTH; + } + else if (IsGmemReservedSlot(FBF_ARM_STENCIL, decl->asOperands[0].ui32RegisterNumber)) + { + fetchType |= FBF_ARM_STENCIL; + } + } + else if (decl->eOpcode == OPCODE_DCL_OUTPUT && psShader->eShaderType == PIXEL_SHADER && decl->asOperands[0].eType != OPERAND_TYPE_OUTPUT_DEPTH) + { + ASSERT(decl->asOperands[0].ui32RegisterNumber < MAX_COLOR_MRT); + psContext->rendertargetUse[decl->asOperands[0].ui32RegisterNumber] |= OUTPUT_RENDERTARGET; + } + } + + return fetchType; +} + +uint16_t GetOpcodeWriteMask(OPCODE_TYPE eOpcode) +{ + switch (eOpcode) + { + default: + ASSERT(0); + + // No writes + case OPCODE_ENDREP: + case OPCODE_REP: + case OPCODE_BREAK: + case OPCODE_BREAKC: + case OPCODE_CALL: + case OPCODE_CALLC: + case OPCODE_CASE: + case OPCODE_CONTINUE: + case OPCODE_CONTINUEC: + case OPCODE_CUT: + case OPCODE_DISCARD: + case OPCODE_ELSE: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_ENDIF: + case OPCODE_ENDLOOP: + case OPCODE_ENDSWITCH: + case OPCODE_IF: + case OPCODE_LABEL: + case OPCODE_LOOP: + case OPCODE_NOP: + case OPCODE_RET: + case OPCODE_RETC: + case OPCODE_SWITCH: + case OPCODE_HS_DECLS: + case OPCODE_HS_CONTROL_POINT_PHASE: + case OPCODE_HS_FORK_PHASE: + case OPCODE_HS_JOIN_PHASE: + case OPCODE_EMIT_STREAM: + case OPCODE_CUT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + case OPCODE_INTERFACE_CALL: + case OPCODE_STORE_UAV_TYPED: + case OPCODE_STORE_RAW: + case OPCODE_STORE_STRUCTURED: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_UMIN: + case OPCODE_SYNC: + case OPCODE_ABORT: + case OPCODE_DEBUG_BREAK: + return 0; + + // Write to 0 + case OPCODE_POW: + case OPCODE_DP2ADD: + case OPCODE_LRP: + case OPCODE_ADD: + case OPCODE_AND: + case OPCODE_DERIV_RTX: + case OPCODE_DERIV_RTY: + case OPCODE_DEFAULT: + case OPCODE_DIV: + case OPCODE_DP2: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_EXP: + case OPCODE_FRC: + case OPCODE_ITOF: + case OPCODE_LOG: + case OPCODE_LT: + case OPCODE_MAD: + case OPCODE_MIN: + case OPCODE_MAX: + case OPCODE_MUL: + case OPCODE_ROUND_NE: + case OPCODE_ROUND_NI: + case OPCODE_ROUND_PI: + case OPCODE_ROUND_Z: + case OPCODE_RSQ: + case OPCODE_SQRT: + case OPCODE_UTOF: + case OPCODE_SAMPLE_POS: + case OPCODE_SAMPLE_INFO: + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_RCP: + case OPCODE_F32TOF16: + case OPCODE_F16TOF32: + case OPCODE_DTOF: + case OPCODE_EQ: + case OPCODE_FTOU: + case OPCODE_GE: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_NE: + case OPCODE_NOT: + case OPCODE_OR: + case OPCODE_ULT: + case OPCODE_UGE: + case OPCODE_UMAD: + case OPCODE_XOR: + case OPCODE_UMAX: + case OPCODE_UMIN: + case OPCODE_USHR: + case OPCODE_COUNTBITS: + case OPCODE_FIRSTBIT_HI: + case OPCODE_FIRSTBIT_LO: + case OPCODE_FIRSTBIT_SHI: + case OPCODE_UBFE: + case OPCODE_BFI: + case OPCODE_BFREV: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_MSAD: + case OPCODE_DTOU: + case OPCODE_FTOI: + case OPCODE_IADD: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_BUFINFO: + case OPCODE_IBFE: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_DTOI: + case OPCODE_DADD: + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_FTOD: + case OPCODE_DDIV: + case OPCODE_DFMA: + case OPCODE_DRCP: + case OPCODE_ITOD: + case OPCODE_UTOD: + case OPCODE_LD: + case OPCODE_LD_MS: + case OPCODE_RESINFO: + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_D: + case OPCODE_SAMPLE_B: + case OPCODE_LOD: + case OPCODE_GATHER4: + case OPCODE_GATHER4_C: + case OPCODE_GATHER4_PO: + case OPCODE_GATHER4_PO_C: + case OPCODE_LD_UAV_TYPED: + case OPCODE_LD_RAW: + case OPCODE_LD_STRUCTURED: + case OPCODE_EVAL_SNAPPED: + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_CENTROID: + case OPCODE_MOV: + case OPCODE_MOVC: + return 1u << 0; + + // Write to 0, 1 + case OPCODE_SINCOS: + case OPCODE_UDIV: + case OPCODE_UMUL: + case OPCODE_UADDC: + case OPCODE_USUBB: + case OPCODE_SWAPC: + return (1u << 0) | (1u << 1); + } +} + +void CreateTracingInfo(Shader* psShader) +{ + VariableTraceInfo asInputVarsInfo[MAX_SHADER_VEC4_INPUT * 4]; + uint32_t ui32NumInputVars = 0; + uint32_t uInputVec, uInstruction; + + psShader->sInfo.ui32NumTraceSteps = psShader->ui32InstCount + 1; + psShader->sInfo.psTraceSteps = hlslcc_malloc(sizeof(StepTraceInfo) * psShader->sInfo.ui32NumTraceSteps); + + for (uInputVec = 0; uInputVec < psShader->sInfo.ui32NumInputSignatures; ++uInputVec) + { + uint32_t ui32RWMask = psShader->sInfo.psInputSignatures[uInputVec].ui32ReadWriteMask; + uint8_t ui8Component = 0; + + while (ui32RWMask != 0) + { + if (ui32RWMask & 1) + { + TRACE_VARIABLE_TYPE eType; + switch (psShader->sInfo.psInputSignatures[uInputVec].eComponentType) + { + default: + ASSERT(0); + case INOUT_COMPONENT_UNKNOWN: + case INOUT_COMPONENT_UINT32: + eType = TRACE_VARIABLE_UINT; + break; + case INOUT_COMPONENT_SINT32: + eType = TRACE_VARIABLE_SINT; + break; + case INOUT_COMPONENT_FLOAT32: + eType = TRACE_VARIABLE_FLOAT; + break; + } + + asInputVarsInfo[ui32NumInputVars].eGroup = TRACE_VARIABLE_INPUT; + asInputVarsInfo[ui32NumInputVars].eType = eType; + asInputVarsInfo[ui32NumInputVars].ui8Index = psShader->sInfo.psInputSignatures[uInputVec].ui32Register; + asInputVarsInfo[ui32NumInputVars].ui8Component = ui8Component; + ++ui32NumInputVars; + } + ui32RWMask >>= 1; + ++ui8Component; + } + } + + psShader->sInfo.psTraceSteps[0].ui32NumVariables = ui32NumInputVars; + psShader->sInfo.psTraceSteps[0].psVariables = hlslcc_malloc(sizeof(VariableTraceInfo) * ui32NumInputVars); + memcpy(psShader->sInfo.psTraceSteps[0].psVariables, asInputVarsInfo, sizeof(VariableTraceInfo) * ui32NumInputVars); + + for (uInstruction = 0; uInstruction < psShader->ui32InstCount; ++uInstruction) + { + VariableTraceInfo* psStepVars = NULL; + uint32_t ui32StepVarsCapacity = 0; + uint32_t ui32StepVarsSize = 0; + uint32_t auStepDirtyVecMask[MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT] = {0}; + uint8_t auStepCompTypeMask[4 * (MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT)] = {0}; + uint32_t uOpcodeWriteMask = GetOpcodeWriteMask(psShader->psInst[uInstruction].eOpcode); + uint32_t uOperand, uStepVec; + + for (uOperand = 0; uOperand < psShader->psInst[uInstruction].ui32NumOperands; ++uOperand) + { + if (uOpcodeWriteMask & (1 << uOperand)) + { + uint32_t ui32OperandCompMask = ConvertOperandSwizzleToComponentMask(&psShader->psInst[uInstruction].asOperands[uOperand]); + uint32_t ui32Register = psShader->psInst[uInstruction].asOperands[uOperand].ui32RegisterNumber; + uint32_t ui32VecOffset = 0; + uint8_t ui8Component = 0; + switch (psShader->psInst[uInstruction].asOperands[uOperand].eType) + { + case OPERAND_TYPE_TEMP: + ui32VecOffset = 0; + break; + case OPERAND_TYPE_OUTPUT: + ui32VecOffset = MAX_TEMP_VEC4; + break; + default: + continue; + } + + auStepDirtyVecMask[ui32VecOffset + ui32Register] |= ui32OperandCompMask; + while (ui32OperandCompMask) + { + ASSERT(ui8Component < 4); + if (ui32OperandCompMask & 1) + { + TRACE_VARIABLE_TYPE eOperandCompType = TRACE_VARIABLE_UNKNOWN; + switch (psShader->psInst[uInstruction].asOperands[uOperand].aeDataType[ui8Component]) + { + case SVT_INT: + eOperandCompType = TRACE_VARIABLE_SINT; + break; + case SVT_FLOAT: + eOperandCompType = TRACE_VARIABLE_FLOAT; + break; + case SVT_UINT: + eOperandCompType = TRACE_VARIABLE_UINT; + break; + case SVT_DOUBLE: + eOperandCompType = TRACE_VARIABLE_DOUBLE; + break; + } + if (auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] == 0) + { + auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] = 1u + (uint8_t)eOperandCompType; + } + else if (auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] != eOperandCompType) + { + auStepCompTypeMask[4 * (ui32VecOffset + ui32Register) + ui8Component] = 1u + (uint8_t)TRACE_VARIABLE_UNKNOWN; + } + } + ui32OperandCompMask >>= 1; + ++ui8Component; + } + } + } + + for (uStepVec = 0; uStepVec < MAX_TEMP_VEC4 + MAX_SHADER_VEC4_OUTPUT; ++uStepVec) + { + TRACE_VARIABLE_GROUP eGroup; + uint32_t uBase; + uint8_t ui8Component = 0; + if (uStepVec < MAX_TEMP_VEC4) + { + eGroup = TRACE_VARIABLE_TEMP; + uBase = 0; + } + else + { + eGroup = TRACE_VARIABLE_OUTPUT; + uBase = MAX_TEMP_VEC4; + } + + while (auStepDirtyVecMask[uStepVec] != 0) + { + if (auStepDirtyVecMask[uStepVec] & 1) + { + if (ui32StepVarsCapacity == ui32StepVarsSize) + { + ui32StepVarsCapacity = (1 > ui32StepVarsCapacity ? 1 : ui32StepVarsCapacity) * 16; + if (psStepVars == NULL) + { + psStepVars = hlslcc_malloc(ui32StepVarsCapacity * sizeof(VariableTraceInfo)); + } + else + { + psStepVars = hlslcc_realloc(psStepVars, ui32StepVarsCapacity * sizeof(VariableTraceInfo)); + } + } + ASSERT(ui32StepVarsSize < ui32StepVarsCapacity); + + psStepVars[ui32StepVarsSize].eGroup = eGroup; + psStepVars[ui32StepVarsSize].eType = auStepCompTypeMask[4 * uStepVec + ui8Component] == 0 ? TRACE_VARIABLE_UNKNOWN : (TRACE_VARIABLE_TYPE)(auStepCompTypeMask[4 * uStepVec + ui8Component] - 1); + psStepVars[ui32StepVarsSize].ui8Component = ui8Component; + psStepVars[ui32StepVarsSize].ui8Index = uStepVec - uBase; + ++ui32StepVarsSize; + } + + ++ui8Component; + auStepDirtyVecMask[uStepVec] >>= 1; + } + } + + psShader->sInfo.psTraceSteps[1 + uInstruction].ui32NumVariables = ui32StepVarsSize; + psShader->sInfo.psTraceSteps[1 + uInstruction].psVariables = psStepVars; + } +} + +void WriteTraceDeclarations(HLSLCrossCompilerContext* psContext) +{ + bstring glsl = *psContext->currentGLSLString; + + AddIndentation(psContext); + bcatcstr(glsl, "layout (std430) buffer Trace\n"); + AddIndentation(psContext); + bcatcstr(glsl, "{\n"); + ++psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceSize;\n"); + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceStride;\n"); + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceCapacity;\n"); + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + AddIndentation(psContext); + bcatcstr(glsl, "float fTracePixelCoordX;\n"); + AddIndentation(psContext); + bcatcstr(glsl, "float fTracePixelCoordY;\n"); + break; + case VERTEX_SHADER: + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceVertexID;\n"); + break; + default: + AddIndentation(psContext); + bcatcstr(glsl, "// Trace ID not implelemented for this shader type\n"); + break; + } + AddIndentation(psContext); + bcatcstr(glsl, "uint auTraceValues[];\n"); + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "};\n"); +} + +void WritePreStepsTrace(HLSLCrossCompilerContext* psContext, StepTraceInfo* psStep) +{ + uint32_t uVar; + bstring glsl = *psContext->currentGLSLString; + + AddIndentation(psContext); + bcatcstr(glsl, "bool bRecord = "); + switch (psContext->psShader->eShaderType) + { + case VERTEX_SHADER: + bcatcstr(glsl, "uint(gl_VertexID) == uTraceVertexID"); + break; + case PIXEL_SHADER: + bcatcstr(glsl, "max(abs(gl_FragCoord.x - fTracePixelCoordX), abs(gl_FragCoord.y - fTracePixelCoordY)) <= 0.5"); + break; + default: + bcatcstr(glsl, "/* Trace condition not implelemented for this shader type */"); + bcatcstr(glsl, "false"); + break; + } + bcatcstr(glsl, ";\n"); + + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceIndex = atomicAdd(uTraceSize, uTraceStride * (bRecord ? 1 : 0));\n"); + AddIndentation(psContext); + bcatcstr(glsl, "uint uTraceEnd = uTraceIndex + uTraceStride;\n"); + AddIndentation(psContext); + bcatcstr(glsl, "bRecord = bRecord && uTraceEnd <= uTraceCapacity;\n"); + AddIndentation(psContext); + bcatcstr(glsl, "uTraceEnd *= (bRecord ? 1 : 0);\n"); + + if (psStep->ui32NumVariables > 0) + { + AddIndentation(psContext); + bformata(glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = uint(0);\n"); // Adreno can't handle 0u (it's treated as int) + + for (uVar = 0; uVar < psStep->ui32NumVariables; ++uVar) + { + VariableTraceInfo* psVar = &psStep->psVariables[uVar]; + ASSERT(psVar->eGroup == TRACE_VARIABLE_INPUT); + if (psVar->eGroup == TRACE_VARIABLE_INPUT) + { + AddIndentation(psContext); + bcatcstr(glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = "); + + switch (psVar->eType) + { + case TRACE_VARIABLE_FLOAT: + bcatcstr(glsl, "floatBitsToUint("); + break; + case TRACE_VARIABLE_SINT: + bcatcstr(glsl, "uint("); + break; + case TRACE_VARIABLE_DOUBLE: + ASSERT(0); + // Not implemented yet; + break; + } + + bformata(glsl, "Input%d.%c", psVar->ui8Index, "xyzw"[psVar->ui8Component]); + + switch (psVar->eType) + { + case TRACE_VARIABLE_FLOAT: + case TRACE_VARIABLE_SINT: + bcatcstr(glsl, ")"); + break; + } + + bcatcstr(glsl, ";\n"); + } + } + } +} + +void WritePostStepTrace(HLSLCrossCompilerContext* psContext, uint32_t uStep) +{ + Instruction* psInstruction = psContext->psShader->psInst + uStep; + StepTraceInfo* psStep = psContext->psShader->sInfo.psTraceSteps + (1 + uStep); + + if (psStep->ui32NumVariables > 0) + { + uint32_t uVar; + + AddIndentation(psContext); + bformata(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = %du;\n", uStep + 1); + + for (uVar = 0; uVar < psStep->ui32NumVariables; ++uVar) + { + VariableTraceInfo* psVar = &psStep->psVariables[uVar]; + uint16_t uOpcodeWriteMask = GetOpcodeWriteMask(psInstruction->eOpcode); + uint8_t uOperand = 0; + OPERAND_TYPE eOperandType = OPERAND_TYPE_NULL; + Operand* psOperand = NULL; + uint32_t uiIgnoreSwizzle = 0; + + switch (psVar->eGroup) + { + case TRACE_VARIABLE_TEMP: + eOperandType = OPERAND_TYPE_TEMP; + break; + case TRACE_VARIABLE_OUTPUT: + eOperandType = OPERAND_TYPE_OUTPUT; + break; + } + + if (psVar->eType == TRACE_VARIABLE_DOUBLE) + { + ASSERT(0); + // Not implemented yet + continue; + } + while (uOpcodeWriteMask) + { + if (uOpcodeWriteMask & 1) + { + if (eOperandType == psInstruction->asOperands[uOperand].eType && + psVar->ui8Index == psInstruction->asOperands[uOperand].ui32RegisterNumber) + { + psOperand = &psInstruction->asOperands[uOperand]; + break; + } + } + uOpcodeWriteMask >>= 1; + ++uOperand; + } + + if (psOperand == NULL) + { + ASSERT(0); + continue; + } + + AddIndentation(psContext); + bcatcstr(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = "); + + TranslateVariableName(psContext, psOperand, TO_FLAG_UNSIGNED_INTEGER, &uiIgnoreSwizzle); + ASSERT(uiIgnoreSwizzle == 0); + + bformata(psContext->glsl, ".%c;\n", "xyzw"[psVar->ui8Component]); + } + } +} + +void WriteEndTrace(HLSLCrossCompilerContext* psContext) +{ + AddIndentation(psContext); + bcatcstr(psContext->glsl, "auTraceValues[min(++uTraceIndex, uTraceEnd)] = 0xFFFFFFFFu;\n"); +} + +int FindEmbeddedResourceName(EmbeddedResourceName* psEmbeddedName, HLSLCrossCompilerContext* psContext, bstring name) +{ + int offset = binstr(psContext->glsl, 0, name); + int size = name->slen; + + if (offset == BSTR_ERR || size > 0x3FF || offset > 0x7FFFF) + { + return 0; + } + + psEmbeddedName->ui20Offset = offset; + psEmbeddedName->ui12Size = size; + return 1; +} + +void IgnoreSampler(ShaderInfo* psInfo, uint32_t index) +{ + if (index + 1 < psInfo->ui32NumSamplers) + { + psInfo->asSamplers[index] = psInfo->asSamplers[psInfo->ui32NumSamplers - 1]; + } + --psInfo->ui32NumSamplers; +} + +void IgnoreResource(Resource* psResources, uint32_t* puSize, uint32_t index) +{ + if (index + 1 < *puSize) + { + psResources[index] = psResources[*puSize - 1]; + } + --*puSize; +} + +void FillInResourceDescriptions(HLSLCrossCompilerContext* psContext) +{ + uint32_t i; + bstring resourceName = bfromcstralloc(MAX_REFLECT_STRING_LENGTH, ""); + Shader* psShader = psContext->psShader; + + for (i = 0; i < psShader->sInfo.ui32NumSamplers; ++i) + { + Sampler* psSampler = psShader->sInfo.asSamplers + i; + SamplerMask* psMask = &psSampler->sMask; + if (psMask->bNormalSample || psMask->bCompareSample) + { + if (psMask->bNormalSample) + { + btrunc(resourceName, 0); + TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 0); + if (!FindEmbeddedResourceName(&psSampler->sNormalName, psContext, resourceName)) + { + psMask->bNormalSample = 0; + } + } + if (psMask->bCompareSample) + { + btrunc(resourceName, 0); + TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 1); + if (!FindEmbeddedResourceName(&psSampler->sCompareName, psContext, resourceName)) + { + psMask->bCompareSample = 0; + } + } + if (!psMask->bNormalSample && !psMask->bCompareSample) + { + IgnoreSampler(&psShader->sInfo, i); // Not used in the shader - ignore + } + } + else + { + btrunc(resourceName, 0); + TextureName(resourceName, psShader, psMask->ui10TextureBindPoint, psMask->ui10SamplerBindPoint, 0); + if (!FindEmbeddedResourceName(&psSampler->sNormalName, psContext, resourceName)) + { + IgnoreSampler(&psShader->sInfo, i); // Not used in the shader - ignore + } + } + } + + for (i = 0; i < psShader->sInfo.ui32NumImages; ++i) + { + Resource* psResources = psShader->sInfo.asImages; + uint32_t* puSize = &psShader->sInfo.ui32NumImages; + + Resource* psResource = psResources + i; + ResourceBinding* psBinding = NULL; + if (!GetResourceFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psBinding)) + { + ASSERT(0); + IgnoreResource(psResources, puSize, i); + } + + btrunc(resourceName, 0); + ConvertToUAVName(resourceName, psShader, psBinding->Name); + if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) + { + IgnoreResource(psResources, puSize, i); + } + } + + for (i = 0; i < psShader->sInfo.ui32NumUniformBuffers; ++i) + { + Resource* psResources = psShader->sInfo.asUniformBuffers; + uint32_t* puSize = &psShader->sInfo.ui32NumUniformBuffers; + + Resource* psResource = psResources + i; + ConstantBuffer* psCB = NULL; + GetConstantBufferFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psCB); + + btrunc(resourceName, 0); + ConvertToUniformBufferName(resourceName, psShader, psCB->Name); + if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) + { + IgnoreResource(psResources, puSize, i); + } + } + + for (i = 0; i < psShader->sInfo.ui32NumStorageBuffers; ++i) + { + Resource* psResources = psShader->sInfo.asStorageBuffers; + uint32_t* puSize = &psShader->sInfo.ui32NumStorageBuffers; + + Resource* psResource = psResources + i; + ConstantBuffer* psCB = NULL; + GetConstantBufferFromBindingPoint(psResource->eGroup, psResource->ui32BindPoint, &psShader->sInfo, &psCB); + + btrunc(resourceName, 0); + if (psResource->eGroup == RGROUP_UAV) + { + ConvertToUAVName(resourceName, psShader, psCB->Name); + } + else + { + ConvertToTextureName(resourceName, psShader, psCB->Name, NULL, 0); + } + if (!FindEmbeddedResourceName(&psResource->sName, psContext, resourceName)) + { + IgnoreResource(psResources, puSize, i); + } + } + + bdestroy(resourceName); +} + +GLLang ChooseLanguage(Shader* psShader) +{ + // Depends on the HLSL shader model extracted from bytecode. + switch (psShader->ui32MajorVersion) + { + case 5: + { + return LANG_430; + } + case 4: + { + return LANG_330; + } + default: + { + return LANG_120; + } + } +} + +const char* GetVersionString(GLLang language) +{ + switch (language) + { + case LANG_ES_100: + { + return "#version 100\n"; + break; + } + case LANG_ES_300: + { + return "#version 300 es\n"; + break; + } + case LANG_ES_310: + { + return "#version 310 es\n"; + break; + } + case LANG_120: + { + return "#version 120\n"; + break; + } + case LANG_130: + { + return "#version 130\n"; + break; + } + case LANG_140: + { + return "#version 140\n"; + break; + } + case LANG_150: + { + return "#version 150\n"; + break; + } + case LANG_330: + { + return "#version 330\n"; + break; + } + case LANG_400: + { + return "#version 400\n"; + break; + } + case LANG_410: + { + return "#version 410\n"; + break; + } + case LANG_420: + { + return "#version 420\n"; + break; + } + case LANG_430: + { + return "#version 430\n"; + break; + } + case LANG_440: + { + return "#version 440\n"; + break; + } + default: + { + return ""; + break; + } + } +} + +// Force precision of vertex output position to highp. +// Using mediump or lowp for the position of the vertex can cause rendering artifacts in OpenGL ES. +void ForcePositionOutputToHighp(Shader* shader) +{ + // Only sensible in vertex shaders + if (shader->eShaderType != VERTEX_SHADER) + { + return; + } + + // Find the output position declaration + Declaration* posDeclaration = NULL; + for (uint32_t i = 0; i < shader->ui32DeclCount; ++i) + { + Declaration* decl = shader->psDecl + i; + if (decl->eOpcode == OPCODE_DCL_OUTPUT_SIV) + { + if (decl->asOperands[0].eSpecialName == NAME_POSITION) + { + posDeclaration = decl; + break; + } + + if (decl->asOperands[0].eSpecialName != NAME_UNDEFINED) + { + continue; + } + + // This might be SV_Position (because d3dcompiler is weird). Get signature and check + InOutSignature *sig = NULL; + GetOutputSignatureFromRegister(decl->asOperands[0].ui32RegisterNumber, decl->asOperands[0].ui32CompMask, 0, &shader->sInfo, &sig); + ASSERT(sig != NULL); + if ((sig->eSystemValueType == NAME_POSITION || strcmp(sig->SemanticName, "POS") == 0) && sig->ui32SemanticIndex == 0) + { + sig->eMinPrec = MIN_PRECISION_DEFAULT; + posDeclaration = decl; + break; + } + } + else if (decl->eOpcode == OPCODE_DCL_OUTPUT) + { + InOutSignature *sig = NULL; + GetOutputSignatureFromRegister(decl->asOperands[0].ui32RegisterNumber, decl->asOperands[0].ui32CompMask, 0, &shader->sInfo, &sig); + ASSERT(sig != NULL); + if ((sig->eSystemValueType == NAME_POSITION || strcmp(sig->SemanticName, "POS") == 0) && sig->ui32SemanticIndex == 0) + { + sig->eMinPrec = MIN_PRECISION_DEFAULT; + posDeclaration = decl; + break; + } + } + } + + // Do nothing if we don't find suitable output. This may well be INTERNALTESSPOS for tessellation etc. + if (!posDeclaration) + { + return; + } + + posDeclaration->asOperands[0].eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; + posDeclaration->asOperands[0].eSpecialName = NAME_POSITION; + // Go through all the instructions and update the operand. + for (uint32_t i = 0; i < shader->ui32InstCount; ++i) + { + Instruction *inst = shader->psInst + i; + for (uint32_t j = 0; j < inst->ui32FirstSrc; ++j) + { + Operand op = inst->asOperands[j]; + // Since it's an output declaration we know that there's only one + // operand and it's in the first slot. + if (op.eType == OPERAND_TYPE_OUTPUT && op.ui32RegisterNumber == posDeclaration->asOperands[0].ui32RegisterNumber) + { + op.eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; + op.eSpecialName = NAME_POSITION; + } + } + } +} + +void TranslateToGLSL(HLSLCrossCompilerContext* psContext, GLLang* planguage, const GlExtensions* extensions) +{ + bstring glsl; + uint32_t i; + Shader* psShader = psContext->psShader; + GLLang language = *planguage; + const uint32_t ui32InstCount = psShader->ui32InstCount; + const uint32_t ui32DeclCount = psShader->ui32DeclCount; + + psContext->indent = 0; + + if (language == LANG_DEFAULT) + { + language = ChooseLanguage(psShader); + *planguage = language; + } + + glsl = bfromcstralloc (1024, ""); + if (!(psContext->flags & HLSLCC_FLAG_NO_VERSION_STRING)) + { + bcatcstr(glsl, GetVersionString(language)); + } + + if (psContext->flags & HLSLCC_FLAG_ADD_DEBUG_HEADER) + { + bstring version = glsl; + glsl = psContext->debugHeader; + bconcat(glsl, version); + bdestroy(version); + } + + psContext->glsl = glsl; + psContext->earlyMain = bfromcstralloc (1024, ""); + for (i = 0; i < NUM_PHASES; ++i) + { + psContext->postShaderCode[i] = bfromcstralloc (1024, ""); + } + + psContext->currentGLSLString = &glsl; + psShader->eTargetLanguage = language; + psShader->extensions = (const struct GlExtensions*)extensions; + psContext->currentPhase = MAIN_PHASE; + + if (extensions) + { + if (extensions->ARB_explicit_attrib_location) + { + bcatcstr(glsl, "#extension GL_ARB_explicit_attrib_location : require\n"); + } + if (extensions->ARB_explicit_uniform_location) + { + bcatcstr(glsl, "#extension GL_ARB_explicit_uniform_location : require\n"); + } + if (extensions->ARB_shading_language_420pack) + { + bcatcstr(glsl, "#extension GL_ARB_shading_language_420pack : require\n"); + } + } + + psContext->psShader->sInfo.ui32SymbolsOffset = blength(glsl); + + FRAMEBUFFER_FETCH_TYPE fetchType = CollectGmemInfo(psContext); + if (fetchType & FBF_EXT_COLOR) + { + bcatcstr(glsl, "#extension GL_EXT_shader_framebuffer_fetch : require\n"); + } + if (fetchType & FBF_ARM_COLOR) + { + bcatcstr(glsl, "#extension GL_ARM_shader_framebuffer_fetch : require\n"); + } + if (fetchType & (FBF_ARM_DEPTH | FBF_ARM_STENCIL)) + { + bcatcstr(glsl, "#extension GL_ARM_shader_framebuffer_fetch_depth_stencil : require\n"); + } + psShader->eGmemType = fetchType; + + AddVersionDependentCode(psContext); + + if (psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) + { + bcatcstr(glsl, "layout(std140) uniform;\n"); + } + + //Special case. Can have multiple phases. + if (psShader->eShaderType == HULL_SHADER) + { + int haveInstancedForkPhase = 0; + uint32_t forkIndex = 0; + + ConsolidateHullTempVars(psShader); + + for (i = 0; i < psShader->ui32HSDeclCount; ++i) + { + TranslateDeclaration(psContext, psShader->psHSDecl + i); + } + + //control + psContext->currentPhase = HS_CTRL_POINT_PHASE; + + if (psShader->ui32HSControlPointDeclCount) + { + bcatcstr(glsl, "//Control point phase declarations\n"); + for (i = 0; i < psShader->ui32HSControlPointDeclCount; ++i) + { + TranslateDeclaration(psContext, psShader->psHSControlPointPhaseDecl + i); + } + } + + if (psShader->ui32HSControlPointInstrCount) + { + SetDataTypes(psContext, psShader->psHSControlPointPhaseInstr, psShader->ui32HSControlPointInstrCount, NULL); + + bcatcstr(glsl, "void control_point_phase()\n{\n"); + psContext->indent++; + + for (i = 0; i < psShader->ui32HSControlPointInstrCount; ++i) + { + TranslateInstruction(psContext, psShader->psHSControlPointPhaseInstr + i); + } + psContext->indent--; + bcatcstr(glsl, "}\n"); + } + + //fork + psContext->currentPhase = HS_FORK_PHASE; + for (forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) + { + bcatcstr(glsl, "//Fork phase declarations\n"); + for (i = 0; i < psShader->aui32HSForkDeclCount[forkIndex]; ++i) + { + TranslateDeclaration(psContext, psShader->apsHSForkPhaseDecl[forkIndex] + i); + if (psShader->apsHSForkPhaseDecl[forkIndex][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) + { + haveInstancedForkPhase = 1; + } + } + + bformata(glsl, "void fork_phase%d()\n{\n", forkIndex); + psContext->indent++; + + SetDataTypes(psContext, psShader->apsHSForkPhaseInstr[forkIndex], psShader->aui32HSForkInstrCount[forkIndex] - 1, NULL); + + if (haveInstancedForkPhase) + { + AddIndentation(psContext); + bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", forkIndex); + psContext->indent++; + } + + //The minus one here is remove the return statement at end of phases. + //This is needed otherwise the for loop will only run once. + ASSERT(psShader->apsHSForkPhaseInstr[forkIndex][psShader->aui32HSForkInstrCount[forkIndex] - 1].eOpcode == OPCODE_RET); + for (i = 0; i < psShader->aui32HSForkInstrCount[forkIndex] - 1; ++i) + { + TranslateInstruction(psContext, psShader->apsHSForkPhaseInstr[forkIndex] + i); + } + + if (haveInstancedForkPhase) + { + psContext->indent--; + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + } + } + + psContext->indent--; + bcatcstr(glsl, "}\n"); + } + + + //join + psContext->currentPhase = HS_JOIN_PHASE; + if (psShader->ui32HSJoinDeclCount) + { + bcatcstr(glsl, "//Join phase declarations\n"); + for (i = 0; i < psShader->ui32HSJoinDeclCount; ++i) + { + TranslateDeclaration(psContext, psShader->psHSJoinPhaseDecl + i); + } + } + + if (psShader->ui32HSJoinInstrCount) + { + SetDataTypes(psContext, psShader->psHSJoinPhaseInstr, psShader->ui32HSJoinInstrCount, NULL); + + bcatcstr(glsl, "void join_phase()\n{\n"); + psContext->indent++; + + for (i = 0; i < psShader->ui32HSJoinInstrCount; ++i) + { + TranslateInstruction(psContext, psShader->psHSJoinPhaseInstr + i); + } + + psContext->indent--; + bcatcstr(glsl, "}\n"); + } + + bcatcstr(glsl, "void main()\n{\n"); + + psContext->indent++; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Start Early Main ---\n"); +#endif + bconcat(glsl, psContext->earlyMain); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End Early Main ---\n"); +#endif + + if (psShader->ui32HSControlPointInstrCount) + { + AddIndentation(psContext); + bcatcstr(glsl, "control_point_phase();\n"); + + if (psShader->ui32ForkPhaseCount || psShader->ui32HSJoinInstrCount) + { + AddIndentation(psContext); + bcatcstr(glsl, "barrier();\n"); + } + } + for (forkIndex = 0; forkIndex < psShader->ui32ForkPhaseCount; ++forkIndex) + { + AddIndentation(psContext); + bformata(glsl, "fork_phase%d();\n", forkIndex); + + if (psShader->ui32HSJoinInstrCount || (forkIndex + 1 < psShader->ui32ForkPhaseCount)) + { + AddIndentation(psContext); + bcatcstr(glsl, "barrier();\n"); + } + } + if (psShader->ui32HSJoinInstrCount) + { + AddIndentation(psContext); + bcatcstr(glsl, "join_phase();\n"); + } + + psContext->indent--; + + bcatcstr(glsl, "}\n"); + + return; + } + + if (psShader->eShaderType == DOMAIN_SHADER) + { + uint32_t ui32TessOutPrimImp = AddImport(psContext, SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE, 0, (uint32_t)TESSELLATOR_OUTPUT_TRIANGLE_CCW); + uint32_t ui32TessPartitioningImp = AddImport(psContext, SYMBOL_TESSELLATOR_PARTITIONING, 0, (uint32_t)TESSELLATOR_PARTITIONING_INTEGER); + + bformata(glsl, "#if IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_POINT); + bcatcstr(glsl, "layout(point_mode) in;\n"); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_LINE); + bcatcstr(glsl, "layout(isolines) in;\n"); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessOutPrimImp, (uint32_t)TESSELLATOR_OUTPUT_TRIANGLE_CW); + bcatcstr(glsl, "layout(cw) in;\n"); + bcatcstr(glsl, "#endif\n"); + + bformata(glsl, "#if IMPORT_%d == %d\n", ui32TessPartitioningImp, (uint32_t)TESSELLATOR_PARTITIONING_FRACTIONAL_ODD); + bcatcstr(glsl, "layout(fractional_odd_spacing) in;\n"); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32TessPartitioningImp, (uint32_t)TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN); + bcatcstr(glsl, "layout(fractional_even_spacing) in;\n"); + bcatcstr(glsl, "#endif\n"); + } + + for (i = 0; i < ui32DeclCount; ++i) + { + TranslateDeclaration(psContext, psShader->psDecl + i); + } + + if (psContext->psShader->ui32NumDx9ImmConst) + { + bformata(psContext->glsl, "vec4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); + } + + MarkIntegerImmediates(psContext); + + SetDataTypes(psContext, psShader->psInst, ui32InstCount, psContext->psShader->aeCommonTempVecType); + + if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) + { + for (i = 0; i < MAX_TEMP_VEC4; ++i) + { + switch (psShader->aeCommonTempVecType[i]) + { + case SVT_VOID: + psShader->aeCommonTempVecType[i] = SVT_FLOAT; + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + bformata(psContext->glsl, "%s Temp%d", GetConstructorForTypeGLSL(psContext, psShader->aeCommonTempVecType[i], 4, true), i); + break; + case SVT_FORCE_DWORD: + // temp register not used + continue; + default: + continue; + } + + if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) + { + bformata(psContext->glsl, "[1]"); + } + bformata(psContext->glsl, ";\n"); + } + + if (psContext->psShader->bUseTempCopy) + { + bcatcstr(psContext->glsl, "vec4 TempCopy;\n"); + bcatcstr(psContext->glsl, "uvec4 TempCopy_uint;\n"); + bcatcstr(psContext->glsl, "ivec4 TempCopy_int;\n"); + } + } + + // Declare auxiliary variables used to save intermediate results to bypass driver issues + SHADER_VARIABLE_TYPE auxVarType = SVT_UINT; + bformata(psContext->glsl, "highp %s %s1;\n", GetConstructorForTypeGLSL(psContext, auxVarType, 4, false), GetAuxArgumentName(auxVarType)); + + if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) + { + CreateTracingInfo(psShader); + WriteTraceDeclarations(psContext); + } + + bcatcstr(glsl, "void main()\n{\n"); + + psContext->indent++; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Start Early Main ---\n"); +#endif + bconcat(glsl, psContext->earlyMain); + if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) + { + WritePreStepsTrace(psContext, psShader->sInfo.psTraceSteps); + } +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End Early Main ---\n"); +#endif + + for (i = 0; i < ui32InstCount; ++i) + { + TranslateInstruction(psContext, psShader->psInst + i); + + if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) + { + WritePostStepTrace(psContext, i); + } + } + + psContext->indent--; + + bcatcstr(glsl, "}\n"); + + // Add exports + if (psShader->eShaderType == PIXEL_SHADER) + { + uint32_t ui32Input; + for (ui32Input = 0; ui32Input < MAX_SHADER_VEC4_INPUT; ++ui32Input) + { + INTERPOLATION_MODE eMode = psShader->sInfo.aePixelInputInterpolation[ui32Input]; + if (eMode != INTERPOLATION_LINEAR) + { + AddExport(psContext, SYMBOL_INPUT_INTERPOLATION_MODE, ui32Input, (uint32_t)eMode); + } + } + } + if (psShader->eShaderType == HULL_SHADER) + { + AddExport(psContext, SYMBOL_TESSELLATOR_PARTITIONING, 0, psShader->sInfo.eTessPartitioning); + AddExport(psContext, SYMBOL_TESSELLATOR_OUTPUT_PRIMITIVE, 0, psShader->sInfo.eTessOutPrim); + } + + FillInResourceDescriptions(psContext); +} + +static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) +{ + uint32_t ui32Inst; + for (ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) + { + Instruction* psCurrentInst = &psInst[ui32Inst]; + const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; + uint32_t ui32Operand; + + for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) + { + uint32_t ui32SubOperand; + for (ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) + { + if (psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) + { + hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); + psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; + } + } + } + } +} + +void RemoveDoubleUnderscores(char* szName) +{ + char* position; + size_t length; + length = strlen(szName); + position = szName; + position = strstr(position, "__"); + while (position) + { + position[1] = '0'; + position += 2; + position = strstr(position, "__"); + } +} + +void RemoveDoubleUnderscoresFromIdentifiers(Shader* psShader) +{ + uint32_t i, j; + for (i = 0; i < psShader->sInfo.ui32NumConstantBuffers; ++i) + { + for (j = 0; j < psShader->sInfo.psConstantBuffers[i].ui32NumVars; ++j) + { + RemoveDoubleUnderscores(psShader->sInfo.psConstantBuffers[i].asVars[j].sType.Name); + } + } +} + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMem(const char* shader, size_t size, unsigned int flags, GLLang language, const GlExtensions* extensions, GLSLShader* result) +{ + uint32_t* tokens; + Shader* psShader; + char* glslcstr = NULL; + int GLSLShaderType = GL_FRAGMENT_SHADER_ARB; + int success = 0; + uint32_t i; + + tokens = (uint32_t*)shader; + + psShader = DecodeDXBC(tokens); + + if (flags & (HLSLCC_FLAG_HASH_INPUT | HLSLCC_FLAG_ADD_DEBUG_HEADER)) + { + uint64_t ui64InputHash = hash64((const uint8_t*)tokens, tokens[6], 0); + psShader->sInfo.ui32InputHash = (uint32_t)ui64InputHash ^ (uint32_t)(ui64InputHash >> 32); + } + + RemoveDoubleUnderscoresFromIdentifiers(psShader); + + if (psShader) + { + ForcePositionOutputToHighp(psShader); + HLSLCrossCompilerContext sContext; + + sContext.psShader = psShader; + sContext.flags = flags; + + for (i = 0; i < NUM_PHASES; ++i) + { + sContext.havePostShaderCode[i] = 0; + } + + if (flags & HLSLCC_FLAG_ADD_DEBUG_HEADER) + { +#if defined(_WIN32) && !defined(PORTABLE) + ID3DBlob* pDisassembly = NULL; +#endif //defined(_WIN32) && !defined(PORTABLE) + + sContext.debugHeader = bformat("// HASH = 0x%08X\n", psShader->sInfo.ui32InputHash); + +#if defined(_WIN32) && !defined(PORTABLE) + D3DDisassemble(shader, size, 0, "", &pDisassembly); + bcatcstr(sContext.debugHeader, "/*\n"); + bcatcstr(sContext.debugHeader, (const char*)pDisassembly->lpVtbl->GetBufferPointer(pDisassembly)); + bcatcstr(sContext.debugHeader, "\n*/\n"); + pDisassembly->lpVtbl->Release(pDisassembly); +#endif //defined(_WIN32) && !defined(PORTABLE) + } + + TranslateToGLSL(&sContext, &language, extensions); + + switch (psShader->eShaderType) + { + case VERTEX_SHADER: + { + GLSLShaderType = GL_VERTEX_SHADER_ARB; + break; + } + case GEOMETRY_SHADER: + { + GLSLShaderType = GL_GEOMETRY_SHADER; + break; + } + case DOMAIN_SHADER: + { + GLSLShaderType = GL_TESS_EVALUATION_SHADER; + break; + } + case HULL_SHADER: + { + GLSLShaderType = GL_TESS_CONTROL_SHADER; + break; + } + case COMPUTE_SHADER: + { + GLSLShaderType = GL_COMPUTE_SHADER; + break; + } + default: + { + break; + } + } + + glslcstr = bstr2cstr(sContext.glsl, '\0'); + + bdestroy(sContext.glsl); + bdestroy(sContext.earlyMain); + for (i = 0; i < NUM_PHASES; ++i) + { + bdestroy(sContext.postShaderCode[i]); + } + + hlslcc_free(psShader->psHSControlPointPhaseDecl); + FreeSubOperands(psShader->psHSControlPointPhaseInstr, psShader->ui32HSControlPointInstrCount); + hlslcc_free(psShader->psHSControlPointPhaseInstr); + + for (i = 0; i < psShader->ui32ForkPhaseCount; ++i) + { + hlslcc_free(psShader->apsHSForkPhaseDecl[i]); + FreeSubOperands(psShader->apsHSForkPhaseInstr[i], psShader->aui32HSForkInstrCount[i]); + hlslcc_free(psShader->apsHSForkPhaseInstr[i]); + } + hlslcc_free(psShader->psHSJoinPhaseDecl); + FreeSubOperands(psShader->psHSJoinPhaseInstr, psShader->ui32HSJoinInstrCount); + hlslcc_free(psShader->psHSJoinPhaseInstr); + + hlslcc_free(psShader->psDecl); + FreeSubOperands(psShader->psInst, psShader->ui32InstCount); + hlslcc_free(psShader->psInst); + + memcpy(&result->reflection, &psShader->sInfo, sizeof(psShader->sInfo)); + + + hlslcc_free(psShader); + + success = 1; + } + + shader = 0; + tokens = 0; + + /* Fill in the result struct */ + + result->shaderType = GLSLShaderType; + result->sourceCode = glslcstr; + result->GLSLLanguage = language; + + return success; +} + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFile(const char* filename, unsigned int flags, GLLang language, const GlExtensions* extensions, GLSLShader* result) +{ + FILE* shaderFile; + int length; + size_t readLength; + char* shader; + int success = 0; + + shaderFile = fopen(filename, "rb"); + + if (!shaderFile) + { + return 0; + } + + fseek(shaderFile, 0, SEEK_END); + length = ftell(shaderFile); + fseek(shaderFile, 0, SEEK_SET); + + shader = (char*)hlslcc_malloc(length + 1); + + readLength = fread(shader, 1, length, shaderFile); + + fclose(shaderFile); + shaderFile = 0; + + shader[readLength] = '\0'; + + success = TranslateHLSLFromMem(shader, readLength, flags, language, extensions, result); + + hlslcc_free(shader); + + return success; +} + +HLSLCC_API void HLSLCC_APIENTRY FreeGLSLShader(GLSLShader* s) +{ + bcstrfree(s->sourceCode); + s->sourceCode = NULL; + FreeShaderInfo(&s->reflection); +} + diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c new file mode 100644 index 0000000000..3f08f2ab3d --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/toGLSLDeclaration.c @@ -0,0 +1,2908 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "hlslcc.h" +#include "internal_includes/toGLSLDeclaration.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/languages.h" +#include "internal_includes/hlslccToolkit.h" +#include "bstrlib.h" +#include "internal_includes/debug.h" +#include <math.h> +#include <float.h> +#include <stdbool.h> + +#if !defined(isnan) +#ifdef _MSC_VER +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#endif +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) + +typedef enum +{ + GLVARTYPE_FLOAT, + GLVARTYPE_INT, + GLVARTYPE_FLOAT4, +} GLVARTYPE; + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); +extern uint32_t AddImport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Default); +extern uint32_t AddExport(HLSLCrossCompilerContext* psContext, SYMBOL_TYPE eType, uint32_t ui32ID, uint32_t ui32Value); + +const char* GetTypeString(GLVARTYPE eType) +{ + switch (eType) + { + case GLVARTYPE_FLOAT: + { + return "float"; + } + case GLVARTYPE_INT: + { + return "int"; + } + case GLVARTYPE_FLOAT4: + { + return "vec4"; + } + default: + { + return ""; + } + } +} +const uint32_t GetTypeElementCount(GLVARTYPE eType) +{ + switch (eType) + { + case GLVARTYPE_FLOAT: + case GLVARTYPE_INT: + { + return 1; + } + case GLVARTYPE_FLOAT4: + { + return 4; + } + default: + { + return 0; + } + } +} + +void GetSTD140Layout(ShaderVarType* pType, uint32_t* puAlignment, uint32_t* puSize) +{ + *puSize = 0; + *puAlignment = 1; + switch (pType->Type) + { + case SVT_BOOL: + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + *puSize = 4; + *puAlignment = 4; + break; + case SVT_DOUBLE: + *puSize = 8; + *puAlignment = 4; + break; + case SVT_VOID: + break; + default: + ASSERT(0); + break; + } + switch (pType->Class) + { + case SVC_SCALAR: + break; + case SVC_MATRIX_ROWS: + case SVC_MATRIX_COLUMNS: + // Matrices are translated to arrays of vectors + *puSize *= pType->Rows; + case SVC_VECTOR: + switch (pType->Columns) + { + case 2: + *puSize *= 2; + *puAlignment *= 2; + break; + case 3: + case 4: + *puSize *= 4; + *puAlignment *= 4; + break; + } + break; + case SVC_STRUCT: + { + uint32_t uMember; + for (uMember = 0; uMember < pType->MemberCount; ++uMember) + { + uint32_t uMemberAlignment, uMemberSize; + *puSize += pType->Members[uMember].Offset; + GetSTD140Layout(pType->Members + uMember, &uMemberAlignment, &uMemberSize); + *puSize += uMemberAlignment - 1; + *puSize -= *puSize % uMemberAlignment; + *puAlignment = *puAlignment > uMemberAlignment ? *puAlignment : uMemberAlignment; + } + } + break; + default: + ASSERT(0); + break; + } + + if (pType->Elements > 1) + { + *puSize *= pType->Elements; + } + + if (pType->Elements > 1 || pType->Class == SVC_MATRIX_ROWS || pType->Class == SVC_MATRIX_COLUMNS) + { + *puAlignment = (*puAlignment + 0x0000000F) & 0xFFFFFFF0; + } +} + +void AddToDx9ImmConstIndexableArray(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + bstring* savedStringPtr = psContext->currentGLSLString; + + psContext->currentGLSLString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; + bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); + TranslateOperand(psContext, psOperand, TO_FLAG_NONE); + bcatcstr(psContext->earlyMain, ";\n"); + psContext->indent--; + psContext->psShader->ui32NumDx9ImmConst++; + + psContext->currentGLSLString = savedStringPtr; +} + +void DeclareConstBufferShaderVariable(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType, int unsizedArray) +{ + bstring glsl = *psContext->currentGLSLString; + + if (psType->Class == SVC_STRUCT) + { + bcatcstr(glsl, "\t"); + ShaderVarName(glsl, psContext->psShader, Name); + bcatcstr(glsl, "_Type "); + ShaderVarName(glsl, psContext->psShader, Name); + if (psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) + { + switch (psType->Type) + { + case SVT_FLOAT: + { + bformata(glsl, "\tvec%d ", psType->Columns); + ShaderVarName(glsl, psContext->psShader, Name); + bformata(glsl, "[%d", psType->Rows); + break; + } + default: + { + ASSERT(0); + break; + } + } + if (psType->Elements > 1) + { + bformata(glsl, " * %d", psType->Elements); + } + bformata(glsl, "]"); + } + else + if (psType->Class == SVC_VECTOR) + { + switch (psType->Type) + { + default: + ASSERT(0); + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + bformata(glsl, "\t%s ", GetConstructorForTypeGLSL(psContext, psType->Type, psType->Columns, true)); + break; + case SVT_DOUBLE: + bformata(glsl, "\tdvec%d ", psType->Columns); + break; + } + + ShaderVarName(glsl, psContext->psShader, Name); + + if (psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + else + if (psType->Class == SVC_SCALAR) + { + switch (psType->Type) + { + default: + ASSERT(0); + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + bformata(glsl, "\t%s ", GetConstructorForTypeGLSL(psContext, psType->Type, 1, true)); + break; + case SVT_DOUBLE: + bformata(glsl, "\tdouble "); + break; + case SVT_BOOL: + //Use int instead of bool. + //Allows implicit conversions to integer and + //bool consumes 4-bytes in HLSL and GLSL anyway. + bformata(glsl, "\tint "); + break; + } + + ShaderVarName(glsl, psContext->psShader, Name); + + if (psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + if (unsizedArray) + { + bformata(glsl, "[]"); + } + bformata(glsl, ";\n"); +} + +//In GLSL embedded structure definitions are not supported. +void PreDeclareStructType(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType) +{ + uint32_t i; + bstring glsl = *psContext->currentGLSLString; + + for (i = 0; i < psType->MemberCount; ++i) + { + if (psType->Members[i].Class == SVC_STRUCT) + { + PreDeclareStructType(psContext, psType->Members[i].Name, &psType->Members[i]); + } + } + + if (psType->Class == SVC_STRUCT) + { +#if !defined(NDEBUG) + uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; +#endif + //Not supported at the moment + ASSERT(!unnamed_struct); + + bcatcstr(glsl, "struct "); + ShaderVarName(glsl, psContext->psShader, Name); + bcatcstr(glsl, "_Type {\n"); + + for (i = 0; i < psType->MemberCount; ++i) + { + ASSERT(psType->Members != 0); + + DeclareConstBufferShaderVariable(psContext, psType->Members[i].Name, &psType->Members[i], 0); + } + + bformata(glsl, "};\n"); + } +} + +void DeclarePLSStructVars(HLSLCrossCompilerContext* psContext, const char* Name, const struct ShaderVarType_TAG* psType) +{ + (void)Name; + + uint32_t i; + bstring glsl = *psContext->currentGLSLString; + + ASSERT(psType->Members != 0); + + for (i = 0; i < psType->MemberCount; ++i) + { + if (psType->Members[i].Class == SVC_STRUCT) + { + ASSERT(0); // PLS can't have nested structs + } + } + + if (psType->Class == SVC_STRUCT) + { + for (i = 0; i < psType->MemberCount; ++i) + { + ShaderVarType cur_member = psType->Members[i]; + + if (cur_member.Class == SVC_VECTOR) + { + switch (cur_member.Type) + { + case SVT_FLOAT: + { + // float2 -> rg16f + if (2 == cur_member.Columns) + { + bcatcstr(glsl, "\tlayout(rg16f) highp vec2 "); + } + // float3 -> r11f_g11f_b10f + else if (3 == cur_member.Columns) + { + bcatcstr(glsl, "\tlayout(r11f_g11f_b10f) highp vec3 "); + } + // float4 -> rgba8 + else if (4 == cur_member.Columns) + { + bcatcstr(glsl, "\tlayout(rgba8) highp vec4 "); + } + else + { + ASSERT(0); // not supported + } + break; + } + case SVT_INT: + { + // int2 -> rg16i + if (2 == cur_member.Columns) + { + bcatcstr(glsl, "\tlayout(rg16i) highp ivec2 "); + } + // int4 -> rgba8i + else if (4 == cur_member.Columns) + { + bcatcstr(glsl, "\tlayout(rgba8i) highp ivec4 "); + } + else + { + ASSERT(0); // not supported + } + break; + } + case SVT_UINT: + case SVT_DOUBLE: + default: + ASSERT(0); + } + + if (cur_member.Elements > 1) + { + ASSERT(0); // PLS can't have arrays + } + } + else if (cur_member.Class == SVC_SCALAR) + { + switch (cur_member.Type) + { + case SVT_UINT: + bcatcstr(glsl, "\tlayout(r32ui) highp uint "); + break; + case SVT_FLOAT: + case SVT_INT: + case SVT_DOUBLE: + case SVT_BOOL: + default: + ASSERT(0); + } + } + + ShaderVarName(glsl, psContext->psShader, cur_member.Name); + bcatcstr(glsl, ";\n"); + } + } + else + { + ASSERT(0); + } +} + +char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) +{ + bstring inputName; + char* cstr; + InOutSignature* psIn; + + if (eShaderType == GEOMETRY_SHADER) + { + inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else if (eShaderType == HULL_SHADER) + { + inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + else if (eShaderType == DOMAIN_SHADER) + { + inputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); + } + else if (eShaderType == PIXEL_SHADER) + { + if (psContext->flags & HLSLCC_FLAG_TESS_ENABLED) + { + inputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); + } + else + { + inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + } + else + { + ASSERT(eShaderType == VERTEX_SHADER); + inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); + } + if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn)) + { + bformata(inputName, "_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + } + + cstr = bstr2cstr(inputName, '\0'); + bdestroy(inputName); + return cstr; +} + +char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, + const SHADER_TYPE eShaderType, + const Operand* psOperand, + int* piStream) +{ + bstring outputName; + char* cstr; + InOutSignature* psOut; + + int foundOutput = GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, + psOperand->ui32CompMask, + psContext->psShader->ui32CurrentVertexOutputStream, + &psContext->psShader->sInfo, + &psOut); + + (void)(foundOutput); + ASSERT(foundOutput); + + if (eShaderType == GEOMETRY_SHADER) + { + if (psOut->ui32Stream != 0) + { + outputName = bformat("VtxGeoOutput%d_S%d", psOperand->ui32RegisterNumber, psOut->ui32Stream); + piStream[0] = psOut->ui32Stream; + } + else + { + outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + } + else if (eShaderType == DOMAIN_SHADER) + { + outputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); + } + else if (eShaderType == VERTEX_SHADER) + { + if (psContext->flags & HLSLCC_FLAG_GS_ENABLED) + { + outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else + { + outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + } + else if (eShaderType == PIXEL_SHADER) + { + outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); + } + else + { + ASSERT(eShaderType == HULL_SHADER); + outputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); + } + if (psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) + { + bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); + } + + cstr = bstr2cstr(outputName, '\0'); + bdestroy(outputName); + return cstr; +} +static void DeclareInput( + HLSLCrossCompilerContext* psContext, + const Declaration* psDecl, + const char* Interpolation, const char* StorageQualifier, const char* Precision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) +{ + Shader* psShader = psContext->psShader; + bstring glsl = *psContext->currentGLSLString; + + // This falls within the specified index ranges. The default is 0 if no input range is specified + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + return; + } + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + const char* vecType = "vec"; + const char* scalarType = "float"; + InOutSignature* psSignature = NULL; + + if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature)) + { + switch (psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + vecType = "uvec"; + scalarType = "uint"; + break; + } + case INOUT_COMPONENT_SINT32: + { + vecType = "ivec"; + scalarType = "int"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + } + + if (psShader->eShaderType == PIXEL_SHADER) + { + psShader->sInfo.aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; + } + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) || + (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage))) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + switch (eIndexDim) + { + case INDEX_2D: + { + if (iNumComponents == 1) + { + const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; + + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; + + bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, arraySize); + + bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; + } + else + { + bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, psDecl->asOperands[0].aui32ArraySizes[0]); + + bformata(glsl, "%s %s%d Input%d[%d];\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].aui32ArraySizes[0]); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; + } + break; + } + default: + { + if (psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) + { + InputName = "TexCoord"; + } + + if (iNumComponents == 1) + { + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; + + bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); + bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + else + { + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) + { + bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + bformata(glsl, "%s %s%d Input%d[%d];\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; + } + else + { + bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "%s %s%d Input%d;\n", Precision, vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + } + break; + } + } + } + + if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) + { + psContext->currentGLSLString = &psContext->earlyMain; + psContext->indent++; + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array + { + AddIndentation(psContext); + bformata(psContext->earlyMain, "Input%d = %s;\n", psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else + { + int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; + + while (arrayIndex) + { + AddIndentation(psContext); + bformata(psContext->earlyMain, "Input%d[%d] = %s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex - 1, InputName, arrayIndex - 1); + + arrayIndex--; + } + } + psContext->indent--; + psContext->currentGLSLString = &psContext->glsl; + } +} + +void AddBuiltinInput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName, uint32_t uNumComponents) +{ + (void)uNumComponents; + + bstring glsl = *psContext->currentGLSLString; + Shader* psShader = psContext->psShader; + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, &psDecl->asOperands[0]); + bformata(glsl, "%s ", GetConstructorForTypeGLSL(psContext, eType, 4, false)); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, ";\n"); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; + } + else + { + //This register has already been declared. The HLSL bytecode likely looks + //something like this then: + // dcl_input_ps constant v3.x + // dcl_input_ps_sgv v3.y, primitive_id + + //GLSL does not allow assignment to a varying! + } + + psContext->currentGLSLString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + + bformata(psContext->earlyMain, " = %s", builtinName); + + switch (psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); + // Invert w coordinate if necessary to be the same as SV_Position + if (psContext->psShader->eShaderType == PIXEL_SHADER) + { + if (psDecl->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE && + psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) + { + if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + uint32_t ui32IgnoreSwizzle; + bcatcstr(psContext->earlyMain, ";\n#ifdef EMULATE_DEPTH_CLAMP\n"); + AddIndentation(psContext); + TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); + bcatcstr(psContext->earlyMain, ".z = unclampedDepth;\n"); + bcatcstr(psContext->earlyMain, "#endif\n"); + } + if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + uint32_t ui32IgnoreSwizzle; + bcatcstr(psContext->earlyMain, ";\n"); + AddIndentation(psContext); + TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); + bcatcstr(psContext->earlyMain, ".w = 1.0 / "); + TranslateVariableName(psContext, &psDecl->asOperands[0], TO_FLAG_NONE, &ui32IgnoreSwizzle); + bcatcstr(psContext->earlyMain, ".w;\n"); + } + } + else + { + ASSERT(0); + } + } + + break; + default: + //Scalar built-in. Don't apply swizzle. + break; + } + bcatcstr(psContext->earlyMain, ";\n"); + + psContext->indent--; + psContext->currentGLSLString = &psContext->glsl; +} + +int OutputNeedsDeclaring(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) +{ + Shader* psShader = psContext->psShader; + + // Depth Output operands are a special case and won't have a ui32RegisterNumber, + // so first we have to check if the output operand is depth. + if (psShader->eShaderType == PIXEL_SHADER) + { + if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL) + { + return 1; + } + else if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) + { + return 0; // OpenGL doesn't need to declare depth output variable (gl_FragDepth) + } + } + + const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; + ASSERT(psOperand->ui32RegisterNumber >= 0); + ASSERT(psOperand->ui32RegisterNumber < MAX_SHADER_VEC4_OUTPUT); + if (psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) + { + int offset; + + for (offset = 0; offset < count; offset++) + { + psShader->aiOutputDeclared[psOperand->ui32RegisterNumber + offset] = declared; + } + return 1; + } + + return 0; +} + +void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) +{ + bstring glsl = *psContext->currentGLSLString; + Shader* psShader = psContext->psShader; + + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + if (OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) + { + InOutSignature* psSignature = NULL; + + GetOutputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].ui32CompMask, + 0, + &psShader->sInfo, &psSignature); + + bcatcstr(glsl, "#undef "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "\n"); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, " phase%d_", psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "\n"); + + bcatcstr(glsl, "vec4 "); + bformata(glsl, "phase%d_", psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + if (arrayElements) + { + bformata(glsl, "[%d];\n", arrayElements); + } + else + { + bcatcstr(glsl, ";\n"); + } + + psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; + glsl = *psContext->currentGLSLString; + psContext->indent++; + if (arrayElements) + { + int elem; + for (elem = 0; elem < arrayElements; elem++) + { + AddIndentation(psContext); + bformata(glsl, "%s[%d] = %s(phase%d_", builtinName, elem, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, "[%d]", elem); + TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); + bformata(glsl, ");\n"); + } + } + else + { + if (psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) + { + int max = GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + + int applySiwzzle = GetNumSwizzleElements(&psDecl->asOperands[0]) > 1 ? 1 : 0; + int index; + int i; + int multiplier = 1; + char* swizzle[] = {".x", ".y", ".z", ".w"}; + + ASSERT(psSignature != NULL); + + index = psSignature->ui32SemanticIndex; + + //Clip distance can be spread across 1 or 2 outputs (each no more than a vec4). + //Some examples: + //float4 clip[2] : SV_ClipDistance; //8 clip distances + //float3 clip[2] : SV_ClipDistance; //6 clip distances + //float4 clip : SV_ClipDistance; //4 clip distances + //float clip : SV_ClipDistance; //1 clip distance. + + //In GLSL the clip distance built-in is an array of up to 8 floats. + //So vector to array conversion needs to be done here. + if (index == 1) + { + InOutSignature* psFirstClipSignature; + if (GetOutputSignatureFromSystemValue(NAME_CLIP_DISTANCE, 1, &psShader->sInfo, &psFirstClipSignature)) + { + if (psFirstClipSignature->ui32Mask & (1 << 3)) + { + multiplier = 4; + } + else + if (psFirstClipSignature->ui32Mask & (1 << 2)) + { + multiplier = 3; + } + else + if (psFirstClipSignature->ui32Mask & (1 << 1)) + { + multiplier = 2; + } + } + } + + for (i = 0; i < max; ++i) + { + AddIndentation(psContext); + bformata(glsl, "%s[%d] = (phase%d_", builtinName, i + multiplier * index, psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + if (applySiwzzle) + { + bformata(glsl, ")%s;\n", swizzle[i]); + } + else + { + bformata(glsl, ");\n"); + } + } + } + else + { + uint32_t elements = GetNumSwizzleElements(&psDecl->asOperands[0]); + + if (elements != GetTypeElementCount(type)) + { + //This is to handle float3 position seen in control point phases + //struct HS_OUTPUT + //{ + // float3 vPosition : POSITION; + //}; -> dcl_output o0.xyz + //gl_Position is vec4. + AddIndentation(psContext); + bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, ", 1);\n"); + } + else + { + AddIndentation(psContext); + bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, ");\n"); + } + } + + if (psShader->eShaderType == VERTEX_SHADER && psDecl->asOperands[0].eSpecialName == NAME_POSITION) + { + if (psContext->flags & HLSLCC_FLAG_INVERT_CLIP_SPACE_Y) + { + AddIndentation(psContext); + bformata(glsl, "gl_Position.y = -gl_Position.y;\n"); + } + + if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#ifdef EMULATE_DEPTH_CLAMP\n"); + bcatcstr(glsl, "#if EMULATE_DEPTH_CLAMP == 1\n"); + AddIndentation(psContext); + bcatcstr(glsl, "unclampedDepth = gl_DepthRange.near + gl_DepthRange.diff * gl_Position.z / gl_Position.w;\n"); + bcatcstr(glsl, "#elif EMULATE_DEPTH_CLAMP == 2\n"); + AddIndentation(psContext); + bcatcstr(glsl, "unclampedZ = gl_DepthRange.diff * gl_Position.z;\n"); + bcatcstr(glsl, "#endif\n"); + AddIndentation(psContext); + bcatcstr(glsl, "gl_Position.z = 0.0;\n"); + } + + if (psContext->flags & HLSLCC_FLAG_CONVERT_CLIP_SPACE_Z) + { + if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#else\n"); + } + + AddIndentation(psContext); + bcatcstr(glsl, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n"); + } + + if (EmulateDepthClamp(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "#endif\n"); + } + } + } + psContext->indent--; + psContext->currentGLSLString = &psContext->glsl; + } +} + +void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) +{ + bstring glsl = *psContext->currentGLSLString; + Shader* psShader = psContext->psShader; + + if (OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) + { + const Operand* psOperand = &psDecl->asOperands[0]; + const char* Precision = ""; + const char* type = "vec"; + + InOutSignature* psSignature = NULL; + + GetOutputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].ui32CompMask, + psShader->ui32CurrentVertexOutputStream, + &psShader->sInfo, + &psSignature); + + switch (psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uvec"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "ivec"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + + if (HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch (psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + //type = "ivec"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + //type = "uvec"; + break; + } + } + } + + switch (psShader->eShaderType) + { + case PIXEL_SHADER: + { + switch (psDecl->asOperands[0].eType) + { + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + { + bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); + bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); + bcatcstr(glsl, "layout (depth_greater) out float gl_FragDepth;\n"); + bcatcstr(glsl, "#endif\n"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); + bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); + bcatcstr(glsl, "layout (depth_less) out float gl_FragDepth;\n"); + bcatcstr(glsl, "#endif\n"); + break; + } + default: + { + if (WriteToFragData(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "#define Output%d gl_FragData[%d]\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); + } + else + { + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, PIXEL_SHADER, psOperand, &stream); + + uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; + + // Check if we already defined this as a "inout" + if ((psContext->rendertargetUse[renderTarget] & INPUT_RENDERTARGET) == 0) + { + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) || HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage)) + { + uint32_t index = 0; + + if ((psContext->flags & HLSLCC_FLAG_DUAL_SOURCE_BLENDING) && DualSourceBlendSupported(psContext->psShader->eTargetLanguage)) + { + if (renderTarget > 0) + { + renderTarget = 0; + index = 1; + } + bformata(glsl, "layout(location = %d, index = %d) ", renderTarget, index); + } + else + { + bformata(glsl, "layout(location = %d) ", renderTarget); + } + } + + bformata(glsl, "out %s %s4 %s;\n", Precision, type, OutputName); + } + + if (stream) + { + bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); + } + else + { + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + } + bcstrfree(OutputName); + } + break; + } + } + break; + } + case VERTEX_SHADER: + { + int iNumComponents = 4; //GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); + + if (psShader->eShaderType == VERTEX_SHADER) + { + uint32_t ui32InterpImp = AddImport(psContext, SYMBOL_INPUT_INTERPOLATION_MODE, psDecl->asOperands[0].ui32RegisterNumber, (uint32_t)INTERPOLATION_LINEAR); + bformata(glsl, "#if IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_CONSTANT); + bformata(glsl, "#define Output%dInterpolation flat\n", psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_CENTROID); + bformata(glsl, "#define Output%dInterpolation centroid\n", psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE); + bformata(glsl, "#define Output%dInterpolation noperspective\n", psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID); + bformata(glsl, "#define Output%dInterpolation noperspective centroid\n", psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_SAMPLE); + bformata(glsl, "#define Output%dInterpolation sample\n", psDecl->asOperands[0].ui32RegisterNumber); + bformata(glsl, "#elif IMPORT_%d == %d\n", ui32InterpImp, INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE); + bformata(glsl, "#define Output%dInterpolation noperspective sample\n", psDecl->asOperands[0].ui32RegisterNumber); + bcatcstr(glsl, "#else\n"); + bformata(glsl, "#define Output%dInterpolation \n", psDecl->asOperands[0].ui32RegisterNumber); + bcatcstr(glsl, "#endif\n"); + } + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + if (psShader->eShaderType == VERTEX_SHADER) + { + bformata(glsl, "Output%dInterpolation ", psDecl->asOperands[0].ui32RegisterNumber); + } + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "out %s %s%d %s;\n", Precision, type, iNumComponents, OutputName); + } + else + { + bformata(glsl, "varying %s %s%d %s;\n", Precision, type, iNumComponents, OutputName); + } + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + bcstrfree(OutputName); + + break; + } + case GEOMETRY_SHADER: + { + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, GEOMETRY_SHADER, psOperand, &stream); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + bformata(glsl, "out %s4 %s;\n", type, OutputName); + if (stream) + { + bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); + } + else + { + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + } + bcstrfree(OutputName); + break; + } + case HULL_SHADER: + { + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, HULL_SHADER, psOperand, &stream); + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber != 0); //Reg 0 should be gl_out[gl_InvocationID].gl_Position. + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + bformata(glsl, "out %s4 %s[];\n", type, OutputName); + bformata(glsl, "#define Output%d %s[gl_InvocationID]\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + bcstrfree(OutputName); + break; + } + case DOMAIN_SHADER: + { + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, DOMAIN_SHADER, psOperand, &stream); + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + bformata(glsl, "out %s4 %s;\n", type, OutputName); + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + bcstrfree(OutputName); + break; + } + } + } + else + { + /* + Multiple outputs can be packed into one register. e.g. + // Name Index Mask Register SysValue Format Used + // -------------------- ----- ------ -------- -------- ------- ------ + // FACTOR 0 x 3 NONE int x + // MAX 0 y 3 NONE int y + + We want unique outputs to make it easier to use transform feedback. + + out ivec4 FACTOR0; + #define Output3 FACTOR0 + out ivec4 MAX0; + + MAIN SHADER CODE. Writes factor and max to Output3 which aliases FACTOR0. + + MAX0.x = FACTOR0.y; + + This unpacking of outputs is only done when using HLSLCC_FLAG_INOUT_SEMANTIC_NAMES. + When not set the application will be using HLSL reflection information to discover + what the input and outputs mean if need be. + */ + + // + + if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT)) + { + const Operand* psOperand = &psDecl->asOperands[0]; + InOutSignature* psSignature = NULL; + const char* type = "vec"; + int stream = 0; + char* OutputName = GetDeclaredOutputName(psContext, psShader->eShaderType, psOperand, &stream); + + GetOutputSignatureFromRegister(psOperand->ui32RegisterNumber, + psOperand->ui32CompMask, + 0, + &psShader->sInfo, + &psSignature); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + switch (psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uvec"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "ivec"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + bformata(glsl, "out %s4 %s;\n", type, OutputName); + + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + psContext->currentGLSLString = &psContext->postShaderCode[psContext->currentPhase]; + glsl = *psContext->currentGLSLString; + + bcatcstr(glsl, OutputName); + bcstrfree(OutputName); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); + bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); + TranslateOperandSwizzle(psContext, psOperand); + bcatcstr(glsl, ";\n"); + + psContext->currentGLSLString = &psContext->glsl; + glsl = *psContext->currentGLSLString; + } + } +} + +void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf) +{ + bstring glsl = *psContext->currentGLSLString; + + uint32_t i, implicitOffset; + const char* Name = psCBuf->Name; + uint32_t auiSortedVars[MAX_SHADER_VARS]; + if (psCBuf->Name[0] == '$') //For $Globals + { + Name++; + } + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + PreDeclareStructType(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType); + } + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) + { + bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); + } + + bformata(glsl, "uniform "); + ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); + bformata(glsl, " {\n "); + + if (psCBuf->ui32NumVars > 0) + { + uint32_t bSorted = 1; + auiSortedVars[0] = 0; + for (i = 1; i < psCBuf->ui32NumVars; ++i) + { + auiSortedVars[i] = i; + bSorted = bSorted && psCBuf->asVars[i - 1].ui32StartOffset <= psCBuf->asVars[i].ui32StartOffset; + } + while (!bSorted) + { + bSorted = 1; + for (i = 1; i < psCBuf->ui32NumVars; ++i) + { + if (psCBuf->asVars[auiSortedVars[i - 1]].ui32StartOffset > psCBuf->asVars[auiSortedVars[i]].ui32StartOffset) + { + uint32_t uiTemp = auiSortedVars[i]; + auiSortedVars[i] = auiSortedVars[i - 1]; + auiSortedVars[i - 1] = uiTemp; + bSorted = 0; + } + } + } + } + + implicitOffset = 0; + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + uint32_t uVarAlignment, uVarSize; + ShaderVar* psVar = psCBuf->asVars + auiSortedVars[i]; + GetSTD140Layout(&psVar->sType, &uVarAlignment, &uVarSize); + + if ((implicitOffset + 16 - 1) / 16 < psVar->ui32StartOffset / 16) + { + uint32_t uNumPaddingUvecs = psVar->ui32StartOffset / 16 - (implicitOffset + 16 - 1) / 16; + bcatcstr(glsl, "\tuvec4 padding_"); + ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); + bformata(glsl, "_%d[%d];\n", implicitOffset, uNumPaddingUvecs); + implicitOffset = psVar->ui32StartOffset - psVar->ui32StartOffset % 16; + } + + if ((implicitOffset + 4 - 1) / 4 < psVar->ui32StartOffset / 4) + { + uint32_t uNumPaddingUints = psVar->ui32StartOffset / 4 - (implicitOffset + 4 - 1) / 4; + uint32_t uPaddingUint; + for (uPaddingUint = 0; uPaddingUint < uNumPaddingUints; ++uPaddingUint) + { + bcatcstr(glsl, "\tuint padding_"); + ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); + bformata(glsl, "_%d_%d;\n", psVar->ui32StartOffset, uPaddingUint); + } + implicitOffset = psVar->ui32StartOffset - psVar->ui32StartOffset % 4; + } + + implicitOffset += uVarAlignment - 1; + implicitOffset -= implicitOffset % uVarAlignment; + + ASSERT(implicitOffset == psVar->ui32StartOffset); + + DeclareConstBufferShaderVariable(psContext, psVar->sType.Name, &psVar->sType, 0); + implicitOffset += uVarSize; + } + + bcatcstr(glsl, "};\n"); +} + +void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, const Operand* psOperand, const uint32_t ui32GloballyCoherentAccess, const ResourceType eResourceType) +{ + const char* Name = psCBuf->Name; + bstring StructName; +#if !defined(NDEBUG) + uint32_t unnamed_struct = strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; +#endif + bstring glsl = *psContext->currentGLSLString; + + ASSERT(psCBuf->ui32NumVars == 1); + ASSERT(unnamed_struct); + + StructName = bfromcstr(""); + + //TranslateOperand(psContext, psOperand, TO_FLAG_NAME_ONLY); + if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) + { + bformata(StructName, "StructuredRes%d", psOperand->ui32RegisterNumber); + } + else if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) + { + bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); + } + else + { + bformata(StructName, "UAV%d", psOperand->ui32RegisterNumber); + } + + PreDeclareStructType(psContext, bstr2cstr(StructName, '\0'), &psCBuf->asVars[0].sType); + + // Add 'std430' layout for storage buffers. + // We don't use a global setting for all buffers because Mali drivers don't like that. + bcatcstr(glsl, "layout(std430"); + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + // If storage blocking binding is not supported, then we must set the binding location in the shader. If we don't do it, + // all the storage buffers of the program get assigned the same value (0). + // Unfortunately this could cause binding collisions between different render stages for a storage buffer. + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && + (!StorageBlockBindingSupported(psContext->psShader->eTargetLanguage) || (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0)) + { + bformata(glsl, ", binding = %d", ui32BindingPoint); + } + + // Close 'layout' + bcatcstr(glsl, ")"); + + if (ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) + { + bcatcstr(glsl, "coherent "); + } + + if (eResourceType == RTYPE_STRUCTURED) + { + bcatcstr(glsl, "readonly "); + } + + bcatcstr(glsl, "buffer "); + if (eResourceType == RTYPE_STRUCTURED) + { + ConvertToTextureName(glsl, psContext->psShader, Name, NULL, 0); + } + else + { + ConvertToUAVName(glsl, psContext->psShader, Name); + } + bcatcstr(glsl, " {\n "); + + DeclareConstBufferShaderVariable(psContext, bstr2cstr(StructName, '\0'), &psCBuf->asVars[0].sType, 1); + + bcatcstr(glsl, "};\n"); + + bdestroy(StructName); +} + +void DeclarePLSVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* plsVar, const Operand* psOperand, const uint32_t ui32GloballyCoherentAccess, const ResourceType eResourceType) +{ + (void)psOperand; + (void)ui32GloballyCoherentAccess; + (void)eResourceType; + + const char* Name = plsVar->Name; +#if !defined(NDEBUG) + uint32_t unnamed_struct = strcmp(plsVar->asVars[0].Name, "$Element") == 0 ? 1 : 0; +#endif + bstring glsl = *psContext->currentGLSLString; + + ASSERT(plsVar->ui32NumVars == 1); + ASSERT(unnamed_struct); + + // Define extension + // TODO: if we need more than one PLS var... we can't redefine the extension every time + // Extensions need to be declared before any non-preprocessor symbols. So we put it all the way at the beginning. + bstring ext = bfromcstralloc(1024, "#extension GL_EXT_shader_pixel_local_storage : require\n"); + bconcat(ext, glsl); + bassign(glsl, ext); + bdestroy(ext); + + switch (ui32BindingPoint) + { + case GMEM_PLS_RO_SLOT: + bcatcstr(glsl, "__pixel_local_inEXT PLS_STRUCT_READ_ONLY"); + break; + case GMEM_PLS_WO_SLOT: + bcatcstr(glsl, "__pixel_local_outEXT PLS_STRUCT_WRITE_ONLY"); + break; + case GMEM_PLS_RW_SLOT: + bcatcstr(glsl, "__pixel_localEXT PLS_STRUCT_READ_WRITE"); + break; + default: + ASSERT(0); + } + + bcatcstr(glsl, "\n{\n"); + + ASSERT(plsVar->ui32NumVars == 1); + ASSERT(plsVar->asVars[0].sType.Members != 0); + DeclarePLSStructVars(psContext, plsVar->asVars[0].sType.Name, &plsVar->asVars[0].sType); + + bcatcstr(glsl, "\n} "); + ConvertToUAVName(glsl, psContext->psShader, Name); + bcatcstr(glsl, ";\n\n"); +} + +void DeclareStructConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, ConstantBuffer* psCBuf, const Operand* psOperand) +{ + bstring glsl = *psContext->currentGLSLString; + + uint32_t i; + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + PreDeclareStructType(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType); + } + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) + { + bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + } + bcatcstr(glsl, "uniform struct "); + TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); + + bcatcstr(glsl, "_Type {\n"); + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + DeclareConstBufferShaderVariable(psContext, psCBuf->asVars[i].sType.Name, &psCBuf->asVars[i].sType, 0); + } + + bcatcstr(glsl, "} "); + + TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); + + bcatcstr(glsl, ";\n"); +} + +void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) +{ + bstring glsl = *psContext->currentGLSLString; + Shader* psShader = psContext->psShader; + + switch (psDecl->eOpcode) + { + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_PS_SGV: + case OPCODE_DCL_INPUT_PS_SIV: + { + const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; + switch (eSpecialName) + { + case NAME_POSITION: + { + if (psShader->eShaderType == PIXEL_SHADER) + { + AddBuiltinInput(psContext, psDecl, "gl_FragCoord", 4); + } + else + { + AddBuiltinInput(psContext, psDecl, "gl_Position", 4); + } + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_Layer", 1); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinInput(psContext, psDecl, "gl_ClipDistance", 4); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_ViewportIndex", 1); + break; + } + case NAME_INSTANCE_ID: + { + AddBuiltinInput(psContext, psDecl, "uint(gl_InstanceID)", 1); + break; + } + case NAME_IS_FRONT_FACE: + { + /* + Cast to uint used because + if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. + Suggests no implicit conversion for bool<->uint. + */ + + AddBuiltinInput(psContext, psDecl, "uint(gl_FrontFacing)", 1); + break; + } + case NAME_SAMPLE_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_SampleID", 1); + break; + } + case NAME_VERTEX_ID: + { + AddBuiltinInput(psContext, psDecl, "uint(gl_VertexID)", 1); + break; + } + case NAME_PRIMITIVE_ID: + { + AddBuiltinInput(psContext, psDecl, "gl_PrimitiveID", 1); + break; + } + default: + { + bformata(glsl, "in vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); + break; + } + } + break; + } + + case OPCODE_DCL_OUTPUT_SIV: + { + switch (psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_Position"); + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_Layer"); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_ClipDistance"); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_ViewportIndex"); + break; + } + case NAME_VERTEX_ID: + { + ASSERT(0); //VertexID is not an output + break; + } + case NAME_PRIMITIVE_ID: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_PrimitiveID"); + break; + } + case NAME_INSTANCE_ID: + { + ASSERT(0); //InstanceID is not an output + break; + } + case NAME_IS_FRONT_FACE: + { + ASSERT(0); //FrontFacing is not an output + break; + } + case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: + { + if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 4, "gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); + break; + } + case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[3]"); + break; + } + case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: + { + if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 3, "gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); + break; + } + case NAME_FINAL_LINE_DENSITY_TESSFACTOR: + { + if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_LINE_DETAIL_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_TRI_INSIDE_TESSFACTOR: + case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: + { + if (psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelInner"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[0]"); + } + break; + } + case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[1]"); + break; + } + default: + { + bformata(glsl, "out vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); + break; + } + } + break; + } + case OPCODE_DCL_INPUT: + { + const Operand* psOperand = &psDecl->asOperands[0]; + //Force the number of components to be 4. + /*dcl_output o3.xy + dcl_output o3.z + + Would generate a vec2 and a vec3. We discard the second one making .z invalid! + + */ + int iNumComponents = 4; //GetMaxComponentFromComponentMask(psOperand); + const char* StorageQualifier = "attribute"; + char* InputName; + const char* Precision = ""; + + if ((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT) || + (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID) || + (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK) || + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID) || + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID) || + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP) || + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED)) + { + break; + } + + //Already declared as part of an array. + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + break; + } + + InputName = GetDeclaredInputName(psContext, psShader->eShaderType, psOperand); + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + StorageQualifier = "in"; + } + + if (HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch (psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + break; + } + } + } + + DeclareInput(psContext, psDecl, + "", StorageQualifier, Precision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); + bcstrfree(InputName); + + break; + } + case OPCODE_DCL_INPUT_SIV: + { + if (psShader->eShaderType == PIXEL_SHADER) + { + psShader->sInfo.aePixelInputInterpolation[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eInterpolation; + } + break; + } + case OPCODE_DCL_INPUT_PS: + { + const Operand* psOperand = &psDecl->asOperands[0]; + int iNumComponents = 4; //GetMaxComponentFromComponentMask(psOperand); + const char* StorageQualifier = "varying"; + const char* Precision = ""; + char* InputName = GetDeclaredInputName(psContext, PIXEL_SHADER, psOperand); + const char* Interpolation = ""; + + //Already declared as part of an array. + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + break; + } + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + StorageQualifier = "in"; + } + + switch (psDecl->value.eInterpolation) + { + case INTERPOLATION_CONSTANT: + { + Interpolation = "flat"; + break; + } + case INTERPOLATION_LINEAR: + { + break; + } + case INTERPOLATION_LINEAR_CENTROID: + { + Interpolation = "centroid"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE: + { + Interpolation = "noperspective"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: + { + Interpolation = "noperspective centroid"; + break; + } + case INTERPOLATION_LINEAR_SAMPLE: + { + Interpolation = "sample"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: + { + Interpolation = "noperspective sample"; + break; + } + } + + if (HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch (psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + break; + } + } + } + + DeclareInput(psContext, psDecl, + Interpolation, StorageQualifier, Precision, iNumComponents, INDEX_1D, InputName); + bcstrfree(InputName); + + break; + } + case OPCODE_DCL_TEMPS: + { + const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; + + if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) + { + break; + } + + if (ui32NumTemps > 0) + { + bformata(glsl, "vec4 Temp[%d];\n", ui32NumTemps); + if (psContext->psShader->bUseTempCopy) + { + bcatcstr(glsl, "vec4 TempCopy;\n"); + } + + bformata(glsl, "ivec4 Temp_int[%d];\n", ui32NumTemps); + if (psContext->psShader->bUseTempCopy) + { + bcatcstr(glsl, "vec4 TempCopy_int;\n"); + } + if (HaveUVec(psShader->eTargetLanguage)) + { + bformata(glsl, "uvec4 Temp_uint[%d];\n", ui32NumTemps); + if (psContext->psShader->bUseTempCopy) + { + bcatcstr(glsl, "uvec4 TempCopy_uint;\n"); + } + } + if (psShader->fp64) + { + bformata(glsl, "dvec4 Temp_double[%d];\n", ui32NumTemps); + if (psContext->psShader->bUseTempCopy) + { + bcatcstr(glsl, "dvec4 TempCopy_double;\n"); + } + } + } + + break; + } + case OPCODE_SPECIAL_DCL_IMMCONST: + { + const Operand* psDest = &psDecl->asOperands[0]; + const Operand* psSrc = &psDecl->asOperands[1]; + + ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); + if (psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) + { + bformata(glsl, "const ivec4 IntImmConst%d = ", psDest->ui32RegisterNumber); + } + else + { + bformata(glsl, "const vec4 ImmConst%d = ", psDest->ui32RegisterNumber); + AddToDx9ImmConstIndexableArray(psContext, psDest); + } + TranslateOperand(psContext, psSrc, TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + + break; + } + case OPCODE_DCL_CONSTANT_BUFFER: + { + const Operand* psOperand = &psDecl->asOperands[0]; + const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; + + ConstantBuffer* psCBuf = NULL; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + if (psCBuf) + { + // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. + // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads + // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. + psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; + } + + // We don't have a original resource name, maybe generate one??? + if (!psCBuf) + { + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) + { + bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + } + + bformata(glsl, "layout(std140) uniform ConstantBuffer%d {\n\tvec4 data[%d];\n} cb%d;\n", ui32BindingPoint, psOperand->aui32ArraySizes[1], ui32BindingPoint); + break; + } + else if (psCBuf->blob) + { + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) + { + bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + } + + bcatcstr(glsl, "layout(std140) uniform "); + ConvertToUniformBufferName(glsl, psShader, psCBuf->Name); + bcatcstr(glsl, " {\n\tvec4 "); + ConvertToUniformBufferName(glsl, psShader, psCBuf->Name); + bformata(glsl, "_data[%d];\n};\n", psOperand->aui32ArraySizes[1]); + break; + } + + if (psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) + { + if (psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO && psCBuf->Name[0] == '$') + { + DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand); + } + else + { + DeclareUBOConstants(psContext, ui32BindingPoint, psCBuf); + } + } + else + { + DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand); + } + break; + } + case OPCODE_DCL_RESOURCE: + { + bool isGmemResource = false; + const int initialMemSize = 64; + bstring earlyMain = bfromcstralloc(initialMemSize, ""); + if (IsGmemReservedSlot(FBF_EXT_COLOR, psDecl->asOperands[0].ui32RegisterNumber)) + { + // A GMEM reserve slot was used. + // This is not a resource but an inout RT of the pixel shader + int regNum = GetGmemInputResourceSlot(psDecl->asOperands[0].ui32RegisterNumber); + // FXC thinks this is a texture so we can't trust the number of elements. We get that from the "register number". + int numElements = GetGmemInputResourceNumElements(psDecl->asOperands[0].ui32RegisterNumber); + ASSERT(numElements); + + const char* Precision = "highp"; + const char* outputName = "PixOutput"; + + bformata(glsl, "layout(location = %d) ", regNum); + bformata(glsl, "inout %s vec%d %s%d;\n", Precision, numElements, outputName, regNum); + + const char* mask[] = { "x", "y", "z", "w" }; + // Since we are using Textures as GMEM inputs FXC will threat them as vec4 values. The rendertarget may not be a vec4 (numElements != 4) + // so we create a new variable (GMEM_InputXX) at the beginning of the shader that wraps the rendertarget value. + bformata(earlyMain, "%s vec4 GMEM_Input%d = %s vec4(%s%d.", Precision, regNum, Precision, outputName, regNum); + for (int i = 0; i < 4; ++i) + { + bformata(earlyMain, "%s", i < numElements ? mask[i] : mask[numElements - 1]); + } + bcatcstr(earlyMain, ");\n"); + isGmemResource = true; + } + else if (IsGmemReservedSlot(FBF_ARM_COLOR, psDecl->asOperands[0].ui32RegisterNumber)) + { + bcatcstr(earlyMain, "vec4 GMEM_Input0 = vec4(gl_LastFragColorARM);\n"); + isGmemResource = true; + } + else if (IsGmemReservedSlot(FBF_ARM_DEPTH, psDecl->asOperands[0].ui32RegisterNumber)) + { + bcatcstr(earlyMain, "vec4 GMEM_Depth = vec4(gl_LastFragDepthARM);\n"); + isGmemResource = true; + } + else if (IsGmemReservedSlot(FBF_ARM_STENCIL, psDecl->asOperands[0].ui32RegisterNumber)) + { + bcatcstr(earlyMain, "ivec4 GMEM_Stencil = ivec4(gl_LastFragStencilARM);\n"); + isGmemResource = true; + } + + if (isGmemResource) + { + if (earlyMain->slen) + { + bstring* savedStringPtr = psContext->currentGLSLString; + psContext->currentGLSLString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + bconcat(*psContext->currentGLSLString, earlyMain); + psContext->indent--; + psContext->currentGLSLString = savedStringPtr; + } + break; + } + + char* szResourceTypeName = ""; + uint32_t bCanBeCompare; + uint32_t i; + SamplerMask sMask; + + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions) && (psContext->flags & HLSLCC_FLAG_AVOID_RESOURCE_BINDINGS_AND_LOCATIONS) == 0) + { + //Constant buffer locations start at 0. Resource locations start at ui32NumConstantBuffers. + bformata(glsl, "layout(location = %d) ", psContext->psShader->sInfo.ui32NumConstantBuffers + psDecl->asOperands[0].ui32RegisterNumber); + } + + switch (psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_BUFFER: + szResourceTypeName = "Buffer"; + bCanBeCompare = 0; + break; + case RESOURCE_DIMENSION_TEXTURE1D: + szResourceTypeName = "1D"; + bCanBeCompare = 1; + break; + case RESOURCE_DIMENSION_TEXTURE2D: + szResourceTypeName = "2D"; + bCanBeCompare = 1; + break; + case RESOURCE_DIMENSION_TEXTURE2DMS: + szResourceTypeName = "2DMS"; + bCanBeCompare = 0; + break; + case RESOURCE_DIMENSION_TEXTURE3D: + szResourceTypeName = "3D"; + bCanBeCompare = 0; + break; + case RESOURCE_DIMENSION_TEXTURECUBE: + szResourceTypeName = "Cube"; + bCanBeCompare = 1; + break; + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + szResourceTypeName = "1DArray"; + bCanBeCompare = 1; + break; + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + szResourceTypeName = "2DArray"; + bCanBeCompare = 1; + break; + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + szResourceTypeName = "2DMSArray"; + bCanBeCompare = 0; + break; + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + szResourceTypeName = "CubeArray"; + bCanBeCompare = 1; + break; + } + + for (i = 0; i < psShader->sInfo.ui32NumSamplers; ++i) + { + if (psShader->sInfo.asSamplers[i].sMask.ui10TextureBindPoint == psDecl->asOperands[0].ui32RegisterNumber) + { + sMask = psShader->sInfo.asSamplers[i].sMask; + + if (bCanBeCompare && sMask.bCompareSample) // Sampled with depth comparison + { + bformata(glsl, "uniform sampler%sShadow ", szResourceTypeName); + TextureName(*psContext->currentGLSLString, psContext->psShader, psDecl->asOperands[0].ui32RegisterNumber, sMask.ui10SamplerBindPoint, 1); + bcatcstr(glsl, ";\n"); + } + if (sMask.bNormalSample || !sMask.bCompareSample) // Either sampled normally or with texelFetch + { + if (psDecl->ui32TexReturnType == RETURN_TYPE_SINT) + { + bformata(glsl, "uniform isampler%s ", szResourceTypeName); + } + else if (psDecl->ui32TexReturnType == RETURN_TYPE_UINT) + { + bformata(glsl, "uniform usampler%s ", szResourceTypeName); + } + else + { + bformata(glsl, "uniform sampler%s ", szResourceTypeName); + } + TextureName(*psContext->currentGLSLString, psContext->psShader, psDecl->asOperands[0].ui32RegisterNumber, sMask.ui10SamplerBindPoint, 0); + bcatcstr(glsl, ";\n"); + } + } + } + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); + psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; + break; + } + case OPCODE_DCL_OUTPUT: + { + if (psShader->eShaderType == HULL_SHADER && psDecl->asOperands[0].ui32RegisterNumber == 0) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_out[gl_InvocationID].gl_Position"); + } + else + { + AddUserOutput(psContext, psDecl); + } + break; + } + case OPCODE_DCL_GLOBAL_FLAGS: + { + uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; + + // OpenGL versions lower than 4.1 don't support the + // layout(early_fragment_tests) directive and will fail to compile + // the shader + if (ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL && EarlyDepthTestSupported(psShader->eTargetLanguage) && + !(psShader->eGmemType & (FBF_ARM_DEPTH | FBF_ARM_STENCIL))) // Early fragment test is not allowed when fetching from the depth/stencil buffer. + { + bcatcstr(glsl, "layout(early_fragment_tests) in;\n"); + } + if (!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) + { + //TODO add precise + //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx + } + if (ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) + { + bcatcstr(glsl, "#extension GL_ARB_gpu_shader_fp64 : enable\n"); + psShader->fp64 = 1; + } + break; + } + + case OPCODE_DCL_THREAD_GROUP: + { + bformata(glsl, "layout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\n", + psDecl->value.aui32WorkGroupSize[0], + psDecl->value.aui32WorkGroupSize[1], + psDecl->value.aui32WorkGroupSize[2]); + break; + } + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + { + if (psContext->psShader->eShaderType == HULL_SHADER) + { + psContext->psShader->sInfo.eTessOutPrim = psDecl->value.eTessOutPrim; + } + break; + } + case OPCODE_DCL_TESS_DOMAIN: + { + if (psContext->psShader->eShaderType == DOMAIN_SHADER) + { + switch (psDecl->value.eTessDomain) + { + case TESSELLATOR_DOMAIN_ISOLINE: + { + bcatcstr(glsl, "layout(isolines) in;\n"); + break; + } + case TESSELLATOR_DOMAIN_TRI: + { + bcatcstr(glsl, "layout(triangles) in;\n"); + break; + } + case TESSELLATOR_DOMAIN_QUAD: + { + bcatcstr(glsl, "layout(quads) in;\n"); + break; + } + default: + { + break; + } + } + } + break; + } + case OPCODE_DCL_TESS_PARTITIONING: + { + if (psContext->psShader->eShaderType == HULL_SHADER) + { + psContext->psShader->sInfo.eTessPartitioning = psDecl->value.eTessPartitioning; + } + break; + } + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + { + switch (psDecl->value.eOutputPrimitiveTopology) + { + case PRIMITIVE_TOPOLOGY_POINTLIST: + { + bcatcstr(glsl, "layout(points) out;\n"); + break; + } + case PRIMITIVE_TOPOLOGY_LINELIST_ADJ: + case PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: + case PRIMITIVE_TOPOLOGY_LINELIST: + case PRIMITIVE_TOPOLOGY_LINESTRIP: + { + bcatcstr(glsl, "layout(line_strip) out;\n"); + break; + } + + case PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: + case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: + case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + case PRIMITIVE_TOPOLOGY_TRIANGLELIST: + { + bcatcstr(glsl, "layout(triangle_strip) out;\n"); + break; + } + default: + { + break; + } + } + break; + } + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + bformata(glsl, "layout(max_vertices = %d) out;\n", psDecl->value.ui32MaxOutputVertexCount); + break; + } + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + { + switch (psDecl->value.eInputPrimitive) + { + case PRIMITIVE_POINT: + { + bcatcstr(glsl, "layout(points) in;\n"); + break; + } + case PRIMITIVE_LINE: + { + bcatcstr(glsl, "layout(lines) in;\n"); + break; + } + case PRIMITIVE_LINE_ADJ: + { + bcatcstr(glsl, "layout(lines_adjacency) in;\n"); + break; + } + case PRIMITIVE_TRIANGLE: + { + bcatcstr(glsl, "layout(triangles) in;\n"); + break; + } + case PRIMITIVE_TRIANGLE_ADJ: + { + bcatcstr(glsl, "layout(triangles_adjacency) in;\n"); + break; + } + default: + { + break; + } + } + break; + } + case OPCODE_DCL_INTERFACE: + { + const uint32_t interfaceID = psDecl->value.interface.ui32InterfaceID; + const uint32_t numUniforms = psDecl->value.interface.ui32ArraySize; + const uint32_t ui32NumBodiesPerTable = psContext->psShader->funcPointer[interfaceID].ui32NumBodiesPerTable; + ShaderVar* psVar; + uint32_t varFound; + + const char* uniformName; + + varFound = GetInterfaceVarFromOffset(interfaceID, &psContext->psShader->sInfo, &psVar); + ASSERT(varFound); + uniformName = &psVar->sType.Name[0]; + + bformata(glsl, "subroutine uniform SubroutineType %s[%d*%d];\n", uniformName, numUniforms, ui32NumBodiesPerTable); + break; + } + case OPCODE_DCL_FUNCTION_BODY: + { + //bformata(glsl, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); + break; + } + case OPCODE_DCL_FUNCTION_TABLE: + { + break; + } + case OPCODE_CUSTOMDATA: + { + const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; + const uint32_t ui32NumVec4Minus1 = (ui32NumVec4 - 1); + uint32_t ui32ConstIndex = 0; + int integerCoords[4]; + bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; + + if (qualcommWorkaround) + { + bformata(glsl, "const "); + } + + bformata(glsl, "ivec4 immediateConstBufferInt[%d] = ivec4[%d] (\n", ui32NumVec4, ui32NumVec4); + for (ui32ConstIndex = 0; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) + { + integerCoords[0] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + integerCoords[1] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + integerCoords[2] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + integerCoords[3] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + + bformata(glsl, "\tivec4(%d, %d, %d, %d), \n", integerCoords[0], integerCoords[1], integerCoords[2], integerCoords[3]); + } + //No trailing comma on this one + integerCoords[0] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + integerCoords[1] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + integerCoords[2] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + integerCoords[3] = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + + bformata(glsl, "\tivec4(%d, %d, %d, %d)\n", integerCoords[0], integerCoords[1], integerCoords[2], integerCoords[3]); + bcatcstr(glsl, ");\n"); + + //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. + //else 2 buffers - one integer and one float. - More data + + if (ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) + { + float floatCoords[4]; + bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(glsl, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); + + bformata(glsl, "vec4 immediateConstBuffer[%d] = vec4[%d] (\n", ui32NumVec4, ui32NumVec4); + for (ui32ConstIndex = 0; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) + { + floatCoords[0] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + floatCoords[1] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + floatCoords[2] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + floatCoords[3] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + + //A single vec4 can mix integer and float types. + //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. + if (fpcheck(floatCoords[0])) + { + floatCoords[0] = 0; + } + if (fpcheck(floatCoords[1])) + { + floatCoords[1] = 0; + } + if (fpcheck(floatCoords[2])) + { + floatCoords[2] = 0; + } + if (fpcheck(floatCoords[3])) + { + floatCoords[3] = 0; + } + + bformata(glsl, "\tvec4(%e, %e, %e, %e), \n", floatCoords[0], floatCoords[1], floatCoords[2], floatCoords[3]); + } + //No trailing comma on this one + floatCoords[0] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + floatCoords[1] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + floatCoords[2] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + floatCoords[3] = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + if (fpcheck(floatCoords[0])) + { + floatCoords[0] = 0; + } + if (fpcheck(floatCoords[1])) + { + floatCoords[1] = 0; + } + if (fpcheck(floatCoords[2])) + { + floatCoords[2] = 0; + } + if (fpcheck(floatCoords[3])) + { + floatCoords[3] = 0; + } + bformata(glsl, "\tvec4(%e, %e, %e, %e)\n", floatCoords[0], floatCoords[1], floatCoords[2], floatCoords[3]); + bcatcstr(glsl, ");\n"); + } + else + { + if (qualcommWorkaround) + { + bcatcstr(glsl, "ivec4 immediateConstBufferI(int idx) { return immediateConstBufferInt[idx]; }\n"); + bcatcstr(glsl, "vec4 immediateConstBufferF(int idx) { return intBitsToFloat(immediateConstBufferInt[idx]); }\n"); + } + else + { + bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(glsl, "#define immediateConstBufferF(idx) intBitsToFloat(immediateConstBufferInt[idx])\n"); + } + } + + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + const uint32_t forkPhaseNum = psDecl->value.aui32HullPhaseInstanceInfo[0]; + const uint32_t instanceCount = psDecl->value.aui32HullPhaseInstanceInfo[1]; + bformata(glsl, "const int HullPhase%dInstanceCount = %d;\n", forkPhaseNum, instanceCount); + break; + } + case OPCODE_DCL_INDEXABLE_TEMP: + { + const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; + const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; + const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; + bformata(glsl, "vec%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + bformata(glsl, "ivec%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + if (HaveUVec(psShader->eTargetLanguage)) + { + bformata(glsl, "uvec%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + } + if (psShader->fp64) + { + bformata(glsl, "dvec%d TempArray%d_double[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + } + break; + } + case OPCODE_DCL_INDEX_RANGE: + { + break; + } + case OPCODE_HS_DECLS: + { + break; + } + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + { + if (psContext->psShader->eShaderType == HULL_SHADER) + { + bformata(glsl, "layout(vertices=%d) out;\n", psDecl->value.ui32MaxOutputVertexCount); + } + break; + } + case OPCODE_HS_FORK_PHASE: + { + break; + } + case OPCODE_HS_JOIN_PHASE: + { + break; + } + case OPCODE_DCL_SAMPLER: + { + break; + } + case OPCODE_DCL_HS_MAX_TESSFACTOR: + { + //For GLSL the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + { + if (psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) + { + bcatcstr(glsl, "coherent "); + } + + if (psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] == 0) + { + bcatcstr(glsl, "writeonly "); + } + else + { + if (psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) + { + bcatcstr(glsl, "readonly "); + } + + switch (psDecl->sUAV.Type) + { + case RETURN_TYPE_FLOAT: + bcatcstr(glsl, "layout(rgba32f) "); + break; + case RETURN_TYPE_UNORM: + bcatcstr(glsl, "layout(rgba8) "); + break; + case RETURN_TYPE_SNORM: + bcatcstr(glsl, "layout(rgba8_snorm) "); + break; + case RETURN_TYPE_UINT: + bcatcstr(glsl, "layout(rgba32ui) "); + break; + case RETURN_TYPE_SINT: + bcatcstr(glsl, "layout(rgba32i) "); + break; + default: + ASSERT(0); + } + } + + { + char* prefix = ""; + switch (psDecl->sUAV.Type) + { + case RETURN_TYPE_UINT: + prefix = "u"; + break; + case RETURN_TYPE_SINT: + prefix = "i"; + break; + default: + break; + } + + switch (psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_BUFFER: + bformata(glsl, "uniform %simageBuffer ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE1D: + bformata(glsl, "uniform %simage1D ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE2D: + bformata(glsl, "uniform %simage2D ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE2DMS: + bformata(glsl, "uniform %simage2DMS ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE3D: + bformata(glsl, "uniform %simage3D ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURECUBE: + bformata(glsl, "uniform %simageCube ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + bformata(glsl, "uniform %simage1DArray ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + bformata(glsl, "uniform %simage2DArray ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + bformata(glsl, "uniform %simage3DArray ", prefix); + break; + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + bformata(glsl, "uniform %simageCubeArray ", prefix); + break; + } + } + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + { + const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; + ConstantBuffer* psCBuf = NULL; + + if (psDecl->sUAV.bCounter) + { + bformata(glsl, "layout (binding = 1) uniform atomic_uint UAV%d_counter;\n", psDecl->asOperands[0].ui32RegisterNumber); + } + + GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + if (ui32BindingPoint >= GMEM_PLS_RO_SLOT && ui32BindingPoint <= GMEM_PLS_RW_SLOT) + { + DeclarePLSVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED); + } + else + { + DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED); + } + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + { + bstring varName; + if (psDecl->sUAV.bCounter) + { + bformata(glsl, "layout (binding = 1) uniform atomic_uint UAV%d_counter;\n", psDecl->asOperands[0].ui32RegisterNumber); + } + + varName = bfromcstralloc(16, ""); + bformata(varName, "UAV%d", psDecl->asOperands[0].ui32RegisterNumber); + + bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); + ShaderVarName(glsl, psShader, bstr2cstr(varName, '\0')); + bcatcstr(glsl, "[];\n};\n"); + + bdestroy(varName); + break; + } + case OPCODE_DCL_RESOURCE_STRUCTURED: + { + ConstantBuffer* psCBuf = NULL; + + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], 0, RTYPE_STRUCTURED); + break; + } + case OPCODE_DCL_RESOURCE_RAW: + { + bstring varName = bfromcstralloc(16, ""); + bformata(varName, "RawRes%d", psDecl->asOperands[0].ui32RegisterNumber); + + bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); + ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); + bcatcstr(glsl, "[];\n};\n"); + + bdestroy(varName); + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + { + ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); + ASSERT(psDecl->sTGSM.ui32Count == 1); + + bcatcstr(glsl, "shared uint "); + + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, "[%d];\n", psDecl->sTGSM.ui32Count); + + memset(psVarType, 0, sizeof(ShaderVarType)); + strcpy(psVarType->Name, "$Element"); + + psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; + psVarType->Elements = psDecl->sTGSM.ui32Count; + psVarType->Type = SVT_UINT; + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + { + ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); + + bcatcstr(glsl, "shared struct {\n"); + bformata(glsl, "uint value[%d];\n", psDecl->sTGSM.ui32Stride / 4); + bcatcstr(glsl, "} "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, "[%d];\n", + psDecl->sTGSM.ui32Count); + + memset(psVarType, 0, sizeof(ShaderVarType)); + strcpy(psVarType->Name, "$Element"); + + psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; + psVarType->Elements = psDecl->sTGSM.ui32Count; + psVarType->Type = SVT_UINT; + break; + } + case OPCODE_DCL_STREAM: + { + ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_STREAM); + + psShader->ui32CurrentVertexOutputStream = psDecl->asOperands[0].ui32RegisterNumber; + + bformata(glsl, "layout(stream = %d) out;\n", psShader->ui32CurrentVertexOutputStream); + + break; + } + case OPCODE_DCL_GS_INSTANCE_COUNT: + { + bformata(glsl, "layout(invocations = %d) in;\n", psDecl->value.ui32GSInstanceCount); + break; + } + default: + { + ASSERT(0); + break; + } + } +} + +//Convert from per-phase temps to global temps for GLSL. +void ConsolidateHullTempVars(Shader* psShader) +{ + uint32_t i, k; + const uint32_t ui32NumDeclLists = 3 + psShader->ui32ForkPhaseCount; + Declaration* pasDeclArray[3 + MAX_FORK_PHASES]; + uint32_t aui32DeclCounts[3 + MAX_FORK_PHASES]; + uint32_t ui32NumTemps = 0; + + i = 0; + + pasDeclArray[i] = psShader->psHSDecl; + aui32DeclCounts[i++] = psShader->ui32HSDeclCount; + + pasDeclArray[i] = psShader->psHSControlPointPhaseDecl; + aui32DeclCounts[i++] = psShader->ui32HSControlPointDeclCount; + for (k = 0; k < psShader->ui32ForkPhaseCount; ++k) + { + pasDeclArray[i] = psShader->apsHSForkPhaseDecl[k]; + aui32DeclCounts[i++] = psShader->aui32HSForkDeclCount[k]; + } + pasDeclArray[i] = psShader->psHSJoinPhaseDecl; + aui32DeclCounts[i++] = psShader->ui32HSJoinDeclCount; + + for (k = 0; k < ui32NumDeclLists; ++k) + { + for (i = 0; i < aui32DeclCounts[k]; ++i) + { + Declaration* psDecl = pasDeclArray[k] + i; + + if (psDecl->eOpcode == OPCODE_DCL_TEMPS) + { + if (ui32NumTemps < psDecl->value.ui32NumTemps) + { + //Find the total max number of temps needed by the entire + //shader. + ui32NumTemps = psDecl->value.ui32NumTemps; + } + //Only want one global temp declaration. + psDecl->value.ui32NumTemps = 0; + } + } + } + + //Find the first temp declaration and make it + //declare the max needed amount of temps. + for (k = 0; k < ui32NumDeclLists; ++k) + { + for (i = 0; i < aui32DeclCounts[k]; ++i) + { + Declaration* psDecl = pasDeclArray[k] + i; + + if (psDecl->eOpcode == OPCODE_DCL_TEMPS) + { + psDecl->value.ui32NumTemps = ui32NumTemps; + return; + } + } + } +} + +const char* GetMangleSuffix(const SHADER_TYPE eShaderType) +{ + switch (eShaderType) + { + case VERTEX_SHADER: + return "VS"; + case PIXEL_SHADER: + return "PS"; + case GEOMETRY_SHADER: + return "GS"; + case HULL_SHADER: + return "HS"; + case DOMAIN_SHADER: + return "DS"; + case COMPUTE_SHADER: + return "CS"; + } + ASSERT(0); + return ""; +} + diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c new file mode 100644 index 0000000000..e5124b4122 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/toGLSLInstruction.c @@ -0,0 +1,5598 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toGLSLInstruction.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/languages.h" +#include "internal_includes/hlslccToolkit.h" +#include "bstrlib.h" +#include "stdio.h" +#include "internal_includes/debug.h" + +#include <stdbool.h> + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); +extern void WriteEndTrace(HLSLCrossCompilerContext* psContext); + +typedef enum +{ + CMP_EQ, + CMP_LT, + CMP_GE, + CMP_NE, +} ComparisonType; + +void BeginAssignmentEx(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate, const char* szDestSwizzle) +{ + if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) + { + const char* szCastFunction = ""; + SHADER_VARIABLE_TYPE eSrcType; + SHADER_VARIABLE_TYPE eDestType = GetOperandDataType(psContext, psDestOperand); + uint32_t uDestElemCount = GetNumSwizzleElements(psDestOperand); + + eSrcType = TypeFlagsToSVTType(uSrcToFlag); + if (bSaturate) + { + eSrcType = SVT_FLOAT; + } + + if (!DoAssignmentDataTypesMatch(eDestType, eSrcType)) + { + switch (eDestType) + { + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + { + switch (eSrcType) + { + case SVT_UINT: + case SVT_UINT16: + szCastFunction = GetConstructorForTypeGLSL(psContext, eDestType, uDestElemCount, false); + break; + case SVT_FLOAT: + szCastFunction = "floatBitsToInt"; + break; + default: + // Bitcasts from lower precisions floats are ambiguous + ASSERT(0); + break; + } + } + break; + case SVT_UINT: + case SVT_UINT16: + { + switch (eSrcType) + { + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + szCastFunction = GetConstructorForTypeGLSL(psContext, eDestType, uDestElemCount, false); + break; + case SVT_FLOAT: + szCastFunction = "floatBitsToUint"; + break; + default: + // Bitcasts from lower precisions floats are ambiguous + ASSERT(0); + break; + } + } + break; + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + { + switch (eSrcType) + { + case SVT_UINT: + szCastFunction = "uintBitsToFloat"; + break; + case SVT_INT: + szCastFunction = "intBitsToFloat"; + break; + default: + // Bitcasts from lower precisions int/uint are ambiguous + ASSERT(0); + break; + } + } + break; + default: + ASSERT(0); + break; + } + } + + TranslateOperand(psContext, psDestOperand, TO_FLAG_DESTINATION); + if (szDestSwizzle) + { + bformata(*psContext->currentGLSLString, ".%s = %s(", szDestSwizzle, szCastFunction); + } + else + { + bformata(*psContext->currentGLSLString, " = %s(", szCastFunction); + } + } + else + { + TranslateOperand(psContext, psDestOperand, TO_FLAG_DESTINATION | uSrcToFlag); + if (szDestSwizzle) + { + bformata(*psContext->currentGLSLString, ".%s = ", szDestSwizzle); + } + else + { + bcatcstr(*psContext->currentGLSLString, " = "); + } + } + if (bSaturate) + { + bcatcstr(*psContext->currentGLSLString, "clamp("); + } +} + +void BeginAssignment(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate) +{ + BeginAssignmentEx(psContext, psDestOperand, uSrcToFlag, bSaturate, NULL); +} + +void EndAssignment(HLSLCrossCompilerContext* psContext, const Operand* psDestOperand, uint32_t uSrcToFlag, uint32_t bSaturate) +{ + (void)psDestOperand; + (void)uSrcToFlag; + + if (bSaturate) + { + bcatcstr(*psContext->currentGLSLString, ", 0.0, 1.0)"); + } + + if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) + { + bcatcstr(*psContext->currentGLSLString, ")"); + } +} + +static void AddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, ComparisonType eType, + uint32_t typeFlag) +{ + bstring glsl = *psContext->currentGLSLString; + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + const uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); + + uint32_t minElemCount = destElemCount < s0ElemCount ? destElemCount : s0ElemCount; + + minElemCount = s1ElemCount < minElemCount ? s1ElemCount : minElemCount; + + if (typeFlag == TO_FLAG_NONE) + { + const SHADER_VARIABLE_TYPE e0Type = GetOperandDataType(psContext, &psInst->asOperands[1]); + const SHADER_VARIABLE_TYPE e1Type = GetOperandDataType(psContext, &psInst->asOperands[2]); + if (e0Type != e1Type) + { + typeFlag = TO_FLAG_INTEGER; + } + else + { + switch (e0Type) + { + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + typeFlag = TO_FLAG_INTEGER; + break; + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + typeFlag = TO_FLAG_UNSIGNED_INTEGER; + break; + default: + typeFlag = TO_FLAG_FLOAT; + } + } + } + + if (destElemCount > 1) + { + const char* glslOpcode [] = { + "equal", + "lessThan", + "greaterThanEqual", + "notEqual", + }; + char* constructor = "vec"; + + if (typeFlag & TO_FLAG_INTEGER) + { + constructor = "ivec"; + } + else if (typeFlag & TO_FLAG_UNSIGNED_INTEGER) + { + constructor = "uvec"; + } + + bstring varName = bfromcstr(GetAuxArgumentName(SVT_UINT)); + bcatcstr(varName, "1"); + + //Component-wise compare + AddIndentation(psContext); + if (psContext->psShader->ui32MajorVersion < 4) + { + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + } + else + { + // Qualcomm driver workaround. Save the operation result into + // a temporary variable before assigning it to the register. + bconcat(glsl, varName); + AddSwizzleUsingElementCount(psContext, minElemCount); + bcatcstr(glsl, " = "); + } + + bformata(glsl, "uvec%d(%s(%s4(", minElemCount, glslOpcode[eType], constructor); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + //AddSwizzleUsingElementCount(psContext, minElemCount); + bformata(glsl, ", %s4(", constructor); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + //AddSwizzleUsingElementCount(psContext, minElemCount); + if (psContext->psShader->ui32MajorVersion < 4) + { + //Result is 1.0f or 0.0f + bcatcstr(glsl, "))"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + } + else + { + bcatcstr(glsl, ")) * 0xFFFFFFFFu;\n"); + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bconcat(glsl, varName); + AddSwizzleUsingElementCount(psContext, minElemCount); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + } + bcatcstr(glsl, ";\n"); + } + else + { + const char* glslOpcode [] = { + "==", + "<", + ">=", + "!=", + }; + + bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; + const char* tempVariableName = "cond"; + //Scalar compare + AddIndentation(psContext); + // There's a bug with Qualcomm OpenGLES 3.0 drivers that + // makes something like this: "temp1.x = temp2.x == 0 ? 1.0f : 0.0f" always return 0.0f + // The workaround is saving the result in a temp variable: bool cond = temp2.x == 0; temp1.x = !!cond ? 1.0f : 0.0f + if (qualcommWorkaround) + { + bcatcstr(glsl, "{\n"); + ++psContext->indent; + AddIndentation(psContext); + bformata(glsl, "bool %s = ", tempVariableName); + bcatcstr(glsl, "("); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bcatcstr(glsl, ")"); + if (s0ElemCount > minElemCount) + { + AddSwizzleUsingElementCount(psContext, minElemCount); + } + bformata(glsl, " %s (", glslOpcode[eType]); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(glsl, ")"); + if (s1ElemCount > minElemCount) + { + AddSwizzleUsingElementCount(psContext, minElemCount); + } + bcatcstr(glsl, ";\n"); + AddIndentation(psContext); + } + + if (psContext->psShader->ui32MajorVersion < 4) + { + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + } + else + { + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + } + + if (qualcommWorkaround) + { + // Using the temporary variable where we stored the result of the comparison for the ternary operator. + bformata(glsl, "!!%s ", tempVariableName); + } + else + { + bcatcstr(glsl, "(("); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bcatcstr(glsl, ")"); + if (s0ElemCount > minElemCount) + { + AddSwizzleUsingElementCount(psContext, minElemCount); + } + bformata(glsl, " %s (", glslOpcode[eType]); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(glsl, ")"); + if (s1ElemCount > minElemCount) + { + AddSwizzleUsingElementCount(psContext, minElemCount); + } + bcatcstr(glsl, ") "); + } + + if (psContext->psShader->ui32MajorVersion < 4) + { + bcatcstr(glsl, "? 1.0f : 0.0f"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + } + else + { + bcatcstr(glsl, "? 0xFFFFFFFFu : uint(0)"); // Adreno can't handle 0u (it's treated as int) + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + } + bcatcstr(glsl, ";\n"); + if (qualcommWorkaround) + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + } + } +} + +static void AddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDst, const Operand* pSrc, uint32_t bSrcCopy, uint32_t bSaturate) +{ + bstring glsl = *psContext->currentGLSLString; + + const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataType(psContext, pSrc); + uint32_t srcCount = GetNumSwizzleElements(pSrc); + uint32_t dstCount = GetNumSwizzleElements(pDst); + uint32_t bMismatched = 0; + + uint32_t ui32SrcFlags = TO_FLAG_FLOAT; + if (!bSaturate) + { + switch (eSrcType) + { + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + ui32SrcFlags = TO_FLAG_INTEGER; + break; + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + ui32SrcFlags = TO_FLAG_UNSIGNED_INTEGER; + break; + } + } + if (bSrcCopy) + { + ui32SrcFlags |= TO_FLAG_COPY; + } + + AddIndentation(psContext); + BeginAssignment(psContext, pDst, ui32SrcFlags, bSaturate); + + //Mismatched element count or destination has any swizzle + if (srcCount != dstCount || (GetFirstOperandSwizzle(psContext, pDst) != -1)) + { + bMismatched = 1; + + // Special case for immediate operands that can be folded into *vec4 + if (srcCount == 1) + { + switch (ui32SrcFlags) + { + case TO_FLAG_INTEGER: + bcatcstr(glsl, "ivec4"); + break; + case TO_FLAG_UNSIGNED_INTEGER: + bcatcstr(glsl, "uvec4"); + break; + default: + bcatcstr(glsl, "vec4"); + } + } + + bcatcstr(glsl, "("); + } + + TranslateOperand(psContext, pSrc, ui32SrcFlags); + + if (bMismatched) + { + bcatcstr(glsl, ")"); + + if (GetFirstOperandSwizzle(psContext, pDst) != -1) + { + TranslateOperandSwizzle(psContext, pDst); + } + else + { + AddSwizzleUsingElementCount(psContext, dstCount); + } + } + + EndAssignment(psContext, pDst, ui32SrcFlags, bSaturate); + bcatcstr(glsl, ";\n"); +} + +static void AddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, uint32_t bDestCopy, const Operand* src0, const Operand* src1, const Operand* src2) +{ + bstring glsl = *psContext->currentGLSLString; + + uint32_t destElemCount = GetNumSwizzleElements(pDest); + uint32_t s0ElemCount = GetNumSwizzleElements(src0); + uint32_t s1ElemCount = GetNumSwizzleElements(src1); + uint32_t s2ElemCount = GetNumSwizzleElements(src2); + uint32_t destElem; + int qualcommWorkaround = psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND; + + const char* swizzles = "xyzw"; + uint32_t eDstDataType; + const char* szVecType; + + uint32_t uDestFlags = TO_FLAG_DESTINATION; + if (bDestCopy) + { + uDestFlags |= TO_FLAG_COPY; + } + + AddIndentation(psContext); + // Qualcomm OpenGLES 3.0 bug that makes something likes this: + // temp4.xyz = vec3(floatsToInt(temp1).x != 0 ? temp2.x : temp2.x, floatsToInt(temp1).y != 0 ? temp2.y : temp2.y, floatsToInt(temp1).z != 0 ? temp2.z : temp2.z) + // to fail in the ternary operator. The workaround is to save the floatToInt(temp1) into a temp variable: + // { ivec4 cond = floatsToInt(temp1); temp4.xyz = vec3(cond.x != 0 ? temp2.x : temp2.x, cond.y != 0 ? temp2.y : temp2.y, cond.z != 0 ? temp2.z : temp2.z); } + if (qualcommWorkaround) + { + bformata(glsl, "{\n"); + ++psContext->indent; + AddIndentation(psContext); + if (s0ElemCount > 1) + bformata(glsl, "ivec%d cond = ", s0ElemCount); + else + bformata(glsl, "int cond = "); + TranslateOperand(psContext, src0, TO_FLAG_INTEGER); + bformata(glsl, ";\n"); + AddIndentation(psContext); + } + + TranslateOperand(psContext, pDest, uDestFlags); + + switch (GetOperandDataType(psContext, pDest)) + { + case SVT_UINT: + case SVT_UINT8: + case SVT_UINT16: + szVecType = "uvec"; + eDstDataType = TO_FLAG_UNSIGNED_INTEGER; + break; + case SVT_INT: + case SVT_INT12: + case SVT_INT16: + szVecType = "ivec"; + eDstDataType = TO_FLAG_INTEGER; + break; + default: + szVecType = "vec"; + eDstDataType = TO_FLAG_FLOAT; + break; + } + + if (destElemCount > 1) + { + bformata(glsl, " = %s%d(", szVecType, destElemCount); + } + else + { + bcatcstr(glsl, " = "); + } + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + if (destElem > 0) + { + bcatcstr(glsl, ", "); + } + + if (qualcommWorkaround) + { + bcatcstr(glsl, "cond"); + } + else + { + TranslateOperand(psContext, src0, TO_FLAG_INTEGER); + } + + if (s0ElemCount > 1) + { + TranslateOperandSwizzle(psContext, pDest); + bformata(glsl, ".%c", swizzles[destElem]); + } + + bcatcstr(glsl, " != 0 ? "); + + TranslateOperand(psContext, src1, eDstDataType); + if (s1ElemCount > 1) + { + TranslateOperandSwizzle(psContext, pDest); + bformata(glsl, ".%c", swizzles[destElem]); + } + + bcatcstr(glsl, " : "); + + TranslateOperand(psContext, src2, eDstDataType); + if (s2ElemCount > 1) + { + TranslateOperandSwizzle(psContext, pDest); + bformata(glsl, ".%c", swizzles[destElem]); + } + } + if (destElemCount > 1) + { + bcatcstr(glsl, ");\n"); + } + else + { + bcatcstr(glsl, ";\n"); + } + + if (qualcommWorkaround) + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + } +} + +void CallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, uint32_t dataType) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); + uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + + AddIndentation(psContext); + // Qualcomm OpenGLES 3.0 drivers don't support bitwise operators for vectors. + // Because of this we need to do the operation per component. + bool qualcommWorkaround = (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) != 0; + bool isBitwiseOperator = psInst->eOpcode == OPCODE_AND || psInst->eOpcode == OPCODE_OR || psInst->eOpcode == OPCODE_XOR; + const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; + if (src1SwizCount == src0SwizCount == dstSwizCount) + { + BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + if (qualcommWorkaround && isBitwiseOperator && src0SwizCount > 1) + { + for (uint32_t i = 0; i < src0SwizCount; ++i) + { + if (i > 0) + { + bcatcstr(glsl, ", "); + } + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, "%s", swizzleString[i]); + bformata(glsl, " %s ", name); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + bformata(glsl, "%s", swizzleString[i]); + } + } + else + { + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", name); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + } + EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + else + { + //Upconvert the inputs to vec4 then apply the dest swizzle. + BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + if (dataType == TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(glsl, "uvec4("); + } + else if (dataType == TO_FLAG_INTEGER) + { + bcatcstr(glsl, "ivec4("); + } + else + { + bcatcstr(glsl, "vec4("); + } + + if (qualcommWorkaround && isBitwiseOperator && src0SwizCount > 1) + { + for (uint32_t i = 0; i < src0SwizCount; ++i) + { + if (i > 0) + { + bcatcstr(glsl, ", "); + } + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, "%s", swizzleString[i]); + bformata(glsl, " %s ", name); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + bformata(glsl, "%s", swizzleString[i]); + } + } + else + { + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", name); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + } + bcatcstr(glsl, ")"); + //Limit src swizzles based on dest swizzle + //e.g. given hlsl asm: add r0.xy, v0.xyxx, l(0.100000, 0.000000, 0.000000, 0.000000) + //the two sources must become vec2 + //Temp0.xy = Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000); + //becomes + //Temp0.xy = vec4(Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000)).xy; + + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } +} + +void CallTernaryOp(HLSLCrossCompilerContext* psContext, const char* op1, const char* op2, Instruction* psInst, + int dest, int src0, int src1, int src2, uint32_t dataType) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t src2SwizCount = GetNumSwizzleElements(&psInst->asOperands[src2]); + uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); + uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + + AddIndentation(psContext); + + if (src1SwizCount == src0SwizCount == src2SwizCount == dstSwizCount) + { + BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", op1); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", op2); + TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_NONE | dataType); + EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + else + { + BeginAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + if (dataType == TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(glsl, "uvec4("); + } + else if (dataType == TO_FLAG_INTEGER) + { + bcatcstr(glsl, "ivec4("); + } + else + { + bcatcstr(glsl, "vec4("); + } + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", op1); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_NONE | dataType); + bformata(glsl, " %s ", op2); + TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_NONE | dataType); + bcatcstr(glsl, ")"); + //Limit src swizzles based on dest swizzle + //e.g. given hlsl asm: add r0.xy, v0.xyxx, l(0.100000, 0.000000, 0.000000, 0.000000) + //the two sources must become vec2 + //Temp0.xy = Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000); + //becomes + //Temp0.xy = vec4(Input0.xyxx + vec4(0.100000, 0.000000, 0.000000, 0.000000)).xy; + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], dataType, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } +} + +void CallHelper3(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, int src2) +{ + bstring glsl = *psContext->currentGLSLString; + AddIndentation(psContext); + + BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + + bcatcstr(glsl, "vec4("); + + bcatcstr(glsl, name); + bcatcstr(glsl, "("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_FLOAT); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[src2], TO_FLAG_FLOAT); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} + +void CallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1) +{ + bstring glsl = *psContext->currentGLSLString; + AddIndentation(psContext); + + BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + + bcatcstr(glsl, "vec4("); + + bcatcstr(glsl, name); + bcatcstr(glsl, "("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_FLOAT); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} + +void CallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1) +{ + bstring glsl = *psContext->currentGLSLString; + AddIndentation(psContext); + + BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_INTEGER, psInst->bSaturate); + + bcatcstr(glsl, "ivec4("); + + bcatcstr(glsl, name); + bcatcstr(glsl, "(int("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_INTEGER); + bcatcstr(glsl, "), int("); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} +void CallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1) +{ + bstring glsl = *psContext->currentGLSLString; + AddIndentation(psContext); + + BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + + bcatcstr(glsl, "uvec4("); + + bcatcstr(glsl, name); + bcatcstr(glsl, "(uint("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, "), uint("); + TranslateOperand(psContext, &psInst->asOperands[src1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ")))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} + +void CallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0) +{ + bstring glsl = *psContext->currentGLSLString; + + AddIndentation(psContext); + + BeginAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + + // Qualcomm driver workaround + // Example: Instead of Temp1.xyz = (vec4(log2(Temp0[0].xyzx)).xyz); we write + // Temp1.xyz = (log2(vec4(Temp0[0].xyzx).xyz)); + if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) + { + bcatcstr(glsl, name); + bcatcstr(glsl, "("); + bcatcstr(glsl, "vec4("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + bcatcstr(glsl, ")"); + } + else + { + bcatcstr(glsl, "vec4("); + bcatcstr(glsl, name); + bcatcstr(glsl, "("); + TranslateOperand(psContext, &psInst->asOperands[src0], TO_FLAG_FLOAT); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[dest]); + } + EndAssignment(psContext, &psInst->asOperands[dest], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} + +//Makes sure the texture coordinate swizzle is appropriate for the texture type. +//i.e. vecX for X-dimension texture. +//Currently supports floating point coord only, so not used for texelFetch. +static void TranslateTexCoord(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eResDim, + Operand* psTexCoordOperand) +{ + unsigned int uNumCoords = psTexCoordOperand->iNumComponents; + int constructor = 0; + bstring glsl = *psContext->currentGLSLString; + + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + //Vec1 texcoord. Mask out the other components. + psTexCoordOperand->aui32Swizzle[1] = 0xFFFFFFFF; + psTexCoordOperand->aui32Swizzle[2] = 0xFFFFFFFF; + psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; + if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || + psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + psTexCoordOperand->iNumComponents = 1; + } + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + //Vec2 texcoord. Mask out the other components. + psTexCoordOperand->aui32Swizzle[2] = 0xFFFFFFFF; + psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; + if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || + psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + psTexCoordOperand->iNumComponents = 2; + } + if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + constructor = 1; + bcatcstr(glsl, "vec2("); + } + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + //Vec3 texcoord. Mask out the other component. + psTexCoordOperand->aui32Swizzle[3] = 0xFFFFFFFF; + if (psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE32 || + psTexCoordOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + psTexCoordOperand->iNumComponents = 3; + } + if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + constructor = 1; + bcatcstr(glsl, "vec3("); + } + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + uNumCoords = 4; + if (psTexCoordOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + constructor = 1; + bcatcstr(glsl, "vec4("); + } + break; + } + default: + { + ASSERT(0); + break; + } + } + + //Mask out the other components. + switch (psTexCoordOperand->eSelMode) + { + case OPERAND_4_COMPONENT_SELECT_1_MODE: + ASSERT(uNumCoords == 1); + break; + case OPERAND_4_COMPONENT_SWIZZLE_MODE: + while (uNumCoords < 4) + { + psTexCoordOperand->aui32Swizzle[uNumCoords] = 0xFFFFFFFF; + ++uNumCoords; + } + break; + case OPERAND_4_COMPONENT_MASK_MODE: + if (psTexCoordOperand->ui32CompMask < 4) + { + psTexCoordOperand->ui32CompMask = + (uNumCoords > 0) * OPERAND_4_COMPONENT_MASK_X | + (uNumCoords > 1) * OPERAND_4_COMPONENT_MASK_Y | + (uNumCoords > 2) * OPERAND_4_COMPONENT_MASK_Z; + } + break; + } + TranslateOperand(psContext, psTexCoordOperand, TO_FLAG_FLOAT); + + if (constructor) + { + bcatcstr(glsl, ")"); + } +} + +static int GetNumTextureDimensions(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eResDim) +{ + (void)(psContext); + + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + return 1; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBE: + { + return 2; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + return 3; + } + default: + { + ASSERT(0); + break; + } + } + return 0; +} + +void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index) +{ + bstring glsl = *psContext->currentGLSLString; + const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + //[width, height, depth or array size, total-mip-count] + if (index < 3) + { + int dim = GetNumTextureDimensions(psContext, eResDim); + + if (dim < (index + 1)) + { + bcatcstr(glsl, "0"); + } + else + { + if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + { + bformata(glsl, "ivec%d(textureSize(", dim); + } + else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) + { + bformata(glsl, "vec%d(1.0f) / vec%d(textureSize(", dim, dim); + } + else + { + bformata(glsl, "vec%d(textureSize(", dim); + } + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + + switch (index) + { + case 0: + bcatcstr(glsl, ".x"); + break; + case 1: + bcatcstr(glsl, ".y"); + break; + case 2: + bcatcstr(glsl, ".z"); + break; + } + } + } + else + { + bcatcstr(glsl, "textureQueryLevels("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ")"); + } +} + +uint32_t GetReturnTypeToFlags(RESOURCE_RETURN_TYPE eReturnType) +{ + switch (eReturnType) + { + case RETURN_TYPE_FLOAT: + return TO_FLAG_FLOAT; + case RETURN_TYPE_UINT: + return TO_FLAG_UNSIGNED_INTEGER; + case RETURN_TYPE_SINT: + return TO_FLAG_INTEGER; + case RETURN_TYPE_DOUBLE: + return TO_FLAG_DOUBLE; + } + ASSERT(0); + return TO_FLAG_NONE; +} + +uint32_t GetResourceReturnTypeToFlags(ResourceGroup eGroup, uint32_t ui32BindPoint, HLSLCrossCompilerContext* psContext) +{ + ResourceBinding* psBinding; + if (GetResourceFromBindingPoint(eGroup, ui32BindPoint, &psContext->psShader->sInfo, &psBinding)) + { + return GetReturnTypeToFlags(psBinding->ui32ReturnType); + } + ASSERT(0); + return TO_FLAG_NONE; +} + +#define TEXSMP_FLAG_NONE 0x0 +#define TEXSMP_FLAG_LOD 0x1 //LOD comes from operand +#define TEXSMP_FLAG_COMPARE 0x2 +#define TEXSMP_FLAG_FIRSTLOD 0x4 //LOD is 0 +#define TEXSMP_FLAG_BIAS 0x8 +#define TEXSMP_FLAGS_GRAD 0x10 +static void TranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, uint32_t ui32Flags) +{ + bstring glsl = *psContext->currentGLSLString; + + const char* funcName = "texture"; + const char* offset = ""; + const char* depthCmpCoordType = ""; + const char* gradSwizzle = ""; + uint32_t sampleTypeToFlags = TO_FLAG_FLOAT; + + uint32_t ui32NumOffsets = 0; + + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); + + ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); + + if (psInst->bAddressOffset) + { + offset = "Offset"; + } + + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + depthCmpCoordType = "vec2"; + gradSwizzle = ".x"; + ui32NumOffsets = 1; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture1D"; + if (ui32Flags & TEXSMP_FLAG_COMPARE) + { + funcName = "shadow1D"; + } + } + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture2D"; + if (ui32Flags & TEXSMP_FLAG_COMPARE) + { + funcName = "shadow2D"; + } + } + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (!iHaveOverloadedTexFuncs) + { + funcName = "textureCube"; + } + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + depthCmpCoordType = "vec4"; + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture3D"; + } + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".x"; + ui32NumOffsets = 1; + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + depthCmpCoordType = "vec4"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (ui32Flags & TEXSMP_FLAG_COMPARE) + { + //Special. Reference is a separate argument. + AddIndentation(psContext); + sampleTypeToFlags = TO_FLAG_FLOAT; + BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bcatcstr(glsl, "(vec4(textureLod("); + } + else + { + bcatcstr(glsl, "(vec4(texture("); + } + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); + bcatcstr(glsl, ","); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ","); + //.z = reference. + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); + + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + + bcatcstr(glsl, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + return; + } + + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (ui32Flags & TEXSMP_FLAG_COMPARE) + { + //For non-cubeMap Arrays the reference value comes from the + //texture coord vector in GLSL. For cubmap arrays there is a + //separate parameter. + //It is always separate paramter in HLSL. + AddIndentation(psContext); + sampleTypeToFlags = TO_FLAG_FLOAT; + BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); + + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bformata(glsl, "(vec4(%sLod%s(", funcName, offset); + } + else + { + bformata(glsl, "(vec4(%s%s(", funcName, offset); + } + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); + bformata(glsl, ", %s(", depthCmpCoordType); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ","); + //.z = reference. + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); + bcatcstr(glsl, ")"); + + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + + bcatcstr(glsl, "))"); + } + else + { + AddIndentation(psContext); + sampleTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); + BeginAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bformata(glsl, "(%sLod%s(", funcName, offset); + } + else + if (ui32Flags & TEXSMP_FLAGS_GRAD) + { + bformata(glsl, "(%sGrad%s(", funcName, offset); + } + else + { + bformata(glsl, "(%s%s(", funcName, offset); + } + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); + bcatcstr(glsl, ", "); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + if (ui32Flags & (TEXSMP_FLAG_LOD)) + { + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); + if (psContext->psShader->ui32MajorVersion < 4) + { + bcatcstr(glsl, ".w"); + } + } + else + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + else + if (ui32Flags & TEXSMP_FLAGS_GRAD) + { + bcatcstr(glsl, ", vec4("); + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT);//dx + bcatcstr(glsl, ")"); + bcatcstr(glsl, gradSwizzle); + bcatcstr(glsl, ", vec4("); + TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_FLOAT);//dy + bcatcstr(glsl, ")"); + bcatcstr(glsl, gradSwizzle); + } + + if (psInst->bAddressOffset) + { + if (ui32NumOffsets == 1) + { + bformata(glsl, ", %d", + psInst->iUAddrOffset); + } + else + if (ui32NumOffsets == 2) + { + bformata(glsl, ", ivec2(%d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset); + } + else + if (ui32NumOffsets == 3) + { + bformata(glsl, ", ivec3(%d, %d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset, + psInst->iWAddrOffset); + } + } + + if (ui32Flags & (TEXSMP_FLAG_BIAS)) + { + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_FLOAT); + } + + bcatcstr(glsl, ")"); + } + + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], sampleTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); +} + +static ShaderVarType* LookupStructuredVarExtended(HLSLCrossCompilerContext* psContext, + Operand* psResource, + Operand* psByteOffset, + uint32_t ui32Component, + uint32_t* swizzle) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; + int byteOffset = psByteOffset ? ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component : 0; + int vec4Offset = byteOffset >> 4; + int32_t index = -1; + int32_t rebase = -1; + int found; + //TODO: multi-component stores and vector writes need testing. + + //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; + + switch (byteOffset % 16) + { + case 0: + aui32Swizzle[0] = 0; + break; + case 4: + aui32Swizzle[0] = 1; + break; + case 8: + aui32Swizzle[0] = 2; + break; + case 12: + aui32Swizzle[0] = 3; + break; + } + + switch (psResource->eType) + { + case OPERAND_TYPE_RESOURCE: + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + //dcl_tgsm_structured defines the amount of memory and a stride. + ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); + ASSERT(swizzle == NULL); + return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; + } + default: + ASSERT(0); + break; + } + + found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + ASSERT(found); + + if (swizzle) + { + // Assuming the components are 4 bytes in length + const int bytesPerComponent = 4; + // Calculate the variable swizzling based on the byteOffset and the position of the variable in the structure + ASSERT((byteOffset - psVarType->Offset) % 4 == 0); + *swizzle = (byteOffset - psVarType->Offset) / bytesPerComponent; + ASSERT(*swizzle < 4); + } + + return psVarType; +} + +static ShaderVarType* LookupStructuredVar(HLSLCrossCompilerContext* psContext, + Operand* psResource, + Operand* psByteOffset, + uint32_t ui32Component) +{ + return LookupStructuredVarExtended(psContext, psResource, psByteOffset, ui32Component, NULL); +} + +static void TranslateShaderStorageVarName(bstring output, Shader* psShader, const Operand* operand, int structured) +{ + bstring varName = bfromcstr(""); + if (operand->eType == OPERAND_TYPE_RESOURCE) + { + if (structured) + { + bformata(varName, "StructuredRes%d", operand->ui32RegisterNumber); + } + else + { + bformata(varName, "RawRes%d", operand->ui32RegisterNumber); + } + } + else if(operand->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) + { + bformata(varName, "UAV%d", operand->ui32RegisterNumber); + } + else + { + ASSERT(0); + } + ShaderVarName(output, psShader, bstr2cstr(varName, '\0')); + bdestroy(varName); +} + +static void TranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + ShaderVarType* psVarType = NULL; + int component; + int srcComponent = 0; + + Operand* psDest = 0; + Operand* psDestAddr = 0; + Operand* psDestByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_STORE_STRUCTURED: + psDest = &psInst->asOperands[0]; + psDestAddr = &psInst->asOperands[1]; + psDestByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + break; + case OPCODE_STORE_RAW: + psDest = &psInst->asOperands[0]; + psDestByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + for (component = 0; component < 4; component++) + { + const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; + ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psInst->asOperands[0].ui32CompMask & (1 << component)) + { + uint32_t swizzle = 0; + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + psVarType = LookupStructuredVarExtended(psContext, psDest, psDestByteOff, component, &swizzle); + } + + AddIndentation(psContext); + TranslateShaderStorageVarName(glsl, psContext->psShader, psDest, structured); + bformata(glsl, "["); + if (structured) //Dest address and dest byte offset + { + if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, "].value["); + TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, " >> 2u ");//bytes to floats + } + else + { + TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + } + else + { + TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + + //RAW: change component using index offset + if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(glsl, " + %d", component); + } + + bformata(glsl, "]"); + + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + if (strcmp(psVarType->Name, "$Element") != 0) + { + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + } + + if (psVarType->Columns > 1) + { + bformata(glsl, swizzleString[swizzle]); + } + } + + + if (structured) + { + uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; + if (psVarType) + { + if (psVarType->Type == SVT_INT) + { + flags = TO_FLAG_INTEGER; + } + else if (psVarType->Type == SVT_FLOAT) + { + flags = TO_FLAG_NONE; + } + } + //TGSM always uint + bformata(glsl, " = ("); + TranslateOperand(psContext, psSrc, flags); + } + else + { + //Dest type is currently always a uint array. + bformata(glsl, " = ("); + TranslateOperand(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER); + } + + if (GetNumSwizzleElements(psSrc) > 1) + { + bformata(glsl, swizzleString[srcComponent++]); + } + + //Double takes an extra slot. + if (psVarType && psVarType->Type == SVT_DOUBLE) + { + if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + bcatcstr(glsl, ")"); + } + component++; + } + + bformata(glsl, ");\n"); + } + } +} + +static void TranslateShaderPLSStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + ShaderVarType* psVarType = NULL; + int component; + int srcComponent = 0; + + Operand* psDest = 0; + Operand* psDestAddr = 0; + Operand* psDestByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_STORE_STRUCTURED: + psDest = &psInst->asOperands[0]; + psDestAddr = &psInst->asOperands[1]; + psDestByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + break; + case OPCODE_STORE_RAW: + default: + ASSERT(0); + } + + ASSERT(structured); + + for (component = 0; component < 4; component++) + { + const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; + ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psInst->asOperands[0].ui32CompMask & (1 << component)) + { + + ASSERT(psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY); + + psVarType = LookupStructuredVar(psContext, psDest, psDestByteOff, component); + + AddIndentation(psContext); + + if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) + { + bstring varName = bfromcstralloc(16, ""); + bformata(varName, "StructuredRes%d", psDest->ui32RegisterNumber); + ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); + bdestroy(varName); + } + else + { + TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + } + + ASSERT(strcmp(psVarType->Name, "$Element") != 0); + + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + + if (psVarType->Class == SVC_VECTOR) + { + int byteOffset = ((int*)psDestByteOff->afImmediates)[0] + 4 * (psDest->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psDest->aui32Swizzle[component] : component); + int byteOffsetOfVar = psVarType->Offset; + unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; + unsigned int s = startComponent; + + bformata(glsl, "%s", swizzleString[s]); + } + + uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; + if (psVarType) + { + if (psVarType->Type == SVT_INT) + { + flags = TO_FLAG_INTEGER; + } + else if (psVarType->Type == SVT_FLOAT) + { + flags = TO_FLAG_NONE; + } + else + { + ASSERT(0); + } + } + //TGSM always uint + bformata(glsl, " = ("); + TranslateOperand(psContext, psSrc, flags); + + + + if (GetNumSwizzleElements(psSrc) > 1) + { + bformata(glsl, swizzleString[srcComponent++]); + } + + //Double takes an extra slot. + if (psVarType && psVarType->Type == SVT_DOUBLE) + { + if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + bcatcstr(glsl, ")"); + } + component++; + } + + bformata(glsl, ");\n"); + } + } +} + +static void TranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; + uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; + int component; + int destComponent = 0; + + Operand* psDest = 0; + Operand* psSrcAddr = 0; + Operand* psSrcByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_LD_STRUCTURED: + psDest = &psInst->asOperands[0]; + psSrcAddr = &psInst->asOperands[1]; + psSrcByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + break; + case OPCODE_LD_RAW: + psDest = &psInst->asOperands[0]; + psSrcByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + if (psInst->eOpcode == OPCODE_LD_RAW) + { + unsigned int ui32CompNum = GetNumSwizzleElements(psDest); + + for (component = 0; component < 4; component++) + { + const char* swizzleString [] = { "x", "y", "z", "w" }; + ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psDest->ui32CompMask & (1 << component)) + { + int addedBitcast = 0; + + if (structured) + { + psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); + } + + AddIndentation(psContext); + + aui32Swizzle[0] = psSrc->aui32Swizzle[component]; + + if (ui32CompNum > 1) + { + BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); + } + else + { + BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + } + + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + // unknown how to make this without TO_FLAG_NAME_ONLY + bcatcstr(glsl, "uintBitsToFloat("); + addedBitcast = 1; + + TranslateOperand(psContext, psSrc, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); + + if (((int*)psSrcByteOff->afImmediates)[0] == 0) + { + bformata(glsl, "[0"); + } + else + { + bformata(glsl, "[(("); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(glsl, ") >> 2u)"); + } + } + else + { + bstring varName = bfromcstralloc(16, ""); + bformata(varName, "RawRes%d", psSrc->ui32RegisterNumber); + + ShaderVarName(glsl, psContext->psShader, bstr2cstr(varName, '\0')); + bcatcstr(glsl, "[(("); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(glsl, ") >> 2u)"); + + bdestroy(varName); + } + + if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) + { + bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); + } + bcatcstr(glsl, "]"); + + if (addedBitcast) + { + bcatcstr(glsl, ")"); + } + + EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + bformata(glsl, ";\n"); + } + } + } + else + { + unsigned int ui32CompNum = GetNumSwizzleElements(psDest); + + //(int)GetNumSwizzleElements(&psInst->asOperands[0]) + for (component = 0; component < 4; component++) + { + const char* swizzleString [] = { "x", "y", "z", "w" }; + ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psDest->ui32CompMask & (1 << component)) + { + int addedBitcast = 0; + + psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); + + AddIndentation(psContext); + + aui32Swizzle[0] = psSrc->aui32Swizzle[component]; + + if (ui32CompNum > 1) + { + BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); + } + else + { + BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + } + + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + // unknown how to make this without TO_FLAG_NAME_ONLY + if (psVarType->Type == SVT_UINT) + { + bcatcstr(glsl, "uintBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_INT) + { + bcatcstr(glsl, "intBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_DOUBLE) + { + bcatcstr(glsl, "unpackDouble2x32("); + addedBitcast = 1; + } + + // input already in uints + TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "["); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "].value[("); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, " >> 2u)]"); + } + else + { + ConstantBuffer* psCBuf = NULL; + uint32_t swizzle = 0; + psVarType = LookupStructuredVarExtended(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component, &swizzle); + GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + if (psVarType->Type == SVT_UINT) + { + bcatcstr(glsl, "uintBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_INT) + { + bcatcstr(glsl, "intBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_DOUBLE) + { + bcatcstr(glsl, "unpackDouble2x32("); + addedBitcast = 1; + } + + if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) + { + TranslateShaderStorageVarName(glsl, psContext->psShader, psSrc, 1); + bformata(glsl, "["); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + if (strcmp(psVarType->Name, "$Element") != 0) + { + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + } + + if (psVarType->Columns > 1) + { + bformata(glsl, ".%s", swizzleString[swizzle]); + } + } + else if (psSrc->eType == OPERAND_TYPE_RESOURCE) + { + TranslateShaderStorageVarName(glsl, psContext->psShader, psSrc, 1); + bcatcstr(glsl, "["); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + + if (strcmp(psVarType->Name, "$Element") != 0) + { + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + } + + if (psVarType->Class == SVC_SCALAR) + { + } + else if (psVarType->Class == SVC_VECTOR) + { + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + int byteOffsetOfVar = psVarType->Offset; + unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; + unsigned int s = startComponent; + + bcatcstr(glsl, "."); +#if 0 + for (s = startComponent; s < min(min(psVarType->Columns, 4U - component), ui32CompNum); ++s) +#endif + bformata(glsl, "%s", swizzleString[s]); + } + else if (psVarType->Class == SVC_MATRIX_ROWS) + { + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + int byteOffsetOfVar = psVarType->Offset; + unsigned int startRow = ((byteOffset - byteOffsetOfVar) >> 2) / psVarType->Columns; + unsigned int startComponent = ((byteOffset - byteOffsetOfVar) >> 2) % psVarType->Columns; + unsigned int s = startComponent; + + bformata(glsl, "[%d]", startRow); + bcatcstr(glsl, "."); +#if 0 + for (s = startComponent; s < min(min(psVarType->Rows, 4U - component), ui32CompNum); ++s) +#endif + bformata(glsl, "%s", swizzleString[s]); + } + else if (psVarType->Class == SVC_MATRIX_COLUMNS) + { + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + int byteOffsetOfVar = psVarType->Offset; + unsigned int startCol = ((byteOffset - byteOffsetOfVar) >> 2) / psVarType->Rows; + unsigned int startComponent = ((byteOffset - byteOffsetOfVar) >> 2) % psVarType->Rows; + unsigned int s = startComponent; + + bformata(glsl, "[%d]", startCol); + bcatcstr(glsl, "."); +#if 0 + for (s = startComponent; s < min(min(psVarType->Columns, 4U - component), ui32CompNum); ++s) +#endif + bformata(glsl, "%s", swizzleString[s]); + } + else + { + //assert(0); + } + } + else + { + TranslateOperand(psContext, psSrc, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); + bformata(glsl, "["); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "]."); + + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + } + + if (psVarType->Type == SVT_DOUBLE) + { + component++; // doubles take up 2 slots + } +#if 0 + if (psVarType->Class == SVC_VECTOR) + { + component += min(psVarType->Columns, ui32CompNum) - 1; // vector take up various slots + } + if (psVarType->Class == SVC_MATRIX_ROWS) + { + component += min(psVarType->Columns * psVarType->Rows, ui32CompNum) - 1; // matrix take up various slots + } + if (psVarType->Class == SVC_MATRIX_COLUMNS) + { + component += min(psVarType->Columns * psVarType->Rows, ui32CompNum) - 1; // matrix take up various slots + } +#endif + } + + if (addedBitcast) + { + bcatcstr(glsl, ")"); + } + + EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + bformata(glsl, ";\n"); + } + } + } +} + +static void TranslateShaderPLSLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; + int component; + int destComponent = 0; + + Operand* psDest = 0; + Operand* psSrcAddr = 0; + Operand* psSrcByteOff = 0; + Operand* psSrc = 0; + + switch (psInst->eOpcode) + { + case OPCODE_LD_STRUCTURED: + psDest = &psInst->asOperands[0]; + psSrcAddr = &psInst->asOperands[1]; + psSrcByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + break; + case OPCODE_LD_RAW: + default: + ASSERT(0); + } + + unsigned int ui32CompNum = GetNumSwizzleElements(psDest); + + for (component = 0; component < 4; component++) + { + const char* swizzleString[] = { "x", "y", "z", "w" }; + ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psDest->ui32CompMask & (1 << component)) + { + int addedBitcast = 0; + + psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); + + AddIndentation(psContext); + + aui32Swizzle[0] = psSrc->aui32Swizzle[component]; + + if (ui32CompNum > 1) + { + BeginAssignmentEx(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate, swizzleString[destComponent++]); + } + else + { + BeginAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + } + + ASSERT(psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY); + + ConstantBuffer* psCBuf = NULL; + psVarType = LookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + if (psVarType->Type == SVT_UINT) + { + bcatcstr(glsl, "uintBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_INT) + { + bcatcstr(glsl, "intBitsToFloat("); + addedBitcast = 1; + } + else if (psVarType->Type == SVT_DOUBLE) + { + ASSERT(0); + } + + ASSERT(psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW); + + TranslateOperand(psContext, psSrc, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + ASSERT(strcmp(psVarType->Name, "$Element") != 0); + + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + + ASSERT(psVarType->Type != SVT_DOUBLE); + ASSERT(psVarType->Class != SVC_MATRIX_ROWS); + ASSERT(psVarType->Class != SVC_MATRIX_COLUMNS); + + if (psVarType->Class == SVC_VECTOR) + { + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + int byteOffsetOfVar = psVarType->Offset; + unsigned int startComponent = (byteOffset - byteOffsetOfVar) >> 2; + unsigned int s = startComponent; + + bcatcstr(glsl, "."); + bformata(glsl, "%s", swizzleString[s]); + } + + if (addedBitcast) + { + bcatcstr(glsl, ")"); + } + + EndAssignment(psContext, psDest, TO_FLAG_FLOAT, psInst->bSaturate); + bformata(glsl, ";\n"); + } + } +} + +void TranslateAtomicMemOp(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + ShaderVarType* psVarType = NULL; + uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; + const char* func = ""; + Operand* dest = 0; + Operand* previousValue = 0; + Operand* destAddr = 0; + Operand* src = 0; + Operand* compare = 0; + + switch (psInst->eOpcode) + { + case OPCODE_IMM_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IADD\n"); +#endif + func = "atomicAdd"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IADD\n"); +#endif + func = "atomicAdd"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_AND\n"); +#endif + func = "atomicAnd"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_AND\n"); +#endif + func = "atomicAnd"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_OR\n"); +#endif + func = "atomicOr"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_OR\n"); +#endif + func = "atomicOr"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_XOR\n"); +#endif + func = "atomicXor"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_XOR\n"); +#endif + func = "atomicXor"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + + case OPCODE_IMM_ATOMIC_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_EXCH\n"); +#endif + func = "atomicExchange"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_CMP_EXC\n"); +#endif + func = "atomicCompSwap"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + compare = &psInst->asOperands[3]; + src = &psInst->asOperands[4]; + break; + } + case OPCODE_ATOMIC_CMP_STORE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_CMP_STORE\n"); +#endif + func = "atomicCompSwap"; + previousValue = 0; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + compare = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_UMIN\n"); +#endif + func = "atomicMin"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_UMIN\n"); +#endif + func = "atomicMin"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IMIN\n"); +#endif + func = "atomicMin"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IMIN\n"); +#endif + func = "atomicMin"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_UMAX\n"); +#endif + func = "atomicMax"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_UMAX\n"); +#endif + func = "atomicMax"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IMAX\n"); +#endif + func = "atomicMax"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IMAX\n"); +#endif + func = "atomicMax"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + } + + AddIndentation(psContext); + + psVarType = LookupStructuredVar(psContext, dest, NULL, 0); + + if (psVarType->Type == SVT_UINT) + { + ui32DataTypeFlag = TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER; + } + else if (psVarType->Type == SVT_INT) + { + ui32DataTypeFlag = TO_FLAG_INTEGER; + } + + if (previousValue) + { + BeginAssignment(psContext, previousValue, ui32DataTypeFlag, psInst->bSaturate); + } + + if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + bcatcstr(glsl, func); + bcatcstr(glsl, "("); + TranslateOperand(psContext, dest, ui32DataTypeFlag & TO_FLAG_NAME_ONLY); + bformata(glsl, "[%d]", 0); + } + else + { + bcatcstr(glsl, func); + bcatcstr(glsl, "("); + TranslateShaderStorageVarName(glsl, psContext->psShader, dest, 1); + bformata(glsl, "["); + TranslateOperand(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + // For some reason the destAddr with the swizzle doesn't translate to an index + // I'm not sure if ".x" is the correct behavior. + bformata(glsl, ".x]"); + } + + if (strcmp(psVarType->Name, "$Element") != 0) + { + bcatcstr(glsl, "."); + ShaderVarName(glsl, psContext->psShader, psVarType->Name); + } + bcatcstr(glsl, ", "); + + if (compare) + { + TranslateOperand(psContext, compare, ui32DataTypeFlag); + bcatcstr(glsl, ", "); + } + + TranslateOperand(psContext, src, ui32DataTypeFlag); + bcatcstr(glsl, ")"); + + if (previousValue) + { + EndAssignment(psContext, previousValue, ui32DataTypeFlag, psInst->bSaturate); + } + + bcatcstr(glsl, ";\n"); +} + +static void TranslateConditional(HLSLCrossCompilerContext* psContext, + Instruction* psInst, + bstring glsl) +{ + const char* statement = ""; + uint32_t bWriteTraceEnd = 0; + if (psInst->eOpcode == OPCODE_BREAKC) + { + statement = "break"; + } + else if (psInst->eOpcode == OPCODE_CONTINUEC) + { + statement = "continue"; + } + else if (psInst->eOpcode == OPCODE_RETC) + { + statement = "return"; + bWriteTraceEnd = (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) != 0; + } + + if (psContext->psShader->ui32MajorVersion < 4) + { + bcatcstr(glsl, "if("); + + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + switch (psInst->eDX9TestType) + { + case D3DSPC_GT: + { + bcatcstr(glsl, " > "); + break; + } + case D3DSPC_EQ: + { + bcatcstr(glsl, " == "); + break; + } + case D3DSPC_GE: + { + bcatcstr(glsl, " >= "); + break; + } + case D3DSPC_LT: + { + bcatcstr(glsl, " < "); + break; + } + case D3DSPC_NE: + { + bcatcstr(glsl, " != "); + break; + } + case D3DSPC_LE: + { + bcatcstr(glsl, " <= "); + break; + } + case D3DSPC_BOOLEAN: + { + bcatcstr(glsl, " != 0"); + break; + } + default: + { + break; + } + } + + if (psInst->eDX9TestType != D3DSPC_BOOLEAN) + { + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + } + + if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) + { + bformata(glsl, "){ %s; }\n", statement); + } + else + { + bcatcstr(glsl, "){\n"); + } + } + else + { + if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) + { + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + bformata(glsl, ")==uint(0){%s;}\n", statement); // Adreno can't handle 0u (it's treated as int) + } + else + { + bformata(glsl, ")==0){%s;}\n", statement); + } + } + else + { + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + bcatcstr(glsl, ")==uint(0){\n"); // Adreno can't handle 0u (it's treated as int) + } + else + { + bcatcstr(glsl, ")==0){\n"); + } + } + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF && !bWriteTraceEnd) + { + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + bformata(glsl, ")!=uint(0)){%s;}\n", statement); // Adreno can't handle 0u (it's treated as int) + } + else + { + bformata(glsl, ")!=0){%s;}\n", statement); + } + } + else + { + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + bcatcstr(glsl, ")!=uint(0)){\n"); // Adreno can't handle 0u (it's treated as int) + } + else + { + bcatcstr(glsl, ")!=0){\n"); + } + } + } + } + + if (bWriteTraceEnd) + { + ASSERT(*psContext->currentGLSLString == glsl); + ++psContext->indent; + WriteEndTrace(psContext); + AddIndentation(psContext); + bformata(glsl, "%s;\n", statement); + AddIndentation(psContext); + --psContext->indent; + bcatcstr(glsl, "}\n"); + } +} + +void UpdateCommonTempVecType(SHADER_VARIABLE_TYPE* peCommonTempVecType, SHADER_VARIABLE_TYPE eNewType) +{ + if (*peCommonTempVecType == SVT_FORCE_DWORD) + { + *peCommonTempVecType = eNewType; + } + else if (*peCommonTempVecType != eNewType) + { + *peCommonTempVecType = SVT_VOID; + } +} + +bool IsFloatType(SHADER_VARIABLE_TYPE type) +{ + switch (type) + { + case SVT_FLOAT: + case SVT_FLOAT10: + case SVT_FLOAT16: + return true; + default: + return false; + } +} + +void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount, SHADER_VARIABLE_TYPE* aeCommonTempVecType) +{ + int32_t i; + + SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; + + for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) + { + aeTempVecType[i] = SVT_FLOAT; + } + if (aeCommonTempVecType != NULL) + { + for (i = 0; i < MAX_TEMP_VEC4; ++i) + { + aeCommonTempVecType[i] = SVT_FORCE_DWORD; + } + } + + for (i = 0; i < i32InstCount; ++i, psInst++) + { + int k = 0; + + if (psInst->ui32NumOperands == 0) + { + continue; + } + + //Preserve the current type on dest array index + if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) + { + Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; + if (psSubOperand != 0) + { + const uint32_t ui32RegIndex = psSubOperand->ui32RegisterNumber * 4; + ASSERT(psSubOperand->eType == OPERAND_TYPE_TEMP); + + if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; + } + else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psSubOperand->ui32Swizzle == (NO_SWIZZLE)) + { + psSubOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; + } + else + { + psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; + } + } + else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psSubOperand->ui32CompMask; + if (!psSubOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + psSubOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; + } + } + } + } + } + + //Preserve the current type on sources. + for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) + { + int32_t subOperand; + Operand* psOperand = &psInst->asOperands[k]; + + if (psOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; + psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; + psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; + psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; + } + else + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; + } + } + } + } + + for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) + { + if (psOperand->psSubOperand[subOperand] != 0) + { + Operand* psSubOperand = psOperand->psSubOperand[subOperand]; + if (psSubOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psSubOperand->ui32RegisterNumber * 4; + + if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; + } + else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psSubOperand->ui32Swizzle == (NO_SWIZZLE)) + { + psSubOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[1] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[2] = aeTempVecType[ui32RegIndex]; + psSubOperand->aeDataType[3] = aeTempVecType[ui32RegIndex]; + } + else + { + psSubOperand->aeDataType[psSubOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psSubOperand->aui32Swizzle[0]]; + } + } + else if (psSubOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psSubOperand->ui32CompMask; + if (!psSubOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + psSubOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; + } + } + } + } + } + } + } + + SHADER_VARIABLE_TYPE eNewType = SVT_FORCE_DWORD; + + switch (psInst->eOpcode) + { + case OPCODE_RESINFO: + { + if (psInst->eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + { + eNewType = SVT_INT; + } + else + { + eNewType = SVT_FLOAT; + } + break; + } + case OPCODE_AND: + case OPCODE_OR: + case OPCODE_XOR: + case OPCODE_NOT: + { + eNewType = SVT_UINT; + break; + } + case OPCODE_IADD: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + { + eNewType = SVT_UINT; + + //If the rhs evaluates to signed then that is the dest type picked. + for (uint32_t kk = psInst->ui32FirstSrc; kk < psInst->ui32NumOperands; ++kk) + { + if (GetOperandDataType(psContext, &psInst->asOperands[kk]) == SVT_INT || + psInst->asOperands[kk].eModifier == OPERAND_MODIFIER_NEG || + psInst->asOperands[kk].eModifier == OPERAND_MODIFIER_ABSNEG) + { + eNewType = SVT_INT; + break; + } + } + + break; + } + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + Operand* dest = &psInst->asOperands[1]; + ShaderVarType* type = LookupStructuredVar(psContext, dest, NULL, 0); + eNewType = type->Type; + break; + } + + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_INE: + case OPCODE_EQ: + case OPCODE_GE: + case OPCODE_LT: + case OPCODE_NE: + case OPCODE_UDIV: + case OPCODE_ULT: + case OPCODE_UGE: + case OPCODE_UMUL: + case OPCODE_UMAD: + case OPCODE_UMAX: + case OPCODE_UMIN: + case OPCODE_USHR: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + { + if (psContext->psShader->ui32MajorVersion < 4) + { + //SLT and SGE are translated to LT and GE respectively. + //But SLT and SGE have a floating point 1.0f or 0.0f result + //instead of setting all bits on or all bits off. + eNewType = SVT_FLOAT; + } + else + { + eNewType = SVT_UINT; + } + break; + } + + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_D: + case OPCODE_SAMPLE_B: + case OPCODE_LD: + case OPCODE_LD_MS: + case OPCODE_LD_UAV_TYPED: + { + ResourceBinding* psRes = NULL; + if (psInst->eOpcode == OPCODE_LD_UAV_TYPED) + { + GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); + } + else + { + GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); + } + switch (psRes->ui32ReturnType) + { + case RETURN_TYPE_SINT: + eNewType = SVT_INT; + break; + case RETURN_TYPE_UINT: + eNewType = SVT_UINT; + break; + case RETURN_TYPE_FLOAT: + eNewType = SVT_FLOAT; + break; + default: + ASSERT(0); + break; + } + break; + } + + case OPCODE_MOV: + { + //Inherit the type of the source operand + const Operand* psOperand = &psInst->asOperands[0]; + if (psOperand->eType == OPERAND_TYPE_TEMP) + { + eNewType = GetOperandDataType(psContext, &psInst->asOperands[1]); + } + else + { + continue; + } + break; + } + case OPCODE_MOVC: + { + //Inherit the type of the source operand + const Operand* psOperand = &psInst->asOperands[0]; + if (psOperand->eType == OPERAND_TYPE_TEMP) + { + eNewType = GetOperandDataType(psContext, &psInst->asOperands[2]); + //Check assumption that both the values which MOVC might pick have the same basic data type. + if (!psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) + { + ASSERT(GetOperandDataType(psContext, &psInst->asOperands[2]) == GetOperandDataType(psContext, &psInst->asOperands[3])); + } + } + else + { + continue; + } + break; + } + case OPCODE_FTOI: + { + ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1])) || + GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_VOID); + eNewType = SVT_INT; + break; + } + case OPCODE_FTOU: + { + ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1])) || + GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_VOID); + eNewType = SVT_UINT; + break; + } + + case OPCODE_UTOF: + case OPCODE_ITOF: + { + eNewType = SVT_FLOAT; + break; + } + case OPCODE_IF: + case OPCODE_SWITCH: + case OPCODE_BREAKC: + { + const Operand* psOperand = &psInst->asOperands[0]; + if (psOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + eNewType = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + eNewType = aeTempVecType[ui32RegIndex]; + } + else + { + eNewType = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + for (; k < 4; ++k) + { + if (ui32CompMask & (1 << k)) + { + eNewType = aeTempVecType[ui32RegIndex + k]; + } + } + } + } + else + { + continue; + } + break; + } + case OPCODE_DADD: + { + eNewType = SVT_DOUBLE; + break; + } + case OPCODE_STORE_RAW: + { + eNewType = SVT_FLOAT; + break; + } + default: + { + eNewType = SVT_FLOAT; + break; + } + } + + if (eNewType == SVT_UINT && HaveUVec(psContext->psShader->eTargetLanguage) == 0) + { + //Fallback to signed int if unsigned int is not supported. + eNewType = SVT_INT; + } + + //Process the destination last in order to handle instructions + //where the destination register is also used as a source. + for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) + { + Operand* psOperand = &psInst->asOperands[k]; + if (psOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + if (HavePrecisionQualifers(psContext->psShader->eTargetLanguage)) + { + switch (psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + break; + case OPERAND_MIN_PRECISION_SINT_16: + eNewType = SVT_INT16; + break; + case OPERAND_MIN_PRECISION_UINT_16: + eNewType = SVT_UINT16; + break; + case OPERAND_MIN_PRECISION_FLOAT_2_8: + eNewType = SVT_FLOAT10; + break; + case OPERAND_MIN_PRECISION_FLOAT_16: + eNewType = SVT_FLOAT16; + break; + default: + break; + } + } + + if (aeCommonTempVecType != NULL) + { + UpdateCommonTempVecType(aeCommonTempVecType + psOperand->ui32RegisterNumber, eNewType); + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]] = eNewType; + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = eNewType; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + aeTempVecType[ui32RegIndex] = eNewType; + psOperand->aeDataType[0] = eNewType; + psOperand->aeDataType[1] = eNewType; + psOperand->aeDataType[2] = eNewType; + psOperand->aeDataType[3] = eNewType; + } + else + { + aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]] = eNewType; + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = eNewType; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + aeTempVecType[ui32RegIndex + c] = eNewType; + psOperand->aeDataType[c] = eNewType; + } + } + } + } + } + ASSERT(eNewType != SVT_FORCE_DWORD); + } +} + +void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentGLSLString; + +#ifdef _DEBUG + AddIndentation(psContext); + bformata(glsl, "//Instruction %d\n", psInst->id); +#if 0 + if (psInst->id == 73) + { + ASSERT(1); //Set breakpoint here to debug an instruction from its ID. + } +#endif +#endif + + switch (psInst->eOpcode) + { + case OPCODE_FTOI: //Fall-through to MOV + case OPCODE_FTOU: //Fall-through to MOV + case OPCODE_MOV: + { + uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t ui32DstFlags = TO_FLAG_NONE; + + if (psInst->eOpcode == OPCODE_FTOU) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FTOU\n"); +#endif + ui32DstFlags |= TO_FLAG_UNSIGNED_INTEGER; + + ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1]))); + } + else if (psInst->eOpcode == OPCODE_FTOI) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FTOI\n"); +#endif + ui32DstFlags |= TO_FLAG_INTEGER; + + ASSERT(IsFloatType(GetOperandDataType(psContext, &psInst->asOperands[1]))); + } + else + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MOV\n"); +#endif + } + + if (psInst->eOpcode == OPCODE_FTOU) + { + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + + if (srcCount == 1) + { + bcatcstr(glsl, "uint("); + } + if (srcCount == 2) + { + bcatcstr(glsl, "uvec2("); + } + if (srcCount == 3) + { + bcatcstr(glsl, "uvec3("); + } + if (srcCount == 4) + { + bcatcstr(glsl, "uvec4("); + } + + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + if (srcCount != dstCount) + { + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + else + { + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + } + else + if (psInst->eOpcode == OPCODE_FTOI) + { + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + + if (srcCount == 1) + { + bcatcstr(glsl, "int("); + } + if (srcCount == 2) + { + bcatcstr(glsl, "ivec2("); + } + if (srcCount == 3) + { + bcatcstr(glsl, "ivec3("); + } + if (srcCount == 4) + { + bcatcstr(glsl, "ivec4("); + } + + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + + if (srcCount != dstCount) + { + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + else + { + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], ui32DstFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + } + else + { + AddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], 0, psInst->bSaturate); + } + break; + } + case OPCODE_ITOF: //signed to float + case OPCODE_UTOF: //unsigned to float + { +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_ITOF) + { + bcatcstr(glsl, "//ITOF\n"); + } + else + { + bcatcstr(glsl, "//UTOF\n"); + } +#endif + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "vec4("); + TranslateOperand(psContext, &psInst->asOperands[1], (psInst->eOpcode == OPCODE_ITOF) ? TO_FLAG_INTEGER : TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_MAD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MAD\n"); +#endif + CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_FLOAT); + break; + } + case OPCODE_IMAD: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMAD\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + CallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); + break; + } + case OPCODE_DADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DADD\n"); +#endif + CallBinaryOp(psContext, "+", psInst, 0, 1, 2, TO_FLAG_DOUBLE); + break; + } + case OPCODE_IADD: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IADD\n"); +#endif + //Is this a signed or unsigned add? + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + CallBinaryOp(psContext, "+", psInst, 0, 1, 2, ui32Flags); + break; + } + case OPCODE_ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ADD\n"); +#endif + CallBinaryOp(psContext, "+", psInst, 0, 1, 2, TO_FLAG_FLOAT); + break; + } + case OPCODE_OR: + { + /*Todo: vector version */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//OR\n"); +#endif + CallBinaryOp(psContext, "|", psInst, 0, 1, 2, TO_FLAG_INTEGER); + break; + } + case OPCODE_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//AND\n"); +#endif + CallBinaryOp(psContext, "&", psInst, 0, 1, 2, TO_FLAG_INTEGER); + break; + } + case OPCODE_GE: + { + /* + dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); + Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. + */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GE\n"); +#endif + AddComparision(psContext, psInst, CMP_GE, TO_FLAG_FLOAT); + break; + } + case OPCODE_MUL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MUL\n"); +#endif + CallBinaryOp(psContext, "*", psInst, 0, 1, 2, TO_FLAG_FLOAT); + break; + } + case OPCODE_IMUL: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMUL\n"); +#endif + if (GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); + + CallBinaryOp(psContext, "*", psInst, 1, 2, 3, ui32Flags); + break; + } + case OPCODE_UDIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UDIV\n"); +#endif + //destQuotient, destRemainder, src0, src1 + CallBinaryOp(psContext, "/", psInst, 0, 2, 3, TO_FLAG_UNSIGNED_INTEGER); + CallBinaryOp(psContext, "%", psInst, 1, 2, 3, TO_FLAG_UNSIGNED_INTEGER); + break; + } + case OPCODE_DIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DIV\n"); +#endif + CallBinaryOp(psContext, "/", psInst, 0, 1, 2, TO_FLAG_FLOAT); + break; + } + case OPCODE_SINCOS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SINCOS\n"); +#endif + if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) + { + CallHelper1(psContext, "sin", psInst, 0, 2); + } + + if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) + { + CallHelper1(psContext, "cos", psInst, 1, 2); + } + break; + } + + case OPCODE_DP2: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP2\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "vec4(dot(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + bcatcstr(glsl, ").xy, ("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bcatcstr(glsl, ").xy))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DP3: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP3\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "vec4(dot(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + bcatcstr(glsl, ").xyz, ("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bcatcstr(glsl, ").xyz))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DP4: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP4\n"); +#endif + CallHelper2(psContext, "dot", psInst, 0, 1, 2); + break; + } + case OPCODE_INE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INE\n"); +#endif + AddComparision(psContext, psInst, CMP_NE, TO_FLAG_INTEGER); + break; + } + case OPCODE_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//NE\n"); +#endif + AddComparision(psContext, psInst, CMP_NE, TO_FLAG_FLOAT); + break; + } + case OPCODE_IGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IGE\n"); +#endif + AddComparision(psContext, psInst, CMP_GE, TO_FLAG_INTEGER); + break; + } + case OPCODE_ILT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ILT\n"); +#endif + AddComparision(psContext, psInst, CMP_LT, TO_FLAG_INTEGER); + break; + } + case OPCODE_LT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LT\n"); +#endif + AddComparision(psContext, psInst, CMP_LT, TO_FLAG_FLOAT); + break; + } + case OPCODE_IEQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IEQ\n"); +#endif + AddComparision(psContext, psInst, CMP_EQ, TO_FLAG_INTEGER); + break; + } + case OPCODE_ULT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ULT\n"); +#endif + AddComparision(psContext, psInst, CMP_LT, TO_FLAG_UNSIGNED_INTEGER); + break; + } + case OPCODE_UGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UGE\n"); +#endif + AddComparision(psContext, psInst, CMP_GE, TO_FLAG_UNSIGNED_INTEGER); + break; + } + case OPCODE_MOVC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MOVC\n"); +#endif + AddMOVCBinaryOp(psContext, &psInst->asOperands[0], 0, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); + break; + } + case OPCODE_SWAPC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SWAPC\n"); +#endif + AddMOVCBinaryOp(psContext, &psInst->asOperands[0], 1, &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); + AddMOVCBinaryOp(psContext, &psInst->asOperands[1], 0, &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); + AddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[0], 1, 0); + break; + } + + case OPCODE_LOG: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOG\n"); +#endif + CallHelper1(psContext, "log2", psInst, 0, 1); + break; + } + case OPCODE_RSQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RSQ\n"); +#endif + CallHelper1(psContext, "inversesqrt", psInst, 0, 1); + break; + } + case OPCODE_EXP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EXP\n"); +#endif + CallHelper1(psContext, "exp2", psInst, 0, 1); + break; + } + case OPCODE_SQRT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SQRT\n"); +#endif + CallHelper1(psContext, "sqrt", psInst, 0, 1); + break; + } + case OPCODE_ROUND_PI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_PI\n"); +#endif + CallHelper1(psContext, "ceil", psInst, 0, 1); + break; + } + case OPCODE_ROUND_NI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_NI\n"); +#endif + CallHelper1(psContext, "floor", psInst, 0, 1); + break; + } + case OPCODE_ROUND_Z: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_Z\n"); +#endif + CallHelper1(psContext, "trunc", psInst, 0, 1); + break; + } + case OPCODE_ROUND_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_NE\n"); +#endif + CallHelper1(psContext, "roundEven", psInst, 0, 1); + break; + } + case OPCODE_FRC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FRC\n"); +#endif + CallHelper1(psContext, "fract", psInst, 0, 1); + break; + } + case OPCODE_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMAX\n"); +#endif + CallHelper2Int(psContext, "max", psInst, 0, 1, 2); + break; + } + case OPCODE_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMAX\n"); +#endif + CallHelper2UInt(psContext, "max", psInst, 0, 1, 2); + break; + } + case OPCODE_MAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MAX\n"); +#endif + CallHelper2(psContext, "max", psInst, 0, 1, 2); + break; + } + case OPCODE_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMIN\n"); +#endif + CallHelper2Int(psContext, "min", psInst, 0, 1, 2); + break; + } + case OPCODE_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UMIN\n"); +#endif + CallHelper2UInt(psContext, "min", psInst, 0, 1, 2); + break; + } + case OPCODE_MIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MIN\n"); +#endif + CallHelper2(psContext, "min", psInst, 0, 1, 2); + break; + } + case OPCODE_GATHER4: + { + //dest, coords, tex, sampler + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + const uint32_t ui32SampleToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4\n"); +#endif + //gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); + bcatcstr(glsl, "(textureGather("); + + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0); + bcatcstr(glsl, ", "); + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ")"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_GATHER4_PO_C: + { + //dest, coords, offset, tex, sampler, srcReferenceValue + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_PO_C\n"); +#endif + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "(textureGatherOffset("); + + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 1); + + bcatcstr(glsl, ", "); + + TranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_NONE); + + bcatcstr(glsl, ", ivec2("); + //ivec2 offset + psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_GATHER4_PO: + { + //dest, coords, offset, tex, sampler + const uint32_t ui32SampleToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, psContext); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_PO\n"); +#endif + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); + bcatcstr(glsl, "(textureGatherOffset("); + + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0); + + bcatcstr(glsl, ", "); + //Texture coord cannot be vec4 + //Determining if it is a vec3 for vec2 yet to be done. + psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + + bcatcstr(glsl, ", ivec2("); + //ivec2 offset + psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32SampleToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_GATHER4_C: + { + //dest, coords, tex, sampler srcReferenceValue +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_C\n"); +#endif + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "(textureGather("); + + TextureName(*psContext->currentGLSLString, psContext->psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1); + + bcatcstr(glsl, ", "); + //Texture coord cannot be vec4 + //Determining if it is a vec3 for vec2 yet to be done. + psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_NONE); + bcatcstr(glsl, ")"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + bcatcstr(glsl, ")"); + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_SAMPLE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE\n"); +#endif + TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); + break; + } + case OPCODE_SAMPLE_L: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_L\n"); +#endif + TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); + break; + } + case OPCODE_SAMPLE_C: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_C\n"); +#endif + + TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_COMPARE); + break; + } + case OPCODE_SAMPLE_C_LZ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_C_LZ\n"); +#endif + + TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_COMPARE | TEXSMP_FLAG_FIRSTLOD); + break; + } + case OPCODE_SAMPLE_D: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_D\n"); +#endif + + TranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); + break; + } + case OPCODE_SAMPLE_B: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_B\n"); +#endif + + TranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); + break; + } + case OPCODE_RET: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RET\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + } + if (psContext->flags & HLSLCC_FLAG_TRACING_INSTRUMENTATION) + { + WriteEndTrace(psContext); + } + AddIndentation(psContext); + bcatcstr(glsl, "return;\n"); + break; + } + case OPCODE_INTERFACE_CALL: + { + const char* name; + ShaderVar* psVar; + uint32_t varFound; + + uint32_t funcPointer; + uint32_t funcTableIndex; + uint32_t funcTable; + uint32_t funcBodyIndex; + uint32_t funcBody; + uint32_t ui32NumBodiesPerTable; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INTERFACE_CALL\n"); +#endif + + ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); + + funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; + funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; + funcBodyIndex = psInst->ui32FuncIndexWithinInterface; + + ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; + + funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; + + funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; + + varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); + + ASSERT(varFound); + + name = &psVar->sType.Name[0]; + + AddIndentation(psContext); + bcatcstr(glsl, name); + TranslateOperandIndexMAD(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); + //bformata(glsl, "[%d]", funcBodyIndex); + bcatcstr(glsl, "();\n"); + break; + } + case OPCODE_LABEL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LABEL\n"); +#endif + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); //Closing brace ends the previous function. + AddIndentation(psContext); + + bcatcstr(glsl, "subroutine(SubroutineType)\n"); + bcatcstr(glsl, "void "); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, "(){\n"); + ++psContext->indent; + break; + } + case OPCODE_COUNTBITS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//COUNTBITS\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "bitCount("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_FIRSTBIT_HI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_HI\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "findMSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_FIRSTBIT_LO: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_LO\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "findLSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_FIRSTBIT_SHI: //signed high + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_SHI\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "findMSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_BFREV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BFREV\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "bitfieldReverse("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_BFI: + { + uint32_t numelements_width = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t numelements_offset = GetNumSwizzleElements(&psInst->asOperands[2]); + uint32_t numelements_dest = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t numoverall_elements = min(min(numelements_width, numelements_offset), numelements_dest); + uint32_t i, j; + static const char* bfi_elementidx[] = { "x", "y", "z", "w" }; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BFI\n"); +#endif + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bformata(glsl, "ivec%d(", numoverall_elements); + for (i = 0; i < numoverall_elements; ++i) + { + bcatcstr(glsl, "bitfieldInsert("); + + for (j = 4; j >= 1; --j) + { + uint32_t opSwizzleCount = GetNumSwizzleElements(&psInst->asOperands[j]); + + if (opSwizzleCount != 1) + { + bcatcstr(glsl, " ("); + } + TranslateOperand(psContext, &psInst->asOperands[j], TO_FLAG_INTEGER); + if (opSwizzleCount != 1) + { + bformata(glsl, " ).%s", bfi_elementidx[i]); + } + if (j != 1) + { + bcatcstr(glsl, ","); + } + } + + bcatcstr(glsl, ") "); + if (i + 1 != numoverall_elements) + { + bcatcstr(glsl, ", "); + } + } + + bcatcstr(glsl, ")."); + for (i = 0; i < numoverall_elements; ++i) + { + bformata(glsl, "%s", bfi_elementidx[i]); + } + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_CUT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EndPrimitive();\n"); + break; + } + case OPCODE_EMIT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMIT\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + AddIndentation(psContext); + } + + AddIndentation(psContext); + bcatcstr(glsl, "EmitVertex();\n"); + break; + } + case OPCODE_EMITTHENCUT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMITTHENCUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EmitVertex();\nEndPrimitive();\n"); + break; + } + + case OPCODE_CUT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EndStreamPrimitive("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + + break; + } + case OPCODE_EMIT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMIT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EmitStreamVertex("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_EMITTHENCUT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMITTHENCUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EmitStreamVertex("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + bcatcstr(glsl, "EndStreamPrimitive("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_REP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//REP\n"); +#endif + //Need to handle nesting. + //Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx + + AddIndentation(psContext); + bcatcstr(glsl, "RepCounter = ivec4("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ").x;\n"); + + AddIndentation(psContext); + bcatcstr(glsl, "while(RepCounter!=0){\n"); + ++psContext->indent; + break; + } + case OPCODE_ENDREP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ENDREP\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "RepCounter--;\n"); + + --psContext->indent; + + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_LOOP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOOP\n"); +#endif + AddIndentation(psContext); + + if (psInst->ui32NumOperands == 2) + { + //DX9 version + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); + bcatcstr(glsl, "for("); + bcatcstr(glsl, "LoopCounter = "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".y, ZeroBasedCounter = 0;"); + bcatcstr(glsl, "ZeroBasedCounter < "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".x;"); + + bcatcstr(glsl, "LoopCounter += "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".z, ZeroBasedCounter++){\n"); + ++psContext->indent; + } + else + { + bcatcstr(glsl, "while(true){\n"); + ++psContext->indent; + } + break; + } + case OPCODE_ENDLOOP: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ENDLOOP\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_BREAK: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BREAK\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "break;\n"); + break; + } + case OPCODE_BREAKC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BREAKC\n"); +#endif + AddIndentation(psContext); + + TranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_CONTINUEC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CONTINUEC\n"); +#endif + AddIndentation(psContext); + + TranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_IF: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IF\n"); +#endif + AddIndentation(psContext); + + TranslateConditional(psContext, psInst, glsl); + ++psContext->indent; + break; + } + case OPCODE_RETC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RETC\n"); +#endif + AddIndentation(psContext); + + TranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_ELSE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ELSE\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "} else {\n"); + psContext->indent++; + break; + } + case OPCODE_ENDSWITCH: + case OPCODE_ENDIF: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "//ENDIF\n"); + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_CONTINUE: + { + AddIndentation(psContext); + bcatcstr(glsl, "continue;\n"); + break; + } + case OPCODE_DEFAULT: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "default:\n"); + ++psContext->indent; + break; + } + case OPCODE_NOP: + { + break; + } + case OPCODE_SYNC: + { + const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SYNC\n"); +#endif + + if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) + { + AddIndentation(psContext); + bcatcstr(glsl, "barrier();\n"); + AddIndentation(psContext); + bcatcstr(glsl, "groupMemoryBarrier();\n"); + } + if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) + { + AddIndentation(psContext); + bcatcstr(glsl, "memoryBarrierShared();\n"); + } + if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) + { + AddIndentation(psContext); + bcatcstr(glsl, "memoryBarrier();\n"); + } + break; + } + case OPCODE_SWITCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SWITCH\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "switch(int("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ")){\n"); + + psContext->indent += 2; + break; + } + case OPCODE_CASE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//case\n"); +#endif + AddIndentation(psContext); + + bcatcstr(glsl, "case "); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ":\n"); + + ++psContext->indent; + break; + } + case OPCODE_EQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EQ\n"); +#endif + AddComparision(psContext, psInst, CMP_EQ, TO_FLAG_FLOAT); + break; + } + case OPCODE_USHR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//USHR\n"); +#endif + CallBinaryOp(psContext, ">>", psInst, 0, 1, 2, TO_FLAG_UNSIGNED_INTEGER); + break; + } + case OPCODE_ISHL: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ISHL\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + CallBinaryOp(psContext, "<<", psInst, 0, 1, 2, ui32Flags); + break; + } + case OPCODE_ISHR: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ISHR\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + CallBinaryOp(psContext, ">>", psInst, 0, 1, 2, ui32Flags); + break; + } + case OPCODE_LD: + case OPCODE_LD_MS: + { + ResourceBinding* psBinding = 0; + uint32_t ui32FetchTypeToFlags; +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_LD) + { + bcatcstr(glsl, "//LD\n"); + } + else + { + bcatcstr(glsl, "//LD_MS\n"); + } +#endif + + GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + ui32FetchTypeToFlags = GetReturnTypeToFlags(psBinding->ui32ReturnType); + + const char* fetchFunctionString = psInst->bAddressOffset ? "texelFetchOffset" : "texelFetch"; + switch (psBinding->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + { + //texelFetch(samplerBuffer, int coord, level) + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, fetchFunctionString); + bcatcstr(glsl, "("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").x, int(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").w)"); + if (psInst->bAddressOffset) + { + bformata(glsl, ", %d", psInst->iUAddrOffset); + } + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + { + //texelFetch(samplerBuffer, ivec3 coord, level) + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, fetchFunctionString); + bcatcstr(glsl, "("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").xyz, int(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").w)"); + if (psInst->bAddressOffset) + { + if (psBinding->eDimension == REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY) + { + bformata(glsl, ", ivec2(%d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset); + } + else + { + bformata(glsl, ", ivec3(%d, %d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset, + psInst->iWAddrOffset); + } + } + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + + if (IsGmemReservedSlot(FBF_ANY, psInst->asOperands[2].ui32RegisterNumber)) // FRAMEBUFFER FETCH + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + } + else + { + bcatcstr(glsl, fetchFunctionString); + bcatcstr(glsl, "("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").xy, int(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").w)"); + if (psInst->bAddressOffset) + { + if (psBinding->eDimension == REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY) + { + bformata(glsl, ", int(%d)", psInst->iUAddrOffset); + } + else + { + bformata(glsl, ", ivec2(%d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset); + } + } + bcatcstr(glsl, ")"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + } + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_BUFFER: + { + //texelFetch(samplerBuffer, scalar integer coord) + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, "texelFetch("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").x)"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + { + //texelFetch(samplerBuffer, ivec2 coord, sample) + + ASSERT(psInst->eOpcode == OPCODE_LD_MS); + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, "texelFetch("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").xy, int("); + TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + //texelFetch(samplerBuffer, ivec3 coord, sample) + + ASSERT(psInst->eOpcode == OPCODE_LD_MS); + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, "texelFetch("); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", ivec3(("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").xyz), int("); + TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32FetchTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + case REFLECT_RESOURCE_DIMENSION_BUFFEREX: + default: + { + break; + } + } + break; + } + case OPCODE_DISCARD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DISCARD\n"); +#endif + AddIndentation(psContext); + if (psContext->psShader->ui32MajorVersion <= 3) + { + bcatcstr(glsl, "if(any(lessThan(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); + + if (psContext->psShader->ui32MajorVersion == 1) + { + /* SM1.X only kills based on the rgb channels */ + bcatcstr(glsl, ").xyz, vec3(0.0)))){discard;}\n"); + } + else + { + bcatcstr(glsl, "), vec4(0.0)))){discard;}\n"); + } + } + else if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); + bcatcstr(glsl, ")==0.0){discard;}\n"); + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT); + bcatcstr(glsl, ")!=0.0){discard;}\n"); + } + break; + } + case OPCODE_LOD: + { + uint32_t ui32SampleTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, psContext); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOD\n"); +#endif + //LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) + + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32SampleTypeToFlags, psInst->bSaturate); + + //If the core language does not have query-lod feature, + //then the extension is used. The name of the function + //changed between extension and core. + if (HaveQueryLod(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "textureQueryLod("); + } + else + { + bcatcstr(glsl, "textureQueryLOD("); + } + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ","); + TranslateTexCoord(psContext, + psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], + &psInst->asOperands[1]); + bcatcstr(glsl, ")"); + + //The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. + + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + EndAssignment(psContext, &psInst->asOperands[0], ui32SampleTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_EVAL_CENTROID: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_CENTROID\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "interpolateAtCentroid("); + //interpolateAtCentroid accepts in-qualified variables. + //As long as bytecode only writes vX registers in declarations + //we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_EVAL_SAMPLE_INDEX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_SAMPLE_INDEX\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "interpolateAtSample("); + //interpolateAtSample accepts in-qualified variables. + //As long as bytecode only writes vX registers in declarations + //we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_EVAL_SNAPPED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_SNAPPED\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "interpolateAtOffset("); + //interpolateAtOffset accepts in-qualified variables. + //As long as bytecode only writes vX registers in declarations + //we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + bcatcstr(glsl, ".xy)"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_LD_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_STRUCTURED "); +#endif + uint32_t reg_num = psInst->asOperands[3].ui32RegisterNumber; + if (reg_num >= GMEM_PLS_RO_SLOT && reg_num <= GMEM_PLS_RW_SLOT) + { +#ifdef _DEBUG + bcatcstr(glsl, "-> LOAD FROM PLS\n"); +#endif + // Ensure it's not a write only PLS + ASSERT(reg_num != GMEM_PLS_WO_SLOT); + + TranslateShaderPLSLoad(psContext, psInst); + } + else + { + bcatcstr(glsl, "\n"); + TranslateShaderStorageLoad(psContext, psInst); + } + break; + } + case OPCODE_LD_UAV_TYPED: + { + uint32_t ui32UAVReturnTypeToFlags = GetResourceReturnTypeToFlags(RGROUP_UAV, psInst->asOperands[2].ui32RegisterNumber, psContext); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_UAV_TYPED\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], ui32UAVReturnTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, "imageLoad("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); + + switch (psInst->eResDim) + { + case RESOURCE_DIMENSION_BUFFER: + case RESOURCE_DIMENSION_TEXTURE1D: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").x)"); + break; + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + case RESOURCE_DIMENSION_TEXTURE2DMS: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").xy)"); + break; + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case RESOURCE_DIMENSION_TEXTURECUBE: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").xyz)"); + break; + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").xyzw)"); + break; + } + + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + EndAssignment(psContext, &psInst->asOperands[0], ui32UAVReturnTypeToFlags, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_STORE_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_RAW\n"); +#endif + TranslateShaderStorageStore(psContext, psInst); + break; + } + case OPCODE_STORE_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_STRUCTURE "); +#endif + uint32_t reg_num = psInst->asOperands[0].ui32RegisterNumber; + if (reg_num >= GMEM_PLS_RO_SLOT && reg_num <= GMEM_PLS_RW_SLOT) + { +#ifdef _DEBUG + bcatcstr(glsl, "-> STORE TO PLS\n"); +#endif + // Ensure it's not a read only PLS + ASSERT(reg_num != GMEM_PLS_RO_SLOT); + + TranslateShaderPLSStore(psContext, psInst); + } + else + { + bcatcstr(glsl, "\n"); + TranslateShaderStorageStore(psContext, psInst); + } + break; + } + + case OPCODE_STORE_UAV_TYPED: + { + ResourceBinding* psRes; + int foundResource; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_UAV_TYPED\n"); +#endif + AddIndentation(psContext); + + foundResource = GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); + + ASSERT(foundResource); + + bcatcstr(glsl, "imageStore("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); + + switch (psRes->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_BUFFER: + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ").x"); + + // HACK!! + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, ");\n"); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ".xy)"); + + // HACK!! + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bformata(glsl, ");\n"); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ".xyz)"); + + // HACK!! + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bformata(glsl, ");\n"); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ".xyzw)"); + + // HACK!! + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bformata(glsl, ");\n"); + break; + } + + break; + } + case OPCODE_LD_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_RAW\n"); +#endif + + TranslateShaderStorageLoad(psContext, psInst); + break; + } + + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMIN: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + TranslateAtomicMemOp(psContext, psInst); + break; + } + case OPCODE_UBFE: + case OPCODE_IBFE: + { + const char* swizzles = "xyzw"; + uint32_t eDataType, destElem; + uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); + uint32_t s2ElemCount = GetNumSwizzleElements(&psInst->asOperands[3]); + const char* szVecType; + const char* szDataType; +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_UBFE) + { + bcatcstr(glsl, "//OPCODE_UBFE\n"); + } + else + { + bcatcstr(glsl, "//OPCODE_IBFE\n"); + } +#endif + if (psInst->eOpcode == OPCODE_UBFE) + { + eDataType = TO_FLAG_UNSIGNED_INTEGER; + szVecType = "uvec"; + szDataType = "uint"; + } + else + { + eDataType = TO_FLAG_INTEGER; + szVecType = "ivec"; + szDataType = "int"; + } + + if (psContext->psShader->eTargetLanguage != LANG_ES_300) + { + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], eDataType, psInst->bSaturate); + + if (destElemCount > 1) + { + bformata(glsl, "%s%d(", szVecType, destElemCount); + } + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + if (destElem > 0) + { + bcatcstr(glsl, ", "); + } + + bformata(glsl, "bitfieldExtract("); + + TranslateOperand(psContext, &psInst->asOperands[3], eDataType); + if (s2ElemCount > 1) + { + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + bformata(glsl, ".%c", swizzles[destElem]); + } + + bcatcstr(glsl, ", "); + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + if (s1ElemCount > 1) + { + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + bformata(glsl, ".%c", swizzles[destElem]); + } + + bcatcstr(glsl, ", "); + + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + if (s0ElemCount > 1) + { + TranslateOperandSwizzle(psContext, &psInst->asOperands[1]); + bformata(glsl, ".%c", swizzles[destElem]); + } + + bformata(glsl, ")"); + } + if (destElemCount > 1) + { + bcatcstr(glsl, ")"); + } + EndAssignment(psContext, &psInst->asOperands[0], eDataType, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + else + { + // Following is the explicit impl' for ES3.0 + // Here's the description of what bitfieldExtract actually does + // https://www.opengl.org/registry/specs/ARB/gpu_shader5.txt + + + AddIndentation(psContext); + bcatcstr(glsl, "{\n"); + + // << (32-bits-offset) + AddIndentation(psContext); + AddIndentation(psContext); + bcatcstr(glsl, "int offsetLeft = (32 - "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, " - "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + + // >> (32-bits) + AddIndentation(psContext); + AddIndentation(psContext); + bcatcstr(glsl, "int offsetRight = (32 - "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + + AddIndentation(psContext); + AddIndentation(psContext); + bformata(glsl, "%s tmp;\n", szDataType); + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + AddIndentation(psContext); + AddIndentation(psContext); + bcatcstr(glsl, "tmp = "); + + if (psInst->eOpcode == OPCODE_IBFE) + { + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, " ? "); + } + + TranslateOperand(psContext, &psInst->asOperands[3], eDataType); + if (s2ElemCount > 1) + { + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + bformata(glsl, ".%c", swizzles[destElem]); + } + if (psInst->eOpcode == OPCODE_IBFE) + { + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, " : 0 "); + } + bcatcstr(glsl, ";\n"); + + AddIndentation(psContext); + AddIndentation(psContext); + bcatcstr(glsl, "tmp = ((tmp << offsetLeft) >> offsetRight);\n"); + + AddIndentation(psContext); + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], 0, psInst->bSaturate); + if (eDataType == TO_FLAG_INTEGER) + { + bcatcstr(glsl, "intBitsToFloat(tmp));\n"); + } + else + { + bcatcstr(glsl, "uintBitsToFloat(tmp));\n"); + } + } + + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + } + + break; + } + case OPCODE_RCP: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RCP\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "(vec4(1.0) / vec4("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + bcatcstr(glsl, "))"); + AddSwizzleUsingElementCount(psContext, destElemCount); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_F16TOF32: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//F16TOF32\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = {".x", ".y", ".z", ".w"}; + + //unpackHalf2x16 converts two f16s packed into uint to two f32s. + + //dest.swiz.x = unpackHalf2x16(src.swiz.x).x + //dest.swiz.y = unpackHalf2x16(src.swiz.y).x + //dest.swiz.z = unpackHalf2x16(src.swiz.z).x + //dest.swiz.w = unpackHalf2x16(src.swiz.w).x + + AddIndentation(psContext); + if (destElemCount > 1) + { + BeginAssignmentEx(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate, swizzle[destElem]); + } + else + { + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + } + + bcatcstr(glsl, "unpackHalf2x16("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + if (s0ElemCount > 1) + { + bcatcstr(glsl, swizzle[destElem]); + } + bcatcstr(glsl, ").x"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + break; + } + case OPCODE_F32TOF16: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//F32TOF16\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = {".x", ".y", ".z", ".w"}; + + //packHalf2x16 converts two f32s to two f16s packed into a uint. + + //dest.swiz.x = packHalf2x16(vec2(src.swiz.x)) & 0xFFFF + //dest.swiz.y = packHalf2x16(vec2(src.swiz.y)) & 0xFFFF + //dest.swiz.z = packHalf2x16(vec2(src.swiz.z)) & 0xFFFF + //dest.swiz.w = packHalf2x16(vec2(src.swiz.w)) & 0xFFFF + + AddIndentation(psContext); + if (destElemCount > 1) + { + BeginAssignmentEx(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate, swizzle[destElem]); + } + else + { + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + } + + bcatcstr(glsl, "packHalf2x16(vec2("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + if (s0ElemCount > 1) + { + bcatcstr(glsl, swizzle[destElem]); + } + bcatcstr(glsl, ")) & 0xFFFFu"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + } + break; + } + case OPCODE_INEG: + { + uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INEG\n"); +#endif + //dest = 0 - src0 + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + //bcatcstr(glsl, " = 0 - "); + bcatcstr(glsl, "-("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); + if (srcCount > dstCount) + { + AddSwizzleUsingElementCount(psContext, dstCount); + } + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DERIV_RTX\n"); +#endif + CallHelper1(psContext, "dFdx", psInst, 0, 1); + break; + } + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_DERIV_RTY: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DERIV_RTY\n"); +#endif + CallHelper1(psContext, "dFdy", psInst, 0, 1); + break; + } + case OPCODE_LRP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LRP\n"); +#endif + CallHelper3(psContext, "mix", psInst, 0, 2, 3, 1); + break; + } + case OPCODE_DP2ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP2ADD\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "dot(vec2("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + bcatcstr(glsl, "), vec2("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bcatcstr(glsl, ")) + "); + TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_FLOAT); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_POW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//POW\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, "pow(abs("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_FLOAT); + bcatcstr(glsl, "), "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_FLOAT); + bcatcstr(glsl, ")"); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_FLOAT, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + + case OPCODE_IMM_ATOMIC_ALLOC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_ALLOC\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "atomicCounterIncrement("); + bformata(glsl, "UAV%d_counter)", psInst->asOperands[1].ui32RegisterNumber); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_IMM_ATOMIC_CONSUME: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_CONSUME\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, "atomicCounterDecrement("); + bformata(glsl, "UAV%d_counter)", psInst->asOperands[1].ui32RegisterNumber); + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + + case OPCODE_NOT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INOT\n"); +#endif + AddIndentation(psContext); + BeginAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + + uint32_t uDestElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t uSrcElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + + if (uDestElemCount == uSrcElemCount) + { + bcatcstr(glsl, "~("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + } + else + { + ASSERT(uSrcElemCount > uDestElemCount); + bformata(glsl, "ivec%d(~(", uSrcElemCount); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + } + + EndAssignment(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, psInst->bSaturate); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//XOR\n"); +#endif + + CallBinaryOp(psContext, "^", psInst, 0, 1, 2, TO_FLAG_INTEGER); + break; + } + case OPCODE_RESINFO: + { + const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; + uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RESINFO\n"); +#endif + + //ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + //ASSERT(psInst->asOperands[0].ui32CompMask == OPERAND_4_COMPONENT_MASK_ALL); + + + + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = {"x", "y", "z", "w"}; + uint32_t ui32ResInfoReturnTypeToFlags = (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) ? TO_FLAG_INTEGER /* currently it's treated as int */ : TO_FLAG_FLOAT; + + AddIndentation(psContext); + if (destElemCount > 1) + { + BeginAssignmentEx(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate, swizzle[destElem]); + } + else + { + BeginAssignment(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate); + } + + GetResInfoData(psContext, psInst, destElem); + + EndAssignment(psContext, &psInst->asOperands[0], ui32ResInfoReturnTypeToFlags, psInst->bSaturate); + + bcatcstr(glsl, ";\n"); + } + + break; + } + + + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_DTOF: + case OPCODE_FTOD: + case OPCODE_DDIV: + case OPCODE_DFMA: + case OPCODE_DRCP: + case OPCODE_MSAD: + case OPCODE_DTOI: + case OPCODE_DTOU: + case OPCODE_ITOD: + case OPCODE_UTOD: + default: + { + ASSERT(0); + break; + } + } +} + +static int IsIntegerOpcode(OPCODE_TYPE eOpcode) +{ + switch (eOpcode) + { + case OPCODE_IADD: + case OPCODE_IF: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_ITOF: + case OPCODE_AND: + case OPCODE_OR: + { + return 1; + } + default: + { + return 0; + } + } +} + +int InstructionUsesRegister(const Instruction* psInst, const Operand* psOperand) +{ + uint32_t operand; + for (operand = 0; operand < psInst->ui32NumOperands; ++operand) + { + if (psInst->asOperands[operand].eType == psOperand->eType) + { + if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) + { + if (CompareOperandSwizzles(&psInst->asOperands[operand], psOperand)) + { + return 1; + } + } + } + } + return 0; +} + +void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext) +{ + const uint32_t count = psContext->psShader->ui32InstCount; + Instruction* psInst = psContext->psShader->psInst; + uint32_t i; + + for (i = 0; i < count; ) + { + if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && + psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) + { + uint32_t k; + + for (k = i + 1; k < count; ++k) + { + if (psInst[k].eOpcode == OPCODE_ILT) + { + k = k; + } + if (InstructionUsesRegister(&psInst[k], &psInst[i].asOperands[0])) + { + if (IsIntegerOpcode(psInst[k].eOpcode)) + { + psInst[i].asOperands[1].iIntegerImmediate = 1; + } + + goto next_iteration; + } + } + } +next_iteration: + ++i; + } +} diff --git a/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c b/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c new file mode 100644 index 0000000000..b77576ed51 --- /dev/null +++ b/Code/Tools/HLSLCrossCompiler/src/toGLSLOperand.c @@ -0,0 +1,2121 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/toGLSLDeclaration.h" +#include "internal_includes/hlslccToolkit.h" +#include "internal_includes/languages.h" +#include "bstrlib.h" +#include "hlslcc.h" +#include "internal_includes/debug.h" + +#include <float.h> +#include <math.h> +#include <stdbool.h> + +#if !defined(isnan) +#ifdef _MSC_VER +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#endif +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +// Returns true if types are just different precisions of the same underlying type +static bool AreTypesCompatible(SHADER_VARIABLE_TYPE a, uint32_t ui32TOFlag) +{ + SHADER_VARIABLE_TYPE b = TypeFlagsToSVTType(ui32TOFlag); + + if (a == b) + return true; + + // Special case for array indices: both uint and int are fine + if ((ui32TOFlag & TO_FLAG_INTEGER) && (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) && + (a == SVT_INT || a == SVT_INT16 || a == SVT_UINT || a == SVT_UINT16)) + return true; + + if ((a == SVT_FLOAT || a == SVT_FLOAT16 || a == SVT_FLOAT10) && + (b == SVT_FLOAT || b == SVT_FLOAT16 || b == SVT_FLOAT10)) + return true; + + if ((a == SVT_INT || a == SVT_INT16 || a == SVT_INT12) && + (b == SVT_INT || b == SVT_INT16 || a == SVT_INT12)) + return true; + + if ((a == SVT_UINT || a == SVT_UINT16) && + (b == SVT_UINT || b == SVT_UINT16)) + return true; + + return false; +} + +int GetMaxComponentFromComponentMask(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Comonent Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 4; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 3; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 1; + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + return 4; + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return 1; + } + } + + return 4; +} + +//Single component repeated +//e..g .wwww +uint32_t IsSwizzleReplacated(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == WWWW_SWIZZLE || + psOperand->ui32Swizzle == ZZZZ_SWIZZLE || + psOperand->ui32Swizzle == YYYY_SWIZZLE || + psOperand->ui32Swizzle == XXXX_SWIZZLE) + { + return 1; + } + } + } + return 0; +} + +//e.g. +//.z = 1 +//.x = 1 +//.yw = 2 +uint32_t GetNumSwizzleElements(const Operand* psOperand) +{ + uint32_t count = 0; + + switch (psOperand->eType) + { + case OPERAND_TYPE_IMMEDIATE32: + case OPERAND_TYPE_IMMEDIATE64: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + return psOperand->iNumComponents; + } + default: + { + break; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Comonent Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + count++; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + count++; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + count++; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + count++; + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + count++; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + count++; + } + } + + //Component Select 1 + } + + if (!count) + { + return psOperand->iNumComponents; + } + + return count; +} + +void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count) +{ + bstring glsl = *psContext->currentGLSLString; + if (count) + { + bcatcstr(glsl, "."); + bcatcstr(glsl, "x"); + count--; + } + if (count) + { + bcatcstr(glsl, "y"); + count--; + } + if (count) + { + bcatcstr(glsl, "z"); + count--; + } + if (count) + { + bcatcstr(glsl, "w"); + count--; + } +} + +uint32_t ConvertOperandSwizzleToComponentMask(const Operand* psOperand) +{ + uint32_t mask = 0; + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Comonent Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + mask = psOperand->ui32CompMask; + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + + //Component Select 1 + } + + return mask; +} + +//Non-zero means the components overlap +int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB) +{ + uint32_t maskA = ConvertOperandSwizzleToComponentMask(psOperandA); + uint32_t maskB = ConvertOperandSwizzleToComponentMask(psOperandB); + + return maskA & maskB; +} + + +void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + bstring glsl = *psContext->currentGLSLString; + + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return; + } + } + + if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + /*ConstantBuffer* psCBuf = NULL; + ShaderVar* psVar = NULL; + int32_t index = -1; + GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) + //then apply the sizzle. + + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); + + bformata(glsl, ".%s", psVar->Name); + if(index != -1) + { + bformata(glsl, "[%d]", index); + }*/ + + //return; + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Comonent Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + bcatcstr(glsl, "."); + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + bcatcstr(glsl, "x"); + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + bcatcstr(glsl, "y"); + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + bcatcstr(glsl, "z"); + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + bcatcstr(glsl, "w"); + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + bcatcstr(glsl, "."); + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + bcatcstr(glsl, "x"); + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(glsl, "y"); + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(glsl, "z"); + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + bcatcstr(glsl, "w"); + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + bcatcstr(glsl, "."); + + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + bcatcstr(glsl, "x"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(glsl, "y"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(glsl, "z"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + bcatcstr(glsl, "w"); + } + } + + //Component Select 1 + } +} + +int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return -1; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Comonent Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 0; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 1; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 3; + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + + //Component Select 1 + } + + return -1; +} + +void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) +{ + int i = index; + int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; + + bstring glsl = *psContext->currentGLSLString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0 || isGeoShader) + { + bformata(glsl, "[%d]", psOperand->aui32ArraySizes[i]); + } + else + { + bformata(glsl, "%d", psOperand->aui32ArraySizes[i]); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(glsl, "[int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bcatcstr(glsl, ")]"); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(glsl, "[int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bformata(glsl, ") + %d]", psOperand->aui32ArraySizes[i]); + break; + } + default: + { + break; + } + } +} + +void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) +{ + int i = index; + int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; + + bstring glsl = *psContext->currentGLSLString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0 || isGeoShader) + { + bformata(glsl, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + } + else + { + bformata(glsl, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(glsl, "[int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bformata(glsl, ")*%d+%d]", multiply, add); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(glsl, "[(int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bformata(glsl, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + break; + } + default: + { + break; + } + } +} + +void TranslateVariableNameByOperandType(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) +{ + bstring glsl = *psContext->currentGLSLString; + + switch (psOperand->eType) + { + case OPERAND_TYPE_IMMEDIATE32: + { + if (psOperand->iNumComponents == 1) + { + if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bformata(glsl, "%uu", + *((unsigned int*)(&psOperand->afImmediates[0]))); + } + else + if ((ui32TOFlag & TO_FLAG_INTEGER) || ((ui32TOFlag & TO_FLAG_FLOAT) == 0 && psOperand->iIntegerImmediate) || fpcheck(psOperand->afImmediates[0])) + { + if (ui32TOFlag & TO_FLAG_FLOAT) + { + bcatcstr(glsl, "float"); + } + else if (ui32TOFlag & TO_FLAG_INTEGER) + { + bcatcstr(glsl, "int"); + } + bcatcstr(glsl, "("); + + // yet another Qualcomm's special case + // GLSL compiler thinks that -2147483648 is an integer overflow which is not + if (*((int*)(&psOperand->afImmediates[0])) == 2147483648) + { + bformata(glsl, "-2147483647-1"); + } + else + { + // this is expected to fix paranoid compiler checks such as Qualcomm's + if (*((unsigned int*)(&psOperand->afImmediates[0])) >= 2147483648) + { + bformata(glsl, "%d", + *((int*)(&psOperand->afImmediates[0]))); + } + else + { + bformata(glsl, "%d", + *((int*)(&psOperand->afImmediates[0]))); + } + } + bcatcstr(glsl, ")"); + } + else + { + bformata(glsl, "%e", + psOperand->afImmediates[0]); + } + } + else + { + if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bformata(glsl, "uvec4(%uu, %uu, %uu, %uu)", + *(unsigned int*)&psOperand->afImmediates[0], + *(unsigned int*)&psOperand->afImmediates[1], + *(unsigned int*)&psOperand->afImmediates[2], + *(unsigned int*)&psOperand->afImmediates[3]); + } + else + if ((ui32TOFlag & TO_FLAG_INTEGER) || + ((ui32TOFlag & TO_FLAG_FLOAT) == 0 && psOperand->iIntegerImmediate) || + fpcheck(psOperand->afImmediates[0]) || + fpcheck(psOperand->afImmediates[1]) || + fpcheck(psOperand->afImmediates[2]) || + fpcheck(psOperand->afImmediates[3])) + { + // this is expected to fix paranoid compiler checks such as Qualcomm's + if (ui32TOFlag & TO_FLAG_FLOAT) + { + bcatcstr(glsl, "vec4"); + } + else if (ui32TOFlag & TO_FLAG_INTEGER) + { + bcatcstr(glsl, "ivec4"); + } + else if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(glsl, "uvec4"); + } + bcatcstr(glsl, "("); + + if ((*(unsigned int*)&psOperand->afImmediates[0]) == 2147483648u) + { + bformata(glsl, "int(-2147483647-1), "); + } + else + { + bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[0]); + } + if ((*(unsigned int*)&psOperand->afImmediates[1]) == 2147483648u) + { + bformata(glsl, "int(-2147483647-1), "); + } + else + { + bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[1]); + } + if ((*(unsigned int*)&psOperand->afImmediates[2]) == 2147483648u) + { + bformata(glsl, "int(-2147483647-1), "); + } + else + { + bformata(glsl, "%d, ", *(int*)&psOperand->afImmediates[2]); + } + if ((*(unsigned int*)&psOperand->afImmediates[3]) == 2147483648u) + { + bformata(glsl, "int(-2147483647-1)) "); + } + else + { + bformata(glsl, "%d)", *(int*)&psOperand->afImmediates[3]); + } + } + else + { + bformata(glsl, "vec4(%e, %e, %e, %e)", + psOperand->afImmediates[0], + psOperand->afImmediates[1], + psOperand->afImmediates[2], + psOperand->afImmediates[3]); + } + if (psOperand->iNumComponents != 4) + { + AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); + } + } + break; + } + case OPERAND_TYPE_IMMEDIATE64: + { + if (psOperand->iNumComponents == 1) + { + bformata(glsl, "%e", + psOperand->adImmediates[0]); + } + else + { + bformata(glsl, "dvec4(%e, %e, %e, %e)", + psOperand->adImmediates[0], + psOperand->adImmediates[1], + psOperand->adImmediates[2], + psOperand->adImmediates[3]); + if (psOperand->iNumComponents != 4) + { + AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + switch (psOperand->iIndexDims) + { + case INDEX_2D: + { + if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. + { + bcatcstr(glsl, "gl_in"); + TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE); //Vertex index + bcatcstr(glsl, ".gl_Position"); + } + else + { + const char* name = "Input"; + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); + } + + bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + bcstrfree((char*)name); + } + TranslateOperandIndex(psContext, psOperand, TO_FLAG_NONE); //Vertex index + } + break; + } + default: + { + if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) + { + bformata(glsl, "Input%d[int(", psOperand->ui32RegisterNumber); + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")]"); + } + else + { + if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) + { + const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; + bformata(glsl, "Input%d[%d]", parentIndex, + psOperand->ui32RegisterNumber - parentIndex); + } + else + { + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); + bcatcstr(glsl, name); + bcstrfree(name); + } + else + { + bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); + } + } + } + break; + } + } + break; + } + case OPERAND_TYPE_OUTPUT: + { + bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); + if (psOperand->psSubOperand[0]) + { + bcatcstr(glsl, "[int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")]"); + } + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bcatcstr(glsl, "gl_FragDepth"); + break; + } + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); + bcatcstr(glsl, "Temp"); + + if ((psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) == 0 || psContext->psShader->eShaderType == HULL_SHADER) + { + if (eType == SVT_INT) + { + bcatcstr(glsl, "_int"); + } + else if (eType == SVT_UINT) + { + bcatcstr(glsl, "_uint"); + } + else if (eType == SVT_DOUBLE) + { + bcatcstr(glsl, "_double"); + } + else if (eType == SVT_VOID || + (ui32TOFlag & TO_FLAG_DESTINATION)) + { + if (ui32TOFlag & TO_FLAG_INTEGER) + { + bcatcstr(glsl, "_int"); + } + else + if (ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(glsl, "_uint"); + } + } + + bformata(glsl, "[%d]", psOperand->ui32RegisterNumber); + } + else + { + if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) + bformata(glsl, "%d[0]", psOperand->ui32RegisterNumber); + else + bformata(glsl, "%d", psOperand->ui32RegisterNumber); + } + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONSTINT: + { + bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONST: + { + if (psOperand->psSubOperand[0] != NULL) + { + bformata(glsl, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_NONE); + bcatcstr(glsl, "]"); + } + else + { + bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber); + } + break; + } + case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: + { + bcatcstr(glsl, "BaseColour"); + break; + } + case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: + { + bcatcstr(glsl, "OffsetColour"); + break; + } + case OPERAND_TYPE_SPECIAL_POSITION: + { + bcatcstr(glsl, "gl_Position"); + break; + } + case OPERAND_TYPE_SPECIAL_FOG: + { + bcatcstr(glsl, "Fog"); + break; + } + case OPERAND_TYPE_SPECIAL_POINTSIZE: + { + bcatcstr(glsl, "gl_PointSize"); + break; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + { + bcatcstr(glsl, "Address"); + break; + } + case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: + { + bcatcstr(glsl, "LoopCounter"); + pui32IgnoreSwizzle[0] = 1; + break; + } + case OPERAND_TYPE_SPECIAL_TEXCOORD: + { + bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + bool addParentheses = false; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + pui32IgnoreSwizzle[0] = 1; + } + + if ((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) + { + if (psCBuf) + { + //$Globals. + if (psCBuf->Name[0] == '$') + { + ConvertToUniformBufferName(glsl, psContext->psShader, "$Globals"); + } + else + { + ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); + } + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(glsl, "."); + } + } + else + { + //bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]); + } + } + + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + //Work out the variable name. Don't apply swizzle to that variable yet. + int32_t rebase = 0; + + if (psCBuf && !psCBuf->blob) + { + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + if (psContext->flags & HLSLCC_FLAG_QUALCOMM_GLES30_DRIVER_WORKAROUND) + { + if (psVarType->Class == SVC_VECTOR || psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) + { + switch (psVarType->Type) + { + case SVT_FLOAT: + case SVT_FLOAT16: + case SVT_FLOAT10: + { + bformata(glsl, "vec%d(", psVarType->Columns); + break; + } + case SVT_UINT: + case SVT_UINT16: + { + bformata(glsl, "uvec%d(", psVarType->Columns); + break; + } + case SVT_INT: + case SVT_INT16: + case SVT_INT12: + { + bformata(glsl, "ivec%d(", psVarType->Columns); + break; + } + default: + { + ASSERT(0); + break; + } + } + addParentheses = true; + } + else if (psVarType->Class == SVC_SCALAR) + { + switch (psVarType->Type) + { + case SVT_FLOAT: + case SVT_FLOAT16: + case SVT_FLOAT10: + { + bformata(glsl, "float("); + break; + } + case SVT_UINT: + case SVT_UINT16: + { + bformata(glsl, "uint("); + break; + } + case SVT_INT: + case SVT_INT16: + case SVT_INT12: + { + bformata(glsl, "int("); + break; + } + default: + { + ASSERT(0); + break; + } + } + addParentheses = true; + } + } + ShaderVarFullName(glsl, psContext->psShader, psVarType); + } + else if (psCBuf) + { + ConvertToUniformBufferName(glsl, psContext->psShader, psCBuf->Name); + bcatcstr(glsl, "_data"); + index = psOperand->aui32ArraySizes[1]; + } + else + // We don't have a semantic for this variable, so try the raw dump appoach. + { + bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]); // + index = psOperand->aui32ArraySizes[1]; + } + + //Dx9 only? + if (psOperand->psSubOperand[0] != NULL) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[0]); + if (eType != SVT_INT && eType != SVT_UINT) + { + bcatcstr(glsl, "[int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")]"); + } + else + { + bcatcstr(glsl, "["); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + } + } + else + if (index != -1 && psOperand->psSubOperand[1] != NULL) + { + //Array of matrices is treated as array of vec4s + if (index != -1) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); + if (eType != SVT_INT && eType != SVT_UINT) + { + bcatcstr(glsl, "[int("); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bformata(glsl, ") + %d]", index); + } + else + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bformata(glsl, " + %d]", index); + } + } + } + else if (index != -1) + { + bformata(glsl, "[%d]", index); + } + else if (psOperand->psSubOperand[1] != NULL) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand->psSubOperand[1]); + if (eType != SVT_INT && eType != SVT_UINT) + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + } + else + { + bcatcstr(glsl, "[int("); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ")]"); + } + } + + if (addParentheses) + bcatcstr(glsl, ")"); + + if (psVarType && psVarType->Class == SVC_VECTOR) + { + switch (rebase) + { + case 4: + { + if (psVarType->Columns == 2) + { + //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) + bcatcstr(glsl, ".xxyx"); + } + else if (psVarType->Columns == 3) + { + //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL) + bcatcstr(glsl, ".xxyz"); + } + break; + } + case 8: + { + if (psVarType->Columns == 2) + { + //.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL) + bcatcstr(glsl, ".xxxy"); + } + break; + } + case 0: + default: + { + //No rebase, but extend to vec4. + if (psVarType->Columns == 2) + { + bcatcstr(glsl, ".xyxx"); + } + else if (psVarType->Columns == 3) + { + bcatcstr(glsl, ".xyzx"); + } + break; + } + } + } + + if (psVarType && psVarType->Class == SVC_SCALAR) + { + *pui32IgnoreSwizzle = 1; + } + } + break; + } + case OPERAND_TYPE_RESOURCE: + { + TextureName(*psContext->currentGLSLString, psContext->psShader, psOperand->ui32RegisterNumber, MAX_RESOURCE_BINDINGS, 0); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_SAMPLER: + { + bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_FUNCTION_BODY: + { + const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; + const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; + //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; + const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; + const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; + const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; + + bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); + break; + } + case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: + { + bcatcstr(glsl, "forkInstanceID"); + *pui32IgnoreSwizzle = 1; + return; + } + case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + { + bcatcstr(glsl, "immediateConstBufferF"); + + if (psOperand->psSubOperand[0]) + { + bcatcstr(glsl, "(int("); //Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + } + break; + } + case OPERAND_TYPE_INPUT_DOMAIN_POINT: + { + bcatcstr(glsl, "gl_TessCoord"); + break; + } + case OPERAND_TYPE_INPUT_CONTROL_POINT: + { + if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. + { + bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); + } + else + { + bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); + } + break; + } + case OPERAND_TYPE_NULL: + { + // Null register, used to discard results of operations + bcatcstr(glsl, "//null"); + break; + } + case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: + { + bcatcstr(glsl, "gl_InvocationID"); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + bcatcstr(glsl, "gl_SampleMask[0]"); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_COVERAGE_MASK: + { + bcatcstr(glsl, "gl_SampleMaskIn[0]"); + //Skip swizzle on scalar types. + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID://SV_DispatchThreadID + { + bcatcstr(glsl, "gl_GlobalInvocationID.xyzz"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID://SV_GroupThreadID + { + bcatcstr(glsl, "gl_WorkGroupID.xyzz"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP://SV_GroupID + { + bcatcstr(glsl, "gl_LocalInvocationID.xyzz"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED://SV_GroupIndex + { + bcatcstr(glsl, "gl_LocalInvocationIndex.xyzz"); + break; + } + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + { + UAVName(*psContext->currentGLSLString, psContext->psShader, psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_PRIMITIVEID: + { + bcatcstr(glsl, "gl_PrimitiveID"); + break; + } + case OPERAND_TYPE_INDEXABLE_TEMP: + { + bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]); + bformata(glsl, "[%d", psOperand->aui32ArraySizes[1]); + + if (psOperand->psSubOperand[1]) + { + bcatcstr(glsl, "+"); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_UNSIGNED_INTEGER); + } + bcatcstr(glsl, "]"); + break; + } + case OPERAND_TYPE_STREAM: + { + bformata(glsl, "%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: + { + bcatcstr(glsl, "gl_InvocationID"); + break; + } + case OPERAND_TYPE_THIS_POINTER: + { + /* + The "this" register is a register that provides up to 4 pieces of information: + X: Which CB holds the instance data + Y: Base element offset of the instance data within the instance CB + Z: Base sampler index + W: Base Texture index + + Can be different for each function call + */ + break; + } + default: + { + ASSERT(0); + break; + } + } +} + +void TranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) +{ + bool hasConstructor = false; + bstring glsl = *psContext->currentGLSLString; + + *pui32IgnoreSwizzle = 0; + + if (psOperand->eType != OPERAND_TYPE_IMMEDIATE32 && + psOperand->eType != OPERAND_TYPE_IMMEDIATE64) + { + if (ui32TOFlag != TO_FLAG_NONE && !(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) + { + SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTType(ui32TOFlag); + const uint32_t swizCount = psOperand->iNumComponents; + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); + + if (!AreTypesCompatible(eType, ui32TOFlag)) + { + if (CanDoDirectCast(eType, requestedType)) + { + bformata(glsl, "%s(", GetConstructorForTypeGLSL(psContext, requestedType, swizCount, false)); + } + else + { + // Direct cast not possible, need to do bitcast. + bformata(glsl, "%s(", GetBitcastOp(eType, requestedType)); + } + + hasConstructor = true; + } + } + } + + if (ui32TOFlag & TO_FLAG_COPY) + { + bcatcstr(glsl, "TempCopy"); + if ((psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING) == 0) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, psOperand); + switch (eType) + { + case SVT_FLOAT: + break; + case SVT_INT: + bcatcstr(glsl, "_int"); + break; + case SVT_UINT: + bcatcstr(glsl, "_uint"); + break; + case SVT_DOUBLE: + bcatcstr(glsl, "_double"); + break; + default: + ASSERT(0); + break; + } + } + } + else + { + TranslateVariableNameByOperandType(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle); + } + + if (hasConstructor) + { + bcatcstr(glsl, ")"); + } +} +SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + if (HavePrecisionQualifers(psContext->psShader->eTargetLanguage)) + { + // The min precision qualifier overrides all of the stuff below + switch (psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_FLOAT_16: + return SVT_FLOAT16; + case OPERAND_MIN_PRECISION_FLOAT_2_8: + return SVT_FLOAT10; + case OPERAND_MIN_PRECISION_SINT_16: + return SVT_INT16; + case OPERAND_MIN_PRECISION_UINT_16: + return SVT_UINT16; + default: + break; + } + } + + switch (psOperand->eType) + { + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; + int i = 0; + + if (psContext->flags & HLSLCC_FLAG_AVOID_TEMP_REGISTER_ALIASING && psContext->psShader->eShaderType != HULL_SHADER) + { + return psContext->psShader->aeCommonTempVecType[psOperand->ui32RegisterNumber]; + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + return psOperand->aeDataType[0]; + } + + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + for (; i < 4; ++i) + { + if (ui32CompMask & (1 << i)) + { + eCurrentType = psOperand->aeDataType[i]; + break; + } + } + +#ifdef _DEBUG + //Check if all elements have the same basic type. + for (; i < 4; ++i) + { + if (psOperand->ui32CompMask & (1 << i)) + { + if (eCurrentType != psOperand->aeDataType[i]) + { + ASSERT(0); + } + } + } +#endif + return eCurrentType; + } + + ASSERT(0); + + break; + } + case OPERAND_TYPE_OUTPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psOut; + + if (GetOutputSignatureFromRegister(ui32Register, psOperand->ui32CompMask, 0, &psContext->psShader->sInfo, &psOut)) + { + if (psOut->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psIn; + + //UINT in DX, INT in GL. + if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) + { + return SVT_INT; + } + + if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) + { + if (psIn->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + int32_t rebase = -1; + int foundVar; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + if (psCBuf && !psCBuf->blob) + { + foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) + { + return psVarType->Type; + } + } + else + { + // Todo: this isn't correct yet. + return SVT_FLOAT; + } + break; + } + case OPERAND_TYPE_IMMEDIATE32: + { + return psOperand->iIntegerImmediate ? SVT_INT : SVT_FLOAT; + } + + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + { + return SVT_UINT; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + { + return SVT_INT; + } + default: + { + return SVT_FLOAT; + } + } + + return SVT_FLOAT; +} + +void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) +{ + bstring glsl = *psContext->currentGLSLString; + uint32_t ui32IgnoreSwizzle = 0; + + if (ui32TOFlag & TO_FLAG_NAME_ONLY) + { + TranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); + return; + } + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + bcatcstr(glsl, "-"); + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(glsl, "abs("); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(glsl, "-abs("); + break; + } + } + + TranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); + + if (!ui32IgnoreSwizzle || IsGmemReservedSlot(FBF_ANY, psOperand->ui32RegisterNumber)) + { + TranslateOperandSwizzle(psContext, psOperand); + } + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(glsl, ")"); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(glsl, ")"); + break; + } + } +} + +char ShaderTypePrefix(Shader* psShader) +{ + switch (psShader->eShaderType) + { + default: + ASSERT(0); + case PIXEL_SHADER: + return 'p'; + case VERTEX_SHADER: + return 'v'; + case GEOMETRY_SHADER: + return 'g'; + case HULL_SHADER: + return 'h'; + case DOMAIN_SHADER: + return 'd'; + case COMPUTE_SHADER: + return 'c'; + } +} + +char ResourceGroupPrefix(ResourceGroup eResGroup) +{ + switch (eResGroup) + { + default: + ASSERT(0); + case RGROUP_CBUFFER: + return 'c'; + case RGROUP_TEXTURE: + return 't'; + case RGROUP_SAMPLER: + return 's'; + case RGROUP_UAV: + return 'u'; + } +} + +void ResourceName(bstring output, Shader* psShader, const char* szName, ResourceGroup eGroup, const char* szSecondaryName, ResourceGroup eSecondaryGroup, uint32_t ui32ArrayOffset, const char* szModifier) +{ + + const char* pBracket; + + bconchar(output, ShaderTypePrefix(psShader)); + bcatcstr(output, szModifier); + + bconchar(output, ResourceGroupPrefix(eGroup)); + while ((pBracket = strpbrk(szName, "[]")) != NULL) + { + //array syntax [X] becomes _0_ + //Otherwise declarations could end up as: + //uniform sampler2D SomeTextures[0]; + //uniform sampler2D SomeTextures[1]; + bcatblk(output, (const void*)szName, (int)(pBracket - szName)); + bconchar(output, '_'); + szName = pBracket + 1; + } + bcatcstr(output, szName); + + if (ui32ArrayOffset) + { + bformata(output, "%d", ui32ArrayOffset); + } + + if (szSecondaryName != NULL) + { + bconchar(output, ResourceGroupPrefix(eSecondaryGroup)); + bcatcstr(output, szSecondaryName); + } +} + +void TextureName(bstring output, Shader* psShader, const uint32_t ui32TextureRegister, const uint32_t ui32SamplerRegister, const int bCompare) +{ + ResourceBinding* psTextureBinding = 0; + ResourceBinding* psSamplerBinding = 0; + int found; + const char* szModifier = bCompare ? "c" : ""; + + found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegister, &psShader->sInfo, &psTextureBinding); + if (ui32SamplerRegister < MAX_RESOURCE_BINDINGS) + { + found &= GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegister, &psShader->sInfo, &psSamplerBinding); + } + + if (found) + { + if (IsGmemReservedSlot(FBF_EXT_COLOR, ui32TextureRegister) || IsGmemReservedSlot(FBF_ARM_COLOR, ui32TextureRegister)) // FRAMEBUFFER FETCH + { + int regNum = GetGmemInputResourceSlot(ui32TextureRegister); + bformata(output, "GMEM_Input%d", regNum); + } + else if (IsGmemReservedSlot(FBF_ARM_DEPTH, ui32TextureRegister)) + { + bcatcstr(output, "GMEM_Depth"); + } + else if (IsGmemReservedSlot(FBF_ARM_STENCIL, ui32TextureRegister)) + { + bcatcstr(output, "GMEM_Stencil"); + } + else + { + ResourceName(output, psShader, psTextureBinding->Name, RGROUP_TEXTURE, psSamplerBinding ? psSamplerBinding->Name : NULL, RGROUP_SAMPLER, ui32TextureRegister - psTextureBinding->ui32BindPoint, szModifier); + } + } + else if (ui32SamplerRegister < MAX_RESOURCE_BINDINGS) + { + bformata(output, "UnknownTexture%s_%d_%d", szModifier, ui32TextureRegister, ui32SamplerRegister); + } + else + { + bformata(output, "UnknownTexture%s_%d", szModifier, ui32TextureRegister); + } +} + +void UAVName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber) +{ + ResourceBinding* psBinding = 0; + int found; + + found = GetResourceFromBindingPoint(RGROUP_UAV, ui32RegisterNumber, &psShader->sInfo, &psBinding); + + if (found) + { + ResourceName(output, psShader, psBinding->Name, RGROUP_UAV, NULL, RGROUP_COUNT, ui32RegisterNumber - psBinding->ui32BindPoint, ""); + } + else + { + bformata(output, "UnknownUAV%d", ui32RegisterNumber); + } +} + +void UniformBufferName(bstring output, Shader* psShader, const uint32_t ui32RegisterNumber) +{ + ResourceBinding* psBinding = 0; + int found; + + found = GetResourceFromBindingPoint(RGROUP_CBUFFER, ui32RegisterNumber, &psShader->sInfo, &psBinding); + + if (found) + { + ResourceName(output, psShader, psBinding->Name, RGROUP_CBUFFER, NULL, RGROUP_COUNT, ui32RegisterNumber - psBinding->ui32BindPoint, ""); + } + else + { + bformata(output, "UnknownUniformBuffer%d", ui32RegisterNumber); + } +} + +void ShaderVarName(bstring output, Shader* psShader, const char* OriginalName) +{ + bconchar(output, ShaderTypePrefix(psShader)); + bcatcstr(output, OriginalName); +} + +void ShaderVarFullName(bstring output, Shader* psShader, const ShaderVarType* psShaderVar) +{ + if (psShaderVar->Parent != NULL) + { + ShaderVarFullName(output, psShader, psShaderVar->Parent); + bconchar(output, '.'); + } + ShaderVarName(output, psShader, psShaderVar->Name); +} + +void ConvertToTextureName(bstring output, Shader* psShader, const char* szName, const char* szSamplerName, const int bCompare) +{ + (void)bCompare; + + ResourceName(output, psShader, szName, RGROUP_TEXTURE, szSamplerName, RGROUP_SAMPLER, 0, ""); +} + +void ConvertToUAVName(bstring output, Shader* psShader, const char* szOriginalUAVName) +{ + ResourceName(output, psShader, szOriginalUAVName, RGROUP_UAV, NULL, RGROUP_COUNT, 0, ""); +} + +void ConvertToUniformBufferName(bstring output, Shader* psShader, const char* szConstantBufferName) +{ + ResourceName(output, psShader, szConstantBufferName, RGROUP_CBUFFER, NULL, RGROUP_COUNT, 0, ""); +} + +uint32_t GetGmemInputResourceSlot(uint32_t const slotIn) +{ + if (slotIn == GMEM_ARM_COLOR_SLOT) + { + // ARM framebuffer fetch only works with COLOR0 + return 0; + } + if (slotIn >= GMEM_FLOAT4_START_SLOT) + { + return slotIn - GMEM_FLOAT4_START_SLOT; + } + if (slotIn >= GMEM_FLOAT3_START_SLOT) + { + return slotIn - GMEM_FLOAT3_START_SLOT; + } + if (slotIn >= GMEM_FLOAT2_START_SLOT) + { + return slotIn - GMEM_FLOAT2_START_SLOT; + } + if (slotIn >= GMEM_FLOAT_START_SLOT) + { + return slotIn - GMEM_FLOAT_START_SLOT; + } + return slotIn; +} + +uint32_t GetGmemInputResourceNumElements(uint32_t const slotIn) +{ + if (slotIn >= GMEM_FLOAT4_START_SLOT) + { + return 4; + } + if (slotIn >= GMEM_FLOAT3_START_SLOT) + { + return 3; + } + if (slotIn >= GMEM_FLOAT2_START_SLOT) + { + return 2; + } + if (slotIn >= GMEM_FLOAT_START_SLOT) + { + return 1; + } + return 0; +} + +void TranslateGmemOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements) +{ + // Similar as TranslateOperandSwizzleWithMaskMETAL but need to considerate max # of elements + + bstring metal = *psContext->currentGLSLString; + + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents != 1) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t mask; + if (psOperand->ui32CompMask != 0) + { + mask = psOperand->ui32CompMask & ui32ComponentMask; + } + else + { + mask = ui32ComponentMask; + } + + if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) + { + bcatcstr(metal, "."); + if (mask & OPERAND_4_COMPONENT_MASK_X) + { + bcatcstr(metal, "x"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + if (mask & OPERAND_4_COMPONENT_MASK_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + if (mask & OPERAND_4_COMPONENT_MASK_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || + !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && + psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && + psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && + psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W + ) + ) + { + uint32_t i; + + bcatcstr(metal, "."); + + for (i = 0; i < 4; ++i) + { + if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) + { + continue; + } + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case + { + bcatcstr(metal, "."); + + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + + //Component Select 1 + } +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt b/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt new file mode 100644 index 0000000000..33fcc54e34 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +if (PAL_TRAIT_BUILD_HOST_TOOLS) + + ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) + + include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + if (NOT PAL_TRAIT_BUILD_HLSLCC_METAL) + return() + endif() + + ly_add_target( + NAME HLSLcc_Metal EXECUTABLE + NAMESPACE AZ + OUTPUT_NAME HLSLcc + OUTPUT_SUBDIRECTORY Compiler/PCGMETAL/HLSLcc + FILES_CMAKE + hlslcc_metal_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + include + src + src/cbstring + offline/cjson + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + ) + ly_add_source_properties( + SOURCES + offline/compilerStandalone.cpp + offline/cjson/cJSON.c + src/toGLSL.c + src/toGLSLDeclaration.c + src/cbstring/bstrlib.c + src/cbstring/bstraux.c + src/reflect.c + src/decode.c + src/toMETAL.c + src/toMETALDeclaration.c + PROPERTY COMPILE_DEFINITIONS + VALUES _CRT_SECURE_NO_WARNINGS + ) + +endif() diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake new file mode 100644 index 0000000000..6dc23ee057 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Linux/PAL_linux.cmake @@ -0,0 +1,12 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(PAL_TRAIT_BUILD_HLSLCC_METAL FALSE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake new file mode 100644 index 0000000000..6dc23ee057 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Mac/PAL_mac.cmake @@ -0,0 +1,12 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(PAL_TRAIT_BUILD_HLSLCC_METAL FALSE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake new file mode 100644 index 0000000000..ee003b245b --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/Platform/Windows/PAL_windows.cmake @@ -0,0 +1,12 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(PAL_TRAIT_BUILD_HLSLCC_METAL TRUE) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/README b/Code/Tools/HLSLCrossCompilerMETAL/README new file mode 100644 index 0000000000..2f36e0966e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/README @@ -0,0 +1,52 @@ +What does this software do? + Cross compiles HLSL bytecode to GLSL or GLSL ES. It also provides functions to + decode the reflection information embedded in HLSL bytecode. Both offline and online compiliation + is supported. + +Supported bytecode formats: + cs_4_0 cs_4_1 cs_5_0 + ds_5_0 + hs_5_0 + gs_4_0 gs_4_1 gs_5_0 + ps_4_0 ps_4_0_level_9_1 ps_4_0_level_9_3 ps_4_0_level_9_0 ps_4_1 ps_5_0 + vs_4_0_level_9_3 vs_4_0_level_9_0 vs_4_1 vs_5_0 + +Work is underway to support the DX9 bytecode formats: + ps_2_0 ps_2_a ps_2_b ps_3_0 + vs_1_1 vs_2_0 vs_2_a vs_3_0 + +Supported target languages: + GLSL ES 100 + GLSL ES 300 + GLSL ES 310 + GLSL 120 + GLSL 130 + GLSL 140 + GLSL 150 + GLSL 330 + GLSL 400 + GLSL 410 + GLSL 420 + GLSL 430 + GLSL 440 + METAL + +I have plans to add support for more target languages including: + ARB assembly (ARB_vertex_program et al.) + NVIDIA assembly (NV_vertex_program et al.) + +If the source shader contains instructions not support by the target language then compilation is allowed +to fail at the GLSL compile stage, i.e. the cross compiler may not generate errors/warnings but an OpenGL +driver will reject the shader. + +The tests directory contains HLSL, bytecode and asm versions of some shaders used to verify this decoder. +There are also a few sample applications used to make sure that generated GLSL is correct. + +A cmake makefile can be found in the mk directory. + +Generating hlsl_opcode_funcs_glsl.h + Use fwrap.py -f hlsl_opcode_funcs.glsl + fwrap.py can be found in my Helpful-scripts github repository. + +For further information please see the Wiki page for this project at +https://github.com/James-Jones/HLSLCrossCompiler/wiki. diff --git a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe new file mode 100644 index 0000000000..f1206847af --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35285dbf53617bf58f22035bb502d0b3328678344245635de578c2e73d484d04 +size 216064 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe new file mode 100644 index 0000000000..64dab82ae4 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/bin/win32/HLSLcc_d.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99f686d3fc04c80f3460e6d35507acb09f5975f7c4d5e5cae95834e48a46898a +size 462848 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake b/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake new file mode 100644 index 0000000000..ffeb9d9755 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/hlslcc_metal_files.cmake @@ -0,0 +1,65 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +set(FILES + include/hlslcc.h + include/hlslcc.hpp + include/pstdint.h + include/hlslcc_bin.hpp + offline/hash.h + offline/serializeReflection.h + offline/timer.h + offline/compilerStandalone.cpp + offline/serializeReflection.cpp + offline/timer.cpp + offline/cjson/cJSON.h + offline/cjson/cJSON.c + src/decode.c + src/decodeDX9.c + src/reflect.c + src/toGLSL.c + src/toMETAL.c + src/toMETALDeclaration.c + src/toMETALInstruction.c + src/toMETALOperand.c + src/toGLSLDeclaration.c + src/toGLSLInstruction.c + src/toGLSLOperand.c + src/internal_includes/debug.h + src/internal_includes/decode.h + src/internal_includes/hlslcc_malloc.h + src/internal_includes/hlslcc_malloc.c + src/internal_includes/languages.h + src/internal_includes/reflect.h + src/internal_includes/shaderLimits.h + src/internal_includes/structs.h + src/internal_includes/toMETALDeclaration.h + src/internal_includes/toMETALInstruction.h + src/internal_includes/toMETALOperand.h + src/internal_includes/toGLSLDeclaration.h + src/internal_includes/toGLSLInstruction.h + src/internal_includes/toGLSLOperand.h + src/internal_includes/tokens.h + src/internal_includes/tokensDX9.h + src/internal_includes/structsMetal.h + src/internal_includes/structsMetal.c + src/cbstring/bsafe.h + src/cbstring/bstraux.h + src/cbstring/bstrlib.h + src/cbstring/bsafe.c + src/cbstring/bstraux.c + src/cbstring/bstrlib.c +) + +set(SKIP_UNITY_BUILD_INCLUSION_FILES + # 'bsafe.c' tries to forward declar 'strncpy', 'strncat', etc, but they are already declared in other modules. Remove from unity builds conideration + src/cbstring/bsafe.c +) \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h new file mode 100644 index 0000000000..b7444121bc --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.h @@ -0,0 +1,537 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HLSLCC_H_ +#define HLSLCC_H_ + +#if defined (_WIN32) && defined(HLSLCC_DYNLIB) + #define HLSLCC_APIENTRY __stdcall + #if defined(libHLSLcc_EXPORTS) + #define HLSLCC_API __declspec(dllexport) + #else + #define HLSLCC_API __declspec(dllimport) + #endif +#else + #define HLSLCC_APIENTRY + #define HLSLCC_API +#endif + +#include <stdint.h> +#include <stddef.h> + +#ifndef __cplusplus + #ifndef max + #define max(a,b) (((a) > (b)) ? (a) : (b)) + #endif + + #ifndef min + #define min(a,b) (((a) < (b)) ? (a) : (b)) + #endif +#endif //__cplusplus + +typedef enum +{ + LANG_DEFAULT,// Depends on the HLSL shader model. + LANG_ES_100, + LANG_ES_300, + LANG_ES_310, + LANG_120, + LANG_130, + LANG_140, + LANG_150, + LANG_330, + LANG_400, + LANG_410, + LANG_420, + LANG_430, + LANG_440, + // CONFETTI + LANG_METAL, +} ShaderLang; + +typedef struct +{ + uint32_t ARB_explicit_attrib_location : 1; + uint32_t ARB_explicit_uniform_location : 1; + uint32_t ARB_shading_language_420pack : 1; +}GlExtensions; + +enum +{ + MAX_SHADER_VEC4_OUTPUT = 512 +}; +enum +{ + MAX_SHADER_VEC4_INPUT = 512 +}; +enum +{ + MAX_TEXTURES = 128 +}; +enum +{ + MAX_FORK_PHASES = 2 +}; +enum +{ + MAX_FUNCTION_BODIES = 1024 +}; +enum +{ + MAX_CLASS_TYPES = 1024 +}; +enum +{ + MAX_FUNCTION_POINTERS = 128 +}; + +//Reflection +#define MAX_REFLECT_STRING_LENGTH 512 +#define MAX_CBUFFERS 256 +#define MAX_UAV 256 +#define MAX_FUNCTION_TABLES 256 +#define MAX_RESOURCE_BINDINGS 256 + +typedef enum SPECIAL_NAME +{ + NAME_UNDEFINED = 0, + NAME_POSITION = 1, + NAME_CLIP_DISTANCE = 2, + NAME_CULL_DISTANCE = 3, + NAME_RENDER_TARGET_ARRAY_INDEX = 4, + NAME_VIEWPORT_ARRAY_INDEX = 5, + NAME_VERTEX_ID = 6, + NAME_PRIMITIVE_ID = 7, + NAME_INSTANCE_ID = 8, + NAME_IS_FRONT_FACE = 9, + NAME_SAMPLE_INDEX = 10, + // The following are added for D3D11 + NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR = 11, + NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR = 12, + NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR = 13, + NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR = 14, + NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR = 15, + NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR = 16, + NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR = 17, + NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR = 18, + NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR = 19, + NAME_FINAL_TRI_INSIDE_TESSFACTOR = 20, + NAME_FINAL_LINE_DETAIL_TESSFACTOR = 21, + NAME_FINAL_LINE_DENSITY_TESSFACTOR = 22, +} SPECIAL_NAME; + + +typedef enum +{ + INOUT_COMPONENT_UNKNOWN = 0, + INOUT_COMPONENT_UINT32 = 1, + INOUT_COMPONENT_SINT32 = 2, + INOUT_COMPONENT_FLOAT32 = 3 +} INOUT_COMPONENT_TYPE; + +typedef enum MIN_PRECISION +{ + MIN_PRECISION_DEFAULT = 0, + MIN_PRECISION_FLOAT_16 = 1, + MIN_PRECISION_FLOAT_2_8 = 2, + MIN_PRECISION_RESERVED = 3, + MIN_PRECISION_SINT_16 = 4, + MIN_PRECISION_UINT_16 = 5, + MIN_PRECISION_ANY_16 = 0xf0, + MIN_PRECISION_ANY_10 = 0xf1 +} MIN_PRECISION; + +typedef struct InOutSignature_TAG +{ + char SemanticName[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32SemanticIndex; + SPECIAL_NAME eSystemValueType; + INOUT_COMPONENT_TYPE eComponentType; + uint32_t ui32Register; + uint32_t ui32Mask; + uint32_t ui32ReadWriteMask; + + uint32_t ui32Stream; + MIN_PRECISION eMinPrec; +} InOutSignature; + +typedef enum ResourceType_TAG +{ + RTYPE_CBUFFER,//0 + RTYPE_TBUFFER,//1 + RTYPE_TEXTURE,//2 + RTYPE_SAMPLER,//3 + RTYPE_UAV_RWTYPED,//4 + RTYPE_STRUCTURED,//5 + RTYPE_UAV_RWSTRUCTURED,//6 + RTYPE_BYTEADDRESS,//7 + RTYPE_UAV_RWBYTEADDRESS,//8 + RTYPE_UAV_APPEND_STRUCTURED,//9 + RTYPE_UAV_CONSUME_STRUCTURED,//10 + RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER,//11 + RTYPE_COUNT, +} ResourceType; + +typedef enum ResourceGroup_TAG +{ + RGROUP_CBUFFER, + RGROUP_TEXTURE, + RGROUP_SAMPLER, + RGROUP_UAV, + RGROUP_COUNT, +} ResourceGroup; + +typedef enum UAVBindingArea_TAG +{ + UAVAREA_INVALID, + UAVAREA_CBUFFER, + UAVAREA_TEXTURE, + UAVAREA_COUNT, +} UAVBindingArea; + +typedef enum REFLECT_RESOURCE_DIMENSION +{ + REFLECT_RESOURCE_DIMENSION_UNKNOWN = 0, + REFLECT_RESOURCE_DIMENSION_BUFFER = 1, + REFLECT_RESOURCE_DIMENSION_TEXTURE1D = 2, + REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY = 3, + REFLECT_RESOURCE_DIMENSION_TEXTURE2D = 4, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY = 5, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS = 6, + REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 7, + REFLECT_RESOURCE_DIMENSION_TEXTURE3D = 8, + REFLECT_RESOURCE_DIMENSION_TEXTURECUBE = 9, + REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, + REFLECT_RESOURCE_DIMENSION_BUFFEREX = 11, +} REFLECT_RESOURCE_DIMENSION; + +typedef struct ResourceBinding_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + ResourceType eType; + uint32_t ui32BindPoint; + uint32_t ui32BindCount; + uint32_t ui32Flags; + REFLECT_RESOURCE_DIMENSION eDimension; + uint32_t ui32ReturnType; + uint32_t ui32NumSamples; + UAVBindingArea eBindArea; +} ResourceBinding; + +typedef enum _SHADER_VARIABLE_TYPE +{ + SVT_VOID = 0, + SVT_BOOL = 1, + SVT_INT = 2, + SVT_FLOAT = 3, + SVT_STRING = 4, + SVT_TEXTURE = 5, + SVT_TEXTURE1D = 6, + SVT_TEXTURE2D = 7, + SVT_TEXTURE3D = 8, + SVT_TEXTURECUBE = 9, + SVT_SAMPLER = 10, + SVT_PIXELSHADER = 15, + SVT_VERTEXSHADER = 16, + SVT_UINT = 19, + SVT_UINT8 = 20, + SVT_GEOMETRYSHADER = 21, + SVT_RASTERIZER = 22, + SVT_DEPTHSTENCIL = 23, + SVT_BLEND = 24, + SVT_BUFFER = 25, + SVT_CBUFFER = 26, + SVT_TBUFFER = 27, + SVT_TEXTURE1DARRAY = 28, + SVT_TEXTURE2DARRAY = 29, + SVT_RENDERTARGETVIEW = 30, + SVT_DEPTHSTENCILVIEW = 31, + SVT_TEXTURE2DMS = 32, + SVT_TEXTURE2DMSARRAY = 33, + SVT_TEXTURECUBEARRAY = 34, + SVT_HULLSHADER = 35, + SVT_DOMAINSHADER = 36, + SVT_INTERFACE_POINTER = 37, + SVT_COMPUTESHADER = 38, + SVT_DOUBLE = 39, + SVT_RWTEXTURE1D = 40, + SVT_RWTEXTURE1DARRAY = 41, + SVT_RWTEXTURE2D = 42, + SVT_RWTEXTURE2DARRAY = 43, + SVT_RWTEXTURE3D = 44, + SVT_RWBUFFER = 45, + SVT_BYTEADDRESS_BUFFER = 46, + SVT_RWBYTEADDRESS_BUFFER = 47, + SVT_STRUCTURED_BUFFER = 48, + SVT_RWSTRUCTURED_BUFFER = 49, + SVT_APPEND_STRUCTURED_BUFFER = 50, + SVT_CONSUME_STRUCTURED_BUFFER = 51, + + // Partial precision types + SVT_FLOAT10 = 53, + SVT_FLOAT16 = 54, + + + SVT_FORCE_DWORD = 0x7fffffff +} SHADER_VARIABLE_TYPE; + +typedef enum _SHADER_VARIABLE_CLASS +{ + SVC_SCALAR = 0, + SVC_VECTOR = (SVC_SCALAR + 1), + SVC_MATRIX_ROWS = (SVC_VECTOR + 1), + SVC_MATRIX_COLUMNS = (SVC_MATRIX_ROWS + 1), + SVC_OBJECT = (SVC_MATRIX_COLUMNS + 1), + SVC_STRUCT = (SVC_OBJECT + 1), + SVC_INTERFACE_CLASS = (SVC_STRUCT + 1), + SVC_INTERFACE_POINTER = (SVC_INTERFACE_CLASS + 1), + SVC_FORCE_DWORD = 0x7fffffff +} SHADER_VARIABLE_CLASS; + +typedef struct ShaderVarType_TAG +{ + SHADER_VARIABLE_CLASS Class; + SHADER_VARIABLE_TYPE Type; + uint32_t Rows; + uint32_t Columns; + uint32_t Elements; + uint32_t MemberCount; + uint32_t Offset; + char Name[MAX_REFLECT_STRING_LENGTH]; + + uint32_t ParentCount; + struct ShaderVarType_TAG* Parent; + //Includes all parent names. + char FullName[MAX_REFLECT_STRING_LENGTH]; + + struct ShaderVarType_TAG* Members; +} ShaderVarType; + +typedef struct ShaderVar_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + int haveDefaultValue; + uint32_t* pui32DefaultValues; + //Offset/Size in bytes. + uint32_t ui32StartOffset; + uint32_t ui32Size; + + ShaderVarType sType; +} ShaderVar; + +typedef struct ConstantBuffer_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + + uint32_t ui32NumVars; + ShaderVar* asVars; + + uint32_t ui32TotalSizeInBytes; + int blob; // Used with dynamic indexed const. buffers +} ConstantBuffer; + +typedef struct ClassType_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + uint16_t ui16ID; + uint16_t ui16ConstBufStride; + uint16_t ui16Texture; + uint16_t ui16Sampler; +} ClassType; + +typedef struct ClassInstance_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; + uint16_t ui16ID; + uint16_t ui16ConstBuf; + uint16_t ui16ConstBufOffset; + uint16_t ui16Texture; + uint16_t ui16Sampler; +} ClassInstance; + +typedef enum TESSELLATOR_PARTITIONING +{ + TESSELLATOR_PARTITIONING_UNDEFINED = 0, + TESSELLATOR_PARTITIONING_INTEGER = 1, + TESSELLATOR_PARTITIONING_POW2 = 2, + TESSELLATOR_PARTITIONING_FRACTIONAL_ODD = 3, + TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN = 4 +} TESSELLATOR_PARTITIONING; + +typedef enum TESSELLATOR_OUTPUT_PRIMITIVE +{ + TESSELLATOR_OUTPUT_UNDEFINED = 0, + TESSELLATOR_OUTPUT_POINT = 1, + TESSELLATOR_OUTPUT_LINE = 2, + TESSELLATOR_OUTPUT_TRIANGLE_CW = 3, + TESSELLATOR_OUTPUT_TRIANGLE_CCW = 4 +} TESSELLATOR_OUTPUT_PRIMITIVE; + +typedef struct TextureSamplerPair_TAG +{ + char Name[MAX_REFLECT_STRING_LENGTH]; +} TextureSamplerPair; + +typedef struct TextureSamplerInfo_TAG +{ + uint32_t ui32NumTextureSamplerPairs; + TextureSamplerPair aTextureSamplerPair[MAX_RESOURCE_BINDINGS]; +} TextureSamplerInfo; + +typedef struct ShaderInfo_TAG +{ + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + + uint32_t ui32NumInputSignatures; + InOutSignature* psInputSignatures; + + uint32_t ui32NumOutputSignatures; + InOutSignature* psOutputSignatures; + + uint32_t ui32NumPatchConstantSignatures; + InOutSignature* psPatchConstantSignatures; + + uint32_t ui32NumResourceBindings; + ResourceBinding* psResourceBindings; + + uint32_t ui32NumConstantBuffers; + ConstantBuffer* psConstantBuffers; + ConstantBuffer* psThisPointerConstBuffer; + + uint32_t ui32NumClassTypes; + ClassType* psClassTypes; + + uint32_t ui32NumClassInstances; + ClassInstance* psClassInstances; + + //Func table ID to class name ID. + uint32_t aui32TableIDToTypeID[MAX_FUNCTION_TABLES]; + + uint32_t aui32ResourceMap[RGROUP_COUNT][MAX_RESOURCE_BINDINGS]; + + // Texture index to sampler slot + uint32_t aui32SamplerMap[MAX_RESOURCE_BINDINGS]; + + TESSELLATOR_PARTITIONING eTessPartitioning; + TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; + + //compute shader thread number + uint32_t ui32Thread_x; + uint32_t ui32Thread_y; + uint32_t ui32Thread_z; +} ShaderInfo; + +typedef enum INTERPOLATION_MODE +{ + INTERPOLATION_UNDEFINED = 0, + INTERPOLATION_CONSTANT = 1, + INTERPOLATION_LINEAR = 2, + INTERPOLATION_LINEAR_CENTROID = 3, + INTERPOLATION_LINEAR_NOPERSPECTIVE = 4, + INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID = 5, + INTERPOLATION_LINEAR_SAMPLE = 6, + INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE = 7, +} INTERPOLATION_MODE; + +typedef struct +{ + int shaderType; //One of the GL enums. + char* sourceCode; + ShaderInfo reflection; + ShaderLang GLSLLanguage; + TextureSamplerInfo textureSamplerInfo; // HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS fills this out +} Shader; + +// NOTE: HLSLCC flags are specified by command line when executing this cross compiler. +// If these flags change, the command line switch '-flags=XXX' must change as well. +// Open 3D Engine composes the command line in file 'dev\Code\CryEngine\RenderDll\Common\Shaders\RemoteCompiler.cpp' + +/*HLSL constant buffers are treated as default-block unform arrays by default. This is done + to support versions of GLSL which lack ARB_uniform_buffer_object functionality. + Setting this flag causes each one to have its own uniform block. + Note: Currently the nth const buffer will be named UnformBufferN. This is likey to change to the original HLSL name in the future.*/ +static const unsigned int HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT = 0x1; + +static const unsigned int HLSLCC_FLAG_ORIGIN_UPPER_LEFT = 0x2; + +static const unsigned int HLSLCC_FLAG_PIXEL_CENTER_INTEGER = 0x4; + +static const unsigned int HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO = 0x8; + +//GS enabled? +//Affects vertex shader (i.e. need to compile vertex shader again to use with/without GS). +//This flag is needed in order for the interfaces between stages to match when GS is in use. +//PS inputs VtxGeoOutput +//GS outputs VtxGeoOutput +//Vs outputs VtxOutput if GS enabled. VtxGeoOutput otherwise. +static const unsigned int HLSLCC_FLAG_GS_ENABLED = 0x10; + +static const unsigned int HLSLCC_FLAG_TESS_ENABLED = 0x20; + +//Either use this flag or glBindFragDataLocationIndexed. +//When set the first pixel shader output is the first input to blend +//equation, the others go to the second input. +static const unsigned int HLSLCC_FLAG_DUAL_SOURCE_BLENDING = 0x40; + +//If set, shader inputs and outputs are declared with their semantic name. +static const unsigned int HLSLCC_FLAG_INOUT_SEMANTIC_NAMES = 0x80; +//If set, shader inputs and outputs are declared with their semantic name appended. +static const unsigned int HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES = 0x100; + +//If set, combines texture/sampler pairs used together into samplers named "texturename_X_samplername". +static const unsigned int HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS = 0x200; + +//If set, attribute and uniform explicit location qualifiers are disabled (even if the language version supports that) +static const unsigned int HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS = 0x400; + +//If set, global uniforms are not stored in a struct. +static const unsigned int HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT = 0x800; + +// If set, HLSL DX9 lower precision qualifiers (e.g half) will be transformed to DX11 style (e.g min16float) +// before compiling. Necessary to preserve precision information. If not, FXC just silently transform +// everything to full precision (e.g float32). +static const unsigned int HLSLCC_FLAG_HALF_FLOAT_TRANSFORM = 0x40000; + +#ifdef __cplusplus +extern "C" { +#endif + +HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t), + void* (*calloc_override)(size_t, size_t), + void (* free_override)(void*), + void* (*realloc_override)(void*, size_t)); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToGLSL(const char* filename, + unsigned int flags, + ShaderLang language, + const GlExtensions* extensions, + Shader* result + ); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToGLSL(const char* shader, + unsigned int flags, + ShaderLang language, + const GlExtensions* extensions, + Shader* result); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToMETAL(const char* filename, + unsigned int flags, + ShaderLang language, + Shader* result + ); + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToMETAL(const char* shader, + unsigned int flags, + ShaderLang language, + Shader* result); + + +HLSLCC_API void HLSLCC_APIENTRY FreeShader(Shader*); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp new file mode 100644 index 0000000000..193415f277 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc.hpp @@ -0,0 +1,7 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +extern "C" { +#include "hlslcc.h" +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp new file mode 100644 index 0000000000..cc41572aa2 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/include/hlslcc_bin.hpp @@ -0,0 +1,448 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) + +enum +{ + DXBC_BASE_ALIGNMENT = 4, + FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C'), + FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F'), + FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N'), + FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N'), + FOURCC_PCSG = FOURCC('P', 'C', 'S', 'G'), + FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R'), + FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X'), + FOURCC_GLSL = FOURCC('G', 'L', 'S', 'L'), + FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1'), // When lower precision float/int/uint is used + FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1'), // When lower precision float/int/uint is used +}; + +#undef FOURCC + +template <typename T> +inline T DXBCSwapBytes(const T& kValue) +{ + return kValue; +} + +#if defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN + +inline uint16_t DXBCSwapBytes(const uint16_t& uValue) +{ + return + (((uValue) >> 8) & 0xFF) | + (((uValue) << 8) & 0xFF); +} + +inline uint32_t DXBCSwapBytes(const uint32_t& uValue) +{ + return + (((uValue) >> 24) & 0x000000FF) | + (((uValue) >> 8) & 0x0000FF00) | + (((uValue) << 8) & 0x00FF0000) | + (((uValue) << 24) & 0xFF000000); +} + +#endif //defined(__BIG_ENDIAN__) || SYSTEM_IS_BIG_ENDIAN + +template <typename Element> +struct SDXBCBufferBase +{ + Element* m_pBegin; + Element* m_pEnd; + Element* m_pIter; + + SDXBCBufferBase(Element* pBegin, Element* pEnd) + : m_pBegin(pBegin) + , m_pEnd(pEnd) + , m_pIter(pBegin) + { + } + + bool SeekRel(int32_t iOffset) + { + Element* pIterAfter(m_pIter + iOffset); + if (pIterAfter > m_pEnd) + { + return false; + } + + m_pIter = pIterAfter; + return true; + } + + bool SeekAbs(uint32_t uPosition) + { + Element* pIterAfter(m_pBegin + uPosition); + if (pIterAfter > m_pEnd) + { + return false; + } + + m_pIter = pIterAfter; + return true; + } +}; + +struct SDXBCInputBuffer + : SDXBCBufferBase<const uint8_t> +{ + SDXBCInputBuffer(const uint8_t* pBegin, const uint8_t* pEnd) + : SDXBCBufferBase(pBegin, pEnd) + { + } + + bool Read(void* pElements, size_t uSize) + { + const uint8_t* pIterAfter(m_pIter + uSize); + if (pIterAfter > m_pEnd) + { + return false; + } + + memcpy(pElements, m_pIter, uSize); + + m_pIter = pIterAfter; + return true; + } +}; + +struct SDXBCOutputBuffer + : SDXBCBufferBase<uint8_t> +{ + SDXBCOutputBuffer(uint8_t* pBegin, uint8_t* pEnd) + : SDXBCBufferBase(pBegin, pEnd) + { + } + + bool Write(const void* pElements, size_t uSize) + { + uint8_t* pIterAfter(m_pIter + uSize); + if (pIterAfter > m_pEnd) + { + return false; + } + + memcpy(m_pIter, pElements, uSize); + + m_pIter = pIterAfter; + return true; + } +}; + +template <typename S, typename External, typename Internal> +inline bool DXBCReadAs(S& kStream, External& kValue) +{ + Internal kInternal; + bool bResult(kStream.Read(&kInternal, sizeof(Internal))); + kValue = static_cast<External>(DXBCSwapBytes(kInternal)); + return bResult; +} + +template <typename S, typename Internal> +inline bool DXBCWriteAs(S& kStream, Internal kValue) +{ + Internal kInternal(DXBCSwapBytes(kValue)); + return kStream.Write(&kInternal, sizeof(Internal)); +} + +template <typename S, typename T> +bool DXBCReadUint8 (S& kStream, T& kValue) { return DXBCReadAs<S, T, uint8_t >(kStream, kValue); } +template <typename S, typename T> +bool DXBCReadUint16(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint16_t>(kStream, kValue); } +template <typename S, typename T> +bool DXBCReadUint32(S& kStream, T& kValue) { return DXBCReadAs<S, T, uint32_t>(kStream, kValue); } + +template <typename S> +bool DXBCWriteUint8 (S& kStream, uint8_t kValue) { return DXBCWriteAs<S, uint8_t >(kStream, kValue); } +template <typename S> +bool DXBCWriteUint16(S& kStream, uint16_t kValue) { return DXBCWriteAs<S, uint16_t>(kStream, kValue); } +template <typename S> +bool DXBCWriteUint32(S& kStream, uint32_t kValue) { return DXBCWriteAs<S, uint32_t>(kStream, kValue); } + +template <typename O, typename I> +bool DXBCCopy(O& kOutput, I& kInput, size_t uSize) +{ + char acBuffer[1024]; + while (uSize > 0) + { + size_t uToCopy(std::min<size_t>(uSize, sizeof(acBuffer))); + if (!kInput.Read(acBuffer, uToCopy) || + !kOutput.Write(acBuffer, uToCopy)) + { + return false; + } + uSize -= uToCopy; + } + return true; +} + +enum +{ + DXBC_SIZE_POSITION = 6 * 4, + DXBC_HEADER_SIZE = 7 * 4, + DXBC_CHUNK_HEADER_SIZE = 2 * 4, + DXBC_MAX_NUM_CHUNKS_IN = 128, + DXBC_MAX_NUM_CHUNKS_OUT = 8, + DXBC_OUT_CHUNKS_INDEX_SIZE = (1 + 1 + DXBC_MAX_NUM_CHUNKS_OUT) * 4, + DXBC_OUT_FIXED_SIZE = DXBC_HEADER_SIZE + DXBC_OUT_CHUNKS_INDEX_SIZE, +}; + +inline void DXBCSizeGLSLChunk(uint32_t& uGLSLChunkSize, uint32_t& uNumSamplers, uint32_t& uGLSLSourceSize, const Shader* pShader) +{ + enum + { + GLSL_HEADER_SIZE = 4 * 8, // {uint32 uNumSamplers; uint32 uNumImports; uint32 uNumExports; uint32 uInputHash;uint32 uResources; uint32 ui32Thread_x; uint32 ui32Thread_y; uint32 ui32Thread_z} + GLSL_SAMPLER_SIZE = 4 * 2, // {uint32 uTexture; uint32 uSampler;} + GLSL_SYMBOL_SIZE = 4 * 3, // {uint32 uType; uint32 uID; uint32 uValue} + //extend for metal compute UAV type + GLSL_UAV_RESOURCES_AREA = 4 * 2, //{uint32 uResource; uint32 eBindArea} + }; + + // Only texture registers that are used are written + uNumSamplers = 0; + for (uint32_t uTexture = 0; uTexture < MAX_RESOURCE_BINDINGS; ++uTexture) + { + if (pShader->reflection.aui32SamplerMap[uTexture] != MAX_RESOURCE_BINDINGS) + { + ++uNumSamplers; + } + } + + //uint32_t uNumSymbols( + // pShader->reflection.ui32NumImports + + // pShader->reflection.ui32NumExports); + uint32_t uNumSymbols(0); // always 0 + uint32_t uNumResources(pShader->reflection.ui32NumResourceBindings); + + uint32_t uGLSLInfoSize( + DXBC_CHUNK_HEADER_SIZE + + GLSL_HEADER_SIZE + + uNumSamplers * GLSL_SAMPLER_SIZE + + uNumSymbols * GLSL_SYMBOL_SIZE + + uNumResources * GLSL_UAV_RESOURCES_AREA + ); + uGLSLSourceSize = (uint32_t)strlen(pShader->sourceCode) + 1; + uGLSLChunkSize = uGLSLInfoSize + uGLSLSourceSize; + uGLSLChunkSize += DXBC_BASE_ALIGNMENT - 1 - (uGLSLChunkSize - 1) % DXBC_BASE_ALIGNMENT; +} + +inline uint32_t DXBCSizeOutputChunk(uint32_t uCode, uint32_t uSizeIn) +{ + uint32_t uSizeOut; + switch (uCode) + { + case FOURCC_RDEF: + case FOURCC_ISGN: + case FOURCC_OSGN: + case FOURCC_PCSG: + case FOURCC_OSG1: + case FOURCC_ISG1: + // Preserve entire chunk + uSizeOut = uSizeIn; + break; + case FOURCC_SHDR: + case FOURCC_SHEX: + // Only keep the shader version + uSizeOut = uSizeIn < 4u ? uSizeIn : 4u; + break; + default: + // Discard the chunk + uSizeOut = 0; + break; + } + + return uSizeOut + DXBC_BASE_ALIGNMENT - 1 - (uSizeOut - 1) % DXBC_BASE_ALIGNMENT; +} + +template <typename I> +size_t DXBCGetCombinedSize(I& kDXBCInput, const Shader* pShader) +{ + uint32_t uNumChunksIn; + if (!kDXBCInput.SeekAbs(DXBC_HEADER_SIZE) || + !DXBCReadUint32(kDXBCInput, uNumChunksIn)) + { + return 0; + } + + uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + if (!DXBCReadUint32(kDXBCInput, auChunkOffsetsIn[uChunk])) + { + return 0; + } + } + + uint32_t uNumChunksOut(0); + uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); + for (uint32_t uChunk = 0; uChunk < uNumChunksIn && uNumChunksOut < DXBC_MAX_NUM_CHUNKS_OUT; ++uChunk) + { + uint32_t uChunkCode, uChunkSizeIn; + if (!kDXBCInput.SeekAbs(auChunkOffsetsIn[uChunk]) || + !DXBCReadUint32(kDXBCInput, uChunkCode) || + !DXBCReadUint32(kDXBCInput, uChunkSizeIn)) + { + return 0; + } + + uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); + if (uChunkSizeOut > 0) + { + uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; + } + } + + uint32_t uNumSamplers, uGLSLSourceSize, uGLSLChunkSize; + DXBCSizeGLSLChunk(uGLSLChunkSize, uNumSamplers, uGLSLSourceSize, pShader); + uOutSize += uGLSLChunkSize; + + return uOutSize; +} + +template <typename I, typename O> +bool DXBCCombineWithGLSL(I& kInput, O& kOutput, const Shader* pShader) +{ + uint32_t uNumChunksIn; + if (!DXBCCopy(kOutput, kInput, DXBC_HEADER_SIZE) || + !DXBCReadUint32(kInput, uNumChunksIn) || + uNumChunksIn > DXBC_MAX_NUM_CHUNKS_IN) + { + return false; + } + + uint32_t auChunkOffsetsIn[DXBC_MAX_NUM_CHUNKS_IN]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + if (!DXBCReadUint32(kInput, auChunkOffsetsIn[uChunk])) + { + return false; + } + } + + uint32_t auZeroChunkIndex[DXBC_OUT_CHUNKS_INDEX_SIZE] = {0}; + if (!kOutput.Write(auZeroChunkIndex, DXBC_OUT_CHUNKS_INDEX_SIZE)) + { + return false; + } + + // Copy required input chunks just after the chunk index + uint32_t uOutSize(DXBC_OUT_FIXED_SIZE); + uint32_t uNumChunksOut(0); + uint32_t auChunkOffsetsOut[DXBC_MAX_NUM_CHUNKS_OUT]; + for (uint32_t uChunk = 0; uChunk < uNumChunksIn; ++uChunk) + { + uint32_t uChunkCode, uChunkSizeIn; + if (!kInput.SeekAbs(auChunkOffsetsIn[uChunk]) || + !DXBCReadUint32(kInput, uChunkCode) || + !DXBCReadUint32(kInput, uChunkSizeIn)) + { + return false; + } + + // Filter only input chunks of the specified types + uint32_t uChunkSizeOut(DXBCSizeOutputChunk(uChunkCode, uChunkSizeIn)); + if (uChunkSizeOut > 0) + { + if (uNumChunksOut >= DXBC_MAX_NUM_CHUNKS_OUT) + { + return false; + } + + if (!DXBCWriteUint32(kOutput, uChunkCode) || + !DXBCWriteUint32(kOutput, uChunkSizeOut) || + !DXBCCopy(kOutput, kInput, uChunkSizeOut)) + { + return false; + } + + auChunkOffsetsOut[uNumChunksOut] = uOutSize; + ++uNumChunksOut; + uOutSize += DXBC_CHUNK_HEADER_SIZE + uChunkSizeOut; + } + } + // Write GLSL chunk + uint32_t uGLSLChunkOffset(uOutSize); + uint32_t uGLSLChunkSize, uNumSamplers, uGLSLSourceSize; + DXBCSizeGLSLChunk(uGLSLChunkSize, uNumSamplers, uGLSLSourceSize, pShader); + if (!DXBCWriteUint32(kOutput, (uint32_t)FOURCC_GLSL) || + !DXBCWriteUint32(kOutput, uGLSLChunkSize) || + !DXBCWriteUint32(kOutput, uNumSamplers) || + !DXBCWriteUint32(kOutput, 0) || + !DXBCWriteUint32(kOutput, 0) || + !DXBCWriteUint32(kOutput, 0) || + /*!DXBCWriteUint32(kOutput, pShader->reflection.ui32NumImports) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumExports) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32InputHash)*/ + !DXBCWriteUint32(kOutput, pShader->reflection.ui32NumResourceBindings) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_x) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_y) || + !DXBCWriteUint32(kOutput, pShader->reflection.ui32Thread_z)) + { + return false; + } + for (uint32_t uTexture = 0; uTexture < MAX_RESOURCE_BINDINGS; ++uTexture) + { + uint32_t uSampler(pShader->reflection.aui32SamplerMap[uTexture]); + if (uSampler != MAX_RESOURCE_BINDINGS) + { + if (!DXBCWriteUint32(kOutput, uTexture) || + !DXBCWriteUint32(kOutput, uSampler)) + { + return false; + } + } + } + //for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumImports; ++uSymbol) + //{ + // if (!DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].eType) || + // !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32ID) || + // !DXBCWriteUint32(kOutput, pShader->reflection.psImports[uSymbol].ui32Value)) + // return false; + //} + //for (uint32_t uSymbol = 0; uSymbol < pShader->reflection.ui32NumExports; ++uSymbol) + //{ + // if (!DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].eType) || + // !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32ID) || + // !DXBCWriteUint32(kOutput, pShader->reflection.psExports[uSymbol].ui32Value)) + // return false; + //} + for (uint32_t uResource = 0; uResource < pShader->reflection.ui32NumResourceBindings; ++uResource) + { + ResourceBinding* rb = pShader->reflection.psResourceBindings + uResource; + if (uResource != MAX_RESOURCE_BINDINGS) + { + if (!DXBCWriteUint32(kOutput, uResource) || + !DXBCWriteUint32(kOutput, rb->eBindArea)) + { + return false; + } + } + } + + if (!kOutput.Write(pShader->sourceCode, uGLSLSourceSize)) + { + return false; + } + uOutSize += uGLSLChunkSize; + + // Write total size and chunk index + if (!kOutput.SeekAbs(DXBC_SIZE_POSITION) || + !DXBCWriteUint32(kOutput, uOutSize) || + !kOutput.SeekAbs(DXBC_HEADER_SIZE) || + !DXBCWriteUint32(kOutput, uNumChunksOut + 1)) + { + return false; + } + for (uint32_t uChunk = 0; uChunk < uNumChunksOut; ++uChunk) + { + if (!DXBCWriteUint32(kOutput, auChunkOffsetsOut[uChunk])) + { + return false; + } + } + DXBCWriteUint32(kOutput, uGLSLChunkOffset); + + return true; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h b/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h new file mode 100644 index 0000000000..6998242aa1 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/include/pstdint.h @@ -0,0 +1,801 @@ +/* A portable stdint.h + **************************************************************************** + * BSD License: + **************************************************************************** + * + * Copyright (c) 2005-2011 Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + **************************************************************************** + * + * Version 0.1.12 + * + * The ANSI C standard committee, for the C99 standard, specified the + * inclusion of a new standard include file called stdint.h. This is + * a very useful and long desired include file which contains several + * very precise definitions for integer scalar types that is + * critically important for making portable several classes of + * applications including cryptography, hashing, variable length + * integer libraries and so on. But for most developers its likely + * useful just for programming sanity. + * + * The problem is that most compiler vendors have decided not to + * implement the C99 standard, and the next C++ language standard + * (which has a lot more mindshare these days) will be a long time in + * coming and its unknown whether or not it will include stdint.h or + * how much adoption it will have. Either way, it will be a long time + * before all compilers come with a stdint.h and it also does nothing + * for the extremely large number of compilers available today which + * do not include this file, or anything comparable to it. + * + * So that's what this file is all about. Its an attempt to build a + * single universal include file that works on as many platforms as + * possible to deliver what stdint.h is supposed to. A few things + * that should be noted about this file: + * + * 1) It is not guaranteed to be portable and/or present an identical + * interface on all platforms. The extreme variability of the + * ANSI C standard makes this an impossibility right from the + * very get go. Its really only meant to be useful for the vast + * majority of platforms that possess the capability of + * implementing usefully and precisely defined, standard sized + * integer scalars. Systems which are not intrinsically 2s + * complement may produce invalid constants. + * + * 2) There is an unavoidable use of non-reserved symbols. + * + * 3) Other standard include files are invoked. + * + * 4) This file may come in conflict with future platforms that do + * include stdint.h. The hope is that one or the other can be + * used with no real difference. + * + * 5) In the current verison, if your platform can't represent + * int32_t, int16_t and int8_t, it just dumps out with a compiler + * error. + * + * 6) 64 bit integers may or may not be defined. Test for their + * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. + * Note that this is different from the C99 specification which + * requires the existence of 64 bit support in the compiler. If + * this is not defined for your platform, yet it is capable of + * dealing with 64 bits then it is because this file has not yet + * been extended to cover all of your system's capabilities. + * + * 7) (u)intptr_t may or may not be defined. Test for its presence + * with the test: #ifdef PTRDIFF_MAX. If this is not defined + * for your platform, then it is because this file has not yet + * been extended to cover all of your system's capabilities, not + * because its optional. + * + * 8) The following might not been defined even if your platform is + * capable of defining it: + * + * WCHAR_MIN + * WCHAR_MAX + * (u)int64_t + * PTRDIFF_MIN + * PTRDIFF_MAX + * (u)intptr_t + * + * 9) The following have not been defined: + * + * WINT_MIN + * WINT_MAX + * + * 10) The criteria for defining (u)int_least(*)_t isn't clear, + * except for systems which don't have a type that precisely + * defined 8, 16, or 32 bit types (which this include file does + * not support anyways). Default definitions have been given. + * + * 11) The criteria for defining (u)int_fast(*)_t isn't something I + * would trust to any particular compiler vendor or the ANSI C + * committee. It is well known that "compatible systems" are + * commonly created that have very different performance + * characteristics from the systems they are compatible with, + * especially those whose vendors make both the compiler and the + * system. Default definitions have been given, but its strongly + * recommended that users never use these definitions for any + * reason (they do *NOT* deliver any serious guarantee of + * improved performance -- not in this file, nor any vendor's + * stdint.h). + * + * 12) The following macros: + * + * PRINTF_INTMAX_MODIFIER + * PRINTF_INT64_MODIFIER + * PRINTF_INT32_MODIFIER + * PRINTF_INT16_MODIFIER + * PRINTF_LEAST64_MODIFIER + * PRINTF_LEAST32_MODIFIER + * PRINTF_LEAST16_MODIFIER + * PRINTF_INTPTR_MODIFIER + * + * are strings which have been defined as the modifiers required + * for the "d", "u" and "x" printf formats to correctly output + * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, + * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. + * PRINTF_INTPTR_MODIFIER is not defined for some systems which + * provide their own stdint.h. PRINTF_INT64_MODIFIER is not + * defined if INT64_MAX is not defined. These are an extension + * beyond what C99 specifies must be in stdint.h. + * + * In addition, the following macros are defined: + * + * PRINTF_INTMAX_HEX_WIDTH + * PRINTF_INT64_HEX_WIDTH + * PRINTF_INT32_HEX_WIDTH + * PRINTF_INT16_HEX_WIDTH + * PRINTF_INT8_HEX_WIDTH + * PRINTF_INTMAX_DEC_WIDTH + * PRINTF_INT64_DEC_WIDTH + * PRINTF_INT32_DEC_WIDTH + * PRINTF_INT16_DEC_WIDTH + * PRINTF_INT8_DEC_WIDTH + * + * Which specifies the maximum number of characters required to + * print the number of that type in either hexadecimal or decimal. + * These are an extension beyond what C99 specifies must be in + * stdint.h. + * + * Compilers tested (all with 0 warnings at their highest respective + * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 + * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio + * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 + * + * This file should be considered a work in progress. Suggestions for + * improvements, especially those which increase coverage are strongly + * encouraged. + * + * Acknowledgements + * + * The following people have made significant contributions to the + * development and testing of this file: + * + * Chris Howie + * John Steele Scott + * Dave Thorup + * John Dill + * + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#include <stddef.h> +#include <limits.h> +#include <signal.h> + +/* + * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and + * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. + */ + +#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined (__UINT_FAST64_TYPE__)) )) && !defined (_PSTDINT_H_INCLUDED) +#include <stdint.h> +#define _PSTDINT_H_INCLUDED +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +# endif +# ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +# endif +# ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +# endif +# ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +# endif +# ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +# endif +# ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +# endif +# ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +# endif +# ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif + +/* + * Something really weird is going on with Open Watcom. Just pull some of + * these duplicated definitions from Open Watcom's stdint.h file for now. + */ + +# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 +# if !defined (INT64_C) +# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) +# endif +# if !defined (UINT64_C) +# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) +# endif +# if !defined (INT32_C) +# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) +# endif +# if !defined (UINT32_C) +# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) +# endif +# if !defined (INT16_C) +# define INT16_C(x) (x) +# endif +# if !defined (UINT16_C) +# define UINT16_C(x) (x) +# endif +# if !defined (INT8_C) +# define INT8_C(x) (x) +# endif +# if !defined (UINT8_C) +# define UINT8_C(x) (x) +# endif +# if !defined (UINT64_MAX) +# define UINT64_MAX 18446744073709551615ULL +# endif +# if !defined (INT64_MAX) +# define INT64_MAX 9223372036854775807LL +# endif +# if !defined (UINT32_MAX) +# define UINT32_MAX 4294967295UL +# endif +# if !defined (INT32_MAX) +# define INT32_MAX 2147483647L +# endif +# if !defined (INTMAX_MAX) +# define INTMAX_MAX INT64_MAX +# endif +# if !defined (INTMAX_MIN) +# define INTMAX_MIN INT64_MIN +# endif +# endif +#endif + +#ifndef _PSTDINT_H_INCLUDED +#define _PSTDINT_H_INCLUDED + +#ifndef SIZE_MAX +# define SIZE_MAX (~(size_t)0) +#endif + +/* + * Deduce the type assignments from limits.h under the assumption that + * integer sizes in bits are powers of 2, and follow the ANSI + * definitions. + */ + +#ifndef UINT8_MAX +# define UINT8_MAX 0xff +#endif +#ifndef uint8_t +# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) + typedef unsigned char uint8_t; +# define UINT8_C(v) ((uint8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef INT8_MAX +# define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +# define INT8_MIN INT8_C(0x80) +#endif +#ifndef int8_t +# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) + typedef signed char int8_t; +# define INT8_C(v) ((int8_t) v) +# else +# error "Platform not supported" +# endif +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 0xffff +#endif +#ifndef uint16_t +#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) + typedef unsigned int uint16_t; +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +# define UINT16_C(v) ((uint16_t) (v)) +#elif (USHRT_MAX == UINT16_MAX) + typedef unsigned short uint16_t; +# define UINT16_C(v) ((uint16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +# define INT16_MIN INT16_C(0x8000) +#endif +#ifndef int16_t +#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) + typedef signed int int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "" +# endif +#elif (SHRT_MAX == INT16_MAX) + typedef signed short int16_t; +# define INT16_C(v) ((int16_t) (v)) +# ifndef PRINTF_INT16_MODIFIER +# define PRINTF_INT16_MODIFIER "h" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (0xffffffffUL) +#endif +#ifndef uint32_t +#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) + typedef unsigned long uint32_t; +# define UINT32_C(v) v ## UL +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (UINT_MAX == UINT32_MAX) + typedef unsigned int uint32_t; +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +# define UINT32_C(v) v ## U +#elif (USHRT_MAX == UINT32_MAX) + typedef unsigned short uint32_t; +# define UINT32_C(v) ((unsigned short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +#ifndef INT32_MAX +# define INT32_MAX (0x7fffffffL) +#endif +#ifndef INT32_MIN +# define INT32_MIN INT32_C(0x80000000) +#endif +#ifndef int32_t +#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) + typedef signed long int32_t; +# define INT32_C(v) v ## L +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "l" +# endif +#elif (INT_MAX == INT32_MAX) + typedef signed int int32_t; +# define INT32_C(v) v +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#elif (SHRT_MAX == INT32_MAX) + typedef signed short int32_t; +# define INT32_C(v) ((short) (v)) +# ifndef PRINTF_INT32_MODIFIER +# define PRINTF_INT32_MODIFIER "" +# endif +#else +#error "Platform not supported" +#endif +#endif + +/* + * The macro stdint_int64_defined is temporarily used to record + * whether or not 64 integer support is available. It must be + * defined for any 64 integer extensions for new platforms that are + * added. + */ + +#undef stdint_int64_defined +#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) +# if (__STDC__ && __STDC_VERSION__ >= 199901L) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# endif +#endif + +#if !defined (stdint_int64_defined) +# if defined(__GNUC__) +# define stdint_int64_defined + __extension__ typedef long long int64_t; + __extension__ typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) +# define stdint_int64_defined + typedef long long int64_t; + typedef unsigned long long uint64_t; +# define UINT64_C(v) v ## ULL +# define INT64_C(v) v ## LL +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "ll" +# endif +# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) +# define stdint_int64_defined + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; +# define UINT64_C(v) v ## UI64 +# define INT64_C(v) v ## I64 +# ifndef PRINTF_INT64_MODIFIER +# define PRINTF_INT64_MODIFIER "I64" +# endif +# endif +#endif + +#if !defined (LONG_LONG_MAX) && defined (INT64_C) +# define LONG_LONG_MAX INT64_C (9223372036854775807) +#endif +#ifndef ULONG_LONG_MAX +# define ULONG_LONG_MAX UINT64_C (18446744073709551615) +#endif + +#if !defined (INT64_MAX) && defined (INT64_C) +# define INT64_MAX INT64_C (9223372036854775807) +#endif +#if !defined (INT64_MIN) && defined (INT64_C) +# define INT64_MIN INT64_C (-9223372036854775808) +#endif +#if !defined (UINT64_MAX) && defined (INT64_C) +# define UINT64_MAX UINT64_C (18446744073709551615) +#endif + +/* + * Width of hexadecimal for number field. + */ + +#ifndef PRINTF_INT64_HEX_WIDTH +# define PRINTF_INT64_HEX_WIDTH "16" +#endif +#ifndef PRINTF_INT32_HEX_WIDTH +# define PRINTF_INT32_HEX_WIDTH "8" +#endif +#ifndef PRINTF_INT16_HEX_WIDTH +# define PRINTF_INT16_HEX_WIDTH "4" +#endif +#ifndef PRINTF_INT8_HEX_WIDTH +# define PRINTF_INT8_HEX_WIDTH "2" +#endif + +#ifndef PRINTF_INT64_DEC_WIDTH +# define PRINTF_INT64_DEC_WIDTH "20" +#endif +#ifndef PRINTF_INT32_DEC_WIDTH +# define PRINTF_INT32_DEC_WIDTH "10" +#endif +#ifndef PRINTF_INT16_DEC_WIDTH +# define PRINTF_INT16_DEC_WIDTH "5" +#endif +#ifndef PRINTF_INT8_DEC_WIDTH +# define PRINTF_INT8_DEC_WIDTH "3" +#endif + +/* + * Ok, lets not worry about 128 bit integers for now. Moore's law says + * we don't need to worry about that until about 2040 at which point + * we'll have bigger things to worry about. + */ + +#ifdef stdint_int64_defined + typedef int64_t intmax_t; + typedef uint64_t uintmax_t; +# define INTMAX_MAX INT64_MAX +# define INTMAX_MIN INT64_MIN +# define UINTMAX_MAX UINT64_MAX +# define UINTMAX_C(v) UINT64_C(v) +# define INTMAX_C(v) INT64_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH +# endif +#else + typedef int32_t intmax_t; + typedef uint32_t uintmax_t; +# define INTMAX_MAX INT32_MAX +# define UINTMAX_MAX UINT32_MAX +# define UINTMAX_C(v) UINT32_C(v) +# define INTMAX_C(v) INT32_C(v) +# ifndef PRINTF_INTMAX_MODIFIER +# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER +# endif +# ifndef PRINTF_INTMAX_HEX_WIDTH +# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH +# endif +# ifndef PRINTF_INTMAX_DEC_WIDTH +# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH +# endif +#endif + +/* + * Because this file currently only supports platforms which have + * precise powers of 2 as bit sizes for the default integers, the + * least definitions are all trivial. Its possible that a future + * version of this file could have different definitions. + */ + +#ifndef stdint_least_defined + typedef int8_t int_least8_t; + typedef uint8_t uint_least8_t; + typedef int16_t int_least16_t; + typedef uint16_t uint_least16_t; + typedef int32_t int_least32_t; + typedef uint32_t uint_least32_t; +# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER +# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER +# define UINT_LEAST8_MAX UINT8_MAX +# define INT_LEAST8_MAX INT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define INT_LEAST16_MAX INT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# ifdef stdint_int64_defined + typedef int64_t int_least64_t; + typedef uint64_t uint_least64_t; +# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER +# define UINT_LEAST64_MAX UINT64_MAX +# define INT_LEAST64_MAX INT64_MAX +# define INT_LEAST64_MIN INT64_MIN +# endif +#endif +#undef stdint_least_defined + +/* + * The ANSI C committee pretending to know or specify anything about + * performance is the epitome of misguided arrogance. The mandate of + * this file is to *ONLY* ever support that absolute minimum + * definition of the fast integer types, for compatibility purposes. + * No extensions, and no attempt to suggest what may or may not be a + * faster integer type will ever be made in this file. Developers are + * warned to stay away from these types when using this or any other + * stdint.h. + */ + +typedef int_least8_t int_fast8_t; +typedef uint_least8_t uint_fast8_t; +typedef int_least16_t int_fast16_t; +typedef uint_least16_t uint_fast16_t; +typedef int_least32_t int_fast32_t; +typedef uint_least32_t uint_fast32_t; +#define UINT_FAST8_MAX UINT_LEAST8_MAX +#define INT_FAST8_MAX INT_LEAST8_MAX +#define UINT_FAST16_MAX UINT_LEAST16_MAX +#define INT_FAST16_MAX INT_LEAST16_MAX +#define UINT_FAST32_MAX UINT_LEAST32_MAX +#define INT_FAST32_MAX INT_LEAST32_MAX +#define INT_FAST8_MIN INT_LEAST8_MIN +#define INT_FAST16_MIN INT_LEAST16_MIN +#define INT_FAST32_MIN INT_LEAST32_MIN +#ifdef stdint_int64_defined + typedef int_least64_t int_fast64_t; + typedef uint_least64_t uint_fast64_t; +# define UINT_FAST64_MAX UINT_LEAST64_MAX +# define INT_FAST64_MAX INT_LEAST64_MAX +# define INT_FAST64_MIN INT_LEAST64_MIN +#endif + +#undef stdint_int64_defined + +/* + * Whatever piecemeal, per compiler thing we can do about the wchar_t + * type limits. + */ + +#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) +# include <wchar.h> +# ifndef WCHAR_MIN +# define WCHAR_MIN 0 +# endif +# ifndef WCHAR_MAX +# define WCHAR_MAX ((wchar_t)-1) +# endif +#endif + +/* + * Whatever piecemeal, per compiler/platform thing we can do about the + * (u)intptr_t types and limits. + */ + +#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +#ifndef STDINT_H_UINTPTR_T_DEFINED +# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) +# define stdint_intptr_bits 64 +# elif defined (__WATCOMC__) || defined (__TURBOC__) +# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) +# define stdint_intptr_bits 16 +# else +# define stdint_intptr_bits 32 +# endif +# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) +# define stdint_intptr_bits 32 +# elif defined (__INTEL_COMPILER) +/* TODO -- what did Intel do about x86-64? */ +# endif + +# ifdef stdint_intptr_bits +# define stdint_intptr_glue3_i(a,b,c) a##b##c +# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) +# ifndef PRINTF_INTPTR_MODIFIER +# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) +# endif +# ifndef PTRDIFF_MAX +# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef PTRDIFF_MIN +# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef UINTPTR_MAX +# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MAX +# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) +# endif +# ifndef INTPTR_MIN +# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) +# endif +# ifndef INTPTR_C +# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) +# endif +# ifndef UINTPTR_C +# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) +# endif + typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; + typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; +# else +/* TODO -- This following is likely wrong for some platforms, and does + nothing for the definition of uintptr_t. */ + typedef ptrdiff_t intptr_t; +# endif +# define STDINT_H_UINTPTR_T_DEFINED +#endif + +/* + * Assumes sig_atomic_t is signed and we have a 2s complement machine. + */ + +#ifndef SIG_ATOMIC_MAX +# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) +#endif + +#endif + +#if defined (__TEST_PSTDINT_FOR_CORRECTNESS) + +/* + * Please compile with the maximum warning settings to make sure macros are not + * defined more than once. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#define glue3_aux(x,y,z) x ## y ## z +#define glue3(x,y,z) glue3_aux(x,y,z) + +#define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); +#define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); + +#define DECL(us,bits) glue3(DECL,us,) (bits) + +#define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) + +int main () { + DECL(I,8) + DECL(U,8) + DECL(I,16) + DECL(U,16) + DECL(I,32) + DECL(U,32) +#ifdef INT64_MAX + DECL(I,64) + DECL(U,64) +#endif + intmax_t imax = INTMAX_C(0); + uintmax_t umax = UINTMAX_C(0); + char str0[256], str1[256]; + + sprintf (str0, "%d %x\n", 0, ~0); + + sprintf (str1, "%d %x\n", i8, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); + sprintf (str1, "%u %x\n", u8, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); + sprintf (str1, "%d %x\n", i16, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); + sprintf (str1, "%u %x\n", u16, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); + sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); +#ifdef INT64_MAX + sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); +#endif + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); + sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); + if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); + + TESTUMAX(8); + TESTUMAX(16); + TESTUMAX(32); +#ifdef INT64_MAX + TESTUMAX(64); +#endif + + return EXIT_SUCCESS; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk b/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk new file mode 100644 index 0000000000..66e2bb4ecf --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/jni/Android.mk @@ -0,0 +1,32 @@ +# +# Android Makefile conversion +# +# Leander Beernaert +# +# How to build: $ANDROID_NDK/ndk-build +# +VERSION=1.17 + +LOCAL_PATH := $(call my-dir)/../ + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm +LOCAL_ARM_NEON := true + +LOCAL_MODULE := HLSLcc + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/src \ + $(LOCAL_PATH)/src/cbstring +LOCAL_CFLAGS += -Wall -W +# For dynamic library +#LOCAL_CFLAGS += -DHLSLCC_DYNLIB +LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/src/*.c) \ + $(wildcard $(LOCAL_PATH)/src/cbstring/*.c) \ + $(wildcard $(LOCAL_PATH)/src/internal_includes/*.c) +#LOCAL_LDLIBS += -lGLESv3 + +include $(BUILD_STATIC_LIBRARY) + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk b/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk new file mode 100644 index 0000000000..a8ae0839b1 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/jni/Application.mk @@ -0,0 +1,3 @@ +APP_PLATFORM := android-18 +APP_ABI := armeabi-v7a +APP_OPTIM := release diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a new file mode 100644 index 0000000000..79305b66b7 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/android-armeabi-v7a/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3469d419dc589eb7a68be97885d7a55b8b0bbbffd74c5c1586959be4698fb273 +size 1046940 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a new file mode 100644 index 0000000000..7ecdd304eb --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/ios/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98fbcc0779c4a400530ad643e1125727c50fdbf01912f059ca296153f209eec5 +size 466488 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a new file mode 100644 index 0000000000..c76e85704a --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:270583c8762539856bf9f7c7cccf743c37db7fd4128cabd8fdfcfe3586177e27 +size 360488 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a new file mode 100644 index 0000000000..ee23387576 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/linux/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85f1fcddb62db461ff1012f91c38d323591a220ef3f6c1e41277161a43959333 +size 1139822 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a new file mode 100644 index 0000000000..85bf31eed4 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af9216c54d23dd3754f7ae18d56b97ae256eb29a0046d8e0d2a0716054d8c230 +size 218888 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a new file mode 100644 index 0000000000..00095a3615 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/mac/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a07bec349614cdd3e40c3577bddace1203148016f9276c7ef807bdbc37dcabf +size 671232 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a new file mode 100644 index 0000000000..c7b92fcc1e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88acec4cedad5699900ec2d1a3ce83ab5e9365ebea4b4af0ababba562382f399 +size 296852 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a new file mode 100644 index 0000000000..29dd7fbf7a --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/steamos/libHLSLcc_d.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c0625b7f534df5817646dd1335f9d7916389f27a83b7d118fadab504064d910 +size 1144250 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib new file mode 100644 index 0000000000..311dec443e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Debug/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4d128256b757a7e800514482f1278348b489db53be2548b7770d701eece7ea9 +size 1022450 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib new file mode 100644 index 0000000000..d7fda333b7 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/Release/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d037d414fea62daf076b41ad1a0ffbb451fcaf4443f8b2f721166a4a33fe5865 +size 632236 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib new file mode 100644 index 0000000000..d531d2635f --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/win32/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e8d6023a2afd3db8f8bc6033db3d937d5a9ec635a9005bbc0dca121a196b2bb +size 428768 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib new file mode 100644 index 0000000000..d167e54c31 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/Release/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d7d890fdabc3b8cb4f61e10140090455bae656ec6d3fc8fa6460d96435120186 +size 809218 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib new file mode 100644 index 0000000000..5135e7e081 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/lib/win64/libHLSLcc.lib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caa74b7cebff2b35d0db9bb8b2eb70065ca7f5816a93004e8fa195aabefefe18 +size 600034 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/license.txt b/Code/Tools/HLSLCrossCompilerMETAL/license.txt new file mode 100644 index 0000000000..e20caeefef --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/license.txt @@ -0,0 +1,52 @@ +Copyright (c) 2012 James Jones +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +This software makes use of the bstring library which is provided under the following license: + +Copyright (c) 2002-2008 Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of bstrlib nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README new file mode 100644 index 0000000000..7531c049a6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/README @@ -0,0 +1,247 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +Welcome to cJSON. + +cJSON aims to be the dumbest possible parser that you can get your job done with. +It's a single file of C, and a single header file. + +JSON is described best here: http://www.json.org/ +It's like XML, but fat-free. You use it to move data around, store things, or just +generally represent your program's state. + + +First up, how do I build? +Add cJSON.c to your project, and put cJSON.h somewhere in the header search path. +For example, to build the test app: + +gcc cJSON.c test.c -o test -lm +./test + + +As a library, cJSON exists to take away as much legwork as it can, but not get in your way. +As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it +in one of two modes: Auto and Manual. Let's have a quick run-through. + + +I lifted some JSON from this page: http://www.json.org/fatfree.html +That page inspired me to write cJSON, which is a parser that tries to share the same +philosophy as JSON itself. Simple, dumb, out of the way. + +Some JSON: +{ + "name": "Jack (\"Bee\") Nimble", + "format": { + "type": "rect", + "width": 1920, + "height": 1080, + "interlace": false, + "frame rate": 24 + } +} + +Assume that you got this from a file, a webserver, or magic JSON elves, whatever, +you have a char * to it. Everything is a cJSON struct. +Get it parsed: + cJSON *root = cJSON_Parse(my_json_string); + +This is an object. We're in C. We don't have objects. But we do have structs. +What's the framerate? + + cJSON *format = cJSON_GetObjectItem(root,"format"); + int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; + + +Want to change the framerate? + cJSON_GetObjectItem(format,"frame rate")->valueint=25; + +Back to disk? + char *rendered=cJSON_Print(root); + +Finished? Delete the root (this takes care of everything else). + cJSON_Delete(root); + +That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers +before you dereference them. If you want to see how you'd build this struct in code? + cJSON *root,*fmt; + root=cJSON_CreateObject(); + cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); + cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); + cJSON_AddStringToObject(fmt,"type", "rect"); + cJSON_AddNumberToObject(fmt,"width", 1920); + cJSON_AddNumberToObject(fmt,"height", 1080); + cJSON_AddFalseToObject (fmt,"interlace"); + cJSON_AddNumberToObject(fmt,"frame rate", 24); + +Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup. +Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and +a few from elsewhere. + +What about manual mode? First up you need some detail. +Let's cover how the cJSON objects represent the JSON data. +cJSON doesn't distinguish arrays from objects in handling; just type. +Each cJSON has, potentially, a child, siblings, value, a name. + +The root object has: Object Type and a Child +The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: +Sibling has type Object, name "format", and a child. +That child has type String, name "type", value "rect", and a sibling: +Sibling has type Number, name "width", value 1920, and a sibling: +Sibling has type Number, name "height", value 1080, and a sibling: +Sibling hs type False, name "interlace", and a sibling: +Sibling has type Number, name "frame rate", value 24 + +Here's the structure: +typedef struct cJSON { + struct cJSON *next,*prev; + struct cJSON *child; + + int type; + + char *valuestring; + int valueint; + double valuedouble; + + char *string; +} cJSON; + +By default all values are 0 unless set by virtue of being meaningful. + +next/prev is a doubly linked list of siblings. next takes you to your sibling, +prev takes you back from your sibling to you. +Only objects and arrays have a "child", and it's the head of the doubly linked list. +A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0. +The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in +cJSON.h + +A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read +valuedouble. + +Any entry which is in the linked list which is the child of an object will have a "string" +which is the "name" of the entry. When I said "name" in the above example, that's "string". +"string" is the JSON name for the 'variable name' if you will. + +Now you can trivially walk the lists, recursively, and parse as you please. +You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take +the root object, and traverse the structure (which is, formally, an N-tree), +and tokenise as you please. If you wanted to build a callback style parser, this is how +you'd do it (just an example, since these things are very specific): + +void parse_and_callback(cJSON *item,const char *prefix) +{ + while (item) + { + char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); + sprintf(newprefix,"%s/%s",prefix,item->name); + int dorecurse=callback(newprefix, item->type, item); + if (item->child && dorecurse) parse_and_callback(item->child,newprefix); + item=item->next; + free(newprefix); + } +} + +The prefix process will build you a separated list, to simplify your callback handling. +The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or +let you invoke it per-item. For the item above, your callback might look like this: + +int callback(const char *name,int type,cJSON *item) +{ + if (!strcmp(name,"name")) { /* populate name */ } + else if (!strcmp(name,"format/type") { /* handle "rect" */ } + else if (!strcmp(name,"format/width") { /* 800 */ } + else if (!strcmp(name,"format/height") { /* 600 */ } + else if (!strcmp(name,"format/interlace") { /* false */ } + else if (!strcmp(name,"format/frame rate") { /* 24 */ } + return 1; +} + +Alternatively, you might like to parse iteratively. +You'd use: + +void parse_object(cJSON *item) +{ + int i; for (i=0;i<cJSON_GetArraySize(item);i++) + { + cJSON *subitem=cJSON_GetArrayItem(item,i); + // handle subitem. + } +} + +Or, for PROPER manual mode: + +void parse_object(cJSON *item) +{ + cJSON *subitem=item->child; + while (subitem) + { + // handle subitem + if (subitem->child) parse_object(subitem->child); + + subitem=subitem->next; + } +} + +Of course, this should look familiar, since this is just a stripped-down version +of the callback-parser. + +This should cover most uses you'll find for parsing. The rest should be possible +to infer.. and if in doubt, read the source! There's not a lot of it! ;) + + +In terms of constructing JSON data, the example code above is the right way to do it. +You can, of course, hand your sub-objects to other functions to populate. +Also, if you find a use for it, you can manually build the objects. +For instance, suppose you wanted to build an array of objects? + +cJSON *objects[24]; + +cJSON *Create_array_of_anything(cJSON **items,int num) +{ + int i;cJSON *prev, *root=cJSON_CreateArray(); + for (i=0;i<24;i++) + { + if (!i) root->child=objects[i]; + else prev->next=objects[i], objects[i]->prev=prev; + prev=objects[i]; + } + return root; +} + +and simply: Create_array_of_anything(objects,24); + +cJSON doesn't make any assumptions about what order you create things in. +You can attach the objects, as above, and later add children to each +of those objects. + +As soon as you call cJSON_Print, it renders the structure to text. + + + +The test.c code shows how to handle a bunch of typical cases. If you uncomment +the code, it'll load, parse and print a bunch of test files, also from json.org, +which are more complex than I'd care to try and stash into a const char array[]. + + +Enjoy cJSON! + + +- Dave Gamble, Aug 2009 diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c new file mode 100644 index 0000000000..56fb753ee8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.c @@ -0,0 +1,578 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +// Modifications copyright Amazon.com, Inc. or its affiliates. + +/* cJSON */ +/* JSON parser in C. */ + +#include <string.h> +#include <stdio.h> +#include <math.h> +#include <stdlib.h> +#include <float.h> +#include <limits.h> +#include <ctype.h> +#include "cJSON.h" +#include <AzCore/PlatformDef.h> + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +AZ_PUSH_DISABLE_WARNING(4232, "-Wunknown-warning-option") // address of malloc/free are not static +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; +AZ_POP_DISABLE_WARNING + +static char* cJSON_strdup(const char* str) +{ + size_t len = strlen(str) + 1; + char* copy = (char*)cJSON_malloc(len); + + if (!copy) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + /* Could use sscanf for this? */ + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + sscanf(ptr+1,"%4x",&uc);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + sscanf(ptr+3,"%4x",&uc2);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str; + token = *ptr; + while (token && ++len) + { + if (strchr("\"\\\b\f\n\r\t",token)) len++; + else if (token<32) len+=5; + ptr++; + token = *ptr; + } + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item = cJSON_New_Item(); + if (!new_item) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=(int)strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]); + cJSON_free(entries); + return 0; + } + + /* Compose the output array. */ + *out='['; + ptr=out+1;*ptr=0; + for (i=0;i<numentries;i++) + { + strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); + if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;} + cJSON_free(entries[i]); + } + cJSON_free(entries); + *ptr++=']';*ptr++=0; + return out; +} + +/* Build an object from the text. */ +static const char *parse_object(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='{') {ep=value;return 0;} /* not an object! */ + + item->type=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item = cJSON_New_Item(); + if (!new_item) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+3:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';} + *ptr++='}';*ptr++=0; + return out; + } + /* Allocate space for the names and the objects */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + names=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!names) {cJSON_free(entries);return 0;} + memset(entries,0,sizeof(char*)*numentries); + memset(names,0,sizeof(char*)*numentries); + + /* Collect all the results into our arrays: */ + child=item->child;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=(int)(strlen(ret)+strlen(str))+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);} + cJSON_free(names);cJSON_free(entries); + return 0; + } + + /* Compose the output: */ + *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0; + for (i=0;i<numentries;i++) + { + if (fmt) for (j=0;j<depth;j++) *ptr++='\t'; + strcpy(ptr,names[i]);ptr+=strlen(names[i]); + *ptr++=':';if (fmt) *ptr++='\t'; + strcpy(ptr,entries[i]);ptr+=strlen(entries[i]); + if (i!=numentries-1) *ptr++=','; + if (fmt) *ptr++='\n';*ptr=0; + cJSON_free(names[i]);cJSON_free(entries[i]); + } + + cJSON_free(names);cJSON_free(entries); + if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t'; + *ptr++='}';*ptr++=0; + return out; +} + +/* Get Array size/item / object item. */ +int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h new file mode 100644 index 0000000000..50ae02b6f9 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/cjson/cJSON.h @@ -0,0 +1,142 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp new file mode 100644 index 0000000000..eaed596a00 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/compilerStandalone.cpp @@ -0,0 +1,825 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "hlslcc.hpp" +#include "stdlib.h" +#include "stdio.h" +#include "bstrlib.h" +#include <string> +#include <string.h> +#include "hash.h" +#include "serializeReflection.h" +#include "hlslcc_bin.hpp" + +#include <algorithm> +#include <cctype> + +#ifdef _WIN32 +#include <direct.h> +#else +#include <sys/stat.h> +#endif + +#include "timer.h" + +#if defined(_WIN32) && !defined(PORTABLE) +#define VALIDATE_OUTPUT +#endif + +#if defined(VALIDATE_OUTPUT) +#if defined(_WIN32) +#include <windows.h> +#include <gl/GL.h> + +#pragma comment(lib, "opengl32.lib") + +typedef char GLcharARB; /* native character */ +typedef unsigned int GLhandleARB; /* shader object handle */ +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +typedef void (WINAPI * PFNGLDELETEOBJECTARBPROC) (GLhandleARB obj); +typedef GLhandleARB(WINAPI * PFNGLCREATESHADEROBJECTARBPROC) (GLenum shaderType); +typedef void (WINAPI * PFNGLSHADERSOURCEARBPROC) (GLhandleARB shaderObj, GLsizei count, const GLcharARB* *string, const GLint *length); +typedef void (WINAPI * PFNGLCOMPILESHADERARBPROC) (GLhandleARB shaderObj); +typedef void (WINAPI * PFNGLGETINFOLOGARBPROC) (GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); +typedef void (WINAPI * PFNGLGETOBJECTPARAMETERIVARBPROC) (GLhandleARB obj, GLenum pname, GLint *params); +typedef GLhandleARB(WINAPI * PFNGLCREATEPROGRAMOBJECTARBPROC) (void); +typedef void (WINAPI * PFNGLATTACHOBJECTARBPROC) (GLhandleARB containerObj, GLhandleARB obj); +typedef void (WINAPI * PFNGLLINKPROGRAMARBPROC) (GLhandleARB programObj); +typedef void (WINAPI * PFNGLUSEPROGRAMOBJECTARBPROC) (GLhandleARB programObj); +typedef void (WINAPI * PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei* length, GLcharARB* infoLog); + +static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; +static PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define ERROR_INVALID_VERSION_ARB 0x2095 +#define ERROR_INVALID_PROFILE_ARB 0x2096 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +typedef HGLRC(WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int* attribList); +static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; + +void InitOpenGL() +{ + HGLRC rc; + + // setup minimal required GL + HWND wnd = CreateWindowA( + "STATIC", + "GL", + WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, + 0, 0, 16, 16, + NULL, NULL, + GetModuleHandle(NULL), NULL); + HDC dc = GetDC(wnd); + + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, + PFD_TYPE_RGBA, 32, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 16, 0, + 0, PFD_MAIN_PLANE, 0, 0, 0, 0 + }; + + int fmt = ChoosePixelFormat(dc, &pfd); + SetPixelFormat(dc, fmt, &pfd); + + rc = wglCreateContext(dc); + wglMakeCurrent(dc, rc); + + wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + + if (wglCreateContextAttribsARB) + { + const int OpenGLContextAttribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 3, + WGL_CONTEXT_MINOR_VERSION_ARB, 3, +#if defined(_DEBUG) + //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, +#else + //WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, +#endif + //WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0, 0 + }; + + const HGLRC OpenGLContext = wglCreateContextAttribsARB(dc, 0, OpenGLContextAttribs); + + wglMakeCurrent(dc, OpenGLContext); + + wglDeleteContext(rc); + + rc = OpenGLContext; + } + + glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB"); + glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB"); + glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB"); + glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB"); + glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB"); + glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB"); + glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB"); + glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB"); + glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB"); + glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB"); + glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)wglGetProcAddress("glGetShaderInfoLog"); +} +#endif + +void PrintSingleLineError(FILE* pFile, char* error) +{ + while (*error != '\0') + { + char* pLineEnd = strchr(error, '\n'); + if (pLineEnd == 0) + pLineEnd = error + strlen(error) - 1; + fwrite(error, 1, pLineEnd - error, pFile); + fwrite("\r", 1, 1, pFile); + error = pLineEnd + 1; + } +} + +int TryCompileShader(GLenum eShaderType, const char* inFilename, char* shader, double* pCompileTime, int useStdErr) +{ + GLint iCompileStatus; + GLuint hShader; + Timer_t timer; + + InitTimer(&timer); + + InitOpenGL(); + + hShader = glCreateShaderObjectARB(eShaderType); + glShaderSourceARB(hShader, 1, (const char **)&shader, NULL); + + ResetTimer(&timer); + glCompileShaderARB(hShader); + *pCompileTime = ReadTimer(&timer); + + /* Check it compiled OK */ + glGetObjectParameterivARB(hShader, GL_OBJECT_COMPILE_STATUS_ARB, &iCompileStatus); + + if (iCompileStatus != GL_TRUE) + { + FILE* errorFile = NULL; + GLint iInfoLogLength = 0; + char* pszInfoLog; + + glGetObjectParameterivARB(hShader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &iInfoLogLength); + + pszInfoLog = new char[iInfoLogLength]; + + printf("Error: Failed to compile GLSL shader\n"); + + glGetInfoLogARB(hShader, iInfoLogLength, NULL, pszInfoLog); + + printf(pszInfoLog); + + if (!useStdErr) + { + std::string filename; + filename += inFilename; + filename += "_compileErrors.txt"; + + //Dump to file + errorFile = fopen(filename.c_str(), "w"); + + fclose(errorFile); + } + else + { + // Present error to stderror with no "new lines" as required by remote shader compiler + fprintf(stderr, "%s(-) error: ", inFilename); + PrintSingleLineError(stderr, pszInfoLog); + fprintf(stderr, "\rshader: "); + PrintSingleLineError(stderr, shader); + } + + delete[] pszInfoLog; + + return 0; + } + + return 1; +} +#endif + +int fileExists(const char* path) +{ + FILE* shaderFile; + shaderFile = fopen(path, "rb"); + + if (shaderFile) + { + fclose(shaderFile); + return 1; + } + return 0; +} + +ShaderLang LanguageFromString(const char* str) +{ + if (strcmp(str, "es100") == 0) + { + return LANG_ES_100; + } + if (strcmp(str, "es300") == 0) + { + return LANG_ES_300; + } + if (strcmp(str, "es310") == 0) + { + return LANG_ES_310; + } + if (strcmp(str, "120") == 0) + { + return LANG_120; + } + if (strcmp(str, "130") == 0) + { + return LANG_130; + } + if (strcmp(str, "140") == 0) + { + return LANG_140; + } + if (strcmp(str, "150") == 0) + { + return LANG_150; + } + if (strcmp(str, "330") == 0) + { + return LANG_330; + } + if (strcmp(str, "400") == 0) + { + return LANG_400; + } + if (strcmp(str, "410") == 0) + { + return LANG_410; + } + if (strcmp(str, "420") == 0) + { + return LANG_420; + } + if (strcmp(str, "430") == 0) + { + return LANG_430; + } + if (strcmp(str, "440") == 0) + { + return LANG_440; + } + if (strcmp(str, "metal") == 0) + { + return LANG_METAL; + } + return LANG_DEFAULT; +} + +#define MAX_PATH_CHARS 256 +#define MAX_FXC_CMD_CHARS 1024 +#define MAX_DEBUG_READ_CHARS 512 + +typedef struct +{ + ShaderLang language; + + int flags; + + const char* shaderFile; + char* outputShaderFile; + + char* reflectPath; + + char cacheKey[MAX_PATH_CHARS]; + + int bUseFxc; + std::string fxcCmdLine; +} Options; + +void InitOptions(Options* psOptions) +{ + psOptions->language = LANG_DEFAULT; + psOptions->flags = 0; + psOptions->reflectPath = NULL; + + psOptions->shaderFile = NULL; + + psOptions->bUseFxc = 0; +} + +void PrintHelp() +{ + printf("Command line options:\n"); + + printf("\t-lang=X \t Language to use. e.g. es100 or 140 or metal.\n"); + printf("\t-flags=X \t The integer value of the HLSLCC_FLAGS to used.\n"); + printf("\t-reflect=X \t File to write reflection JSON to.\n"); + printf("\t-in=X \t Shader file to compile.\n"); + printf("\t-out=X \t File to write the compiled shader from -in to.\n"); + + printf("\t-hashout=[dir/]out-file-name \t Output file name is a hash of 'out-file-name', put in the directory 'dir'.\n"); + + printf("\t-fxc=\"CMD\" HLSL compiler command line. If specified the input shader will be first compiled through this command first and then the resulting bytecode translated.\n"); + + printf("\n"); +} + +int GetOptions(int argc, char** argv, Options* psOptions) +{ + int i; + int fullShaderChain = -1; + + InitOptions(psOptions); + + for (i = 1; i < argc; i++) + { + char *option; + + option = strstr(argv[i], "-help"); + if (option != NULL) + { + PrintHelp(); + return 0; + } + + option = strstr(argv[i], "-reflect="); + if (option != NULL) + { + psOptions->reflectPath = option + strlen("-reflect="); + } + + option = strstr(argv[i], "-lang="); + if (option != NULL) + { + psOptions->language = LanguageFromString((&option[strlen("-lang=")])); + } + + option = strstr(argv[i], "-flags="); + if (option != NULL) + { + psOptions->flags = atol(&option[strlen("-flags=")]); + } + + option = strstr(argv[i], "-in="); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->shaderFile = option + strlen("-in="); + if (!fileExists(psOptions->shaderFile)) + { + printf("Invalid path: %s\n", psOptions->shaderFile); + return 0; + } + } + + option = strstr(argv[i], "-out="); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->outputShaderFile = option + strlen("-out="); + } + + option = strstr(argv[i], "-hashout"); + if (option != NULL) + { + fullShaderChain = 0; + psOptions->outputShaderFile = option + strlen("-hashout="); + + char* dir; + int64_t length; + + uint64_t hash = hash64((const uint8_t*)psOptions->outputShaderFile, (uint32_t)strlen(psOptions->outputShaderFile), 0); + + dir = strrchr(psOptions->outputShaderFile, '\\'); + + if (!dir) + { + dir = strrchr(psOptions->outputShaderFile, '//'); + } + + if (!dir) + { + length = 0; + } + else + { + length = (int)(dir - psOptions->outputShaderFile) + 1; + } + + for (i = 0; i < length; ++i) + { + psOptions->cacheKey[i] = psOptions->outputShaderFile[i]; + } + + //sprintf(psOptions->cacheKey, "%x%x", high, low); + sprintf(&psOptions->cacheKey[i], "%010llX", hash); + + psOptions->outputShaderFile = psOptions->cacheKey; + } + + option = strstr(argv[i], "-fxc="); + if (option != NULL) + { + char* cmdLine = option + strlen("-fxc="); + size_t cmdLineLen = strlen(cmdLine); + if (cmdLineLen == 0 || cmdLineLen + 1 >= MAX_FXC_CMD_CHARS) + return 0; + psOptions->fxcCmdLine = std::string(cmdLine, cmdLineLen); + psOptions->bUseFxc = 1; + } + } + + return 1; +} + +void *malloc_hook(size_t size) +{ + return malloc(size); +} +void *calloc_hook(size_t num, size_t size) +{ + return calloc(num, size); +} +void *realloc_hook(void *p, size_t size) +{ + return realloc(p, size); +} +void free_hook(void *p) +{ + free(p); +} + +int Run(const char* srcPath, const char* destPath, ShaderLang language, int flags, const char* reflectPath, Shader* shader, int useStdErr, [[maybe_unused]] const char *fxcCmdLine, [[maybe_unused]] const char *debugSrcPath) +{ + FILE* outputFile; + Shader tempShader; + Shader* result = shader ? shader : &tempShader; + Timer_t timer; + int compiledOK = 0; + double crossCompileTime = 0; + double glslCompileTime = 0; + + HLSLcc_SetMemoryFunctions(malloc_hook, calloc_hook, free_hook, realloc_hook); + + InitTimer(&timer); + + ResetTimer(&timer); + GlExtensions ext; + ext.ARB_explicit_attrib_location = 0; + ext.ARB_explicit_uniform_location = 0; + ext.ARB_shading_language_420pack = 0; + if (language == LANG_METAL) + { + compiledOK = TranslateHLSLFromFileToMETAL(srcPath, flags, language, result); + } + else + { + compiledOK = TranslateHLSLFromFileToGLSL(srcPath, flags, language, &ext, result); + } + crossCompileTime = ReadTimer(&timer); + + if (compiledOK) + { +#ifdef _DEBUG + bstring debugString = bfromcstr(result->sourceCode); + + bcatcstr(debugString, "\n\n// ------- DEBUG INFORMATION -------"); + + bformata(debugString, "\n// Shader Object Input: %s", srcPath); + bformata(debugString, "\n// Shader Output: %s", destPath); + if (debugSrcPath) + { + char debugStr[MAX_DEBUG_READ_CHARS]; + FILE* debugFile = fopen(debugSrcPath, "r"); + if (debugFile) + { + bformata(debugString, "\n// Shader HLSL Input: "); + while (!feof(debugFile)) + bformata(debugString, "// %s", fgets(debugStr, MAX_DEBUG_READ_CHARS, debugFile)); + fclose(debugFile); + } + } + if (fxcCmdLine) + bformata(debugString, "\n// FXC Command: %s", fxcCmdLine); + + result->sourceCode = bstr2cstr(debugString, '\0'); +#endif + printf("cc time: %.2f us\n", crossCompileTime); + +#if !defined(APPLE) + // https://msdn.microsoft.com/en-us/library/ms175782.aspx. As to disable the "("'n' format specifier disabled", 0)" assertion. + _set_printf_count_output(1); +#endif + + if (destPath) + { + //Dump to file + outputFile = fopen(destPath, "w"); + fprintf(outputFile, result->sourceCode); + + fclose(outputFile); + } + + if (reflectPath) + { + const char* jsonString = SerializeReflection(&result->reflection); + outputFile = fopen(reflectPath, "w"); + fprintf(outputFile, jsonString); + fclose(outputFile); + } + +#if defined(VALIDATE_OUTPUT) + if (language != LANG_METAL) + { + compiledOK = TryCompileShader(result->shaderType, destPath ? destPath : "", result->sourceCode, &glslCompileTime, useStdErr); + + if (compiledOK) + { + printf("glsl time: %.2f us\n", glslCompileTime); + } + } +#endif + + if (!shader) + FreeShader(result); + } + else if (useStdErr) + { + fprintf(stderr, "TranslateHLSLFromFile failed"); + } + + return compiledOK; +} + +struct SDXBCFile +{ + FILE* m_pFile; + + bool Read(void* pElements, size_t uSize) + { + return fread(pElements, 1, uSize, m_pFile) == uSize; + } + + bool Write(const void* pElements, size_t uSize) + { + return fwrite(pElements, 1, uSize, m_pFile) == uSize; + } + + bool SeekRel(int32_t iOffset) + { + return fseek(m_pFile, iOffset, SEEK_CUR) == 0; + } + + bool SeekAbs(uint32_t uPosition) + { + return fseek(m_pFile, uPosition, SEEK_SET) == 0; + } +}; + +int CombineDXBCWithGLSL(char* dxbcFileName, char* outputFileName, Shader* shader) +{ + SDXBCFile dxbcFile = { fopen(dxbcFileName, "rb") }; + SDXBCFile outputFile = { fopen(outputFileName, "wb") }; + + bool result = + dxbcFile.m_pFile != NULL && outputFile.m_pFile != NULL && + DXBCCombineWithGLSL(dxbcFile, outputFile, shader); + + if (dxbcFile.m_pFile != NULL) + fclose(dxbcFile.m_pFile); + if (outputFile.m_pFile != NULL) + fclose(outputFile.m_pFile); + + return result; +} + +#if !defined(_MSC_VER) +#define sprintf_s(dest, size, ...) sprintf(dest, __VA_ARGS__) +#endif + +#if defined(_WIN32) && defined(PORTABLE) + +DWORD FilterException(DWORD uExceptionCode) +{ + const char* szExceptionName; + char acTemp[10]; + switch (uExceptionCode) + { +#define _CASE(_Name) \ + case _Name: \ + szExceptionName = #_Name; \ + break; + _CASE(EXCEPTION_ACCESS_VIOLATION) + _CASE(EXCEPTION_DATATYPE_MISALIGNMENT) + _CASE(EXCEPTION_BREAKPOINT) + _CASE(EXCEPTION_SINGLE_STEP) + _CASE(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) + _CASE(EXCEPTION_FLT_DENORMAL_OPERAND) + _CASE(EXCEPTION_FLT_DIVIDE_BY_ZERO) + _CASE(EXCEPTION_FLT_INEXACT_RESULT) + _CASE(EXCEPTION_FLT_INVALID_OPERATION) + _CASE(EXCEPTION_FLT_OVERFLOW) + _CASE(EXCEPTION_FLT_STACK_CHECK) + _CASE(EXCEPTION_FLT_UNDERFLOW) + _CASE(EXCEPTION_INT_DIVIDE_BY_ZERO) + _CASE(EXCEPTION_INT_OVERFLOW) + _CASE(EXCEPTION_PRIV_INSTRUCTION) + _CASE(EXCEPTION_IN_PAGE_ERROR) + _CASE(EXCEPTION_ILLEGAL_INSTRUCTION) + _CASE(EXCEPTION_NONCONTINUABLE_EXCEPTION) + _CASE(EXCEPTION_STACK_OVERFLOW) + _CASE(EXCEPTION_INVALID_DISPOSITION) + _CASE(EXCEPTION_GUARD_PAGE) + _CASE(EXCEPTION_INVALID_HANDLE) + //_CASE(EXCEPTION_POSSIBLE_DEADLOCK) +#undef _CASE + default: + sprintf_s(acTemp, "0x%08X", uExceptionCode); + szExceptionName = acTemp; + } + + fprintf(stderr, "Hardware exception thrown (%s)\n", szExceptionName); + return 1; +} + +#endif + +const char* PatchHLSLShaderFile(const char* path) +{ + // Need to transform "half" into "min16float" so FXC preserve min precision to the operands. + static char patchedFileName[MAX_PATH_CHARS]; + const char* defines = "#define half min16float\n" + "#define half2 min16float2\n" + "#define half3 min16float3\n" + "#define half4 min16float4\n"; + + sprintf_s(patchedFileName, sizeof(patchedFileName), "%s.hlslPatched", path); + FILE* shaderFile = fopen(path, "rb"); + if (!shaderFile) + { + return NULL; + } + + FILE* patchedFile = fopen(patchedFileName, "wb"); + if (!patchedFile) + { + return NULL; + } + + // Get size of file + bool result = false; + fseek(shaderFile, 0, SEEK_END); + long size = ftell(shaderFile); + fseek(shaderFile, 0, SEEK_SET); + unsigned char* data = new unsigned char[size + 1]; // Extra byte for the '/0' character. + if (fread(data, 1, size, shaderFile) == size) + { + data[size] = '\0'; + fprintf(patchedFile, "%s%s", defines, data); + result = true; + } + + if (shaderFile) + { + fclose(shaderFile); + } + + if (patchedFile) + { + fclose(patchedFile); + } + + delete[] data; + return result ? patchedFileName : NULL; +} + +int main(int argc, char** argv) +{ + Options options; + +#if defined(_WIN32) && defined(PORTABLE) + __try + { +#endif + + if (!GetOptions(argc, argv, &options)) + { + return 1; + } + + if (options.bUseFxc) + { + char dxbcFileName[MAX_PATH_CHARS]; + char glslFileName[MAX_PATH_CHARS]; + char fullFxcCmdLine[MAX_FXC_CMD_CHARS]; + int retValue; + + if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) + { + options.shaderFile = PatchHLSLShaderFile(options.shaderFile); + if (!options.shaderFile) + { + return 1; + } + } + + sprintf_s(dxbcFileName, sizeof(dxbcFileName), "%s.dxbc", options.shaderFile); + sprintf_s(glslFileName, sizeof(glslFileName), "%s.patched", options.shaderFile); + + // Need to extract the path to the executable so we can enclose it in quotes + // in case it contains spaces. + const std::string fxcExeName = "fxc.exe"; + + // Case insensitive search + std::string::iterator fxcPos = std::search( + options.fxcCmdLine.begin(), options.fxcCmdLine.end(), + fxcExeName.begin(), fxcExeName.end(), + [](char ch1, char ch2) { return std::tolower(ch1) == std::tolower(ch2); } + ); + + if (fxcPos == options.fxcCmdLine.end()) + { + fprintf(stderr, "Could not find fxc.exe in command line"); + return 1; + } + + // Add the fxcExeName so it gets copied to the fxcExe path. + fxcPos += fxcExeName.length(); + std::string fxcExe(options.fxcCmdLine.begin(), fxcPos); + std::string fxcArguments(fxcPos, options.fxcCmdLine.end()); + +#if defined(APPLE) + fprintf(stderr, "fxc.exe cannot be executed on Mac"); + return 1; +#else + // Need an extra set of quotes around the full command line because the way "system" executes it using cmd. + sprintf_s(fullFxcCmdLine, sizeof(fullFxcCmdLine), "\"\"%s\" %s \"%s\" \"%s\"\"", fxcExe.c_str(), fxcArguments.c_str(), dxbcFileName, options.shaderFile); +#endif + + retValue = system(fullFxcCmdLine); + + if (retValue == 0) + { + Shader shader; + retValue = !Run(dxbcFileName, glslFileName, options.language, options.flags, options.reflectPath, &shader, 1, fullFxcCmdLine, options.shaderFile); + + if (retValue == 0) + { + retValue = !CombineDXBCWithGLSL(dxbcFileName, options.outputShaderFile, &shader); + FreeShader(&shader); + } + } + + remove(dxbcFileName); + remove(glslFileName); + if (options.flags & HLSLCC_FLAG_HALF_FLOAT_TRANSFORM) + { + // Removed the hlsl patched file that was created. + remove(options.shaderFile); + } + + return retValue; + } + else if (options.shaderFile) + { + if (!Run(options.shaderFile, options.outputShaderFile, options.language, options.flags, options.reflectPath, NULL, 0, NULL, NULL)) + { + return 1; + } + } + +#if defined(_WIN32) && defined(PORTABLE) + } + __except (FilterException(GetExceptionCode())) + { + return 1; + } +#endif + + + return 0; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h new file mode 100644 index 0000000000..e480417717 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/hash.h @@ -0,0 +1,128 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HASH_H_ +#define HASH_H_ + +/* +-------------------------------------------------------------------- +mix -- mix 3 64-bit values reversibly. +mix() takes 48 machine instructions, but only 24 cycles on a superscalar + machine (like Intel's new MMX architecture). It requires 4 64-bit + registers for 4::2 parallelism. +All 1-bit deltas, all 2-bit deltas, all deltas composed of top bits of + (a,b,c), and all deltas of bottom bits were tested. All deltas were + tested both on random keys and on keys that were nearly all zero. + These deltas all cause every bit of c to change between 1/3 and 2/3 + of the time (well, only 113/400 to 287/400 of the time for some + 2-bit delta). These deltas all cause at least 80 bits to change + among (a,b,c) when the mix is run either forward or backward (yes it + is reversible). +This implies that a hash using mix64 has no funnels. There may be + characteristics with 3-bit deltas or bigger, I didn't test for + those. +-------------------------------------------------------------------- +*/ +#define mix64(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>43); \ + b -= c; b -= a; b ^= (a<<9); \ + c -= a; c -= b; c ^= (b>>8); \ + a -= b; a -= c; a ^= (c>>38); \ + b -= c; b -= a; b ^= (a<<23); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>35); \ + b -= c; b -= a; b ^= (a<<49); \ + c -= a; c -= b; c ^= (b>>11); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<18); \ + c -= a; c -= b; c ^= (b>>22); \ +} + +/* +-------------------------------------------------------------------- +hash64() -- hash a variable-length key into a 64-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + level : can be any 8-byte value +Returns a 64-bit value. Every bit of the key affects every bit of +the return value. No funnels. Every 1-bit and 2-bit delta achieves +avalanche. About 41+5len instructions. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 64 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h); + +By Bob Jenkins, Jan 4 1997. bob_jenkins@burtleburtle.net. You may +use this code any way you wish, private, educational, or commercial, +but I would appreciate if you give me credit. + +See http://burtleburtle.net/bob/hash/evahash.html +Use for hash table lookup, or anything where one collision in 2^^64 +is acceptable. Do NOT use for cryptographic purposes. +-------------------------------------------------------------------- +*/ + +static uint64_t hash64( const uint8_t *k, uint32_t length, uint64_t initval ) +{ + uint64_t a,b,c,len; + + /* Set up the internal state */ + len = length; + a = b = initval; /* the previous hash value */ + c = 0x9e3779b97f4a7c13LL; /* the golden ratio; an arbitrary value */ + + /*---------------------------------------- handle most of the key */ + while (len >= 24) + { + a += (k[0] +((uint64_t)k[ 1]<< 8)+((uint64_t)k[ 2]<<16)+((uint64_t)k[ 3]<<24) + +((uint64_t)k[4 ]<<32)+((uint64_t)k[ 5]<<40)+((uint64_t)k[ 6]<<48)+((uint64_t)k[ 7]<<56)); + b += (k[8] +((uint64_t)k[ 9]<< 8)+((uint64_t)k[10]<<16)+((uint64_t)k[11]<<24) + +((uint64_t)k[12]<<32)+((uint64_t)k[13]<<40)+((uint64_t)k[14]<<48)+((uint64_t)k[15]<<56)); + c += (k[16] +((uint64_t)k[17]<< 8)+((uint64_t)k[18]<<16)+((uint64_t)k[19]<<24) + +((uint64_t)k[20]<<32)+((uint64_t)k[21]<<40)+((uint64_t)k[22]<<48)+((uint64_t)k[23]<<56)); + mix64(a,b,c); + k += 24; len -= 24; + } + + /*------------------------------------- handle the last 23 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 23: c+=((uint64_t)k[22]<<56); + case 22: c+=((uint64_t)k[21]<<48); + case 21: c+=((uint64_t)k[20]<<40); + case 20: c+=((uint64_t)k[19]<<32); + case 19: c+=((uint64_t)k[18]<<24); + case 18: c+=((uint64_t)k[17]<<16); + case 17: c+=((uint64_t)k[16]<<8); + /* the first byte of c is reserved for the length */ + case 16: b+=((uint64_t)k[15]<<56); + case 15: b+=((uint64_t)k[14]<<48); + case 14: b+=((uint64_t)k[13]<<40); + case 13: b+=((uint64_t)k[12]<<32); + case 12: b+=((uint64_t)k[11]<<24); + case 11: b+=((uint64_t)k[10]<<16); + case 10: b+=((uint64_t)k[ 9]<<8); + case 9: b+=((uint64_t)k[ 8]); + case 8: a+=((uint64_t)k[ 7]<<56); + case 7: a+=((uint64_t)k[ 6]<<48); + case 6: a+=((uint64_t)k[ 5]<<40); + case 5: a+=((uint64_t)k[ 4]<<32); + case 4: a+=((uint64_t)k[ 3]<<24); + case 3: a+=((uint64_t)k[ 2]<<16); + case 2: a+=((uint64_t)k[ 1]<<8); + case 1: a+=((uint64_t)k[ 0]); + /* case 0: nothing left to add */ + } + mix64(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp new file mode 100644 index 0000000000..15fe8d5b96 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.cpp @@ -0,0 +1,207 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "serializeReflection.h" +#include "cJSON.h" +#include <string> +#include <sstream> + +void* jsonMalloc(size_t sz) +{ + return new char[sz]; +} +void jsonFree(void* ptr) +{ + char* charPtr = static_cast<char*>(ptr); + delete [] charPtr; +} + +static void AppendIntToString(std::string& str, uint32_t num) +{ + std::stringstream ss; + ss << num; + str += ss.str(); +} + +static void WriteInOutSignature(InOutSignature* psSignature, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "SemanticName", cJSON_CreateString(psSignature->SemanticName)); + cJSON_AddItemToObject(obj, "ui32SemanticIndex", cJSON_CreateNumber(psSignature->ui32SemanticIndex)); + cJSON_AddItemToObject(obj, "eSystemValueType", cJSON_CreateNumber(psSignature->eSystemValueType)); + cJSON_AddItemToObject(obj, "eComponentType", cJSON_CreateNumber(psSignature->eComponentType)); + cJSON_AddItemToObject(obj, "ui32Register", cJSON_CreateNumber(psSignature->ui32Register)); + cJSON_AddItemToObject(obj, "ui32Mask", cJSON_CreateNumber(psSignature->ui32Mask)); + cJSON_AddItemToObject(obj, "ui32ReadWriteMask", cJSON_CreateNumber(psSignature->ui32ReadWriteMask)); +} + +static void WriteResourceBinding(ResourceBinding* psBinding, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psBinding->Name)); + cJSON_AddItemToObject(obj, "eType", cJSON_CreateNumber(psBinding->eType)); + cJSON_AddItemToObject(obj, "ui32BindPoint", cJSON_CreateNumber(psBinding->ui32BindPoint)); + cJSON_AddItemToObject(obj, "ui32BindCount", cJSON_CreateNumber(psBinding->ui32BindCount)); + cJSON_AddItemToObject(obj, "ui32Flags", cJSON_CreateNumber(psBinding->ui32Flags)); + cJSON_AddItemToObject(obj, "eDimension", cJSON_CreateNumber(psBinding->eDimension)); + cJSON_AddItemToObject(obj, "ui32ReturnType", cJSON_CreateNumber(psBinding->ui32ReturnType)); + cJSON_AddItemToObject(obj, "ui32NumSamples", cJSON_CreateNumber(psBinding->ui32NumSamples)); +} + +static void WriteShaderVar(ShaderVar* psVar, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psVar->Name)); + if(psVar->haveDefaultValue) + { + cJSON_AddItemToObject(obj, "aui32DefaultValues", cJSON_CreateIntArray((int*)psVar->pui32DefaultValues, psVar->ui32Size/4)); + } + cJSON_AddItemToObject(obj, "ui32StartOffset", cJSON_CreateNumber(psVar->ui32StartOffset)); + cJSON_AddItemToObject(obj, "ui32Size", cJSON_CreateNumber(psVar->ui32Size)); +} + +static void WriteConstantBuffer(ConstantBuffer* psCBuf, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psCBuf->Name)); + cJSON_AddItemToObject(obj, "ui32NumVars", cJSON_CreateNumber(psCBuf->ui32NumVars)); + + for(uint32_t i = 0; i < psCBuf->ui32NumVars; ++i) + { + std::string name; + name += "var"; + AppendIntToString(name, i); + + cJSON* varObj = cJSON_CreateObject(); + cJSON_AddItemToObject(obj, name.c_str(), varObj); + + WriteShaderVar(&psCBuf->asVars[i], varObj); + } + + cJSON_AddItemToObject(obj, "ui32TotalSizeInBytes", cJSON_CreateNumber(psCBuf->ui32TotalSizeInBytes)); +} + +static void WriteClassType(ClassType* psClassType, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassType->Name)); + cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassType->ui16ID)); + cJSON_AddItemToObject(obj, "ui16ConstBufStride", cJSON_CreateNumber(psClassType->ui16ConstBufStride)); + cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassType->ui16Texture)); + cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassType->ui16Sampler)); +} + +static void WriteClassInstance(ClassInstance* psClassInst, cJSON* obj) +{ + cJSON_AddItemToObject(obj, "Name", cJSON_CreateString(psClassInst->Name)); + cJSON_AddItemToObject(obj, "ui16ID", cJSON_CreateNumber(psClassInst->ui16ID)); + cJSON_AddItemToObject(obj, "ui16ConstBuf", cJSON_CreateNumber(psClassInst->ui16ConstBuf)); + cJSON_AddItemToObject(obj, "ui16ConstBufOffset", cJSON_CreateNumber(psClassInst->ui16ConstBufOffset)); + cJSON_AddItemToObject(obj, "ui16Texture", cJSON_CreateNumber(psClassInst->ui16Texture)); + cJSON_AddItemToObject(obj, "ui16Sampler", cJSON_CreateNumber(psClassInst->ui16Sampler)); +} + +const char* SerializeReflection(ShaderInfo* psReflection) +{ + cJSON* root; + + cJSON_Hooks hooks; + hooks.malloc_fn = jsonMalloc; + hooks.free_fn = jsonFree; + cJSON_InitHooks(&hooks); + + root=cJSON_CreateObject(); + cJSON_AddItemToObject(root, "ui32MajorVersion", cJSON_CreateNumber(psReflection->ui32MajorVersion)); + cJSON_AddItemToObject(root, "ui32MinorVersion", cJSON_CreateNumber(psReflection->ui32MinorVersion)); + + cJSON_AddItemToObject(root, "ui32NumInputSignatures", cJSON_CreateNumber(psReflection->ui32NumInputSignatures)); + + for(uint32_t i = 0; i < psReflection->ui32NumInputSignatures; ++i) + { + std::string name; + name += "input"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteInOutSignature(psReflection->psInputSignatures+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumOutputSignatures", cJSON_CreateNumber(psReflection->ui32NumOutputSignatures)); + + for(uint32_t i = 0; i < psReflection->ui32NumOutputSignatures; ++i) + { + std::string name; + name += "output"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteInOutSignature(psReflection->psOutputSignatures+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumResourceBindings", cJSON_CreateNumber(psReflection->ui32NumResourceBindings)); + + for(uint32_t i = 0; i < psReflection->ui32NumResourceBindings; ++i) + { + std::string name; + name += "resource"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteResourceBinding(psReflection->psResourceBindings+i, obj); + } + + cJSON_AddItemToObject(root, "ui32NumConstantBuffers", cJSON_CreateNumber(psReflection->ui32NumConstantBuffers)); + + for(uint32_t i = 0; i < psReflection->ui32NumConstantBuffers; ++i) + { + std::string name; + name += "cbuf"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteConstantBuffer(psReflection->psConstantBuffers+i, obj); + } + + //psThisPointerConstBuffer is a cache. Don't need to write this out. + //It just points to the $ThisPointer cbuffer within the psConstantBuffers array. + + for(uint32_t i = 0; i < psReflection->ui32NumClassTypes; ++i) + { + std::string name; + name += "classType"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteClassType(psReflection->psClassTypes+i, obj); + } + + for(uint32_t i = 0; i < psReflection->ui32NumClassInstances; ++i) + { + std::string name; + name += "classInst"; + AppendIntToString(name, i); + + cJSON* obj = cJSON_CreateObject(); + cJSON_AddItemToObject(root, name.c_str(), obj); + + WriteClassInstance(psReflection->psClassInstances+i, obj); + } + + //psReflection->aui32TableIDToTypeID + //psReflection->aui32ConstBufferBindpointRemap + + cJSON_AddItemToObject(root, "eTessPartitioning", cJSON_CreateNumber(psReflection->eTessPartitioning)); + cJSON_AddItemToObject(root, "eTessOutPrim", cJSON_CreateNumber(psReflection->eTessOutPrim)); + + + const char* jsonString = cJSON_Print(root); + + cJSON_Delete(root); + + return jsonString; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h new file mode 100644 index 0000000000..c8c4175a6a --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/serializeReflection.h @@ -0,0 +1,11 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef SERIALIZE_REFLECTION_H_ +#define SERIALIZE_REFLECTION_H_ + +#include "hlslcc.h" + +const char* SerializeReflection(ShaderInfo* psReflection); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp new file mode 100644 index 0000000000..c707e1bfa8 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.cpp @@ -0,0 +1,40 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "timer.h" + +void InitTimer(Timer_t* psTimer) +{ +#if defined(_WIN32) + QueryPerformanceFrequency(&psTimer->frequency); +#endif +} + +void ResetTimer(Timer_t* psTimer) +{ +#if defined(_WIN32) + QueryPerformanceCounter(&psTimer->startCount); +#else + gettimeofday(&psTimer->startCount, 0); +#endif +} + +/* Returns time in micro seconds */ +double ReadTimer(Timer_t* psTimer) +{ + double startTimeInMicroSec, endTimeInMicroSec; + +#if defined(_WIN32) + const double freq = (1000000.0 / psTimer->frequency.QuadPart); + QueryPerformanceCounter(&psTimer->endCount); + startTimeInMicroSec = psTimer->startCount.QuadPart * freq; + endTimeInMicroSec = psTimer->endCount.QuadPart * freq; +#else + gettimeofday(&psTimer->endCount, 0); + startTimeInMicroSec = (psTimer->startCount.tv_sec * 1000000.0) + psTimer->startCount.tv_usec; + endTimeInMicroSec = (psTimer->endCount.tv_sec * 1000000.0) + psTimer->endCount.tv_usec; +#endif + + return endTimeInMicroSec - startTimeInMicroSec; +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h new file mode 100644 index 0000000000..3f4ea333fd --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/offline/timer.h @@ -0,0 +1,29 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TIMER_H +#define TIMER_H + +#ifdef _WIN32 +#include <Windows.h> +#else +#include <sys/time.h> +#endif + +typedef struct +{ +#ifdef _WIN32 + LARGE_INTEGER frequency; + LARGE_INTEGER startCount; + LARGE_INTEGER endCount; +#else + struct timeval startCount; + struct timeval endCount; +#endif +} Timer_t; + +void InitTimer(Timer_t* psTimer); +void ResetTimer(Timer_t* psTimer); +double ReadTimer(Timer_t* psTimer); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c new file mode 100644 index 0000000000..3f24fa3341 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.c @@ -0,0 +1,20 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bsafe.c + * + * This is an optional module that can be used to help enforce a safety + * standard based on pervasive usage of bstrlib. This file is not necessarily + * portable, however, it has been tested to work correctly with Intel's C/C++ + * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. + */ + +#include <stdio.h> +#include <stdlib.h> +#include "bsafe.h" diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h new file mode 100644 index 0000000000..3e18e33493 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bsafe.h @@ -0,0 +1,39 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bsafe.h + * + * This is an optional module that can be used to help enforce a safety + * standard based on pervasive usage of bstrlib. This file is not necessarily + * portable, however, it has been tested to work correctly with Intel's C/C++ + * compiler, WATCOM C/C++ v11.x and Microsoft Visual C++. + */ + +#ifndef BSTRLIB_BSAFE_INCLUDE +#define BSTRLIB_BSAFE_INCLUDE + +#ifdef __cplusplus +extern "C" { +#endif + +extern char * (strncpy) (char *dst, const char *src, size_t n); +extern char * (strncat) (char *dst, const char *src, size_t n); +extern char * (strtok) (char *s1, const char *s2); +extern char * (strdup) (const char *s); + +#undef strcpy +#undef strcat +#define strcpy(a,b) bsafe_strcpy(a,b) +#define strcat(a,b) bsafe_strcat(a,b) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c new file mode 100644 index 0000000000..2dc7b04840 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.c @@ -0,0 +1,1134 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstraux.c + * + * This file is not necessarily part of the core bstring library itself, but + * is just an auxilliary module which includes miscellaneous or trivial + * functions. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> +#include "bstrlib.h" +#include "bstraux.h" + +/* bstring bTail (bstring b, int n) + * + * Return with a string of the last n characters of b. + */ +bstring bTail (bstring b, int n) { + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; + if (n >= b->slen) return bstrcpy (b); + return bmidstr (b, b->slen - n, n); +} + +/* bstring bHead (bstring b, int n) + * + * Return with a string of the first n characters of b. + */ +bstring bHead (bstring b, int n) { + if (b == NULL || n < 0 || (b->mlen < b->slen && b->mlen > 0)) return NULL; + if (n >= b->slen) return bstrcpy (b); + return bmidstr (b, 0, n); +} + +/* int bFill (bstring a, char c, int len) + * + * Fill a given bstring with the character in parameter c, for a length n. + */ +int bFill (bstring b, char c, int len) { + if (b == NULL || len < 0 || (b->mlen < b->slen && b->mlen > 0)) return -__LINE__; + b->slen = 0; + return bsetstr (b, len, NULL, c); +} + +/* int bReplicate (bstring b, int n) + * + * Replicate the contents of b end to end n times and replace it in b. + */ +int bReplicate (bstring b, int n) { + return bpattern (b, n * b->slen); +} + +/* int bReverse (bstring b) + * + * Reverse the contents of b in place. + */ +int bReverse (bstring b) { +int i, n, m; +unsigned char t; + + if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; + n = b->slen; + if (2 <= n) { + m = ((unsigned)n) >> 1; + n--; + for (i=0; i < m; i++) { + t = b->data[n - i]; + b->data[n - i] = b->data[i]; + b->data[i] = t; + } + } + return 0; +} + +/* int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) + * + * Insert a repeated sequence of a given character into the string at + * position pos for a length len. + */ +int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill) { + if (b == NULL || b->slen < 0 || b->mlen < b->slen || pos < 0 || len <= 0) return -__LINE__; + + if (pos > b->slen + && 0 > bsetstr (b, pos, NULL, fill)) return -__LINE__; + + if (0 > balloc (b, b->slen + len)) return -__LINE__; + if (pos < b->slen) memmove (b->data + pos + len, b->data + pos, b->slen - pos); + memset (b->data + pos, c, len); + b->slen += len; + b->data[b->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bJustifyLeft (bstring b, int space) + * + * Left justify a string. + */ +int bJustifyLeft (bstring b, int space) { +int j, i, s, t; +unsigned char c = (unsigned char) space; + + if (b == NULL || b->slen < 0 || b->mlen < b->slen) return -__LINE__; + if (space != (int) c) return BSTR_OK; + + for (s=j=i=0; i < b->slen; i++) { + t = s; + s = c != (b->data[j] = b->data[i]); + j += (t|s); + } + if (j > 0 && b->data[j-1] == c) j--; + + b->data[j] = (unsigned char) '\0'; + b->slen = j; + return BSTR_OK; +} + +/* int bJustifyRight (bstring b, int width, int space) + * + * Right justify a string to within a given width. + */ +int bJustifyRight (bstring b, int width, int space) { +int ret; + if (width <= 0) return -__LINE__; + if (0 > (ret = bJustifyLeft (b, space))) return ret; + if (b->slen <= width) + return bInsertChrs (b, 0, width - b->slen, (unsigned char) space, (unsigned char) space); + return BSTR_OK; +} + +/* int bJustifyCenter (bstring b, int width, int space) + * + * Center a string's non-white space characters to within a given width by + * inserting whitespaces at the beginning. + */ +int bJustifyCenter (bstring b, int width, int space) { +int ret; + if (width <= 0) return -__LINE__; + if (0 > (ret = bJustifyLeft (b, space))) return ret; + if (b->slen <= width) + return bInsertChrs (b, 0, (width - b->slen + 1) >> 1, (unsigned char) space, (unsigned char) space); + return BSTR_OK; +} + +/* int bJustifyMargin (bstring b, int width, int space) + * + * Stretch a string to flush against left and right margins by evenly + * distributing additional white space between words. If the line is too + * long to be margin justified, it is left justified. + */ +int bJustifyMargin (bstring b, int width, int space) { +struct bstrList * sl; +int i, l, c; + + if (b == NULL || b->slen < 0 || b->mlen == 0 || b->mlen < b->slen) return -__LINE__; + if (NULL == (sl = bsplit (b, (unsigned char) space))) return -__LINE__; + for (l=c=i=0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + c ++; + l += sl->entry[i]->slen; + } + } + + if (l + c >= width || c < 2) { + bstrListDestroy (sl); + return bJustifyLeft (b, space); + } + + b->slen = 0; + for (i=0; i < sl->qty; i++) { + if (sl->entry[i]->slen > 0) { + if (b->slen > 0) { + int s = (width - l + (c / 2)) / c; + bInsertChrs (b, b->slen, s, (unsigned char) space, (unsigned char) space); + l += s; + } + bconcat (b, sl->entry[i]); + c--; + if (c <= 0) break; + } + } + + bstrListDestroy (sl); + return BSTR_OK; +} + +static size_t readNothing (void *buff, size_t elsize, size_t nelem, void *parm) { + buff = buff; + elsize = elsize; + nelem = nelem; + parm = parm; + return 0; /* Immediately indicate EOF. */ +} + +/* struct bStream * bsFromBstr (const_bstring b); + * + * Create a bStream whose contents are a copy of the bstring passed in. + * This allows the use of all the bStream APIs with bstrings. + */ +struct bStream * bsFromBstr (const_bstring b) { +struct bStream * s = bsopen ((bNread) readNothing, NULL); + bsunread (s, b); /* Push the bstring data into the empty bStream. */ + return s; +} + +static size_t readRef (void *buff, size_t elsize, size_t nelem, void *parm) { +struct tagbstring * t = (struct tagbstring *) parm; +size_t tsz = elsize * nelem; + + if (tsz > (size_t) t->slen) tsz = (size_t) t->slen; + if (tsz > 0) { + memcpy (buff, t->data, tsz); + t->slen -= (int) tsz; + t->data += tsz; + return tsz / elsize; + } + return 0; +} + +/* The "by reference" version of the above function. This function puts + * a number of restrictions on the call site (the passed in struct + * tagbstring *will* be modified by this function, and the source data + * must remain alive and constant for the lifetime of the bStream). + * Hence it is not presented as an extern. + */ +static struct bStream * bsFromBstrRef (struct tagbstring * t) { + if (!t) return NULL; + return bsopen ((bNread) readRef, t); +} + +/* char * bStr2NetStr (const_bstring b) + * + * Convert a bstring to a netstring. See + * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * Note: 1) The value returned should be freed with a call to bcstrfree() at + * the point when it will no longer be referenced to avoid a memory + * leak. + * 2) If the returned value is non-NULL, then it also '\0' terminated + * in the character position one past the "," terminator. + */ +char * bStr2NetStr (const_bstring b) { +char strnum[sizeof (b->slen) * 3 + 1]; +bstring s; +unsigned char * buff; + + if (b == NULL || b->data == NULL || b->slen < 0) return NULL; + sprintf (strnum, "%d:", b->slen); + if (NULL == (s = bfromcstr (strnum)) + || bconcat (s, b) == BSTR_ERR || bconchar (s, (char) ',') == BSTR_ERR) { + bdestroy (s); + return NULL; + } + buff = s->data; + bcstrfree ((char *) s); + return (char *) buff; +} + +/* bstring bNetStr2Bstr (const char * buf) + * + * Convert a netstring to a bstring. See + * http://cr.yp.to/proto/netstrings.txt for a description of netstrings. + * Note that the terminating "," *must* be present, however a following '\0' + * is *not* required. + */ +bstring bNetStr2Bstr (const char * buff) { +int i, x; +bstring b; + if (buff == NULL) return NULL; + x = 0; + for (i=0; buff[i] != ':'; i++) { + unsigned int v = buff[i] - '0'; + if (v > 9 || x > ((INT_MAX - (signed int)v) / 10)) return NULL; + x = (x * 10) + v; + } + + /* This thing has to be properly terminated */ + if (buff[i + 1 + x] != ',') return NULL; + + if (NULL == (b = bfromcstr (""))) return NULL; + if (balloc (b, x + 1) != BSTR_OK) { + bdestroy (b); + return NULL; + } + memcpy (b->data, buff + i + 1, x); + b->data[x] = (unsigned char) '\0'; + b->slen = x; + return b; +} + +static char b64ETable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/* bstring bBase64Encode (const_bstring b) + * + * Generate a base64 encoding. See: RFC1341 + */ +bstring bBase64Encode (const_bstring b) { +int i, c0, c1, c2, c3; +bstring out; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + out = bfromcstr (""); + for (i=0; i + 2 < b->slen; i += 3) { + if (i && ((i % 57) == 0)) { + if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { + bdestroy (out); + return NULL; + } + } + c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | + (b->data[i+1] >> 4)) & 0x3F; + c2 = ((b->data[i+1] << 2) | + (b->data[i+2] >> 6)) & 0x3F; + c3 = b->data[i+2] & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, b64ETable[c2]) < 0 || + bconchar (out, b64ETable[c3]) < 0) { + bdestroy (out); + return NULL; + } + } + + if (i && ((i % 57) == 0)) { + if (bconchar (out, (char) '\015') < 0 || bconchar (out, (char) '\012') < 0) { + bdestroy (out); + return NULL; + } + } + + switch (i + 2 - b->slen) { + case 0: c0 = b->data[i] >> 2; + c1 = ((b->data[i] << 4) | + (b->data[i+1] >> 4)) & 0x3F; + c2 = (b->data[i+1] << 2) & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, b64ETable[c2]) < 0 || + bconchar (out, (char) '=') < 0) { + bdestroy (out); + return NULL; + } + break; + case 1: c0 = b->data[i] >> 2; + c1 = (b->data[i] << 4) & 0x3F; + if (bconchar (out, b64ETable[c0]) < 0 || + bconchar (out, b64ETable[c1]) < 0 || + bconchar (out, (char) '=') < 0 || + bconchar (out, (char) '=') < 0) { + bdestroy (out); + return NULL; + } + break; + case 2: break; + } + + return out; +} + +#define B64_PAD (-2) +#define B64_ERR (-1) + +static int base64DecodeSymbol (unsigned char alpha) { + if ((alpha >= 'A') && (alpha <= 'Z')) return (int)(alpha - 'A'); + else if ((alpha >= 'a') && (alpha <= 'z')) + return 26 + (int)(alpha - 'a'); + else if ((alpha >= '0') && (alpha <= '9')) + return 52 + (int)(alpha - '0'); + else if (alpha == '+') return 62; + else if (alpha == '/') return 63; + else if (alpha == '=') return B64_PAD; + else return B64_ERR; +} + +/* bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) + * + * Decode a base64 block of data. All MIME headers are assumed to have been + * removed. See: RFC1341 + */ +bstring bBase64DecodeEx (const_bstring b, int * boolTruncError) { +int i, v; +unsigned char c0, c1, c2; +bstring out; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + if (boolTruncError) *boolTruncError = 0; + out = bfromcstr (""); + i = 0; + for (;;) { + do { + if (i >= b->slen) return out; + if (b->data[i] == '=') { /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c0 = (unsigned char) (v << 2); + do { + if (i >= b->slen || b->data[i] == '=') { /* Bad "too early" truncation */ + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c0 |= (unsigned char) (v >> 4); + c1 = (unsigned char) (v << 4); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (b->data[i] == '=') { + i++; + if (i >= b->slen || b->data[i] != '=' || bconchar (out, c0) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); /* Missing "=" at the end. */ + return NULL; + } + return out; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c1 |= (unsigned char) (v >> 2); + c2 = (unsigned char) (v << 6); + do { + if (i >= b->slen) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (b->data[i] == '=') { + if (bconchar (out, c0) < 0 || bconchar (out, c1) < 0) { + if (boolTruncError) { + *boolTruncError = 1; + return out; + } + bdestroy (out); + return NULL; + } + if (boolTruncError) *boolTruncError = 0; + return out; + } + v = base64DecodeSymbol (b->data[i]); + i++; + } while (v < 0); + c2 |= (unsigned char) (v); + if (bconchar (out, c0) < 0 || + bconchar (out, c1) < 0 || + bconchar (out, c2) < 0) { + if (boolTruncError) { + *boolTruncError = -1; + return out; + } + bdestroy (out); + return NULL; + } + } +} + +#define UU_DECODE_BYTE(b) (((b) == (signed int)'`') ? 0 : (b) - (signed int)' ') + +struct bUuInOut { + bstring src, dst; + int * badlines; +}; + +#define UU_MAX_LINELEN 45 + +static int bUuDecLine (void * parm, int ofs, int len) { +struct bUuInOut * io = (struct bUuInOut *) parm; +bstring s = io->src; +bstring t = io->dst; +int i, llen, otlen, ret, c0, c1, c2, c3, d0, d1, d2, d3; + + if (len == 0) return 0; + llen = UU_DECODE_BYTE (s->data[ofs]); + ret = 0; + + otlen = t->slen; + + if (((unsigned) llen) > UU_MAX_LINELEN) { ret = -__LINE__; + goto bl; + } + + llen += t->slen; + + for (i=1; i < s->slen && t->slen < llen;i += 4) { + unsigned char outoctet[3]; + c0 = UU_DECODE_BYTE (d0 = (int) bchare (s, i+ofs+0, ' ' - 1)); + c1 = UU_DECODE_BYTE (d1 = (int) bchare (s, i+ofs+1, ' ' - 1)); + c2 = UU_DECODE_BYTE (d2 = (int) bchare (s, i+ofs+2, ' ' - 1)); + c3 = UU_DECODE_BYTE (d3 = (int) bchare (s, i+ofs+3, ' ' - 1)); + + if (((unsigned) (c0|c1) >= 0x40)) { if (!ret) ret = -__LINE__; + if (d0 > 0x60 || (d0 < (' ' - 1) && !isspace (d0)) || + d1 > 0x60 || (d1 < (' ' - 1) && !isspace (d1))) { + t->slen = otlen; + goto bl; + } + c0 = c1 = 0; + } + outoctet[0] = (unsigned char) ((c0 << 2) | ((unsigned) c1 >> 4)); + if (t->slen+1 >= llen) { + if (0 > bconchar (t, (char) outoctet[0])) return -__LINE__; + break; + } + if ((unsigned) c2 >= 0x40) { if (!ret) ret = -__LINE__; + if (d2 > 0x60 || (d2 < (' ' - 1) && !isspace (d2))) { + t->slen = otlen; + goto bl; + } + c2 = 0; + } + outoctet[1] = (unsigned char) ((c1 << 4) | ((unsigned) c2 >> 2)); + if (t->slen+2 >= llen) { + if (0 > bcatblk (t, outoctet, 2)) return -__LINE__; + break; + } + if ((unsigned) c3 >= 0x40) { if (!ret) ret = -__LINE__; + if (d3 > 0x60 || (d3 < (' ' - 1) && !isspace (d3))) { + t->slen = otlen; + goto bl; + } + c3 = 0; + } + outoctet[2] = (unsigned char) ((c2 << 6) | ((unsigned) c3)); + if (0 > bcatblk (t, outoctet, 3)) return -__LINE__; + } + if (t->slen < llen) { if (0 == ret) ret = -__LINE__; + t->slen = otlen; + } + bl:; + if (ret && io->badlines) { + (*io->badlines)++; + return 0; + } + return ret; +} + +/* bstring bUuDecodeEx (const_bstring src, int * badlines) + * + * Performs a UUDecode of a block of data. If there are errors in the + * decoding, they are counted up and returned in "badlines", if badlines is + * not NULL. It is assumed that the "begin" and "end" lines have already + * been stripped off. The potential security problem of writing the + * filename in the begin line is something that is beyond the scope of a + * portable library. + */ + +#ifdef _MSC_VER +#pragma warning(disable:4204) +#endif + +bstring bUuDecodeEx (const_bstring src, int * badlines) { +struct tagbstring t; +struct bStream * s; +struct bStream * d; +bstring b; + + if (!src) return NULL; + t = *src; /* Short lifetime alias to header of src */ + s = bsFromBstrRef (&t); /* t is undefined after this */ + if (!s) return NULL; + d = bsUuDecode (s, badlines); + b = bfromcstralloc (256, ""); + if (NULL == b || 0 > bsread (b, d, INT_MAX)) { + bdestroy (b); + bsclose (d); + bsclose (s); + return NULL; + } + return b; +} + +struct bsUuCtx { + struct bUuInOut io; + struct bStream * sInp; +}; + +static size_t bsUuDecodePart (void *buff, size_t elsize, size_t nelem, void *parm) { +static struct tagbstring eol = bsStatic ("\r\n"); +struct bsUuCtx * luuCtx = (struct bsUuCtx *) parm; +size_t tsz; +int l, lret; + + if (NULL == buff || NULL == parm) return 0; + tsz = elsize * nelem; + + CheckInternalBuffer:; + /* If internal buffer has sufficient data, just output it */ + if (((size_t) luuCtx->io.dst->slen) > tsz) { + memcpy (buff, luuCtx->io.dst->data, tsz); + bdelete (luuCtx->io.dst, 0, (int) tsz); + return nelem; + } + + DecodeMore:; + if (0 <= (l = binchr (luuCtx->io.src, 0, &eol))) { + int ol = 0; + struct tagbstring t; + bstring s = luuCtx->io.src; + luuCtx->io.src = &t; + + do { + if (l > ol) { + bmid2tbstr (t, s, ol, l - ol); + lret = bUuDecLine (&luuCtx->io, 0, t.slen); + if (0 > lret) { + luuCtx->io.src = s; + goto Done; + } + } + ol = l + 1; + if (((size_t) luuCtx->io.dst->slen) > tsz) break; + l = binchr (s, ol, &eol); + } while (BSTR_ERR != l); + bdelete (s, 0, ol); + luuCtx->io.src = s; + goto CheckInternalBuffer; + } + + if (BSTR_ERR != bsreada (luuCtx->io.src, luuCtx->sInp, bsbufflength (luuCtx->sInp, BSTR_BS_BUFF_LENGTH_GET))) { + goto DecodeMore; + } + + bUuDecLine (&luuCtx->io, 0, luuCtx->io.src->slen); + + Done:; + /* Output any lingering data that has been translated */ + if (((size_t) luuCtx->io.dst->slen) > 0) { + if (((size_t) luuCtx->io.dst->slen) > tsz) goto CheckInternalBuffer; + memcpy (buff, luuCtx->io.dst->data, luuCtx->io.dst->slen); + tsz = luuCtx->io.dst->slen / elsize; + luuCtx->io.dst->slen = 0; + if (tsz > 0) return tsz; + } + + /* Deallocate once EOF becomes triggered */ + bdestroy (luuCtx->io.dst); + bdestroy (luuCtx->io.src); + free (luuCtx); + return 0; +} + +/* bStream * bsUuDecode (struct bStream * sInp, int * badlines) + * + * Creates a bStream which performs the UUDecode of an an input stream. If + * there are errors in the decoding, they are counted up and returned in + * "badlines", if badlines is not NULL. It is assumed that the "begin" and + * "end" lines have already been stripped off. The potential security + * problem of writing the filename in the begin line is something that is + * beyond the scope of a portable library. + */ + +struct bStream * bsUuDecode (struct bStream * sInp, int * badlines) { +struct bsUuCtx * luuCtx = (struct bsUuCtx *) malloc (sizeof (struct bsUuCtx)); +struct bStream * sOut; + + if (NULL == luuCtx) return NULL; + + luuCtx->io.src = bfromcstr (""); + luuCtx->io.dst = bfromcstr (""); + if (NULL == luuCtx->io.dst || NULL == luuCtx->io.src) { + CleanUpFailureToAllocate:; + bdestroy (luuCtx->io.dst); + bdestroy (luuCtx->io.src); + free (luuCtx); + return NULL; + } + luuCtx->io.badlines = badlines; + if (badlines) *badlines = 0; + + luuCtx->sInp = sInp; + + sOut = bsopen ((bNread) bsUuDecodePart, luuCtx); + if (NULL == sOut) goto CleanUpFailureToAllocate; + return sOut; +} + +#define UU_ENCODE_BYTE(b) (char) (((b) == 0) ? '`' : ((b) + ' ')) + +/* bstring bUuEncode (const_bstring src) + * + * Performs a UUEncode of a block of data. The "begin" and "end" lines are + * not appended. + */ +bstring bUuEncode (const_bstring src) { +bstring out; +int i, j, jm; +unsigned int c0, c1, c2; + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + for (i=0; i < src->slen; i += UU_MAX_LINELEN) { + if ((jm = i + UU_MAX_LINELEN) > src->slen) jm = src->slen; + if (bconchar (out, UU_ENCODE_BYTE (jm - i)) < 0) { + bstrFree (out); + break; + } + for (j = i; j < jm; j += 3) { + c0 = (unsigned int) bchar (src, j ); + c1 = (unsigned int) bchar (src, j + 1); + c2 = (unsigned int) bchar (src, j + 2); + if (bconchar (out, UU_ENCODE_BYTE ( (c0 & 0xFC) >> 2)) < 0 || + bconchar (out, UU_ENCODE_BYTE (((c0 & 0x03) << 4) | ((c1 & 0xF0) >> 4))) < 0 || + bconchar (out, UU_ENCODE_BYTE (((c1 & 0x0F) << 2) | ((c2 & 0xC0) >> 6))) < 0 || + bconchar (out, UU_ENCODE_BYTE ( (c2 & 0x3F))) < 0) { + bstrFree (out); + goto End; + } + } + if (bconchar (out, (char) '\r') < 0 || bconchar (out, (char) '\n') < 0) { + bstrFree (out); + break; + } + } + End:; + return out; +} + +/* bstring bYEncode (const_bstring src) + * + * Performs a YEncode of a block of data. No header or tail info is + * appended. See: http://www.yenc.org/whatis.htm and + * http://www.yenc.org/yenc-draft.1.3.txt + */ +bstring bYEncode (const_bstring src) { +int i; +bstring out; +unsigned char c; + + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + for (i=0; i < src->slen; i++) { + c = (unsigned char)(src->data[i] + 42); + if (c == '=' || c == '\0' || c == '\r' || c == '\n') { + if (0 > bconchar (out, (char) '=')) { + bdestroy (out); + return NULL; + } + c += (unsigned char) 64; + } + if (0 > bconchar (out, c)) { + bdestroy (out); + return NULL; + } + } + return out; +} + +/* bstring bYDecode (const_bstring src) + * + * Performs a YDecode of a block of data. See: + * http://www.yenc.org/whatis.htm and http://www.yenc.org/yenc-draft.1.3.txt + */ +#define MAX_OB_LEN (64) + +bstring bYDecode (const_bstring src) { +int i; +bstring out; +unsigned char c; +unsigned char octetbuff[MAX_OB_LEN]; +int obl; + + if (src == NULL || src->slen < 0 || src->data == NULL) return NULL; + if ((out = bfromcstr ("")) == NULL) return NULL; + + obl = 0; + + for (i=0; i < src->slen; i++) { + if ('=' == (c = src->data[i])) { /* The = escape mode */ + i++; + if (i >= src->slen) { + bdestroy (out); + return NULL; + } + c = (unsigned char) (src->data[i] - 64); + } else { + if ('\0' == c) { + bdestroy (out); + return NULL; + } + + /* Extraneous CR/LFs are to be ignored. */ + if (c == '\r' || c == '\n') continue; + } + + octetbuff[obl] = (unsigned char) ((int) c - 42); + obl++; + + if (obl >= MAX_OB_LEN) { + if (0 > bcatblk (out, octetbuff, obl)) { + bdestroy (out); + return NULL; + } + obl = 0; + } + } + + if (0 > bcatblk (out, octetbuff, obl)) { + bdestroy (out); + out = NULL; + } + return out; +} + +/* bstring bStrfTime (const char * fmt, const struct tm * timeptr) + * + * Takes a format string that is compatible with strftime and a struct tm + * pointer, formats the time according to the format string and outputs + * the bstring as a result. Note that if there is an early generation of a + * '\0' character, the bstring will be truncated to this end point. + */ +bstring bStrfTime (const char * fmt, const struct tm * timeptr) { +#if defined (__TURBOC__) && !defined (__BORLANDC__) +static struct tagbstring ns = bsStatic ("bStrfTime Not supported"); + fmt = fmt; + timeptr = timeptr; + return &ns; +#else +bstring buff; +int n; +size_t r; + + if (fmt == NULL) return NULL; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "strftime" call on increasing + potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < 16) n = 16; + buff = bfromcstralloc (n+2, ""); + + for (;;) { + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return NULL; + } + + r = strftime ((char *) buff->data, n + 1, fmt, timeptr); + + if (r > 0) { + buff->slen = (int) r; + break; + } + + n += n; + } + + return buff; +#endif +} + +/* int bSetCstrChar (bstring a, int pos, char c) + * + * Sets the character at position pos to the character c in the bstring a. + * If the character c is NUL ('\0') then the string is truncated at this + * point. Note: this does not enable any other '\0' character in the bstring + * as terminator indicator for the string. pos must be in the position + * between 0 and b->slen inclusive, otherwise BSTR_ERR will be returned. + */ +int bSetCstrChar (bstring b, int pos, char c) { + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) + return BSTR_ERR; + if (pos < 0 || pos > b->slen) return BSTR_ERR; + + if (pos == b->slen) { + if ('\0' != c) return bconchar (b, c); + return 0; + } + + b->data[pos] = (unsigned char) c; + if ('\0' == c) b->slen = pos; + + return 0; +} + +/* int bSetChar (bstring b, int pos, char c) + * + * Sets the character at position pos to the character c in the bstring a. + * The string is not truncated if the character c is NUL ('\0'). pos must + * be in the position between 0 and b->slen inclusive, otherwise BSTR_ERR + * will be returned. + */ +int bSetChar (bstring b, int pos, char c) { + if (NULL == b || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen) + return BSTR_ERR; + if (pos < 0 || pos > b->slen) return BSTR_ERR; + + if (pos == b->slen) { + return bconchar (b, c); + } + + b->data[pos] = (unsigned char) c; + return 0; +} + +#define INIT_SECURE_INPUT_LENGTH (256) + +/* bstring bSecureInput (int maxlen, int termchar, + * bNgetc vgetchar, void * vgcCtx) + * + * Read input from an abstracted input interface, for a length of at most + * maxlen characters. If maxlen <= 0, then there is no length limit put + * on the input. The result is terminated early if vgetchar() return EOF + * or the user specified value termchar. + * + */ +bstring bSecureInput (int maxlen, int termchar, bNgetc vgetchar, void * vgcCtx) { +int i, m, c; +bstring b, t; + + if (!vgetchar) return NULL; + + b = bfromcstralloc (INIT_SECURE_INPUT_LENGTH, ""); + if ((c = UCHAR_MAX + 1) == termchar) c++; + + for (i=0; ; i++) { + if (termchar == c || (maxlen > 0 && i >= maxlen)) c = EOF; + else c = vgetchar (vgcCtx); + + if (EOF == c) break; + + if (i+1 >= b->mlen) { + + /* Double size, but deal with unusual case of numeric + overflows */ + + if ((m = b->mlen << 1) <= b->mlen && + (m = b->mlen + 1024) <= b->mlen && + (m = b->mlen + 16) <= b->mlen && + (m = b->mlen + 1) <= b->mlen) t = NULL; + else t = bfromcstralloc (m, ""); + + if (t) memcpy (t->data, b->data, i); + bSecureDestroy (b); /* Cleanse previous buffer */ + b = t; + if (!b) return b; + } + + b->data[i] = (unsigned char) c; + } + + b->slen = i; + b->data[i] = (unsigned char) '\0'; + return b; +} + +#define BWS_BUFF_SZ (1024) + +struct bwriteStream { + bstring buff; /* Buffer for underwrites */ + void * parm; /* The stream handle for core stream */ + bNwrite writeFn; /* fwrite work-a-like fnptr for core stream */ + int isEOF; /* track stream's EOF state */ + int minBuffSz; +}; + +/* struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) + * + * Wrap a given open stream (described by a fwrite work-a-like function + * pointer and stream handle) into an open bwriteStream suitable for write + * streaming functions. + */ +struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm) { +struct bwriteStream * ws; + + if (NULL == writeFn) return NULL; + ws = (struct bwriteStream *) malloc (sizeof (struct bwriteStream)); + if (ws) { + if (NULL == (ws->buff = bfromcstr (""))) { + free (ws); + ws = NULL; + } else { + ws->parm = parm; + ws->writeFn = writeFn; + ws->isEOF = 0; + ws->minBuffSz = BWS_BUFF_SZ; + } + } + return ws; +} + +#define internal_bwswriteout(ws,b) { \ + if ((b)->slen > 0) { \ + if (1 != (ws->writeFn ((b)->data, (b)->slen, 1, ws->parm))) { \ + ws->isEOF = 1; \ + return BSTR_ERR; \ + } \ + } \ +} + +/* int bwsWriteFlush (struct bwriteStream * ws) + * + * Force any pending data to be written to the core stream. + */ +int bwsWriteFlush (struct bwriteStream * ws) { + if (NULL == ws || ws->isEOF || 0 >= ws->minBuffSz || + NULL == ws->writeFn || NULL == ws->buff) return BSTR_ERR; + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + return 0; +} + +/* int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) + * + * Send a bstring to a bwriteStream. If the stream is at EOF BSTR_ERR is + * returned. Note that there is no deterministic way to determine the exact + * cut off point where the core stream stopped accepting data. + */ +int bwsWriteBstr (struct bwriteStream * ws, const_bstring b) { +struct tagbstring t; +int l; + + if (NULL == ws || NULL == b || NULL == ws->buff || + ws->isEOF || 0 >= ws->minBuffSz || NULL == ws->writeFn) + return BSTR_ERR; + + /* Buffer prepacking optimization */ + if (b->slen > 0 && ws->buff->mlen - ws->buff->slen > b->slen) { + static struct tagbstring empty = bsStatic (""); + if (0 > bconcat (ws->buff, b)) return BSTR_ERR; + return bwsWriteBstr (ws, &empty); + } + + if (0 > (l = ws->minBuffSz - ws->buff->slen)) { + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + l = ws->minBuffSz; + } + + if (b->slen < l) return bconcat (ws->buff, b); + + if (0 > bcatblk (ws->buff, b->data, l)) return BSTR_ERR; + internal_bwswriteout (ws, ws->buff); + ws->buff->slen = 0; + + bmid2tbstr (t, (bstring) b, l, b->slen); + + if (t.slen >= ws->minBuffSz) { + internal_bwswriteout (ws, &t); + return 0; + } + + return bassign (ws->buff, &t); +} + +/* int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) + * + * Send a block of data a bwriteStream. If the stream is at EOF BSTR_ERR is + * returned. + */ +int bwsWriteBlk (struct bwriteStream * ws, void * blk, int len) { +struct tagbstring t; + if (NULL == blk || len < 0) return BSTR_ERR; + blk2tbstr (t, blk, len); + return bwsWriteBstr (ws, &t); +} + +/* int bwsIsEOF (const struct bwriteStream * ws) + * + * Returns 0 if the stream is currently writable, 1 if the core stream has + * responded by not accepting the previous attempted write. + */ +int bwsIsEOF (const struct bwriteStream * ws) { + if (NULL == ws || NULL == ws->buff || 0 > ws->minBuffSz || + NULL == ws->writeFn) return BSTR_ERR; + return ws->isEOF; +} + +/* int bwsBuffLength (struct bwriteStream * ws, int sz) + * + * Set the length of the buffer used by the bwsStream. If sz is zero, the + * length is not set. This function returns with the previous length. + */ +int bwsBuffLength (struct bwriteStream * ws, int sz) { +int oldSz; + if (ws == NULL || sz < 0) return BSTR_ERR; + oldSz = ws->minBuffSz; + if (sz > 0) ws->minBuffSz = sz; + return oldSz; +} + +/* void * bwsClose (struct bwriteStream * s) + * + * Close the bwriteStream, and return the handle to the stream that was + * originally used to open the given stream. Note that even if the stream + * is at EOF it still needs to be closed with a call to bwsClose. + */ +void * bwsClose (struct bwriteStream * ws) { +void * parm; + if (NULL == ws || NULL == ws->buff || 0 >= ws->minBuffSz || + NULL == ws->writeFn) return NULL; + bwsWriteFlush (ws); + parm = ws->parm; + ws->parm = NULL; + ws->minBuffSz = -1; + ws->writeFn = NULL; + bstrFree (ws->buff); + free (ws); + return parm; +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h new file mode 100644 index 0000000000..e10c6e1a68 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstraux.h @@ -0,0 +1,113 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstraux.h + * + * This file is not a necessary part of the core bstring library itself, but + * is just an auxilliary module which includes miscellaneous or trivial + * functions. + */ + +#ifndef BSTRAUX_INCLUDE +#define BSTRAUX_INCLUDE + +#include <time.h> +#include "bstrlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Safety mechanisms */ +#define bstrDeclare(b) bstring (b) = NULL; +#define bstrFree(b) {if ((b) != NULL && (b)->slen >= 0 && (b)->mlen >= (b)->slen) { bdestroy (b); (b) = NULL; }} + +/* Backward compatibilty with previous versions of Bstrlib */ +#define bAssign(a,b) ((bassign)((a), (b))) +#define bSubs(b,pos,len,a,c) ((breplace)((b),(pos),(len),(a),(unsigned char)(c))) +#define bStrchr(b,c) ((bstrchr)((b), (c))) +#define bStrchrFast(b,c) ((bstrchr)((b), (c))) +#define bCatCstr(b,s) ((bcatcstr)((b), (s))) +#define bCatBlk(b,s,len) ((bcatblk)((b),(s),(len))) +#define bCatStatic(b,s) bCatBlk ((b), ("" s ""), sizeof (s) - 1) +#define bTrunc(b,n) ((btrunc)((b), (n))) +#define bReplaceAll(b,find,repl,pos) ((bfindreplace)((b),(find),(repl),(pos))) +#define bUppercase(b) ((btoupper)(b)) +#define bLowercase(b) ((btolower)(b)) +#define bCaselessCmp(a,b) ((bstricmp)((a), (b))) +#define bCaselessNCmp(a,b,n) ((bstrnicmp)((a), (b), (n))) +#define bBase64Decode(b) (bBase64DecodeEx ((b), NULL)) +#define bUuDecode(b) (bUuDecodeEx ((b), NULL)) + +/* Unusual functions */ +extern struct bStream * bsFromBstr (const_bstring b); +extern bstring bTail (bstring b, int n); +extern bstring bHead (bstring b, int n); +extern int bSetCstrChar (bstring a, int pos, char c); +extern int bSetChar (bstring b, int pos, char c); +extern int bFill (bstring a, char c, int len); +extern int bReplicate (bstring b, int n); +extern int bReverse (bstring b); +extern int bInsertChrs (bstring b, int pos, int len, unsigned char c, unsigned char fill); +extern bstring bStrfTime (const char * fmt, const struct tm * timeptr); +#define bAscTime(t) (bStrfTime ("%c\n", (t))) +#define bCTime(t) ((t) ? bAscTime (localtime (t)) : NULL) + +/* Spacing formatting */ +extern int bJustifyLeft (bstring b, int space); +extern int bJustifyRight (bstring b, int width, int space); +extern int bJustifyMargin (bstring b, int width, int space); +extern int bJustifyCenter (bstring b, int width, int space); + +/* Esoteric standards specific functions */ +extern char * bStr2NetStr (const_bstring b); +extern bstring bNetStr2Bstr (const char * buf); +extern bstring bBase64Encode (const_bstring b); +extern bstring bBase64DecodeEx (const_bstring b, int * boolTruncError); +extern struct bStream * bsUuDecode (struct bStream * sInp, int * badlines); +extern bstring bUuDecodeEx (const_bstring src, int * badlines); +extern bstring bUuEncode (const_bstring src); +extern bstring bYEncode (const_bstring src); +extern bstring bYDecode (const_bstring src); + +/* Writable stream */ +typedef int (* bNwrite) (const void * buf, size_t elsize, size_t nelem, void * parm); + +struct bwriteStream * bwsOpen (bNwrite writeFn, void * parm); +int bwsWriteBstr (struct bwriteStream * stream, const_bstring b); +int bwsWriteBlk (struct bwriteStream * stream, void * blk, int len); +int bwsWriteFlush (struct bwriteStream * stream); +int bwsIsEOF (const struct bwriteStream * stream); +int bwsBuffLength (struct bwriteStream * stream, int sz); +void * bwsClose (struct bwriteStream * stream); + +/* Security functions */ +#define bSecureDestroy(b) { \ +bstring bstr__tmp = (b); \ + if (bstr__tmp && bstr__tmp->mlen > 0 && bstr__tmp->data) { \ + (void) memset (bstr__tmp->data, 0, (size_t) bstr__tmp->mlen); \ + bdestroy (bstr__tmp); \ + } \ +} +#define bSecureWriteProtect(t) { \ + if ((t).mlen >= 0) { \ + if ((t).mlen > (t).slen)) { \ + (void) memset ((t).data + (t).slen, 0, (size_t) (t).mlen - (t).slen); \ + } \ + (t).mlen = -1; \ + } \ +} +extern bstring bSecureInput (int maxlen, int termchar, + bNgetc vgetchar, void * vgcCtx); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c new file mode 100644 index 0000000000..61c8c60ee1 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.c @@ -0,0 +1,2976 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstrlib.c + * + * This file is the core module for implementing the bstring functions. + */ + +#include <stdio.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "bstrlib.h" +#include "../internal_includes/hlslcc_malloc.h" + +/* Optionally include a mechanism for debugging memory */ + +#if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG) +#include "memdbg.h" +#endif + +#ifndef bstr__alloc +#define bstr__alloc(x) malloc (x) +#endif + +#ifndef bstr__free +#define bstr__free(p) free (p) +#endif + +#ifndef bstr__realloc +#define bstr__realloc(p,x) realloc ((p), (x)) +#endif + +#ifndef bstr__memcpy +#define bstr__memcpy(d,s,l) memcpy ((d), (s), (l)) +#endif + +#ifndef bstr__memmove +#define bstr__memmove(d,s,l) memmove ((d), (s), (l)) +#endif + +#ifndef bstr__memset +#define bstr__memset(d,c,l) memset ((d), (c), (l)) +#endif + +#ifndef bstr__memcmp +#define bstr__memcmp(d,c,l) memcmp ((d), (c), (l)) +#endif + +#ifndef bstr__memchr +#define bstr__memchr(s,c,l) memchr ((s), (c), (l)) +#endif + +/* Just a length safe wrapper for memmove. */ + +#define bBlockCopy(D,S,L) { if ((L) > 0) bstr__memmove ((D),(S),(L)); } + +/* Compute the snapped size for a given requested size. By snapping to powers + of 2 like this, repeated reallocations are avoided. */ +static int snapUpSize (int i) { + if (i < 8) { + i = 8; + } else { + unsigned int j; + j = (unsigned int) i; + + j |= (j >> 1); + j |= (j >> 2); + j |= (j >> 4); + j |= (j >> 8); /* Ok, since int >= 16 bits */ +#if (UINT_MAX != 0xffff) + j |= (j >> 16); /* For 32 bit int systems */ +#if (UINT_MAX > 0xffffffffUL) + j |= (j >> 32); /* For 64 bit int systems */ +#endif +#endif + /* Least power of two greater than i */ + j++; + if ((int) j >= i) i = (int) j; + } + return i; +} + +/* int balloc (bstring b, int len) + * + * Increase the size of the memory backing the bstring b to at least len. + */ +int balloc (bstring b, int olen) { + int len; + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen <= 0 || + b->mlen < b->slen || olen <= 0) { + return BSTR_ERR; + } + + if (olen >= b->mlen) { + unsigned char * x; + + if ((len = snapUpSize (olen)) <= b->mlen) return BSTR_OK; + + /* Assume probability of a non-moving realloc is 0.125 */ + if (7 * b->mlen < 8 * b->slen) { + + /* If slen is close to mlen in size then use realloc to reduce + the memory defragmentation */ + + reallocStrategy:; + + x = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (x == NULL) { + + /* Since we failed, try allocating the tighest possible + allocation */ + + if (NULL == (x = (unsigned char *) bstr__realloc (b->data, (size_t) (len = olen)))) { + return BSTR_ERR; + } + } + } else { + + /* If slen is not close to mlen then avoid the penalty of copying + the extra bytes that are allocated, but not considered part of + the string */ + + if (NULL == (x = (unsigned char *) bstr__alloc ((size_t) len))) { + + /* Perhaps there is no available memory for the two + allocations to be in memory at once */ + + goto reallocStrategy; + + } else { + if (b->slen) bstr__memcpy ((char *) x, (char *) b->data, (size_t) b->slen); + bstr__free (b->data); + } + } + b->data = x; + b->mlen = len; + b->data[b->slen] = (unsigned char) '\0'; + } + + return BSTR_OK; +} + +/* int ballocmin (bstring b, int len) + * + * Set the size of the memory backing the bstring b to len or b->slen+1, + * whichever is larger. Note that repeated use of this function can degrade + * performance. + */ +int ballocmin (bstring b, int len) { + unsigned char * s; + + if (b == NULL || b->data == NULL || (b->slen+1) < 0 || b->mlen <= 0 || + b->mlen < b->slen || len <= 0) { + return BSTR_ERR; + } + + if (len < b->slen + 1) len = b->slen + 1; + + if (len != b->mlen) { + s = (unsigned char *) bstr__realloc (b->data, (size_t) len); + if (NULL == s) return BSTR_ERR; + s[b->slen] = (unsigned char) '\0'; + b->data = s; + b->mlen = len; + } + + return BSTR_OK; +} + +/* bstring bfromcstr (const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. + */ +bstring bfromcstr (const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; + b->slen = (int) j; + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring bfromcstralloc (int mlen, const char * str) + * + * Create a bstring which contains the contents of the '\0' terminated char * + * buffer str. The memory buffer backing the string is at least len + * characters in length. + */ +bstring bfromcstralloc (int mlen, const char * str) { +bstring b; +int i; +size_t j; + + if (str == NULL) return NULL; + j = (strlen) (str); + i = snapUpSize ((int) (j + (2 - (j != 0)))); + if (i <= (int) j) return NULL; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = (int) j; + if (i < mlen) i = mlen; + + if (NULL == (b->data = (unsigned char *) bstr__alloc (b->mlen = i))) { + bstr__free (b); + return NULL; + } + + bstr__memcpy (b->data, str, j+1); + return b; +} + +/* bstring blk2bstr (const void * blk, int len) + * + * Create a bstring which contains the content of the block blk of length + * len. + */ +bstring blk2bstr (const void * blk, int len) { +bstring b; +int i; + + if (blk == NULL || len < 0) return NULL; + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b == NULL) return NULL; + b->slen = len; + + i = len + (2 - (len != 0)); + i = snapUpSize (i); + + b->mlen = i; + + b->data = (unsigned char *) bstr__alloc ((size_t) b->mlen); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + if (len > 0) bstr__memcpy (b->data, blk, (size_t) len); + b->data[len] = (unsigned char) '\0'; + + return b; +} + +/* char * bstr2cstr (const_bstring s, char z) + * + * Create a '\0' terminated char * buffer which is equal to the contents of + * the bstring s, except that any contained '\0' characters are converted + * to the character in z. This returned value should be freed with a + * bcstrfree () call, by the calling application. + */ +char * bstr2cstr (const_bstring b, char z) { +int i, l; +char * r; + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + l = b->slen; + r = (char *) bstr__alloc ((size_t) (l + 1)); + if (r == NULL) return r; + + for (i=0; i < l; i ++) { + r[i] = (char) ((b->data[i] == '\0') ? z : (char) (b->data[i])); + } + + r[l] = (unsigned char) '\0'; + + return r; +} + +/* int bcstrfree (char * s) + * + * Frees a C-string generated by bstr2cstr (). This is normally unnecessary + * since it just wraps a call to bstr__free (), however, if bstr__alloc () + * and bstr__free () have been redefined as a macros within the bstrlib + * module (via defining them in memdbg.h after defining + * BSTRLIB_MEMORY_DEBUG) with some difference in behaviour from the std + * library functions, then this allows a correct way of freeing the memory + * that allows higher level code to be independent from these macro + * redefinitions. + */ +int bcstrfree (char * s) { + if (s) { + bstr__free (s); + return BSTR_OK; + } + return BSTR_ERR; +} + +/* int bconcat (bstring b0, const_bstring b1) + * + * Concatenate the bstring b1 to the bstring b0. + */ +int bconcat (bstring b0, const_bstring b1) { +int len, d; +bstring aux = (bstring) b1; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL) return BSTR_ERR; + + d = b0->slen; + len = b1->slen; + if ((d | (b0->mlen - d) | len | (d + len)) < 0) return BSTR_ERR; + + if (b0->mlen <= d + len + 1) { + ptrdiff_t pd = b1->data - b0->data; + if (0 <= pd && pd < b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + if (balloc (b0, d + len + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + } + + bBlockCopy (&b0->data[d], &aux->data[0], (size_t) len); + b0->data[d + len] = (unsigned char) '\0'; + b0->slen = d + len; + if (aux != b1) bdestroy (aux); + return BSTR_OK; +} + +/* int bconchar (bstring b, char c) +/ * + * Concatenate the single character c to the bstring b. + */ +int bconchar (bstring b, char c) { +int d; + + if (b == NULL) return BSTR_ERR; + d = b->slen; + if ((d | (b->mlen - d)) < 0 || balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + b->data[d] = (unsigned char) c; + b->data[d + 1] = (unsigned char) '\0'; + b->slen++; + return BSTR_OK; +} + +/* int bcatcstr (bstring b, const char * s) + * + * Concatenate a char * string to a bstring. + */ +int bcatcstr (bstring b, const char * s) { +char * d; +int i, l; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL) return BSTR_ERR; + + /* Optimistically concatenate directly */ + l = b->mlen - b->slen; + d = (char *) &b->data[b->slen]; + for (i=0; i < l; i++) { + if ((*d++ = *s++) == '\0') { + b->slen += i; + return BSTR_OK; + } + } + b->slen += i; + + /* Need to explicitely resize and concatenate tail */ + return bcatblk (b, (const void *) s, (int) strlen (s)); +} + +/* int bcatblk (bstring b, const void * s, int len) + * + * Concatenate a fixed length buffer to a bstring. + */ +int bcatblk (bstring b, const void * s, int len) { +int nl; + + if (b == NULL || b->data == NULL || b->slen < 0 || b->mlen < b->slen + || b->mlen <= 0 || s == NULL || len < 0) return BSTR_ERR; + + if (0 > (nl = b->slen + len)) return BSTR_ERR; /* Overflow? */ + if (b->mlen <= nl && 0 > balloc (b, nl + 1)) return BSTR_ERR; + + bBlockCopy (&b->data[b->slen], s, (size_t) len); + b->slen = nl; + b->data[nl] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bstrcpy (const_bstring b) + * + * Create a copy of the bstring b. + */ +bstring bstrcpy (const_bstring b) { +bstring b0; +int i,j; + + /* Attempted to copy an invalid string? */ + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + b0 = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (b0 == NULL) { + /* Unable to allocate memory for string header */ + return NULL; + } + + i = b->slen; + j = snapUpSize (i + 1); + + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + j = i + 1; + b0->data = (unsigned char *) bstr__alloc (j); + if (b0->data == NULL) { + /* Unable to allocate memory for string data */ + bstr__free (b0); + return NULL; + } + } + + b0->mlen = j; + b0->slen = i; + + if (i) bstr__memcpy ((char *) b0->data, (char *) b->data, i); + b0->data[b0->slen] = (unsigned char) '\0'; + + return b0; +} + +/* int bassign (bstring a, const_bstring b) + * + * Overwrite the string a with the contents of string b. + */ +int bassign (bstring a, const_bstring b) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + if (b->slen != 0) { + if (balloc (a, b->slen) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data, b->slen); + } else { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + } + a->data[b->slen] = (unsigned char) '\0'; + a->slen = b->slen; + return BSTR_OK; +} + +/* int bassignmidstr (bstring a, const_bstring b, int left, int len) + * + * Overwrite the string a with the middle of contents of string b + * starting from position left and running for a length len. left and + * len are clamped to the ends of b as with the function bmidstr. + */ +int bassignmidstr (bstring a, const_bstring b, int left, int len) { + if (b == NULL || b->data == NULL || b->slen < 0) + return BSTR_ERR; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0) + return BSTR_ERR; + + if (len > 0) { + if (balloc (a, len) != BSTR_OK) return BSTR_ERR; + bstr__memmove (a->data, b->data + left, len); + a->slen = len; + } else { + a->slen = 0; + } + a->data[a->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bassigncstr (bstring a, const char * str) + * + * Overwrite the string a with the contents of char * string str. Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned however a may be partially overwritten. + */ +int bassigncstr (bstring a, const char * str) { +int i; +size_t len; + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == str) + return BSTR_ERR; + + for (i=0; i < a->mlen; i++) { + if ('\0' == (a->data[i] = str[i])) { + a->slen = i; + return BSTR_OK; + } + } + + a->slen = i; + len = strlen (str + i); + if (len > INT_MAX || i + len + 1 > INT_MAX || + 0 > balloc (a, (int) (i + len + 1))) return BSTR_ERR; + bBlockCopy (a->data + i, str + i, (size_t) len + 1); + a->slen += (int) len; + return BSTR_OK; +} + +/* int bassignblk (bstring a, const void * s, int len) + * + * Overwrite the string a with the contents of the block (s, len). Note that + * the bstring a must be a well defined and writable bstring. If an error + * occurs BSTR_ERR is returned and a is not overwritten. + */ +int bassignblk (bstring a, const void * s, int len) { + if (a == NULL || a->data == NULL || a->mlen < a->slen || + a->slen < 0 || a->mlen == 0 || NULL == s || len + 1 < 1) + return BSTR_ERR; + if (len + 1 > a->mlen && 0 > balloc (a, len + 1)) return BSTR_ERR; + bBlockCopy (a->data, s, (size_t) len); + a->data[len] = (unsigned char) '\0'; + a->slen = len; + return BSTR_OK; +} + +/* int btrunc (bstring b, int n) + * + * Truncate the bstring to at most n characters. + */ +int btrunc (bstring b, int n) { + if (n < 0 || b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + if (b->slen > n) { + b->slen = n; + b->data[n] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +#define upcase(c) (toupper ((unsigned char) c)) +#define downcase(c) (tolower ((unsigned char) c)) +#define wspace(c) (isspace ((unsigned char) c)) + +/* int btoupper (bstring b) + * + * Convert contents of bstring to upper case. + */ +int btoupper (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) upcase (b->data[i]); + } + return BSTR_OK; +} + +/* int btolower (bstring b) + * + * Convert contents of bstring to lower case. + */ +int btolower (bstring b) { +int i, len; + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + for (i=0, len = b->slen; i < len; i++) { + b->data[i] = (unsigned char) downcase (b->data[i]); + } + return BSTR_OK; +} + +/* int bstricmp (const_bstring b0, const_bstring b1) + * + * Compare two strings without differentiating between case. The return + * value is the difference of the values of the characters where the two + * strings first differ after lower case transformation, otherwise 0 is + * returned indicating that the strings are equal. If the lengths are + * different, then a difference from 0 is given, but if the first extra + * character is '\0', then it is taken to be the value UCHAR_MAX+1. + */ +int bstricmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return SHRT_MIN; + if ((n = b0->slen) > b1->slen) n = b1->slen; + else if (b0->slen == b1->slen && b0->data == b1->data) return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = (char) downcase (b0->data[i]) + - (char) downcase (b1->data[i]); + if (0 != v) return v; + } + + if (b0->slen > n) { + v = (char) downcase (b0->data[n]); + if (v) return v; + return UCHAR_MAX + 1; + } + if (b1->slen > n) { + v = - (char) downcase (b1->data[n]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); + } + return BSTR_OK; +} + +/* int bstrnicmp (const_bstring b0, const_bstring b1, int n) + * + * Compare two strings without differentiating between case for at most n + * characters. If the position where the two strings first differ is + * before the nth position, the return value is the difference of the values + * of the characters, otherwise 0 is returned. If the lengths are different + * and less than n characters, then a difference from 0 is given, but if the + * first extra character is '\0', then it is taken to be the value + * UCHAR_MAX+1. + */ +int bstrnicmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0 || n < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = (char) downcase (b0->data[i]); + v -= (char) downcase (b1->data[i]); + if (v != 0) return b0->data[i] - b1->data[i]; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) { + v = (char) downcase (b0->data[m]); + if (v) return v; + return UCHAR_MAX + 1; + } + + v = - (char) downcase (b1->data[m]); + if (v) return v; + return - (int) (UCHAR_MAX + 1); +} + +/* int biseqcaseless (const_bstring b0, const_bstring b1) + * + * Compare two strings for equality without differentiating between case. + * If the strings differ other than in case, 0 is returned, if the strings + * are the same, 1 is returned, if there is an error, -1 is returned. If + * the length of the strings are different, this function is O(1). '\0' + * termination characters are not treated in any special way. + */ +int biseqcaseless (const_bstring b0, const_bstring b1) { +int i, n; + + if (bdata (b0) == NULL || b0->slen < 0 || + bdata (b1) == NULL || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + for (i=0, n=b0->slen; i < n; i++) { + if (b0->data[i] != b1->data[i]) { + unsigned char c = (unsigned char) downcase (b0->data[i]); + if (c != (unsigned char) downcase (b1->data[i])) return 0; + } + } + return 1; +} + +/* int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len + * without differentiating between case for equality. If the beginning of b0 + * differs from the memory block other than in case (or if b0 is too short), + * 0 is returned, if the strings are the same, 1 is returned, if there is an + * error, -1 is returned. '\0' characters are not treated in any special + * way. + */ +int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) { + if (downcase (b0->data[i]) != + downcase (((const unsigned char *) blk)[i])) return 0; + } + } + return 1; +} + +/* + * int bltrimws (bstring b) + * + * Delete whitespace contiguous from the left end of the string. + */ +int bltrimws (bstring b) { +int i, len; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (len = b->slen, i = 0; i < len; i++) { + if (!wspace (b->data[i])) { + return bdelete (b, 0, i); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int brtrimws (bstring b) + * + * Delete whitespace contiguous from the right end of the string. + */ +int brtrimws (bstring b) { +int i; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + return BSTR_OK; + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* + * int btrimws (bstring b) + * + * Delete whitespace contiguous from both ends of the string. + */ +int btrimws (bstring b) { +int i, j; + + if (b == NULL || b->data == NULL || b->mlen < b->slen || + b->slen < 0 || b->mlen <= 0) return BSTR_ERR; + + for (i = b->slen - 1; i >= 0; i--) { + if (!wspace (b->data[i])) { + if (b->mlen > i) b->data[i+1] = (unsigned char) '\0'; + b->slen = i + 1; + for (j = 0; wspace (b->data[j]); j++) {} + return bdelete (b, 0, j); + } + } + + b->data[0] = (unsigned char) '\0'; + b->slen = 0; + return BSTR_OK; +} + +/* int biseq (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If the strings differ, 0 is returned, if + * the strings are the same, 1 is returned, if there is an error, -1 is + * returned. If the length of the strings are different, this function is + * O(1). '\0' termination characters are not treated in any special way. + */ +int biseq (const_bstring b0, const_bstring b1) { + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return BSTR_ERR; + if (b0->slen != b1->slen) return BSTR_OK; + if (b0->data == b1->data || b0->slen == 0) return 1; + return !bstr__memcmp (b0->data, b1->data, b0->slen); +} + +/* int bisstemeqblk (const_bstring b0, const void * blk, int len) + * + * Compare beginning of string b0 with a block of memory of length len for + * equality. If the beginning of b0 differs from the memory block (or if b0 + * is too short), 0 is returned, if the strings are the same, 1 is returned, + * if there is an error, -1 is returned. '\0' characters are not treated in + * any special way. + */ +int bisstemeqblk (const_bstring b0, const void * blk, int len) { +int i; + + if (bdata (b0) == NULL || b0->slen < 0 || NULL == blk || len < 0) + return BSTR_ERR; + if (b0->slen < len) return BSTR_OK; + if (b0->data == (const unsigned char *) blk || len == 0) return 1; + + for (i = 0; i < len; i ++) { + if (b0->data[i] != ((const unsigned char *) blk)[i]) return BSTR_OK; + } + return 1; +} + +/* int biseqcstr (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical with the bstring b with no '\0' + * characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal when comparing them in the same format after converting one or the + * other. If the strings are equal 1 is returned, if they are unequal 0 is + * returned and if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstr (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || b->data[i] != (unsigned char) s[i]) return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int biseqcstrcaseless (const_bstring b, const char *s) + * + * Compare the bstring b and char * string s. The C string s must be '\0' + * terminated at exactly the length of the bstring b, and the contents + * between the two must be identical except for case with the bstring b with + * no '\0' characters for the two contents to be considered equal. This is + * equivalent to the condition that their current contents will be always be + * equal ignoring case when comparing them in the same format after + * converting one or the other. If the strings are equal, except for case, + * 1 is returned, if they are unequal regardless of case 0 is returned and + * if there is a detectable error BSTR_ERR is returned. + */ +int biseqcstrcaseless (const_bstring b, const char * s) { +int i; + if (b == NULL || s == NULL || b->data == NULL || b->slen < 0) return BSTR_ERR; + for (i=0; i < b->slen; i++) { + if (s[i] == '\0' || + (b->data[i] != (unsigned char) s[i] && + downcase (b->data[i]) != (unsigned char) downcase (s[i]))) + return BSTR_OK; + } + return s[i] == '\0'; +} + +/* int bstrcmp (const_bstring b0, const_bstring b1) + * + * Compare the string b0 and b1. If there is an error, SHRT_MIN is returned, + * otherwise a value less than or greater than zero, indicating that the + * string pointed to by b0 is lexicographically less than or greater than + * the string pointed to by b1 is returned. If the the string lengths are + * unequal but the characters up until the length of the shorter are equal + * then a value less than, or greater than zero, indicating that the string + * pointed to by b0 is shorter or longer than the string pointed to by b1 is + * returned. 0 is returned if and only if the two strings are the same. If + * the length of the strings are different, this function is O(n). Like its + * standard C library counter part strcmp, the comparison does not proceed + * past any '\0' termination characters encountered. + */ +int bstrcmp (const_bstring b0, const_bstring b1) { +int i, v, n; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + n = b0->slen; if (n > b1->slen) n = b1->slen; + if (b0->slen == b1->slen && (b0->data == b1->data || b0->slen == 0)) + return BSTR_OK; + + for (i = 0; i < n; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + + if (b0->slen > n) return 1; + if (b1->slen > n) return -1; + return BSTR_OK; +} + +/* int bstrncmp (const_bstring b0, const_bstring b1, int n) + * + * Compare the string b0 and b1 for at most n characters. If there is an + * error, SHRT_MIN is returned, otherwise a value is returned as if b0 and + * b1 were first truncated to at most n characters then bstrcmp was called + * with these new strings are paremeters. If the length of the strings are + * different, this function is O(n). Like its standard C library counter + * part strcmp, the comparison does not proceed past any '\0' termination + * characters encountered. + */ +int bstrncmp (const_bstring b0, const_bstring b1, int n) { +int i, v, m; + + if (b0 == NULL || b1 == NULL || b0->data == NULL || b1->data == NULL || + b0->slen < 0 || b1->slen < 0) return SHRT_MIN; + m = n; + if (m > b0->slen) m = b0->slen; + if (m > b1->slen) m = b1->slen; + + if (b0->data != b1->data) { + for (i = 0; i < m; i ++) { + v = ((char) b0->data[i]) - ((char) b1->data[i]); + if (v != 0) return v; + if (b0->data[i] == (unsigned char) '\0') return BSTR_OK; + } + } + + if (n == m || b0->slen == b1->slen) return BSTR_OK; + + if (b0->slen > m) return 1; + return -1; +} + +/* bstring bmidstr (const_bstring b, int left, int len) + * + * Create a bstring which is the substring of b starting from position left + * and running for a length len (clamped by the end of the bstring b.) If + * b is detectably invalid, then NULL is returned. The section described + * by (left, len) is clamped to the boundaries of b. + */ +bstring bmidstr (const_bstring b, int left, int len) { + + if (b == NULL || b->slen < 0 || b->data == NULL) return NULL; + + if (left < 0) { + len += left; + left = 0; + } + + if (len > b->slen - left) len = b->slen - left; + + if (len <= 0) return bfromcstr (""); + return blk2bstr (b->data + left, len); +} + +/* int bdelete (bstring b, int pos, int len) + * + * Removes characters from pos to pos+len-1 inclusive and shifts the tail of + * the bstring starting from pos+len to pos. len must be positive for this + * call to have any effect. The section of the string described by (pos, + * len) is clamped to boundaries of the bstring b. + */ +int bdelete (bstring b, int pos, int len) { + /* Clamp to left side of bstring */ + if (pos < 0) { + len += pos; + pos = 0; + } + + if (len < 0 || b == NULL || b->data == NULL || b->slen < 0 || + b->mlen < b->slen || b->mlen <= 0) + return BSTR_ERR; + if (len > 0 && pos < b->slen) { + if (pos + len >= b->slen) { + b->slen = pos; + } else { + bBlockCopy ((char *) (b->data + pos), + (char *) (b->data + pos + len), + b->slen - (pos+len)); + b->slen -= len; + } + b->data[b->slen] = (unsigned char) '\0'; + } + return BSTR_OK; +} + +/* int bdestroy (bstring b) + * + * Free up the bstring. Note that if b is detectably invalid or not writable + * then no action is performed and BSTR_ERR is returned. Like a freed memory + * allocation, dereferences, writes or any other action on b after it has + * been bdestroyed is undefined. + */ +int bdestroy (bstring b) { + if (b == NULL || b->slen < 0 || b->mlen <= 0 || b->mlen < b->slen || + b->data == NULL) + return BSTR_ERR; + + bstr__free (b->data); + + /* In case there is any stale usage, there is one more chance to + notice this error. */ + + b->slen = -1; + b->mlen = -__LINE__; + b->data = NULL; + + bstr__free (b); + return BSTR_OK; +} + +/* int binstr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstr (const_bstring b1, int pos, const_bstring b2) { +int j, ii, ll, lf; +unsigned char * d0; +unsigned char c0; +register unsigned char * d1; +register unsigned char c1; +register int i; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* No space to find such a string? */ + if ((lf = b1->slen - b2->slen + 1) <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return 0; + + i = pos; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + /* Peel off the b2->slen == 1 case */ + c0 = d0[0]; + if (1 == ll) { + for (;i < lf; i++) if (c0 == d1[i]) return i; + return BSTR_ERR; + } + + c1 = c0; + j = 0; + lf = b1->slen - 1; + + ii = -1; + if (i < lf) do { + /* Unrolled current character test */ + if (c1 != d1[i]) { + if (c1 != d1[1+i]) { + i += 2; + continue; + } + i++; + } + + /* Take note if this is the start of a potential match */ + if (0 == j) ii = i; + + /* Shift the test character down by one */ + j++; + i++; + + /* If this isn't past the last character continue */ + if (j < ll) { + c1 = d0[j]; + continue; + } + + N0:; + + /* If no characters mismatched, then we matched */ + if (i == ii+j) return ii; + + /* Shift back to the beginning */ + i -= j; + j = 0; + c1 = c0; + } while (i < lf); + + /* Deal with last case if unrolling caused a misalignment */ + if (i == lf && ll == j+1 && c1 == d1[i]) goto N0; + + return BSTR_ERR; +} + +/* int binstrr (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward. If it is found then return with the first position where it is + * found, otherwise return BSTR_ERR. Note that this is just a brute force + * string searcher that does not attempt clever things like the Boyer-Moore + * search algorithm. Because of this there are many degenerate cases where + * this can take much longer than it needs to. + */ +int binstrr (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return 0; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j]) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * forward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l, ll; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos) return (b2->slen == 0)?pos:BSTR_ERR; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + l = b1->slen - b2->slen + 1; + + /* No space to find such a string? */ + if (l <= pos) return BSTR_ERR; + + /* An obvious alias case */ + if (b1->data == b2->data && pos == 0) return BSTR_OK; + + i = pos; + j = 0; + + d0 = b2->data; + d1 = b1->data; + ll = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= ll) return i; + } else { + i ++; + if (i >= l) break; + j=0; + } + } + + return BSTR_ERR; +} + +/* int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) + * + * Search for the bstring b2 in b1 starting from position pos, and searching + * backward but without regard to case. If it is found then return with the + * first position where it is found, otherwise return BSTR_ERR. Note that + * this is just a brute force string searcher that does not attempt clever + * things like the Boyer-Moore search algorithm. Because of this there are + * many degenerate cases where this can take much longer than it needs to. + */ +int binstrrcaseless (const_bstring b1, int pos, const_bstring b2) { +int j, i, l; +unsigned char * d0, * d1; + + if (b1 == NULL || b1->data == NULL || b1->slen < 0 || + b2 == NULL || b2->data == NULL || b2->slen < 0) return BSTR_ERR; + if (b1->slen == pos && b2->slen == 0) return pos; + if (b1->slen < pos || pos < 0) return BSTR_ERR; + if (b2->slen == 0) return pos; + + /* Obvious alias case */ + if (b1->data == b2->data && pos == 0 && b2->slen <= b1->slen) return BSTR_OK; + + i = pos; + if ((l = b1->slen - b2->slen) < 0) return BSTR_ERR; + + /* If no space to find such a string then snap back */ + if (l + 1 <= i) i = l; + j = 0; + + d0 = b2->data; + d1 = b1->data; + l = b2->slen; + + for (;;) { + if (d0[j] == d1[i + j] || downcase (d0[j]) == downcase (d1[i + j])) { + j ++; + if (j >= l) return i; + } else { + i --; + if (i < 0) break; + j=0; + } + } + + return BSTR_ERR; +} + + +/* int bstrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b forwards from the position pos + * (inclusive). + */ +int bstrchrp (const_bstring b, int c, int pos) { +unsigned char * p; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + p = (unsigned char *) bstr__memchr ((b->data + pos), (unsigned char) c, (b->slen - pos)); + if (p) return (int) (p - b->data); + return BSTR_ERR; +} + +/* int bstrrchrp (const_bstring b, int c, int pos) + * + * Search for the character c in b backwards from the position pos in string + * (inclusive). + */ +int bstrrchrp (const_bstring b, int c, int pos) { +int i; + + if (b == NULL || b->data == NULL || b->slen <= pos || pos < 0) return BSTR_ERR; + for (i=pos; i >= 0; i--) { + if (b->data[i] == (unsigned char) c) return i; + } + return BSTR_ERR; +} + +#if !defined (BSTRLIB_AGGRESSIVE_MEMORY_FOR_SPEED_TRADEOFF) +#define LONG_LOG_BITS_QTY (3) +#define LONG_BITS_QTY (1 << LONG_LOG_BITS_QTY) +#define LONG_TYPE unsigned char + +#define CFCLEN ((1 << CHAR_BIT) / LONG_BITS_QTY) +struct charField { LONG_TYPE content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(c) >> LONG_LOG_BITS_QTY] & (((long)1) << ((c) & (LONG_BITS_QTY-1)))) +#define setInCharField(cf,idx) { \ + unsigned int c = (unsigned int) (idx); \ + (cf)->content[c >> LONG_LOG_BITS_QTY] |= (LONG_TYPE) (1ul << (c & (LONG_BITS_QTY-1))); \ +} + +#else + +#define CFCLEN (1 << CHAR_BIT) +struct charField { unsigned char content[CFCLEN]; }; +#define testInCharField(cf,c) ((cf)->content[(unsigned char) (c)]) +#define setInCharField(cf,idx) (cf)->content[(unsigned int) (idx)] = ~0 + +#endif + +/* Convert a bstring to charField */ +static int buildCharField (struct charField * cf, const_bstring b) { +int i; + if (b == NULL || b->data == NULL || b->slen <= 0) return BSTR_ERR; + memset ((void *) cf->content, 0, sizeof (struct charField)); + for (i=0; i < b->slen; i++) { + setInCharField (cf, b->data[i]); + } + return BSTR_OK; +} + +static void invertCharField (struct charField * cf) { +int i; + for (i=0; i < CFCLEN; i++) cf->content[i] = ~cf->content[i]; +} + +/* Inner engine for binchr */ +static int binchrCF (const unsigned char * data, int len, int pos, const struct charField * cf) { +int i; + for (i=pos; i < len; i++) { + unsigned char c = (unsigned char) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * one of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int binchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (1 == b1->slen) return bstrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* Inner engine for binchrr */ +static int binchrrCF (const unsigned char * data, int pos, const struct charField * cf) { +int i; + for (i=pos; i >= 0; i--) { + unsigned int c = (unsigned int) data[i]; + if (testInCharField (cf, c)) return i; + } + return BSTR_ERR; +} + +/* int binchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which one of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int binchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || b1 == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (1 == b1->slen) return bstrrchrp (b0, b1->data[0], pos); + if (0 > buildCharField (&chrs, b1)) return BSTR_ERR; + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bninchr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the first position in b0 starting from pos or after, in which + * none of the characters in b1 is found and return it. If such a position + * does not exist in b0, then BSTR_ERR is returned. + */ +int bninchr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen <= pos) return BSTR_ERR; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrCF (b0->data, b0->slen, pos, &chrs); +} + +/* int bninchrr (const_bstring b0, int pos, const_bstring b1); + * + * Search for the last position in b0 no greater than pos, in which none of + * the characters in b1 is found and return it. If such a position does not + * exist in b0, then BSTR_ERR is returned. + */ +int bninchrr (const_bstring b0, int pos, const_bstring b1) { +struct charField chrs; + if (pos < 0 || b0 == NULL || b0->data == NULL || + b0->slen < pos) return BSTR_ERR; + if (pos == b0->slen) pos--; + if (buildCharField (&chrs, b1) < 0) return BSTR_ERR; + invertCharField (&chrs); + return binchrrCF (b0->data, pos, &chrs); +} + +/* int bsetstr (bstring b0, int pos, bstring b1, unsigned char fill) + * + * Overwrite the string b0 starting at position pos with the string b1. If + * the position pos is past the end of b0, then the character "fill" is + * appended as necessary to make up the gap between the end of b0 and pos. + * If b1 is NULL, it behaves as if it were a 0-length string. + */ +int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill) { +int d, newlen; +ptrdiff_t pd; +bstring aux = (bstring) b1; + + if (pos < 0 || b0 == NULL || b0->slen < 0 || NULL == b0->data || + b0->mlen < b0->slen || b0->mlen <= 0) return BSTR_ERR; + if (b1 != NULL && (b1->slen < 0 || b1->data == NULL)) return BSTR_ERR; + + d = pos; + + /* Aliasing case */ + if (NULL != aux) { + if ((pd = (ptrdiff_t) (b1->data - b0->data)) >= 0 && pd < (ptrdiff_t) b0->mlen) { + if (NULL == (aux = bstrcpy (b1))) return BSTR_ERR; + } + d += aux->slen; + } + + /* Increase memory size if necessary */ + if (balloc (b0, d + 1) != BSTR_OK) { + if (aux != b1) bdestroy (aux); + return BSTR_ERR; + } + + newlen = b0->slen; + + /* Fill in "fill" character as necessary */ + if (pos > newlen) { + bstr__memset (b0->data + b0->slen, (int) fill, (size_t) (pos - b0->slen)); + newlen = pos; + } + + /* Copy b1 to position pos in b0. */ + if (aux != NULL) { + bBlockCopy ((char *) (b0->data + pos), (char *) aux->data, aux->slen); + if (aux != b1) bdestroy (aux); + } + + /* Indicate the potentially increased size of b0 */ + if (d > newlen) newlen = d; + + b0->slen = newlen; + b0->data[newlen] = (unsigned char) '\0'; + + return BSTR_OK; +} + +/* int binsert (bstring b1, int pos, bstring b2, unsigned char fill) + * + * Inserts the string b2 into b1 at position pos. If the position pos is + * past the end of b1, then the character "fill" is appended as necessary to + * make up the gap between the end of b1 and pos. Unlike bsetstr, binsert + * does not allow b2 to be NULL. + */ +int binsert (bstring b1, int pos, const_bstring b2, unsigned char fill) { +int d, l; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || b1 == NULL || b2 == NULL || b1->slen < 0 || + b2->slen < 0 || b1->mlen < b1->slen || b1->mlen <= 0) return BSTR_ERR; + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->mlen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + /* Compute the two possible end pointers */ + d = b1->slen + aux->slen; + l = pos + aux->slen; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b1, l + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bstr__memset (b1->data + b1->slen, (int) fill, (size_t) (pos - b1->slen)); + b1->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b1, d + 1) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + bBlockCopy (b1->data + l, b1->data + pos, d - l); + b1->slen = d; + } + bBlockCopy (b1->data + pos, aux->data, aux->slen); + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* int breplace (bstring b1, int pos, int len, bstring b2, + * unsigned char fill) + * + * Replace a section of a string from pos for a length len with the string b2. + * fill is used is pos > b1->slen. + */ +int breplace (bstring b1, int pos, int len, const_bstring b2, + unsigned char fill) { +int pl, ret; +ptrdiff_t pd; +bstring aux = (bstring) b2; + + if (pos < 0 || len < 0 || (pl = pos + len) < 0 || b1 == NULL || + b2 == NULL || b1->data == NULL || b2->data == NULL || + b1->slen < 0 || b2->slen < 0 || b1->mlen < b1->slen || + b1->mlen <= 0) return BSTR_ERR; + + /* Straddles the end? */ + if (pl >= b1->slen) { + if ((ret = bsetstr (b1, pos, b2, fill)) < 0) return ret; + if (pos + b2->slen < b1->slen) { + b1->slen = pos + b2->slen; + b1->data[b1->slen] = (unsigned char) '\0'; + } + return ret; + } + + /* Aliasing case */ + if ((pd = (ptrdiff_t) (b2->data - b1->data)) >= 0 && pd < (ptrdiff_t) b1->slen) { + if (NULL == (aux = bstrcpy (b2))) return BSTR_ERR; + } + + if (aux->slen > len) { + if (balloc (b1, b1->slen + aux->slen - len) != BSTR_OK) { + if (aux != b2) bdestroy (aux); + return BSTR_ERR; + } + } + + if (aux->slen != len) bstr__memmove (b1->data + pos + aux->slen, b1->data + pos + len, b1->slen - (pos + len)); + bstr__memcpy (b1->data + pos, aux->data, aux->slen); + b1->slen += aux->slen - len; + b1->data[b1->slen] = (unsigned char) '\0'; + if (aux != b2) bdestroy (aux); + return BSTR_OK; +} + +/* + * findreplaceengine is used to implement bfindreplace and + * bfindreplacecaseless. It works by breaking the three cases of + * expansion, reduction and replacement, and solving each of these + * in the most efficient way possible. + */ + +typedef int (*instr_fnptr) (const_bstring s1, int pos, const_bstring s2); + +#define INITIAL_STATIC_FIND_INDEX_COUNT 32 + +static int findreplaceengine (bstring b, const_bstring find, const_bstring repl, int pos, instr_fnptr instr) { +int i, ret, slen, mlen, delta, acc; +int * d; +int static_d[INITIAL_STATIC_FIND_INDEX_COUNT+1]; /* This +1 is unnecessary, but it shuts up LINT. */ +ptrdiff_t pd; +bstring auxf = (bstring) find; +bstring auxr = (bstring) repl; + + if (b == NULL || b->data == NULL || find == NULL || + find->data == NULL || repl == NULL || repl->data == NULL || + pos < 0 || find->slen <= 0 || b->mlen < 0 || b->slen > b->mlen || + b->mlen <= 0 || b->slen < 0 || repl->slen < 0) return BSTR_ERR; + if (pos > b->slen - find->slen) return BSTR_OK; + + /* Alias with find string */ + pd = (ptrdiff_t) (find->data - b->data); + if ((ptrdiff_t) (pos - find->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxf = bstrcpy (find))) return BSTR_ERR; + } + + /* Alias with repl string */ + pd = (ptrdiff_t) (repl->data - b->data); + if ((ptrdiff_t) (pos - repl->slen) < pd && pd < (ptrdiff_t) b->slen) { + if (NULL == (auxr = bstrcpy (repl))) { + if (auxf != find) bdestroy (auxf); + return BSTR_ERR; + } + } + + delta = auxf->slen - auxr->slen; + + /* in-place replacement since find and replace strings are of equal + length */ + if (delta == 0) { + while ((pos = instr (b, pos, auxf)) >= 0) { + bstr__memcpy (b->data + pos, auxr->data, auxr->slen); + pos += auxf->slen; + } + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* shrinking replacement since auxf->slen > auxr->slen */ + if (delta > 0) { + acc = 0; + + while ((i = instr (b, pos, auxf)) >= 0) { + if (acc && i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + if (auxr->slen) + bstr__memcpy (b->data + i - acc, auxr->data, auxr->slen); + acc += delta; + pos = i + auxf->slen; + } + + if (acc) { + i = b->slen; + if (i > pos) + bstr__memmove (b->data + pos - acc, b->data + pos, i - pos); + b->slen -= acc; + b->data[b->slen] = (unsigned char) '\0'; + } + + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return BSTR_OK; + } + + /* expanding replacement since find->slen < repl->slen. Its a lot + more complicated. This works by first finding all the matches and + storing them to a growable array, then doing at most one resize of + the destination bstring and then performing the direct memory transfers + of the string segment pieces to form the final result. The growable + array of matches uses a deferred doubling reallocing strategy. What + this means is that it starts as a reasonably fixed sized auto array in + the hopes that many if not most cases will never need to grow this + array. But it switches as soon as the bounds of the array will be + exceeded. An extra find result is always appended to this array that + corresponds to the end of the destination string, so slen is checked + against mlen - 1 rather than mlen before resizing. + */ + + mlen = INITIAL_STATIC_FIND_INDEX_COUNT; + d = (int *) static_d; /* Avoid malloc for trivial/initial cases */ + acc = slen = 0; + + while ((pos = instr (b, pos, auxf)) >= 0) { + if (slen >= mlen - 1) { + int sl, *t; + + mlen += mlen; + sl = sizeof (int *) * mlen; + if (static_d == d) d = NULL; /* static_d cannot be realloced */ + if (mlen <= 0 || sl < mlen || NULL == (t = (int *) bstr__realloc (d, sl))) { + ret = BSTR_ERR; + goto done; + } + if (NULL == d) bstr__memcpy (t, static_d, sizeof (static_d)); + d = t; + } + d[slen] = pos; + slen++; + acc -= delta; + pos += auxf->slen; + if (pos < 0 || acc < 0) { + ret = BSTR_ERR; + goto done; + } + } + + /* slen <= INITIAL_STATIC_INDEX_COUNT-1 or mlen-1 here. */ + d[slen] = b->slen; + + if (BSTR_OK == (ret = balloc (b, b->slen + acc + 1))) { + b->slen += acc; + for (i = slen-1; i >= 0; i--) { + int s, l; + s = d[i] + auxf->slen; + l = d[i+1] - s; /* d[slen] may be accessed here. */ + if (l) { + bstr__memmove (b->data + s + acc, b->data + s, l); + } + if (auxr->slen) { + bstr__memmove (b->data + s + acc - auxr->slen, + auxr->data, auxr->slen); + } + acc += delta; + } + b->data[b->slen] = (unsigned char) '\0'; + } + + done:; + if (static_d == d) d = NULL; + bstr__free (d); + if (auxf != find) bdestroy (auxf); + if (auxr != repl) bdestroy (auxr); + return ret; +} + +/* int bfindreplace (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string with a replace string after a + * given point in a bstring. + */ +int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstr); +} + +/* int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, + * int pos) + * + * Replace all occurrences of a find string, ignoring case, with a replace + * string after a given point in a bstring. + */ +int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos) { + return findreplaceengine (b, find, repl, pos, binstrcaseless); +} + +/* int binsertch (bstring b, int pos, int len, unsigned char fill) + * + * Inserts the character fill repeatedly into b at position pos for a + * length len. If the position pos is past the end of b, then the + * character "fill" is appended as necessary to make up the gap between the + * end of b and the position pos + len. + */ +int binsertch (bstring b, int pos, int len, unsigned char fill) { +int d, l, i; + + if (pos < 0 || b == NULL || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || len < 0) return BSTR_ERR; + + /* Compute the two possible end pointers */ + d = b->slen + len; + l = pos + len; + if ((d|l) < 0) return BSTR_ERR; + + if (l > d) { + /* Inserting past the end of the string */ + if (balloc (b, l + 1) != BSTR_OK) return BSTR_ERR; + pos = b->slen; + b->slen = l; + } else { + /* Inserting in the middle of the string */ + if (balloc (b, d + 1) != BSTR_OK) return BSTR_ERR; + for (i = d - 1; i >= l; i--) { + b->data[i] = b->data[i - len]; + } + b->slen = d; + } + + for (i=pos; i < l; i++) b->data[i] = fill; + b->data[b->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bpattern (bstring b, int len) + * + * Replicate the bstring, b in place, end to end repeatedly until it + * surpasses len characters, then chop the result to exactly len characters. + * This function operates in-place. The function will return with BSTR_ERR + * if b is NULL or of length 0, otherwise BSTR_OK is returned. + */ +int bpattern (bstring b, int len) { +int i, d; + + d = blength (b); + if (d <= 0 || len < 0 || balloc (b, len + 1) != BSTR_OK) return BSTR_ERR; + if (len > 0) { + if (d == 1) return bsetstr (b, len, NULL, b->data[0]); + for (i = d; i < len; i++) b->data[i] = b->data[i - d]; + } + b->data[len] = (unsigned char) '\0'; + b->slen = len; + return BSTR_OK; +} + +#define BS_BUFF_SZ (1024) + +/* int breada (bstring b, bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to concatenate to the + * bstring b the entire contents of file-like source data in a roughly + * efficient way. + */ +int breada (bstring b, bNread readPtr, void * parm) { +int i, l, n; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || readPtr == NULL) return BSTR_ERR; + + i = b->slen; + for (n=i+16; ; n += ((n < BS_BUFF_SZ) ? n : BS_BUFF_SZ)) { + if (BSTR_OK != balloc (b, n + 1)) return BSTR_ERR; + l = (int) readPtr ((void *) (b->data + i), 1, n - i, parm); + i += l; + b->slen = i; + if (i < n) break; + } + + b->data[i] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* bstring bread (bNread readPtr, void * parm) + * + * Use a finite buffer fread-like function readPtr to create a bstring + * filled with the entire contents of file-like source data in a roughly + * efficient way. + */ +bstring bread (bNread readPtr, void * parm) { +bstring buff; + + if (0 > breada (buff = bfromcstr (""), readPtr, parm)) { + bdestroy (buff); + return NULL; + } + return buff; +} + +/* int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result in b. If there is an empty partial + * result, 1 is returned. If no characters are read, or there is some other + * detectable error, BSTR_ERR is returned. + */ +int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = 0; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated to the end of the + * bstring b. The stream read is terminated by the passed in terminator + * parameter. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * function returns with a partial result concatentated to b. If there is + * an empty partial result, 1 is returned. If no characters are read, or + * there is some other detectable error, BSTR_ERR is returned. + */ +int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator) { +int c, d, e; + + if (b == NULL || b->mlen <= 0 || b->slen < 0 || b->mlen < b->slen || + b->mlen <= 0 || getcPtr == NULL) return BSTR_ERR; + d = b->slen; + e = b->mlen - 2; + + while ((c = getcPtr (parm)) >= 0) { + if (d > e) { + b->slen = d; + if (balloc (b, d + 2) != BSTR_OK) return BSTR_ERR; + e = b->mlen - 2; + } + b->data[d] = (unsigned char) c; + d++; + if (c == terminator) break; + } + + b->data[d] = (unsigned char) '\0'; + b->slen = d; + + return d == 0 && c < 0; +} + +/* bstring bgets (bNgetc getcPtr, void * parm, char terminator) + * + * Use an fgetc-like single character stream reading function (getcPtr) to + * obtain a sequence of characters which are concatenated into a bstring. + * The stream read is terminated by the passed in terminator function. + * + * If getcPtr returns with a negative number, or the terminator character + * (which is appended) is read, then the stream reading is halted and the + * result obtained thus far is returned. If no characters are read, or + * there is some other detectable error, NULL is returned. + */ +bstring bgets (bNgetc getcPtr, void * parm, char terminator) { +bstring buff; + + if (0 > bgetsa (buff = bfromcstr (""), getcPtr, parm, terminator) || 0 >= buff->slen) { + bdestroy (buff); + buff = NULL; + } + return buff; +} + +struct bStream { + bstring buff; /* Buffer for over-reads */ + void * parm; /* The stream handle for core stream */ + bNread readFnPtr; /* fread compatible fnptr for core stream */ + int isEOF; /* track file's EOF state */ + int maxBuffSz; +}; + +/* struct bStream * bsopen (bNread readPtr, void * parm) + * + * Wrap a given open stream (described by a fread compatible function + * pointer and stream handle) into an open bStream suitable for the bstring + * library streaming functions. + */ +struct bStream * bsopen (bNread readPtr, void * parm) { +struct bStream * s; + + if (readPtr == NULL) return NULL; + s = (struct bStream *) bstr__alloc (sizeof (struct bStream)); + if (s == NULL) return NULL; + s->parm = parm; + s->buff = bfromcstr (""); + s->readFnPtr = readPtr; + s->maxBuffSz = BS_BUFF_SZ; + s->isEOF = 0; + return s; +} + +/* int bsbufflength (struct bStream * s, int sz) + * + * Set the length of the buffer used by the bStream. If sz is zero, the + * length is not set. This function returns with the previous length. + */ +int bsbufflength (struct bStream * s, int sz) { +int oldSz; + if (s == NULL || sz < 0) return BSTR_ERR; + oldSz = s->maxBuffSz; + if (sz > 0) s->maxBuffSz = sz; + return oldSz; +} + +int bseof (const struct bStream * s) { + if (s == NULL || s->readFnPtr == NULL) return BSTR_ERR; + return s->isEOF && (s->buff->slen == 0); +} + +/* void * bsclose (struct bStream * s) + * + * Close the bStream, and return the handle to the stream that was originally + * used to open the given stream. + */ +void * bsclose (struct bStream * s) { +void * parm; + if (s == NULL) return NULL; + s->readFnPtr = NULL; + if (s->buff) bdestroy (s->buff); + s->buff = NULL; + parm = s->parm; + s->parm = NULL; + s->isEOF = 1; + bstr__free (s); + return parm; +} + +/* int bsreadlna (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadlna (bstring r, struct bStream * s, char terminator) { +int i, l, ret, rlo; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 || + r->slen < 0 || r->mlen < r->slen) return BSTR_ERR; + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + /* First check if the current buffer holds the terminator */ + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + b[l] = terminator; /* Set sentinel */ + for (i=0; b[i] != terminator; i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreadlnsa (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlnsa (bstring r, struct bStream * s, const_bstring term) { +int i, l, ret, rlo; +unsigned char * b; +struct tagbstring x; +struct charField cf; + + if (s == NULL || s->buff == NULL || r == NULL || term == NULL || + term->data == NULL || r->mlen <= 0 || r->slen < 0 || + r->mlen < r->slen) return BSTR_ERR; + if (term->slen == 1) return bsreadlna (r, s, term->data[0]); + if (term->slen < 1 || buildCharField (&cf, term)) return BSTR_ERR; + + l = s->buff->slen; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) s->buff->data; + x.data = b; + + /* First check if the current buffer holds the terminator */ + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) { + x.slen = i + 1; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, i + 1); + return BSTR_OK; + } + + rlo = r->slen; + + /* If not then just concatenate the entire buffer to the output */ + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) return BSTR_ERR; + + /* Perform direct in-place reads into the destination to allow for + the minimum of data-copies */ + for (;;) { + if (BSTR_OK != balloc (r, r->slen + s->maxBuffSz + 1)) return BSTR_ERR; + b = (unsigned char *) (r->data + r->slen); + l = (int) s->readFnPtr (b, 1, s->maxBuffSz, s->parm); + if (l <= 0) { + r->data[r->slen] = (unsigned char) '\0'; + s->buff->slen = 0; + s->isEOF = 1; + /* If nothing was read return with an error message */ + return BSTR_ERR & -(r->slen == rlo); + } + + b[l] = term->data[0]; /* Set sentinel */ + for (i=0; !testInCharField (&cf, b[i]); i++) ; + if (i < l) break; + r->slen += l; + } + + /* Terminator found, push over-read back to buffer */ + i++; + r->slen += i; + s->buff->slen = l - i; + bstr__memcpy (s->buff->data, b + i, l - i); + r->data[r->slen] = (unsigned char) '\0'; + return BSTR_OK; +} + +/* int bsreada (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsreada (bstring r, struct bStream * s, int n) { +int l, ret, orslen; +char * b; +struct tagbstring x; + + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || r->slen < 0 || r->mlen < r->slen || n <= 0) return BSTR_ERR; + + n += r->slen; + if (n <= 0) return BSTR_ERR; + + l = s->buff->slen; + + orslen = r->slen; + + if (0 == l) { + if (s->isEOF) return BSTR_ERR; + if (r->mlen > n) { + l = (int) s->readFnPtr (r->data + r->slen, 1, n - r->slen, s->parm); + if (0 >= l || l > n - r->slen) { + s->isEOF = 1; + return BSTR_ERR; + } + r->slen += l; + r->data[r->slen] = (unsigned char) '\0'; + return 0; + } + } + + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + b = (char *) s->buff->data; + x.data = (unsigned char *) b; + + do { + if (l + r->slen >= n) { + x.slen = n - r->slen; + ret = bconcat (r, &x); + s->buff->slen = l; + if (BSTR_OK == ret) bdelete (s->buff, 0, x.slen); + return BSTR_ERR & -(r->slen == orslen); + } + + x.slen = l; + if (BSTR_OK != bconcat (r, &x)) break; + + l = n - r->slen; + if (l > s->maxBuffSz) l = s->maxBuffSz; + + l = (int) s->readFnPtr (b, 1, l, s->parm); + + } while (l > 0); + if (l < 0) l = 0; + if (l == 0) s->isEOF = 1; + s->buff->slen = l; + return BSTR_ERR & -(r->slen == orslen); +} + +/* int bsreadln (bstring r, struct bStream * s, char terminator) + * + * Read a bstring terminated by the terminator character or the end of the + * stream from the bStream (s) and return it into the parameter r. This + * function may read additional characters from the core stream that are not + * returned, but will be retained for subsequent read operations. + */ +int bsreadln (bstring r, struct bStream * s, char terminator) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0) + return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlna (r, s, terminator); +} + +/* int bsreadlns (bstring r, struct bStream * s, bstring term) + * + * Read a bstring terminated by any character in the term string or the end + * of the stream from the bStream (s) and return it into the parameter r. + * This function may read additional characters from the core stream that + * are not returned, but will be retained for subsequent read operations. + */ +int bsreadlns (bstring r, struct bStream * s, const_bstring term) { + if (s == NULL || s->buff == NULL || r == NULL || term == NULL + || term->data == NULL || r->mlen <= 0) return BSTR_ERR; + if (term->slen == 1) return bsreadln (r, s, term->data[0]); + if (term->slen < 1) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreadlnsa (r, s, term); +} + +/* int bsread (bstring r, struct bStream * s, int n) + * + * Read a bstring of length n (or, if it is fewer, as many bytes as is + * remaining) from the bStream. This function may read additional + * characters from the core stream that are not returned, but will be + * retained for subsequent read operations. This function will not read + * additional characters from the core stream beyond virtual stream pointer. + */ +int bsread (bstring r, struct bStream * s, int n) { + if (s == NULL || s->buff == NULL || r == NULL || r->mlen <= 0 + || n <= 0) return BSTR_ERR; + if (BSTR_OK != balloc (s->buff, s->maxBuffSz + 1)) return BSTR_ERR; + r->slen = 0; + return bsreada (r, s, n); +} + +/* int bsunread (struct bStream * s, const_bstring b) + * + * Insert a bstring into the bStream at the current position. These + * characters will be read prior to those that actually come from the core + * stream. + */ +int bsunread (struct bStream * s, const_bstring b) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return binsert (s->buff, 0, b, (unsigned char) '?'); +} + +/* int bspeek (bstring r, const struct bStream * s) + * + * Return the currently buffered characters from the bStream that will be + * read prior to reads from the core stream. + */ +int bspeek (bstring r, const struct bStream * s) { + if (s == NULL || s->buff == NULL) return BSTR_ERR; + return bassign (r, s->buff); +} + +/* bstring bjoin (const struct bstrList * bl, const_bstring sep); + * + * Join the entries of a bstrList into one bstring by sequentially + * concatenating them with the sep string in between. If there is an error + * NULL is returned, otherwise a bstring with the correct result is returned. + */ +bstring bjoin (const struct bstrList * bl, const_bstring sep) { +bstring b; +int i, c, v; + + if (bl == NULL || bl->qty < 0) return NULL; + if (sep != NULL && (sep->slen < 0 || sep->data == NULL)) return NULL; + + for (i = 0, c = 1; i < bl->qty; i++) { + v = bl->entry[i]->slen; + if (v < 0) return NULL; /* Invalid input */ + c += v; + if (c < 0) return NULL; /* Wrap around ?? */ + } + + if (sep != NULL) c += (bl->qty - 1) * sep->slen; + + b = (bstring) bstr__alloc (sizeof (struct tagbstring)); + if (NULL == b) return NULL; /* Out of memory */ + b->data = (unsigned char *) bstr__alloc (c); + if (b->data == NULL) { + bstr__free (b); + return NULL; + } + + b->mlen = c; + b->slen = c-1; + + for (i = 0, c = 0; i < bl->qty; i++) { + if (i > 0 && sep != NULL) { + bstr__memcpy (b->data + c, sep->data, sep->slen); + c += sep->slen; + } + v = bl->entry[i]->slen; + bstr__memcpy (b->data + c, bl->entry[i]->data, v); + c += v; + } + b->data[c] = (unsigned char) '\0'; + return b; +} + +#define BSSSC_BUFF_LEN (256) + +/* int bssplitscb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by any of the characters in splitStr. An empty splitStr causes + * the whole stream to be iterated once. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +struct charField chrs; +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + while (bsreada (buff, s, BSSSC_BUFF_LEN) >= 0) ; + if ((ret = cb (parm, 0, buff)) > 0) + ret = 0; + } else { + buildCharField (&chrs, splitStr); + ret = p = i = 0; + for (;;) { + if (i >= buff->slen) { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (i >= buff->slen) { + if (0 < (ret = cb (parm, p, buff))) ret = 0; + break; + } + } + if (testInCharField (&chrs, buff->data[i])) { + struct tagbstring t; + unsigned char c; + + blk2tbstr (t, buff->data + i + 1, buff->slen - (i + 1)); + if ((ret = bsunread (s, &t)) < 0) break; + buff->slen = i; + c = buff->data[i]; + buff->data[i] = (unsigned char) '\0'; + if ((ret = cb (parm, p, buff)) < 0) break; + buff->data[i] = c; + buff->slen = 0; + p += i + 1; + i = -1; + } + i++; + } + } + + bdestroy (buff); + return ret; +} + +/* int bssplitstrcb (struct bStream * s, const_bstring splitStr, + * int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) + * + * Iterate the set of disjoint sequential substrings read from a stream + * divided by the entire substring splitStr. An empty splitStr causes + * each character of the stream to be iterated. + * + * Note: At the point of calling the cb function, the bStream pointer is + * pointed exactly at the position right after having read the split + * character. The cb function can act on the stream by causing the bStream + * pointer to move, and bssplitscb will continue by starting the next split + * at the position of the pointer after the return from cb. + * + * However, if the cb causes the bStream s to be destroyed then the cb must + * return with a negative value, otherwise bssplitscb will continue in an + * undefined manner. + */ +int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm) { +bstring buff; +int i, p, ret; + + if (cb == NULL || s == NULL || s->readFnPtr == NULL + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (splitStr->slen == 1) return bssplitscb (s, splitStr, cb, parm); + + if (NULL == (buff = bfromcstr (""))) return BSTR_ERR; + + if (splitStr->slen == 0) { + for (i=0; bsreada (buff, s, BSSSC_BUFF_LEN) >= 0; i++) { + if ((ret = cb (parm, 0, buff)) < 0) { + bdestroy (buff); + return ret; + } + buff->slen = 0; + } + return BSTR_OK; + } else { + ret = p = i = 0; + for (i=p=0;;) { + if ((ret = binstr (buff, 0, splitStr)) >= 0) { + struct tagbstring t; + blk2tbstr (t, buff->data, ret); + i = ret + splitStr->slen; + if ((ret = cb (parm, p, &t)) < 0) break; + p += i; + bdelete (buff, 0, i); + } else { + bsreada (buff, s, BSSSC_BUFF_LEN); + if (bseof (s)) { + if ((ret = cb (parm, p, buff)) > 0) ret = 0; + break; + } + } + } + } + + bdestroy (buff); + return ret; +} + +/* int bstrListCreate (void) + * + * Create a bstrList. + */ +struct bstrList * bstrListCreate (void) { +struct bstrList * sl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (sl) { + sl->entry = (bstring *) bstr__alloc (1*sizeof (bstring)); + if (!sl->entry) { + bstr__free (sl); + sl = NULL; + } else { + sl->qty = 0; + sl->mlen = 1; + } + } + return sl; +} + +/* int bstrListDestroy (struct bstrList * sl) + * + * Destroy a bstrList that has been created by bsplit, bsplits or bstrListCreate. + */ +int bstrListDestroy (struct bstrList * sl) { +int i; + if (sl == NULL || sl->qty < 0) return BSTR_ERR; + for (i=0; i < sl->qty; i++) { + if (sl->entry[i]) { + bdestroy (sl->entry[i]); + sl->entry[i] = NULL; + } + } + sl->qty = -1; + sl->mlen = -1; + bstr__free (sl->entry); + sl->entry = NULL; + bstr__free (sl); + return BSTR_OK; +} + +/* int bstrListAlloc (struct bstrList * sl, int msz) + * + * Ensure that there is memory for at least msz number of entries for the + * list. + */ +int bstrListAlloc (struct bstrList * sl, int msz) { +bstring * l; +int smsz; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (sl->mlen >= msz) return BSTR_OK; + smsz = snapUpSize (msz); + nsz = ((size_t) smsz) * sizeof (bstring); + if (nsz < (size_t) smsz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) { + smsz = msz; + nsz = ((size_t) smsz) * sizeof (bstring); + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + } + sl->mlen = smsz; + sl->entry = l; + return BSTR_OK; +} + +/* int bstrListAllocMin (struct bstrList * sl, int msz) + * + * Try to allocate the minimum amount of memory for the list to include at + * least msz entries or sl->qty whichever is greater. + */ +int bstrListAllocMin (struct bstrList * sl, int msz) { +bstring * l; +size_t nsz; + if (!sl || msz <= 0 || !sl->entry || sl->qty < 0 || sl->mlen <= 0 || sl->qty > sl->mlen) return BSTR_ERR; + if (msz < sl->qty) msz = sl->qty; + if (sl->mlen == msz) return BSTR_OK; + nsz = ((size_t) msz) * sizeof (bstring); + if (nsz < (size_t) msz) return BSTR_ERR; + l = (bstring *) bstr__realloc (sl->entry, nsz); + if (!l) return BSTR_ERR; + sl->mlen = msz; + sl->entry = l; + return BSTR_OK; +} + +/* int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * character in splitChar. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitcb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitcb will continue in an undefined manner. + */ +int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen) + return BSTR_ERR; + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (str->data[i] == splitChar) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by any + * of the characters in splitStr. An empty splitStr causes the whole str to + * be iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitscb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +struct charField chrs; +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + if (splitStr->slen == 0) { + if ((ret = cb (parm, 0, str->slen)) > 0) ret = 0; + return ret; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + buildCharField (&chrs, splitStr); + + p = pos; + do { + for (i=p; i < str->slen; i++) { + if (testInCharField (&chrs, str->data[i])) break; + } + if ((ret = cb (parm, p, i - p)) < 0) return ret; + p = i + 1; + } while (p <= str->slen); + return BSTR_OK; +} + +/* int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + * int (* cb) (void * parm, int ofs, int len), void * parm) + * + * Iterate the set of disjoint sequential substrings over str divided by the + * substring splitStr. An empty splitStr causes the whole str to be + * iterated once. + * + * Note: Non-destructive modification of str from within the cb function + * while performing this split is not undefined. bsplitstrcb behaves in + * sequential lock step with calls to cb. I.e., after returning from a cb + * that return a non-negative integer, bsplitscb continues from the position + * 1 character after the last detected split character and it will halt + * immediately if the length of str falls below this point. However, if the + * cb function destroys str, then it *must* return with a negative value, + * otherwise bsplitscb will continue in an undefined manner. + */ +int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm) { +int i, p, ret; + + if (cb == NULL || str == NULL || pos < 0 || pos > str->slen + || splitStr == NULL || splitStr->slen < 0) return BSTR_ERR; + + if (0 == splitStr->slen) { + for (i=pos; i < str->slen; i++) { + if ((ret = cb (parm, i, 1)) < 0) return ret; + } + return BSTR_OK; + } + + if (splitStr->slen == 1) + return bsplitcb (str, splitStr->data[0], pos, cb, parm); + + for (i=p=pos; i <= str->slen - splitStr->slen; i++) { + if (0 == bstr__memcmp (splitStr->data, str->data + i, splitStr->slen)) { + if ((ret = cb (parm, p, i - p)) < 0) return ret; + i += splitStr->slen; + p = i; + } + } + if ((ret = cb (parm, p, str->slen - p)) < 0) return ret; + return BSTR_OK; +} + +struct genBstrList { + bstring b; + struct bstrList * bl; +}; + +static int bscb (void * parm, int ofs, int len) { +struct genBstrList * g = (struct genBstrList *) parm; + if (g->bl->qty >= g->bl->mlen) { + int mlen = g->bl->mlen * 2; + bstring * tbl; + + while (g->bl->qty >= mlen) { + if (mlen < g->bl->mlen) return BSTR_ERR; + mlen += mlen; + } + + tbl = (bstring *) bstr__realloc (g->bl->entry, sizeof (bstring) * mlen); + if (tbl == NULL) return BSTR_ERR; + + g->bl->entry = tbl; + g->bl->mlen = mlen; + } + + g->bl->entry[g->bl->qty] = bmidstr (g->b, ofs, len); + g->bl->qty++; + return BSTR_OK; +} + +/* struct bstrList * bsplit (const_bstring str, unsigned char splitChar) + * + * Create an array of sequential substrings from str divided by the character + * splitChar. + */ +struct bstrList * bsplit (const_bstring str, unsigned char splitChar) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitcb (str, splitChar, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) + * + * Create an array of sequential substrings from str divided by the entire + * substring splitStr. + */ +struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if (str == NULL || str->data == NULL || str->slen < 0) return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + + g.b = (bstring) str; + g.bl->qty = 0; + if (bsplitstrcb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +/* struct bstrList * bsplits (const_bstring str, bstring splitStr) + * + * Create an array of sequential substrings from str divided by any of the + * characters in splitStr. An empty splitStr causes a single entry bstrList + * containing a copy of str to be returned. + */ +struct bstrList * bsplits (const_bstring str, const_bstring splitStr) { +struct genBstrList g; + + if ( str == NULL || str->slen < 0 || str->data == NULL || + splitStr == NULL || splitStr->slen < 0 || splitStr->data == NULL) + return NULL; + + g.bl = (struct bstrList *) bstr__alloc (sizeof (struct bstrList)); + if (g.bl == NULL) return NULL; + g.bl->mlen = 4; + g.bl->entry = (bstring *) bstr__alloc (g.bl->mlen * sizeof (bstring)); + if (NULL == g.bl->entry) { + bstr__free (g.bl); + return NULL; + } + g.b = (bstring) str; + g.bl->qty = 0; + + if (bsplitscb (str, splitStr, 0, bscb, &g) < 0) { + bstrListDestroy (g.bl); + return NULL; + } + return g.bl; +} + +#if defined (__TURBOC__) && !defined (__BORLANDC__) +# ifndef BSTRLIB_NOVSNP +# define BSTRLIB_NOVSNP +# endif +#endif + +/* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */ +#if defined(__WATCOMC__) || defined(_MSC_VER) +#define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);} +#else +#ifdef BSTRLIB_NOVSNP +/* This is just a hack. If you are using a system without a vsnprintf, it is + not recommended that bformat be used at all. */ +#define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;} +#define START_VSNBUFF (256) +#else + +#ifdef __GNUC__ +/* Something is making gcc complain about this prototype not being here, so + I've just gone ahead and put it in. */ +//extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg); +#endif + +#define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);} +#endif +#endif + +#if !defined (BSTRLIB_NOVSNP) + +#ifndef START_VSNBUFF +#define START_VSNBUFF (16) +#endif + +/* On IRIX vsnprintf returns n-1 when the operation would overflow the target + buffer, WATCOM and MSVC both return -1, while C99 requires that the + returned value be exactly what the length would be if the buffer would be + large enough. This leads to the idea that if the return value is larger + than n, then changing n to the return value will reduce the number of + iterations required. */ + +/* int bformata (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it appends the results to + * a bstring which contains what would have been output. Note that if there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bformata (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bconcat (b, buff); + bdestroy (buff); + return r; +} + +/* int bassignformat (bstring b, const char * fmt, ...) + * + * After the first parameter, it takes the same parameters as printf (), but + * rather than outputting results to stdio, it outputs the results to + * the bstring parameter b. Note that if there is an early generation of a + * '\0' character, the bstring will be truncated to this end point. + */ +int bassignformat (bstring b, const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (b == NULL || fmt == NULL || b->data == NULL || b->mlen <= 0 + || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return BSTR_ERR; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return BSTR_ERR; + } + } + + r = bassign (b, buff); + bdestroy (buff); + return r; +} + +/* bstring bformat (const char * fmt, ...) + * + * Takes the same parameters as printf (), but rather than outputting results + * to stdio, it forms a bstring which contains what would have been output. + * Note that if there is an early generation of a '\0' character, the + * bstring will be truncated to this end point. + */ +bstring bformat (const char * fmt, ...) { +va_list arglist; +bstring buff; +int n, r; + + if (fmt == NULL) return NULL; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int) (2*strlen (fmt))) < START_VSNBUFF) n = START_VSNBUFF; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) { + n = 1; + if (NULL == (buff = bfromcstralloc (n + 2, ""))) return NULL; + } + + for (;;) { + va_start (arglist, fmt); + exvsnprintf (r, (char *) buff->data, n + 1, fmt, arglist); + va_end (arglist); + + buff->data[n] = (unsigned char) '\0'; + buff->slen = (int) (strlen) ((char *) buff->data); + + if (buff->slen < n) break; + + if (r > n) n = r; else n += n; + + if (BSTR_OK != balloc (buff, n + 2)) { + bdestroy (buff); + return NULL; + } + } + + return buff; +} + +/* int bvcformata (bstring b, int count, const char * fmt, va_list arglist) + * + * The bvcformata function formats data under control of the format control + * string fmt and attempts to append the result to b. The fmt parameter is + * the same as that of the printf function. The variable argument list is + * replaced with arglist, which has been initialized by the va_start macro. + * The size of the appended output is upper bounded by count. If the + * required output exceeds count, the string b is not augmented with any + * contents and a value below BSTR_ERR is returned. If a value below -count + * is returned then it is recommended that the negative of this value be + * used as an update to the count in a subsequent pass. On other errors, + * such as running out of memory, parameter errors or numeric wrap around + * BSTR_ERR is returned. BSTR_OK is returned when the output is successfully + * generated and appended to b. + * + * Note: There is no sanity checking of arglist, and this function is + * destructive of the contents of b from the b->slen point onward. If there + * is an early generation of a '\0' character, the bstring will be truncated + * to this end point. + */ +int bvcformata (bstring b, int count, const char * fmt, va_list arg) { +int n, r, l; + + if (b == NULL || fmt == NULL || count <= 0 || b->data == NULL + || b->mlen <= 0 || b->slen < 0 || b->slen > b->mlen) return BSTR_ERR; + + if (count > (n = b->slen + count) + 2) return BSTR_ERR; + if (BSTR_OK != balloc (b, n + 2)) return BSTR_ERR; + + exvsnprintf (r, (char *) b->data + b->slen, count + 2, fmt, arg); + + /* Did the operation complete successfully within bounds? */ + for (l = b->slen; l <= n; l++) { + if ('\0' == b->data[l]) { + b->slen = l; + return BSTR_OK; + } + } + + /* Abort, since the buffer was not large enough. The return value + tries to help set what the retry length should be. */ + + b->data[b->slen] = '\0'; + if (r > count + 1) { /* Does r specify a particular target length? */ + n = r; + } else { + n = count + count; /* If not, just double the size of count */ + if (count > n) n = INT_MAX; + } + n = -n; + + if (n > BSTR_ERR-1) n = BSTR_ERR-1; + return n; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h new file mode 100644 index 0000000000..edf8c00fc6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.h @@ -0,0 +1,305 @@ +/* + * This source file is part of the bstring string library. This code was + * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause + * BSD open source license or GPL v2.0. Refer to the accompanying documentation + * for details on usage and license. + */ +// Modifications copyright Amazon.com, Inc. or its affiliates + +/* + * bstrlib.h + * + * This file is the header file for the core module for implementing the + * bstring functions. + */ + +#ifndef BSTRLIB_INCLUDE +#define BSTRLIB_INCLUDE + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdarg.h> +#include <string.h> +#include <limits.h> +#include <ctype.h> + +#if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) +# if defined (__TURBOC__) && !defined (__BORLANDC__) +# define BSTRLIB_NOVSNP +# endif +#endif + +#define BSTR_ERR (-1) +#define BSTR_OK (0) +#define BSTR_BS_BUFF_LENGTH_GET (0) + +typedef struct tagbstring * bstring; +typedef const struct tagbstring * const_bstring; + +/* Copy functions */ +#define cstr2bstr bfromcstr +extern bstring bfromcstr (const char * str); +extern bstring bfromcstralloc (int mlen, const char * str); +extern bstring blk2bstr (const void * blk, int len); +extern char * bstr2cstr (const_bstring s, char z); +extern int bcstrfree (char * s); +extern bstring bstrcpy (const_bstring b1); +extern int bassign (bstring a, const_bstring b); +extern int bassignmidstr (bstring a, const_bstring b, int left, int len); +extern int bassigncstr (bstring a, const char * str); +extern int bassignblk (bstring a, const void * s, int len); + +/* Destroy function */ +extern int bdestroy (bstring b); + +/* Space allocation hinting functions */ +extern int balloc (bstring s, int len); +extern int ballocmin (bstring b, int len); + +/* Substring extraction */ +extern bstring bmidstr (const_bstring b, int left, int len); + +/* Various standard manipulations */ +extern int bconcat (bstring b0, const_bstring b1); +extern int bconchar (bstring b0, char c); +extern int bcatcstr (bstring b, const char * s); +extern int bcatblk (bstring b, const void * s, int len); +extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); +extern int binsertch (bstring s1, int pos, int len, unsigned char fill); +extern int breplace (bstring b1, int pos, int len, const_bstring b2, unsigned char fill); +extern int bdelete (bstring s1, int pos, int len); +extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); +extern int btrunc (bstring b, int n); + +/* Scan/search functions */ +extern int bstricmp (const_bstring b0, const_bstring b1); +extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); +extern int biseqcaseless (const_bstring b0, const_bstring b1); +extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); +extern int biseq (const_bstring b0, const_bstring b1); +extern int bisstemeqblk (const_bstring b0, const void * blk, int len); +extern int biseqcstr (const_bstring b, const char * s); +extern int biseqcstrcaseless (const_bstring b, const char * s); +extern int bstrcmp (const_bstring b0, const_bstring b1); +extern int bstrncmp (const_bstring b0, const_bstring b1, int n); +extern int binstr (const_bstring s1, int pos, const_bstring s2); +extern int binstrr (const_bstring s1, int pos, const_bstring s2); +extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); +extern int bstrchrp (const_bstring b, int c, int pos); +extern int bstrrchrp (const_bstring b, int c, int pos); +#define bstrchr(b,c) bstrchrp ((b), (c), 0) +#define bstrrchr(b,c) bstrrchrp ((b), (c), blength(b)-1) +extern int binchr (const_bstring b0, int pos, const_bstring b1); +extern int binchrr (const_bstring b0, int pos, const_bstring b1); +extern int bninchr (const_bstring b0, int pos, const_bstring b1); +extern int bninchrr (const_bstring b0, int pos, const_bstring b1); +extern int bfindreplace (bstring b, const_bstring find, const_bstring repl, int pos); +extern int bfindreplacecaseless (bstring b, const_bstring find, const_bstring repl, int pos); + +/* List of string container functions */ +struct bstrList { + int qty, mlen; + bstring * entry; +}; +extern struct bstrList * bstrListCreate (void); +extern int bstrListDestroy (struct bstrList * sl); +extern int bstrListAlloc (struct bstrList * sl, int msz); +extern int bstrListAllocMin (struct bstrList * sl, int msz); + +/* String split and join functions */ +extern struct bstrList * bsplit (const_bstring str, unsigned char splitChar); +extern struct bstrList * bsplits (const_bstring str, const_bstring splitStr); +extern struct bstrList * bsplitstr (const_bstring str, const_bstring splitStr); +extern bstring bjoin (const struct bstrList * bl, const_bstring sep); +extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); +extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + +/* Miscellaneous functions */ +extern int bpattern (bstring b, int len); +extern int btoupper (bstring b); +extern int btolower (bstring b); +extern int bltrimws (bstring b); +extern int brtrimws (bstring b); +extern int btrimws (bstring b); + +/* <*>printf format functions */ +#if !defined (BSTRLIB_NOVSNP) +extern bstring bformat (const char * fmt, ...); +extern int bformata (bstring b, const char * fmt, ...); +extern int bassignformat (bstring b, const char * fmt, ...); +extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); + +#define bvformata(ret, b, fmt, lastarg) { \ +bstring bstrtmp_b = (b); \ +const char * bstrtmp_fmt = (fmt); \ +int bstrtmp_r = BSTR_ERR, bstrtmp_sz = 16; \ + for (;;) { \ + va_list bstrtmp_arglist; \ + va_start (bstrtmp_arglist, lastarg); \ + bstrtmp_r = bvcformata (bstrtmp_b, bstrtmp_sz, bstrtmp_fmt, bstrtmp_arglist); \ + va_end (bstrtmp_arglist); \ + if (bstrtmp_r >= 0) { /* Everything went ok */ \ + bstrtmp_r = BSTR_OK; \ + break; \ + } else if (-bstrtmp_r <= bstrtmp_sz) { /* A real error? */ \ + bstrtmp_r = BSTR_ERR; \ + break; \ + } \ + bstrtmp_sz = -bstrtmp_r; /* Doubled or target size */ \ + } \ + ret = bstrtmp_r; \ +} + +#endif + +typedef int (*bNgetc) (void *parm); +typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, void *parm); + +/* Input functions */ +extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); +extern bstring bread (bNread readPtr, void * parm); +extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); +extern int breada (bstring b, bNread readPtr, void * parm); + +/* Stream functions */ +extern struct bStream * bsopen (bNread readPtr, void * parm); +extern void * bsclose (struct bStream * s); +extern int bsbufflength (struct bStream * s, int sz); +extern int bsreadln (bstring b, struct bStream * s, char terminator); +extern int bsreadlns (bstring r, struct bStream * s, const_bstring term); +extern int bsread (bstring b, struct bStream * s, int n); +extern int bsreadlna (bstring b, struct bStream * s, char terminator); +extern int bsreadlnsa (bstring r, struct bStream * s, const_bstring term); +extern int bsreada (bstring b, struct bStream * s, int n); +extern int bsunread (struct bStream * s, const_bstring b); +extern int bspeek (bstring r, const struct bStream * s); +extern int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); +extern int bseof (const struct bStream * s); + +struct tagbstring { + int mlen; + int slen; + unsigned char * data; +}; + +/* Accessor macros */ +#define blengthe(b, e) (((b) == (void *)0 || (b)->slen < 0) ? (int)(e) : ((b)->slen)) +#define blength(b) (blengthe ((b), 0)) +#define bdataofse(b, o, e) (((b) == (void *)0 || (b)->data == (void*)0) ? (char *)(e) : ((char *)(b)->data) + (o)) +#define bdataofs(b, o) (bdataofse ((b), (o), (void *)0)) +#define bdatae(b, e) (bdataofse (b, 0, e)) +#define bdata(b) (bdataofs (b, 0)) +#define bchare(b, p, e) ((((unsigned)(p)) < (unsigned)blength(b)) ? ((b)->data[(p)]) : (e)) +#define bchar(b, p) bchare ((b), (p), '\0') + +/* Static constant string initialization macro */ +#define bsStaticMlen(q,m) {(m), (int) sizeof(q)-1, (unsigned char *) ("" q "")} +#if defined(_MSC_VER) +/* There are many versions of MSVC which emit __LINE__ as a non-constant. */ +# define bsStatic(q) bsStaticMlen(q,-32) +#endif +#ifndef bsStatic +# define bsStatic(q) bsStaticMlen(q,-__LINE__) +#endif + +/* Static constant block parameter pair */ +#define bsStaticBlkParms(q) ((void *)("" q "")), ((int) sizeof(q)-1) + +/* Reference building macros */ +#define cstr2tbstr btfromcstr +#define btfromcstr(t,s) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = ((t).data) ? ((int) (strlen) ((char *)(t).data)) : 0; \ + (t).mlen = -1; \ +} +#define blk2tbstr(t,s,l) { \ + (t).data = (unsigned char *) (s); \ + (t).slen = l; \ + (t).mlen = -1; \ +} +#define btfromblk(t,s,l) blk2tbstr(t,s,l) +#define bmid2tbstr(t,b,p,l) { \ + const_bstring bstrtmp_s = (b); \ + if (bstrtmp_s && bstrtmp_s->data && bstrtmp_s->slen >= 0) { \ + int bstrtmp_left = (p); \ + int bstrtmp_len = (l); \ + if (bstrtmp_left < 0) { \ + bstrtmp_len += bstrtmp_left; \ + bstrtmp_left = 0; \ + } \ + if (bstrtmp_len > bstrtmp_s->slen - bstrtmp_left) \ + bstrtmp_len = bstrtmp_s->slen - bstrtmp_left; \ + if (bstrtmp_len <= 0) { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } else { \ + (t).data = bstrtmp_s->data + bstrtmp_left; \ + (t).slen = bstrtmp_len; \ + } \ + } else { \ + (t).data = (unsigned char *)""; \ + (t).slen = 0; \ + } \ + (t).mlen = -__LINE__; \ +} +#define btfromblkltrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l); \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx < bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} +#define btfromblkrtrimws(t,s,l) { \ + int bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_len >= 0; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s; \ + (t).slen = bstrtmp_len + 1; \ + (t).mlen = -__LINE__; \ +} +#define btfromblktrimws(t,s,l) { \ + int bstrtmp_idx = 0, bstrtmp_len = (l) - 1; \ + unsigned char * bstrtmp_s = (s); \ + if (bstrtmp_s && bstrtmp_len >= 0) { \ + for (; bstrtmp_idx <= bstrtmp_len; bstrtmp_idx++) { \ + if (!isspace (bstrtmp_s[bstrtmp_idx])) break; \ + } \ + for (; bstrtmp_len >= bstrtmp_idx; bstrtmp_len--) { \ + if (!isspace (bstrtmp_s[bstrtmp_len])) break; \ + } \ + } \ + (t).data = bstrtmp_s + bstrtmp_idx; \ + (t).slen = bstrtmp_len + 1 - bstrtmp_idx; \ + (t).mlen = -__LINE__; \ +} + +/* Write protection macros */ +#define bwriteprotect(t) { if ((t).mlen >= 0) (t).mlen = -1; } +#define bwriteallow(t) { if ((t).mlen == -1) (t).mlen = (t).slen + ((t).slen == 0); } +#define biswriteprotected(t) ((t).mlen <= 0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt new file mode 100644 index 0000000000..8ebb188853 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/bstrlib.txt @@ -0,0 +1,3201 @@ +Better String library +--------------------- + +by Paul Hsieh + +The bstring library is an attempt to provide improved string processing +functionality to the C and C++ language. At the heart of the bstring library +(Bstrlib for short) is the management of "bstring"s which are a significant +improvement over '\0' terminated char buffers. + +=============================================================================== + +Motivation +---------- + +The standard C string library has serious problems: + + 1) Its use of '\0' to denote the end of the string means knowing a + string's length is O(n) when it could be O(1). + 2) It imposes an interpretation for the character value '\0'. + 3) gets() always exposes the application to a buffer overflow. + 4) strtok() modifies the string its parsing and thus may not be usable in + programs which are re-entrant or multithreaded. + 5) fgets has the unusual semantic of ignoring '\0's that occur before + '\n's are consumed. + 6) There is no memory management, and actions performed such as strcpy, + strcat and sprintf are common places for buffer overflows. + 7) strncpy() doesn't '\0' terminate the destination in some cases. + 8) Passing NULL to C library string functions causes an undefined NULL + pointer access. + 9) Parameter aliasing (overlapping, or self-referencing parameters) + within most C library functions has undefined behavior. + 10) Many C library string function calls take integer parameters with + restricted legal ranges. Parameters passed outside these ranges are + not typically detected and cause undefined behavior. + +So the desire is to create an alternative string library that does not suffer +from the above problems and adds in the following functionality: + + 1) Incorporate string functionality seen from other languages. + a) MID$() - from BASIC + b) split()/join() - from Python + c) string/char x n - from Perl + 2) Implement analogs to functions that combine stream IO and char buffers + without creating a dependency on stream IO functionality. + 3) Implement the basic text editor-style functions insert, delete, find, + and replace. + 4) Implement reference based sub-string access (as a generalization of + pointer arithmetic.) + 5) Implement runtime write protection for strings. + +There is also a desire to avoid "API-bloat". So functionality that can be +implemented trivially in other functionality is omitted. So there is no +left$() or right$() or reverse() or anything like that as part of the core +functionality. + +Explaining Bstrings +------------------- + +A bstring is basically a header which wraps a pointer to a char buffer. Lets +start with the declaration of a struct tagbstring: + + struct tagbstring { + int mlen; + int slen; + unsigned char * data; + }; + +This definition is considered exposed, not opaque (though it is neither +necessary nor recommended that low level maintenance of bstrings be performed +whenever the abstract interfaces are sufficient). The mlen field (usually) +describes a lower bound for the memory allocated for the data field. The +slen field describes the exact length for the bstring. The data field is a +single contiguous buffer of unsigned chars. Note that the existence of a '\0' +character in the unsigned char buffer pointed to by the data field does not +necessarily denote the end of the bstring. + +To be a well formed modifiable bstring the mlen field must be at least the +length of the slen field, and slen must be non-negative. Furthermore, the +data field must point to a valid buffer in which access to the first mlen +characters has been acquired. So the minimal check for correctness is: + + (slen >= 0 && mlen >= slen && data != NULL) + +bstrings returned by bstring functions can be assumed to be either NULL or +satisfy the above property. (When bstrings are only readable, the mlen >= +slen restriction is not required; this is discussed later in this section.) +A bstring itself is just a pointer to a struct tagbstring: + + typedef struct tagbstring * bstring; + +Note that use of the prefix "tag" in struct tagbstring is required to work +around the inconsistency between C and C++'s struct namespace usage. This +definition is also considered exposed. + +Bstrlib basically manages bstrings allocated as a header and an associated +data-buffer. Since the implementation is exposed, they can also be +constructed manually. Functions which mutate bstrings assume that the header +and data buffer have been malloced; the bstring library may perform free() or +realloc() on both the header and data buffer of any bstring parameter. +Functions which return bstring's create new bstrings. The string memory is +freed by a bdestroy() call (or using the bstrFree macro). + +The following related typedef is also provided: + + typedef const struct tagbstring * const_bstring; + +which is also considered exposed. These are directly bstring compatible (no +casting required) but are just used for parameters which are meant to be +non-mutable. So in general, bstring parameters which are read as input but +not meant to be modified will be declared as const_bstring, and bstring +parameters which may be modified will be declared as bstring. This convention +is recommended for user written functions as well. + +Since bstrings maintain interoperability with C library char-buffer style +strings, all functions which modify, update or create bstrings also append a +'\0' character into the position slen + 1. This trailing '\0' character is +not required for bstrings input to the bstring functions; this is provided +solely as a convenience for interoperability with standard C char-buffer +functionality. + +Analogs for the ANSI C string library functions have been created when they +are necessary, but have also been left out when they are not. In particular +there are no functions analogous to fwrite, or puts just for the purposes of +bstring. The ->data member of any string is exposed, and therefore can be +used just as easily as char buffers for C functions which read strings. + +For those that wish to hand construct bstrings, the following should be kept +in mind: + + 1) While bstrlib can accept constructed bstrings without terminating + '\0' characters, the rest of the C language string library will not + function properly on such non-terminated strings. This is obvious + but must be kept in mind. + 2) If it is intended that a constructed bstring be written to by the + bstring library functions then the data portion should be allocated + by the malloc function and the slen and mlen fields should be entered + properly. The struct tagbstring header is not reallocated, and only + freed by bdestroy. + 3) Writing arbitrary '\0' characters at various places in the string + will not modify its length as perceived by the bstring library + functions. In fact, '\0' is a legitimate non-terminating character + for a bstring to contain. + 4) For read only parameters, bstring functions do not check the mlen. + I.e., the minimal correctness requirements are reduced to: + + (slen >= 0 && data != NULL) + +Better pointer arithmetic +------------------------- + +One built-in feature of '\0' terminated char * strings, is that its very easy +and fast to obtain a reference to the tail of any string using pointer +arithmetic. Bstrlib does one better by providing a way to get a reference to +any substring of a bstring (or any other length delimited block of memory.) +So rather than just having pointer arithmetic, with bstrlib one essentially +has segment arithmetic. This is achieved using the macro blk2tbstr() which +builds a reference to a block of memory and the macro bmid2tbstr() which +builds a reference to a segment of a bstring. Bstrlib also includes +functions for direct consumption of memory blocks into bstrings, namely +bcatblk () and blk2bstr (). + +One scenario where this can be extremely useful is when string contains many +substrings which one would like to pass as read-only reference parameters to +some string consuming function without the need to allocate entire new +containers for the string data. More concretely, imagine parsing a command +line string whose parameters are space delimited. This can only be done for +tails of the string with '\0' terminated char * strings. + +Improved NULL semantics and error handling +------------------------------------------ + +Unless otherwise noted, if a NULL pointer is passed as a bstring or any other +detectably illegal parameter, the called function will return with an error +indicator (either NULL or BSTR_ERR) rather than simply performing a NULL +pointer access, or having undefined behavior. + +To illustrate the value of this, consider the following example: + + strcpy (p = malloc (13 * sizeof (char)), "Hello,"); + strcat (p, " World"); + +This is not correct because malloc may return NULL (due to an out of memory +condition), and the behaviour of strcpy is undefined if either of its +parameters are NULL. However: + + bstrcat (p = bfromcstr ("Hello,"), q = bfromcstr (" World")); + bdestroy (q); + +is well defined, because if either p or q are assigned NULL (indicating a +failure to allocate memory) both bstrcat and bdestroy will recognize it and +perform no detrimental action. + +Note that it is not necessary to check any of the members of a returned +bstring for internal correctness (in particular the data member does not need +to be checked against NULL when the header is non-NULL), since this is +assured by the bstring library itself. + +bStreams +-------- + +In addition to the bgets and bread functions, bstrlib can abstract streams +with a high performance read only stream called a bStream. In general, the +idea is to open a core stream (with something like fopen) then pass its +handle as well as a bNread function pointer (like fread) to the bsopen +function which will return a handle to an open bStream. Then the functions +bsread, bsreadln or bsreadlns can be called to read portions of the stream. +Finally, the bsclose function is called to close the bStream -- it will +return a handle to the original (core) stream. So bStreams, essentially, +wrap other streams. + +The bStreams have two main advantages over the bgets and bread (as well as +fgets/ungetc) paradigms: + +1) Improved functionality via the bunread function which allows a stream to + unread characters, giving the bStream stack-like functionality if so + desired. +2) A very high performance bsreadln function. The C library function fgets() + (and the bgets function) can typically be written as a loop on top of + fgetc(), thus paying all of the overhead costs of calling fgetc on a per + character basis. bsreadln will read blocks at a time, thus amortizing the + overhead of fread calls over many characters at once. + +However, clearly bStreams are suboptimal or unusable for certain kinds of +streams (stdin) or certain usage patterns (a few spotty, or non-sequential +reads from a slow stream.) For those situations, using bgets will be more +appropriate. + +The semantics of bStreams allows practical construction of layerable data +streams. What this means is that by writing a bNread compatible function on +top of a bStream, one can construct a new bStream on top of it. This can be +useful for writing multi-pass parsers that don't actually read the entire +input more than once and don't require the use of intermediate storage. + +Aliasing +-------- + +Aliasing occurs when a function is given two parameters which point to data +structures which overlap in the memory they occupy. While this does not +disturb read only functions, for many libraries this can make functions that +write to these memory locations malfunction. This is a common problem of the +C standard library and especially the string functions in the C standard +library. + +The C standard string library is entirely char by char oriented (as is +bstring) which makes conforming implementations alias safe for some +scenarios. However no actual detection of aliasing is typically performed, +so it is easy to find cases where the aliasing will cause anomolous or +undesirable behaviour (consider: strcat (p, p).) The C99 standard includes +the "restrict" pointer modifier which allows the compiler to document and +assume a no-alias condition on usage. However, only the most trivial cases +can be caught (if at all) by the compiler at compile time, and thus there is +no actual enforcement of non-aliasing. + +Bstrlib, by contrast, permits aliasing and is completely aliasing safe, in +the C99 sense of aliasing. That is to say, under the assumption that +pointers of incompatible types from distinct objects can never alias, bstrlib +is completely aliasing safe. (In practice this means that the data buffer +portion of any bstring and header of any bstring are assumed to never alias.) +With the exception of the reference building macros, the library behaves as +if all read-only parameters are first copied and replaced by temporary +non-aliased parameters before any writing to any output bstring is performed +(though actual copying is extremely rarely ever done.) + +Besides being a useful safety feature, bstring searching/comparison +functions can improve to O(1) execution when aliasing is detected. + +Note that aliasing detection and handling code in Bstrlib is generally +extremely cheap. There is almost never any appreciable performance penalty +for using aliased parameters. + +Reenterancy +----------- + +Nearly every function in Bstrlib is a leaf function, and is completely +reenterable with the exception of writing to common bstrings. The split +functions which use a callback mechanism requires only that the source string +not be destroyed by the callback function unless the callback function returns +with an error status (note that Bstrlib functions which return an error do +not modify the string in any way.) The string can in fact be modified by the +callback and the behaviour is deterministic. See the documentation of the +various split functions for more details. + +Undefined scenarios +------------------- + +One of the basic important premises for Bstrlib is to not to increase the +propogation of undefined situations from parameters that are otherwise legal +in of themselves. In particular, except for extremely marginal cases, usages +of bstrings that use the bstring library functions alone cannot lead to any +undefined action. But due to C/C++ language and library limitations, there +is no way to define a non-trivial library that is completely without +undefined operations. All such possible undefined operations are described +below: + +1) bstrings or struct tagbstrings that are not explicitely initialized cannot + be passed as a parameter to any bstring function. +2) The members of the NULL bstring cannot be accessed directly. (Though all + APIs and macros detect the NULL bstring.) +3) A bstring whose data member has not been obtained from a malloc or + compatible call and which is write accessible passed as a writable + parameter will lead to undefined results. (i.e., do not writeAllow any + constructed bstrings unless the data portion has been obtained from the + heap.) +4) If the headers of two strings alias but are not identical (which can only + happen via a defective manual construction), then passing them to a + bstring function in which one is writable is not defined. +5) If the mlen member is larger than the actual accessible length of the data + member for a writable bstring, or if the slen member is larger than the + readable length of the data member for a readable bstring, then the + corresponding bstring operations are undefined. +6) Any bstring definition whose header or accessible data portion has been + assigned to inaccessible or otherwise illegal memory clearly cannot be + acted upon by the bstring library in any way. +7) Destroying the source of an incremental split from within the callback + and not returning with a negative value (indicating that it should abort) + will lead to undefined behaviour. (Though *modifying* or adjusting the + state of the source data, even if those modification fail within the + bstrlib API, has well defined behavior.) +8) Modifying a bstring which is write protected by direct access has + undefined behavior. + +While this may seem like a long list, with the exception of invalid uses of +the writeAllow macro, and source destruction during an iterative split +without an accompanying abort, no usage of the bstring API alone can cause +any undefined scenario to occurr. I.e., the policy of restricting usage of +bstrings to the bstring API can significantly reduce the risk of runtime +errors (in practice it should eliminate them) related to string manipulation +due to undefined action. + +C++ wrapper +----------- + +A C++ wrapper has been created to enable bstring functionality for C++ in the +most natural (for C++ programers) way possible. The mandate for the C++ +wrapper is different from the base C bstring library. Since the C++ language +has far more abstracting capabilities, the CBString structure is considered +fully abstracted -- i.e., hand generated CBStrings are not supported (though +conversion from a struct tagbstring is allowed) and all detectable errors are +manifest as thrown exceptions. + +- The C++ class definitions are all under the namespace Bstrlib. bstrwrap.h + enables this namespace (with a using namespace Bstrlib; directive at the + end) unless the macro BSTRLIB_DONT_ASSUME_NAMESPACE has been defined before + it is included. + +- Erroneous accesses results in an exception being thrown. The exception + parameter is of type "struct CBStringException" which is derived from + std::exception if STL is used. A verbose description of the error message + can be obtained from the what() method. + +- CBString is a C++ structure derived from a struct tagbstring. An address + of a CBString cast to a bstring must not be passed to bdestroy. The bstring + C API has been made C++ safe and can be used directly in a C++ project. + +- It includes constructors which can take a char, '\0' terminated char + buffer, tagbstring, (char, repeat-value), a length delimited buffer or a + CBStringList to initialize it. + +- Concatenation is performed with the + and += operators. Comparisons are + done with the ==, !=, <, >, <= and >= operators. Note that == and != use + the biseq call, while <, >, <= and >= use bstrcmp. + +- CBString's can be directly cast to const character buffers. + +- CBString's can be directly cast to double, float, int or unsigned int so + long as the CBString are decimal representations of those types (otherwise + an exception will be thrown). Converting the other way should be done with + the format(a) method(s). + +- CBString contains the length, character and [] accessor methods. The + character and [] accessors are aliases of each other. If the bounds for + the string are exceeded, an exception is thrown. To avoid the overhead for + this check, first cast the CBString to a (const char *) and use [] to + dereference the array as normal. Note that the character and [] accessor + methods allows both reading and writing of individual characters. + +- The methods: format, formata, find, reversefind, findcaseless, + reversefindcaseless, midstr, insert, insertchrs, replace, findreplace, + findreplacecaseless, remove, findchr, nfindchr, alloc, toupper, tolower, + gets, read are analogous to the functions that can be found in the C API. + +- The caselessEqual and caselessCmp methods are analogous to biseqcaseless + and bstricmp functions respectively. + +- Note that just like the bformat function, the format and formata methods do + not automatically cast CBStrings into char * strings for "%s"-type + substitutions: + + CBString w("world"); + CBString h("Hello"); + CBString hw; + + /* The casts are necessary */ + hw.format ("%s, %s", (const char *)h, (const char *)w); + +- The methods trunc and repeat have been added instead of using pattern. + +- ltrim, rtrim and trim methods have been added. These remove characters + from a given character string set (defaulting to the whitespace characters) + from either the left, right or both ends of the CBString, respectively. + +- The method setsubstr is also analogous in functionality to bsetstr, except + that it cannot be passed NULL. Instead the method fill and the fill-style + constructor have been supplied to enable this functionality. + +- The writeprotect(), writeallow() and iswriteprotected() methods are + analogous to the bwriteprotect(), bwriteallow() and biswriteprotected() + macros in the C API. Write protection semantics in CBString are stronger + than with the C API in that indexed character assignment is checked for + write protection. However, unlike with the C API, a write protected + CBString can be destroyed by the destructor. + +- CBStream is a C++ structure which wraps a struct bStream (its not derived + from it, since destruction is slightly different). It is constructed by + passing in a bNread function pointer and a stream parameter cast to void *. + This structure includes methods for detecting eof, setting the buffer + length, reading the whole stream or reading entries line by line or block + by block, an unread function, and a peek function. + +- If STL is available, the CBStringList structure is derived from a vector of + CBString with various split methods. The split method has been overloaded + to accept either a character or CBString as the second parameter (when the + split parameter is a CBString any character in that CBString is used as a + seperator). The splitstr method takes a CBString as a substring seperator. + Joins can be performed via a CBString constructor which takes a + CBStringList as a parameter, or just using the CBString::join() method. + +- If there is proper support for std::iostreams, then the >> and << operators + and the getline() function have been added (with semantics the same as + those for std::string). + +Multithreading +-------------- + +A mutable bstring is kind of analogous to a small (two entry) linked list +allocated by malloc, with all aliasing completely under programmer control. +I.e., manipulation of one bstring will never affect any other distinct +bstring unless explicitely constructed to do so by the programmer via hand +construction or via building a reference. Bstrlib also does not use any +static or global storage, so there are no hidden unremovable race conditions. +Bstrings are also clearly not inherently thread local. So just like +char *'s, bstrings can be passed around from thread to thread and shared and +so on, so long as modifications to a bstring correspond to some kind of +exclusive access lock as should be expected (or if the bstring is read-only, +which can be enforced by bstring write protection) for any sort of shared +object in a multithreaded environment. + +Bsafe module +------------ + +For convenience, a bsafe module has been included. The idea is that if this +module is included, inadvertant usage of the most dangerous C functions will +be overridden and lead to an immediate run time abort. Of course, it should +be emphasized that usage of this module is completely optional. The +intention is essentially to provide an option for creating project safety +rules which can be enforced mechanically rather than socially. This is +useful for larger, or open development projects where its more difficult to +enforce social rules or "coding conventions". + +Problems not solved +------------------- + +Bstrlib is written for the C and C++ languages, which have inherent weaknesses +that cannot be easily solved: + +1. Memory leaks: Forgetting to call bdestroy on a bstring that is about to be + unreferenced, just as forgetting to call free on a heap buffer that is + about to be dereferenced. Though bstrlib itself is leak free. +2. Read before write usage: In C, declaring an auto bstring does not + automatically fill it with legal/valid contents. This problem has been + somewhat mitigated in C++. (The bstrDeclare and bstrFree macros from + bstraux can be used to help mitigate this problem.) + +Other problems not addressed: + +3. Built-in mutex usage to automatically avoid all bstring internal race + conditions in multitasking environments: The problem with trying to + implement such things at this low a level is that it is typically more + efficient to use locks in higher level primitives. There is also no + platform independent way to implement locks or mutexes. +4. Unicode/widecharacter support. + +Note that except for spotty support of wide characters, the default C +standard library does not address any of these problems either. + +Configurable compilation options +-------------------------------- + +All configuration options are meant solely for the purpose of compiler +compatibility. Configuration options are not meant to change the semantics +or capabilities of the library, except where it is unavoidable. + +Since some C++ compilers don't include the Standard Template Library and some +have the options of disabling exception handling, a number of macros can be +used to conditionally compile support for each of this: + +BSTRLIB_CAN_USE_STL + + - defining this will enable the used of the Standard Template Library. + Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. + +BSTRLIB_CANNOT_USE_STL + + - defining this will disable the use of the Standard Template Library. + Defining BSTRLIB_CAN_USE_STL overrides the BSTRLIB_CANNOT_USE_STL macro. + +BSTRLIB_CAN_USE_IOSTREAM + + - defining this will enable the used of streams from class std. Defining + BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. + +BSTRLIB_CANNOT_USE_IOSTREAM + + - defining this will disable the use of streams from class std. Defining + BSTRLIB_CAN_USE_IOSTREAM overrides the BSTRLIB_CANNOT_USE_IOSTREAM macro. + +BSTRLIB_THROWS_EXCEPTIONS + + - defining this will enable the exception handling within bstring. + Defining BSTRLIB_THROWS_EXCEPTIONS overrides the + BSTRLIB_DOESNT_THROWS_EXCEPTIONS macro. + +BSTRLIB_DOESNT_THROW_EXCEPTIONS + + - defining this will disable the exception handling within bstring. + Defining BSTRLIB_THROWS_EXCEPTIONS overrides the + BSTRLIB_DOESNT_THROW_EXCEPTIONS macro. + +Note that these macros must be defined consistently throughout all modules +that use CBStrings including bstrwrap.cpp. + +Some older C compilers do not support functions such as vsnprintf. This is +handled by the following macro variables: + +BSTRLIB_NOVSNP + + - defining this indicates that the compiler does not support vsnprintf. + This will cause bformat and bformata to not be declared. Note that + for some compilers, such as Turbo C, this is set automatically. + Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. + +BSTRLIB_VSNP_OK + + - defining this will disable the autodetection of compilers the do not + support of compilers that do not support vsnprintf. + Defining BSTRLIB_NOVSNP overrides the BSTRLIB_VSNP_OK macro. + +Semantic compilation options +---------------------------- + +Bstrlib comes with very few compilation options for changing the semantics of +of the library. These are described below. + +BSTRLIB_DONT_ASSUME_NAMESPACE + + - Defining this before including bstrwrap.h will disable the automatic + enabling of the Bstrlib namespace for the C++ declarations. + +BSTRLIB_DONT_USE_VIRTUAL_DESTRUCTOR + + - Defining this will make the CBString destructor non-virtual. + +BSTRLIB_MEMORY_DEBUG + + - Defining this will cause the bstrlib modules bstrlib.c and bstrwrap.cpp + to invoke a #include "memdbg.h". memdbg.h has to be supplied by the user. + +Note that these macros must be defined consistently throughout all modules +that use bstrings or CBStrings including bstrlib.c, bstraux.c and +bstrwrap.cpp. + +=============================================================================== + +Files +----- + +bstrlib.c - C implementaion of bstring functions. +bstrlib.h - C header file for bstring functions. +bstraux.c - C example that implements trivial additional functions. +bstraux.h - C header for bstraux.c +bstest.c - C unit/regression test for bstrlib.c + +bstrwrap.cpp - C++ implementation of CBString. +bstrwrap.h - C++ header file for CBString. +test.cpp - C++ unit/regression test for bstrwrap.cpp + +bsafe.c - C runtime stubs to abort usage of unsafe C functions. +bsafe.h - C header file for bsafe.c functions. + +C projects need only include bstrlib.h and compile/link bstrlib.c to use the +bstring library. C++ projects need to additionally include bstrwrap.h and +compile/link bstrwrap.cpp. For both, there may be a need to make choices +about feature configuration as described in the "Configurable compilation +options" in the section above. + +Other files that are included in this archive are: + +license.txt - The 3 clause BSD license for Bstrlib +gpl.txt - The GPL version 2 +security.txt - A security statement useful for auditting Bstrlib +porting.txt - A guide to porting Bstrlib +bstrlib.txt - This file + +=============================================================================== + +The functions +------------- + + extern bstring bfromcstr (const char * str); + + Take a standard C library style '\0' terminated char buffer and generate + a bstring with the same contents as the char buffer. If an error occurs + NULL is returned. + + So for example: + + bstring b = bfromcstr ("Hello"); + if (!b) { + fprintf (stderr, "Out of memory"); + } else { + puts ((char *) b->data); + } + + .......................................................................... + + extern bstring bfromcstralloc (int mlen, const char * str); + + Create a bstring which contains the contents of the '\0' terminated + char * buffer str. The memory buffer backing the bstring is at least + mlen characters in length. If an error occurs NULL is returned. + + So for example: + + bstring b = bfromcstralloc (64, someCstr); + if (b) b->data[63] = 'x'; + + The idea is that this will set the 64th character of b to 'x' if it is at + least 64 characters long otherwise do nothing. And we know this is well + defined so long as b was successfully created, since it will have been + allocated with at least 64 characters. + + .......................................................................... + + extern bstring blk2bstr (const void * blk, int len); + + Create a bstring whose contents are described by the contiguous buffer + pointing to by blk with a length of len bytes. Note that this function + creates a copy of the data in blk, rather than simply referencing it. + Compare with the blk2tbstr macro. If an error occurs NULL is returned. + + .......................................................................... + + extern char * bstr2cstr (const_bstring s, char z); + + Create a '\0' terminated char buffer which contains the contents of the + bstring s, except that any contained '\0' characters are converted to the + character in z. This returned value should be freed with bcstrfree(), by + the caller. If an error occurs NULL is returned. + + .......................................................................... + + extern int bcstrfree (char * s); + + Frees a C-string generated by bstr2cstr (). This is normally unnecessary + since it just wraps a call to free (), however, if malloc () and free () + have been redefined as a macros within the bstrlib module (via macros in + the memdbg.h backdoor) with some difference in behaviour from the std + library functions, then this allows a correct way of freeing the memory + that allows higher level code to be independent from these macro + redefinitions. + + .......................................................................... + + extern bstring bstrcpy (const_bstring b1); + + Make a copy of the passed in bstring. The copied bstring is returned if + there is no error, otherwise NULL is returned. + + .......................................................................... + + extern int bassign (bstring a, const_bstring b); + + Overwrite the bstring a with the contents of bstring b. Note that the + bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + int bassigncstr (bstring a, const char * str); + + Overwrite the string a with the contents of char * string str. Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a may be partially overwritten. + + .......................................................................... + + int bassignblk (bstring a, const void * s, int len); + + Overwrite the string a with the contents of the block (s, len). Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + extern int bassignmidstr (bstring a, const_bstring b, int left, int len); + + Overwrite the bstring a with the middle of contents of bstring b + starting from position left and running for a length len. left and + len are clamped to the ends of b as with the function bmidstr. Note that + the bstring a must be a well defined and writable bstring. If an error + occurs BSTR_ERR is returned and a is not overwritten. + + .......................................................................... + + extern bstring bmidstr (const_bstring b, int left, int len); + + Create a bstring which is the substring of b starting from position left + and running for a length len (clamped by the end of the bstring b.) If + there was no error, the value of this constructed bstring is returned + otherwise NULL is returned. + + .......................................................................... + + extern int bdelete (bstring s1, int pos, int len); + + Removes characters from pos to pos+len-1 and shifts the tail of the + bstring starting from pos+len to pos. len must be positive for this call + to have any effect. The section of the bstring described by (pos, len) + is clamped to boundaries of the bstring b. The value BSTR_OK is returned + if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int bconcat (bstring b0, const_bstring b1); + + Concatenate the bstring b1 to the end of bstring b0. The value BSTR_OK + is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bconchar (bstring b, char c); + + Concatenate the character c to the end of bstring b. The value BSTR_OK + is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bcatcstr (bstring b, const char * s); + + Concatenate the char * string s to the end of bstring b. The value + BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int bcatblk (bstring b, const void * s, int len); + + Concatenate a fixed length buffer (s, len) to the end of bstring b. The + value BSTR_OK is returned if the operation is successful, otherwise + BSTR_ERR is returned. + + .......................................................................... + + extern int biseq (const_bstring b0, const_bstring b1); + + Compare the bstring b0 and b1 for equality. If the bstrings differ, 0 + is returned, if the bstrings are the same, 1 is returned, if there is an + error, -1 is returned. If the length of the bstrings are different, this + function has O(1) complexity. Contained '\0' characters are not treated + as a termination character. + + Note that the semantics of biseq are not completely compatible with + bstrcmp because of its different treatment of the '\0' character. + + .......................................................................... + + extern int bisstemeqblk (const_bstring b, const void * blk, int len); + + Compare beginning of bstring b0 with a block of memory of length len for + equality. If the beginning of b0 differs from the memory block (or if b0 + is too short), 0 is returned, if the bstrings are the same, 1 is returned, + if there is an error, -1 is returned. + + .......................................................................... + + extern int biseqcaseless (const_bstring b0, const_bstring b1); + + Compare two bstrings for equality without differentiating between case. + If the bstrings differ other than in case, 0 is returned, if the bstrings + are the same, 1 is returned, if there is an error, -1 is returned. If + the length of the bstrings are different, this function is O(1). '\0' + termination characters are not treated in any special way. + + .......................................................................... + + extern int bisstemeqcaselessblk (const_bstring b0, const void * blk, int len); + + Compare beginning of bstring b0 with a block of memory of length len + without differentiating between case for equality. If the beginning of b0 + differs from the memory block other than in case (or if b0 is too short), + 0 is returned, if the bstrings are the same, 1 is returned, if there is an + error, -1 is returned. + + .......................................................................... + + extern int biseqcstr (const_bstring b, const char *s); + + Compare the bstring b and char * bstring s. The C string s must be '\0' + terminated at exactly the length of the bstring b, and the contents + between the two must be identical with the bstring b with no '\0' + characters for the two contents to be considered equal. This is + equivalent to the condition that their current contents will be always be + equal when comparing them in the same format after converting one or the + other. If they are equal 1 is returned, if they are unequal 0 is + returned and if there is a detectable error BSTR_ERR is returned. + + .......................................................................... + + extern int biseqcstrcaseless (const_bstring b, const char *s); + + Compare the bstring b and char * string s. The C string s must be '\0' + terminated at exactly the length of the bstring b, and the contents + between the two must be identical except for case with the bstring b with + no '\0' characters for the two contents to be considered equal. This is + equivalent to the condition that their current contents will be always be + equal ignoring case when comparing them in the same format after + converting one or the other. If they are equal, except for case, 1 is + returned, if they are unequal regardless of case 0 is returned and if + there is a detectable error BSTR_ERR is returned. + + .......................................................................... + + extern int bstrcmp (const_bstring b0, const_bstring b1); + + Compare the bstrings b0 and b1 for ordering. If there is an error, + SHRT_MIN is returned, otherwise a value less than or greater than zero, + indicating that the bstring pointed to by b0 is lexicographically less + than or greater than the bstring pointed to by b1 is returned. If the + bstring lengths are unequal but the characters up until the length of the + shorter are equal then a value less than, or greater than zero, + indicating that the bstring pointed to by b0 is shorter or longer than the + bstring pointed to by b1 is returned. 0 is returned if and only if the + two bstrings are the same. If the length of the bstrings are different, + this function is O(n). Like its standard C library counter part, the + comparison does not proceed past any '\0' termination characters + encountered. + + The seemingly odd error return value, merely provides slightly more + granularity than the undefined situation given in the C library function + strcmp. The function otherwise behaves very much like strcmp(). + + Note that the semantics of bstrcmp are not completely compatible with + biseq because of its different treatment of the '\0' termination + character. + + .......................................................................... + + extern int bstrncmp (const_bstring b0, const_bstring b1, int n); + + Compare the bstrings b0 and b1 for ordering for at most n characters. If + there is an error, SHRT_MIN is returned, otherwise a value is returned as + if b0 and b1 were first truncated to at most n characters then bstrcmp + was called with these new bstrings are paremeters. If the length of the + bstrings are different, this function is O(n). Like its standard C + library counter part, the comparison does not proceed past any '\0' + termination characters encountered. + + The seemingly odd error return value, merely provides slightly more + granularity than the undefined situation given in the C library function + strncmp. The function otherwise behaves very much like strncmp(). + + .......................................................................... + + extern int bstricmp (const_bstring b0, const_bstring b1); + + Compare two bstrings without differentiating between case. The return + value is the difference of the values of the characters where the two + bstrings first differ, otherwise 0 is returned indicating that the + bstrings are equal. If the lengths are different, then a difference from + 0 is given, but if the first extra character is '\0', then it is taken to + be the value UCHAR_MAX+1. + + .......................................................................... + + extern int bstrnicmp (const_bstring b0, const_bstring b1, int n); + + Compare two bstrings without differentiating between case for at most n + characters. If the position where the two bstrings first differ is + before the nth position, the return value is the difference of the values + of the characters, otherwise 0 is returned. If the lengths are different + and less than n characters, then a difference from 0 is given, but if the + first extra character is '\0', then it is taken to be the value + UCHAR_MAX+1. + + .......................................................................... + + extern int bdestroy (bstring b); + + Deallocate the bstring passed. Passing NULL in as a parameter will have + no effect. Note that both the header and the data portion of the bstring + will be freed. No other bstring function which modifies one of its + parameters will free or reallocate the header. Because of this, in + general, bdestroy cannot be called on any declared struct tagbstring even + if it is not write protected. A bstring which is write protected cannot + be destroyed via the bdestroy call. Any attempt to do so will result in + no action taken, and BSTR_ERR will be returned. + + Note to C++ users: Passing in a CBString cast to a bstring will lead to + undefined behavior (free will be called on the header, rather than the + CBString destructor.) Instead just use the ordinary C++ language + facilities to dealloc a CBString. + + .......................................................................... + + extern int binstr (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + forward (increasing) direction. If it is found then it returns with the + first position after pos where it is found, otherwise it returns BSTR_ERR. + The algorithm used is brute force; O(m*n). + + .......................................................................... + + extern int binstrr (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + backward (decreasing) direction. If it is found then it returns with the + first position after pos where it is found, otherwise return BSTR_ERR. + Note that the current position at pos is tested as well -- so to be + disjoint from a previous forward search it is recommended that the + position be backed up (decremented) by one position. The algorithm used + is brute force; O(m*n). + + .......................................................................... + + extern int binstrcaseless (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + forward (increasing) direction but without regard to case. If it is + found then it returns with the first position after pos where it is + found, otherwise it returns BSTR_ERR. The algorithm used is brute force; + O(m*n). + + .......................................................................... + + extern int binstrrcaseless (const_bstring s1, int pos, const_bstring s2); + + Search for the bstring s2 in s1 starting at position pos and looking in a + backward (decreasing) direction but without regard to case. If it is + found then it returns with the first position after pos where it is + found, otherwise return BSTR_ERR. Note that the current position at pos + is tested as well -- so to be disjoint from a previous forward search it + is recommended that the position be backed up (decremented) by one + position. The algorithm used is brute force; O(m*n). + + .......................................................................... + + extern int binchr (const_bstring b0, int pos, const_bstring b1); + + Search for the first position in b0 starting from pos or after, in which + one of the characters in b1 is found. This function has an execution + time of O(b0->slen + b1->slen). If such a position does not exist in b0, + then BSTR_ERR is returned. + + .......................................................................... + + extern int binchrr (const_bstring b0, int pos, const_bstring b1); + + Search for the last position in b0 no greater than pos, in which one of + the characters in b1 is found. This function has an execution time + of O(b0->slen + b1->slen). If such a position does not exist in b0, + then BSTR_ERR is returned. + + .......................................................................... + + extern int bninchr (const_bstring b0, int pos, const_bstring b1); + + Search for the first position in b0 starting from pos or after, in which + none of the characters in b1 is found and return it. This function has + an execution time of O(b0->slen + b1->slen). If such a position does + not exist in b0, then BSTR_ERR is returned. + + .......................................................................... + + extern int bninchrr (const_bstring b0, int pos, const_bstring b1); + + Search for the last position in b0 no greater than pos, in which none of + the characters in b1 is found and return it. This function has an + execution time of O(b0->slen + b1->slen). If such a position does not + exist in b0, then BSTR_ERR is returned. + + .......................................................................... + + extern int bstrchr (const_bstring b, int c); + + Search for the character c in the bstring b forwards from the start of + the bstring. Returns the position of the found character or BSTR_ERR if + it is not found. + + NOTE: This has been implemented as a macro on top of bstrchrp (). + + .......................................................................... + + extern int bstrrchr (const_bstring b, int c); + + Search for the character c in the bstring b backwards from the end of the + bstring. Returns the position of the found character or BSTR_ERR if it is + not found. + + NOTE: This has been implemented as a macro on top of bstrrchrp (). + + .......................................................................... + + extern int bstrchrp (const_bstring b, int c, int pos); + + Search for the character c in b forwards from the position pos + (inclusive). Returns the position of the found character or BSTR_ERR if + it is not found. + + .......................................................................... + + extern int bstrrchrp (const_bstring b, int c, int pos); + + Search for the character c in b backwards from the position pos in bstring + (inclusive). Returns the position of the found character or BSTR_ERR if + it is not found. + + .......................................................................... + + extern int bsetstr (bstring b0, int pos, const_bstring b1, unsigned char fill); + + Overwrite the bstring b0 starting at position pos with the bstring b1. If + the position pos is past the end of b0, then the character "fill" is + appended as necessary to make up the gap between the end of b0 and pos. + If b1 is NULL, it behaves as if it were a 0-length bstring. The value + BSTR_OK is returned if the operation is successful, otherwise BSTR_ERR is + returned. + + .......................................................................... + + extern int binsert (bstring s1, int pos, const_bstring s2, unsigned char fill); + + Inserts the bstring s2 into s1 at position pos. If the position pos is + past the end of s1, then the character "fill" is appended as necessary to + make up the gap between the end of s1 and pos. The value BSTR_OK is + returned if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int binsertch (bstring s1, int pos, int len, unsigned char fill); + + Inserts the character fill repeatedly into s1 at position pos for a + length len. If the position pos is past the end of s1, then the + character "fill" is appended as necessary to make up the gap between the + end of s1 and the position pos + len (exclusive). The value BSTR_OK is + returned if the operation is successful, otherwise BSTR_ERR is returned. + + .......................................................................... + + extern int breplace (bstring b1, int pos, int len, const_bstring b2, + unsigned char fill); + + Replace a section of a bstring from pos for a length len with the bstring + b2. If the position pos is past the end of b1 then the character "fill" + is appended as necessary to make up the gap between the end of b1 and + pos. + + .......................................................................... + + extern int bfindreplace (bstring b, const_bstring find, + const_bstring replace, int position); + + Replace all occurrences of the find substring with a replace bstring + after a given position in the bstring b. The find bstring must have a + length > 0 otherwise BSTR_ERR is returned. This function does not + perform recursive per character replacement; that is to say successive + searches resume at the position after the last replace. + + So for example: + + bfindreplace (a0 = bfromcstr("aabaAb"), a1 = bfromcstr("a"), + a2 = bfromcstr("aa"), 0); + + Should result in changing a0 to "aaaabaaAb". + + This function performs exactly (b->slen - position) bstring comparisons, + and data movement is bounded above by character volume equivalent to size + of the output bstring. + + .......................................................................... + + extern int bfindreplacecaseless (bstring b, const_bstring find, + const_bstring replace, int position); + + Replace all occurrences of the find substring, ignoring case, with a + replace bstring after a given position in the bstring b. The find bstring + must have a length > 0 otherwise BSTR_ERR is returned. This function + does not perform recursive per character replacement; that is to say + successive searches resume at the position after the last replace. + + So for example: + + bfindreplacecaseless (a0 = bfromcstr("AAbaAb"), a1 = bfromcstr("a"), + a2 = bfromcstr("aa"), 0); + + Should result in changing a0 to "aaaabaaaab". + + This function performs exactly (b->slen - position) bstring comparisons, + and data movement is bounded above by character volume equivalent to size + of the output bstring. + + .......................................................................... + + extern int balloc (bstring b, int length); + + Increase the allocated memory backing the data buffer for the bstring b + to a length of at least length. If the memory backing the bstring b is + already large enough, not action is performed. This has no effect on the + bstring b that is visible to the bstring API. Usually this function will + only be used when a minimum buffer size is required coupled with a direct + access to the ->data member of the bstring structure. + + Be warned that like any other bstring function, the bstring must be well + defined upon entry to this function. I.e., doing something like: + + b->slen *= 2; /* ?? Most likely incorrect */ + balloc (b, b->slen); + + is invalid, and should be implemented as: + + int t; + if (BSTR_OK == balloc (b, t = (b->slen * 2))) b->slen = t; + + This function will return with BSTR_ERR if b is not detected as a valid + bstring or length is not greater than 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int ballocmin (bstring b, int length); + + Change the amount of memory backing the bstring b to at least length. + This operation will never truncate the bstring data including the + extra terminating '\0' and thus will not decrease the length to less than + b->slen + 1. Note that repeated use of this function may cause + performance problems (realloc may be called on the bstring more than + the O(log(INT_MAX)) times). This function will return with BSTR_ERR if b + is not detected as a valid bstring or length is not greater than 0, + otherwise BSTR_OK is returned. + + So for example: + + if (BSTR_OK == ballocmin (b, 64)) b->data[63] = 'x'; + + The idea is that this will set the 64th character of b to 'x' if it is at + least 64 characters long otherwise do nothing. And we know this is well + defined so long as the ballocmin call was successfully, since it will + ensure that b has been allocated with at least 64 characters. + + .......................................................................... + + int btrunc (bstring b, int n); + + Truncate the bstring to at most n characters. This function will return + with BSTR_ERR if b is not detected as a valid bstring or n is less than + 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bpattern (bstring b, int len); + + Replicate the starting bstring, b, end to end repeatedly until it + surpasses len characters, then chop the result to exactly len characters. + This function operates in-place. This function will return with BSTR_ERR + if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int btoupper (bstring b); + + Convert contents of bstring to upper case. This function will return with + BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int btolower (bstring b); + + Convert contents of bstring to lower case. This function will return with + BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bltrimws (bstring b); + + Delete whitespace contiguous from the left end of the bstring. This + function will return with BSTR_ERR if b is NULL or of length 0, otherwise + BSTR_OK is returned. + + .......................................................................... + + extern int brtrimws (bstring b); + + Delete whitespace contiguous from the right end of the bstring. This + function will return with BSTR_ERR if b is NULL or of length 0, otherwise + BSTR_OK is returned. + + .......................................................................... + + extern int btrimws (bstring b); + + Delete whitespace contiguous from both ends of the bstring. This function + will return with BSTR_ERR if b is NULL or of length 0, otherwise BSTR_OK + is returned. + + .......................................................................... + + extern int bstrListCreate (void); + + Create an empty struct bstrList. The struct bstrList output structure is + declared as follows: + + struct bstrList { + int qty, mlen; + bstring * entry; + }; + + The entry field actually is an array with qty number entries. The mlen + record counts the maximum number of bstring's for which there is memory + in the entry record. + + The Bstrlib API does *NOT* include a comprehensive set of functions for + full management of struct bstrList in an abstracted way. The reason for + this is because aliasing semantics of the list are best left to the user + of this function, and performance varies wildly depending on the + assumptions made. For a complete list of bstring data type it is + recommended that the C++ public std::vector<CBString> be used, since its + semantics are usage are more standard. + + .......................................................................... + + extern int bstrListDestroy (struct bstrList * sl); + + Destroy a struct bstrList structure that was returned by the bsplit + function. Note that this will destroy each bstring in the ->entry array + as well. See bstrListCreate() above for structure of struct bstrList. + + .......................................................................... + + extern int bstrListAlloc (struct bstrList * sl, int msz); + + Ensure that there is memory for at least msz number of entries for the + list. + + .......................................................................... + + extern int bstrListAllocMin (struct bstrList * sl, int msz); + + Try to allocate the minimum amount of memory for the list to include at + least msz entries or sl->qty whichever is greater. + + .......................................................................... + + extern struct bstrList * bsplit (bstring str, unsigned char splitChar); + + Create an array of sequential substrings from str divided by the + character splitChar. Successive occurrences of the splitChar will be + divided by empty bstring entries, following the semantics from the Python + programming language. To reclaim the memory from this output structure, + bstrListDestroy () should be called. See bstrListCreate() above for + structure of struct bstrList. + + .......................................................................... + + extern struct bstrList * bsplits (bstring str, const_bstring splitStr); + + Create an array of sequential substrings from str divided by any + character contained in splitStr. An empty splitStr causes a single entry + bstrList containing a copy of str to be returned. See bstrListCreate() + above for structure of struct bstrList. + + .......................................................................... + + extern struct bstrList * bsplitstr (bstring str, const_bstring splitStr); + + Create an array of sequential substrings from str divided by the entire + substring splitStr. An empty splitStr causes a single entry bstrList + containing a copy of str to be returned. See bstrListCreate() above for + structure of struct bstrList. + + .......................................................................... + + extern bstring bjoin (const struct bstrList * bl, const_bstring sep); + + Join the entries of a bstrList into one bstring by sequentially + concatenating them with the sep bstring in between. If sep is NULL, it + is treated as if it were the empty bstring. Note that: + + bjoin (l = bsplit (b, s->data[0]), s); + + should result in a copy of b, if s->slen is 1. If there is an error NULL + is returned, otherwise a bstring with the correct result is returned. + See bstrListCreate() above for structure of struct bstrList. + + .......................................................................... + + extern int bsplitcb (const_bstring str, unsigned char splitChar, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by the character splitChar. The parm passed to + bsplitcb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitcb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitcb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitcb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplit that is + abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern int bsplitscb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by any of the characters in splitStr. An empty + splitStr causes the whole str to be iterated once. The parm passed to + bsplitcb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitscb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitscb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitscb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplits that + is abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern int bsplitstrcb (const_bstring str, const_bstring splitStr, int pos, + int (* cb) (void * parm, int ofs, int len), void * parm); + + Iterate the set of disjoint sequential substrings over str starting at + position pos divided by the entire substring splitStr. An empty splitStr + causes each character of str to be iterated. The parm passed to bsplitcb + is passed on to cb. If the function cb returns a value < 0, then further + iterating is halted and this value is returned by bsplitcb. + + Note: Non-destructive modification of str from within the cb function + while performing this split is not undefined. bsplitstrcb behaves in + sequential lock step with calls to cb. I.e., after returning from a cb + that return a non-negative integer, bsplitstrcb continues from the position + 1 character after the last detected split character and it will halt + immediately if the length of str falls below this point. However, if the + cb function destroys str, then it *must* return with a negative value, + otherwise bsplitscb will continue in an undefined manner. + + This function is provided as an incremental alternative to bsplitstr that + is abortable and which does not impose additional memory allocation. + + .......................................................................... + + extern bstring bformat (const char * fmt, ...); + + Takes the same parameters as printf (), but rather than outputting + results to stdio, it forms a bstring which contains what would have been + output. Note that if there is an early generation of a '\0' character, + the bstring will be truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + b0 = bformat ("Hello, %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bformat function is not present. + + .......................................................................... + + extern int bformata (bstring b, const char * fmt, ...); + + In addition to the initial output buffer b, bformata takes the same + parameters as printf (), but rather than outputting results to stdio, it + appends the results to the initial bstring parameter. Note that if + there is an early generation of a '\0' character, the bstring will be + truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + bformata (b0 = bfromcstr ("Hello"), ", %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bformata function is not present. + + .......................................................................... + + extern int bassignformat (bstring b, const char * fmt, ...); + + After the first parameter, it takes the same parameters as printf (), but + rather than outputting results to stdio, it outputs the results to + the bstring parameter b. Note that if there is an early generation of a + '\0' character, the bstring will be truncated to this end point. + + Note that %s format tokens correspond to '\0' terminated char * buffers, + not bstrings. To print a bstring, first dereference data element of the + the bstring: + + /* b1->data needs to be '\0' terminated, so tagbstrings generated + by blk2tbstr () might not be suitable. */ + bassignformat (b0 = bfromcstr ("Hello"), ", %s", b1->data); + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bassignformat function is not present. + + .......................................................................... + + extern int bvcformata (bstring b, int count, const char * fmt, va_list arglist); + + The bvcformata function formats data under control of the format control + string fmt and attempts to append the result to b. The fmt parameter is + the same as that of the printf function. The variable argument list is + replaced with arglist, which has been initialized by the va_start macro. + The size of the output is upper bounded by count. If the required output + exceeds count, the string b is not augmented with any contents and a value + below BSTR_ERR is returned. If a value below -count is returned then it + is recommended that the negative of this value be used as an update to the + count in a subsequent pass. On other errors, such as running out of + memory, parameter errors or numeric wrap around BSTR_ERR is returned. + BSTR_OK is returned when the output is successfully generated and + appended to b. + + Note: There is no sanity checking of arglist, and this function is + destructive of the contents of b from the b->slen point onward. If there + is an early generation of a '\0' character, the bstring will be truncated + to this end point. + + Although this function is part of the external API for Bstrlib, the + interface and semantics (length limitations, and unusual return codes) + are fairly atypical. The real purpose for this function is to provide an + engine for the bvformata macro. + + Note that if the BSTRLIB_NOVSNP macro has been set when bstrlib has been + compiled the bvcformata function is not present. + + .......................................................................... + + extern bstring bread (bNread readPtr, void * parm); + typedef size_t (* bNread) (void *buff, size_t elsize, size_t nelem, + void *parm); + + Read an entire stream into a bstring, verbatum. The readPtr function + pointer is compatible with fread sematics, except that it need not obtain + the stream data from a file. The intention is that parm would contain + the stream data context/state required (similar to the role of the FILE* + I/O stream parameter of fread.) + + Abstracting the block read function allows for block devices other than + file streams to be read if desired. Note that there is an ANSI + compatibility issue if "fread" is used directly; see the ANSI issues + section below. + + .......................................................................... + + extern int breada (bstring b, bNread readPtr, void * parm); + + Read an entire stream and append it to a bstring, verbatum. Behaves + like bread, except that it appends it results to the bstring b. + BSTR_ERR is returned on error, otherwise 0 is returned. + + .......................................................................... + + extern bstring bgets (bNgetc getcPtr, void * parm, char terminator); + typedef int (* bNgetc) (void * parm); + + Read a bstring from a stream. As many bytes as is necessary are read + until the terminator is consumed or no more characters are available from + the stream. If read from the stream, the terminator character will be + appended to the end of the returned bstring. The getcPtr function must + have the same semantics as the fgetc C library function (i.e., returning + an integer whose value is negative when there are no more characters + available, otherwise the value of the next available unsigned character + from the stream.) The intention is that parm would contain the stream + data context/state required (similar to the role of the FILE* I/O stream + parameter of fgets.) If no characters are read, or there is some other + detectable error, NULL is returned. + + bgets will never call the getcPtr function more often than necessary to + construct its output (including a single call, if required, to determine + that the stream contains no more characters.) + + Abstracting the character stream function and terminator character allows + for different stream devices and string formats other than '\n' + terminated lines in a file if desired (consider \032 terminated email + messages, in a UNIX mailbox for example.) + + For files, this function can be used analogously as fgets as follows: + + fp = fopen ( ... ); + if (fp) b = bgets ((bNgetc) fgetc, fp, '\n'); + + (Note that only one terminator character can be used, and that '\0' is + not assumed to terminate the stream in addition to the terminator + character. This is consistent with the semantics of fgets.) + + .......................................................................... + + extern int bgetsa (bstring b, bNgetc getcPtr, void * parm, char terminator); + + Read from a stream and concatenate to a bstring. Behaves like bgets, + except that it appends it results to the bstring b. The value 1 is + returned if no characters are read before a negative result is returned + from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned + in other normal cases. + + .......................................................................... + + extern int bassigngets (bstring b, bNgetc getcPtr, void * parm, char terminator); + + Read from a stream and concatenate to a bstring. Behaves like bgets, + except that it assigns the results to the bstring b. The value 1 is + returned if no characters are read before a negative result is returned + from getcPtr. Otherwise BSTR_ERR is returned on error, and 0 is returned + in other normal cases. + + .......................................................................... + + extern struct bStream * bsopen (bNread readPtr, void * parm); + + Wrap a given open stream (described by a fread compatible function + pointer and stream handle) into an open bStream suitable for the bstring + library streaming functions. + + .......................................................................... + + extern void * bsclose (struct bStream * s); + + Close the bStream, and return the handle to the stream that was + originally used to open the given stream. If s is NULL or detectably + invalid, NULL will be returned. + + .......................................................................... + + extern int bsbufflength (struct bStream * s, int sz); + + Set the length of the buffer used by the bStream. If sz is the macro + BSTR_BS_BUFF_LENGTH_GET (which is 0), the length is not set. If s is + NULL or sz is negative, the function will return with BSTR_ERR, otherwise + this function returns with the previous length. + + .......................................................................... + + extern int bsreadln (bstring r, struct bStream * s, char terminator); + + Read a bstring terminated by the terminator character or the end of the + stream from the bStream (s) and return it into the parameter r. The + matched terminator, if found, appears at the end of the line read. If + the stream has been exhausted of all available data, before any can be + read, BSTR_ERR is returned. This function may read additional characters + into the stream buffer from the core stream that are not returned, but + will be retained for subsequent read operations. When reading from high + speed streams, this function can perform significantly faster than bgets. + + .......................................................................... + + extern int bsreadlna (bstring r, struct bStream * s, char terminator); + + Read a bstring terminated by the terminator character or the end of the + stream from the bStream (s) and concatenate it to the parameter r. The + matched terminator, if found, appears at the end of the line read. If + the stream has been exhausted of all available data, before any can be + read, BSTR_ERR is returned. This function may read additional characters + into the stream buffer from the core stream that are not returned, but + will be retained for subsequent read operations. When reading from high + speed streams, this function can perform significantly faster than bgets. + + .......................................................................... + + extern int bsreadlns (bstring r, struct bStream * s, bstring terminators); + + Read a bstring terminated by any character in the terminators bstring or + the end of the stream from the bStream (s) and return it into the + parameter r. This function may read additional characters from the core + stream that are not returned, but will be retained for subsequent read + operations. + + .......................................................................... + + extern int bsreadlnsa (bstring r, struct bStream * s, bstring terminators); + + Read a bstring terminated by any character in the terminators bstring or + the end of the stream from the bStream (s) and concatenate it to the + parameter r. If the stream has been exhausted of all available data, + before any can be read, BSTR_ERR is returned. This function may read + additional characters from the core stream that are not returned, but + will be retained for subsequent read operations. + + .......................................................................... + + extern int bsread (bstring r, struct bStream * s, int n); + + Read a bstring of length n (or, if it is fewer, as many bytes as is + remaining) from the bStream. This function will read the minimum + required number of additional characters from the core stream. When the + stream is at the end of the file BSTR_ERR is returned, otherwise BSTR_OK + is returned. + + .......................................................................... + + extern int bsreada (bstring r, struct bStream * s, int n); + + Read a bstring of length n (or, if it is fewer, as many bytes as is + remaining) from the bStream and concatenate it to the parameter r. This + function will read the minimum required number of additional characters + from the core stream. When the stream is at the end of the file BSTR_ERR + is returned, otherwise BSTR_OK is returned. + + .......................................................................... + + extern int bsunread (struct bStream * s, const_bstring b); + + Insert a bstring into the bStream at the current position. These + characters will be read prior to those that actually come from the core + stream. + + .......................................................................... + + extern int bspeek (bstring r, const struct bStream * s); + + Return the number of currently buffered characters from the bStream that + will be read prior to reads from the core stream, and append it to the + the parameter r. + + .......................................................................... + + extern int bssplitscb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); + + Iterate the set of disjoint sequential substrings over the stream s + divided by any character from the bstring splitStr. The parm passed to + bssplitscb is passed on to cb. If the function cb returns a value < 0, + then further iterating is halted and this return value is returned by + bssplitscb. + + Note: At the point of calling the cb function, the bStream pointer is + pointed exactly at the position right after having read the split + character. The cb function can act on the stream by causing the bStream + pointer to move, and bssplitscb will continue by starting the next split + at the position of the pointer after the return from cb. + + However, if the cb causes the bStream s to be destroyed then the cb must + return with a negative value, otherwise bssplitscb will continue in an + undefined manner. + + This function is provided as way to incrementally parse through a file + or other generic stream that in total size may otherwise exceed the + practical or desired memory available. As with the other split callback + based functions this is abortable and does not impose additional memory + allocation. + + .......................................................................... + + extern int bssplitstrcb (struct bStream * s, const_bstring splitStr, + int (* cb) (void * parm, int ofs, const_bstring entry), void * parm); + + Iterate the set of disjoint sequential substrings over the stream s + divided by the entire substring splitStr. The parm passed to + bssplitstrcb is passed on to cb. If the function cb returns a + value < 0, then further iterating is halted and this return value is + returned by bssplitstrcb. + + Note: At the point of calling the cb function, the bStream pointer is + pointed exactly at the position right after having read the split + character. The cb function can act on the stream by causing the bStream + pointer to move, and bssplitstrcb will continue by starting the next + split at the position of the pointer after the return from cb. + + However, if the cb causes the bStream s to be destroyed then the cb must + return with a negative value, otherwise bssplitscb will continue in an + undefined manner. + + This function is provided as way to incrementally parse through a file + or other generic stream that in total size may otherwise exceed the + practical or desired memory available. As with the other split callback + based functions this is abortable and does not impose additional memory + allocation. + + .......................................................................... + + extern int bseof (const struct bStream * s); + + Return the defacto "EOF" (end of file) state of a stream (1 if the + bStream is in an EOF state, 0 if not, and BSTR_ERR if stream is closed or + detectably erroneous.) When the readPtr callback returns a value <= 0 + the stream reaches its "EOF" state. Note that bunread with non-empty + content will essentially turn off this state, and the stream will not be + in its "EOF" state so long as its possible to read more data out of it. + + Also note that the semantics of bseof() are slightly different from + something like feof(). I.e., reaching the end of the stream does not + necessarily guarantee that bseof() will return with a value indicating + that this has happened. bseof() will only return indicating that it has + reached the "EOF" and an attempt has been made to read past the end of + the bStream. + +The macros +---------- + + The macros described below are shown in a prototype form indicating their + intended usage. Note that the parameters passed to these macros will be + referenced multiple times. As with all macros, programmer care is + required to guard against unintended side effects. + + int blengthe (const_bstring b, int err); + + Returns the length of the bstring. If the bstring is NULL err is + returned. + + .......................................................................... + + int blength (const_bstring b); + + Returns the length of the bstring. If the bstring is NULL, the length + returned is 0. + + .......................................................................... + + int bchare (const_bstring b, int p, int c); + + Returns the p'th character of the bstring b. If the position p refers to + a position that does not exist in the bstring or the bstring is NULL, + then c is returned. + + .......................................................................... + + char bchar (const_bstring b, int p); + + Returns the p'th character of the bstring b. If the position p refers to + a position that does not exist in the bstring or the bstring is NULL, + then '\0' is returned. + + .......................................................................... + + char * bdatae (bstring b, char * err); + + Returns the char * data portion of the bstring b. If b is NULL, err is + returned. + + .......................................................................... + + char * bdata (bstring b); + + Returns the char * data portion of the bstring b. If b is NULL, NULL is + returned. + + .......................................................................... + + char * bdataofse (bstring b, int ofs, char * err); + + Returns the char * data portion of the bstring b offset by ofs. If b is + NULL, err is returned. + + .......................................................................... + + char * bdataofs (bstring b, int ofs); + + Returns the char * data portion of the bstring b offset by ofs. If b is + NULL, NULL is returned. + + .......................................................................... + + struct tagbstring var = bsStatic ("..."); + + The bsStatic macro allows for static declarations of literal string + constants as struct tagbstring structures. The resulting tagbstring does + not need to be freed or destroyed. Note that this macro is only well + defined for string literal arguments. For more general string pointers, + use the btfromcstr macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + <void * blk, int len> <- bsStaticBlkParms ("...") + + The bsStaticBlkParms macro emits a pair of comma seperated parameters + corresponding to the block parameters for the block functions in Bstrlib + (i.e., blk2bstr, bcatblk, blk2tbstr, bisstemeqblk, bisstemeqcaselessblk.) + Note that this macro is only well defined for string literal arguments. + + Examples: + + bstring b = blk2bstr (bsStaticBlkParms ("Fast init. ")); + bcatblk (b, bsStaticBlkParms ("No frills fast concatenation.")); + + These are faster than using bfromcstr() and bcatcstr() respectively + because the length of the inline string is known as a compile time + constant. Also note that seperate struct tagbstring declarations for + holding the output of a bsStatic() macro are not required. + + .......................................................................... + + void btfromcstr (struct tagbstring& t, const char * s); + + Fill in the tagbstring t with the '\0' terminated char buffer s. This + action is purely reference oriented; no memory management is done. The + data member is just assigned s, and slen is assigned the strlen of s. + The s parameter is accessed exactly once in this macro. + + The resulting struct tagbstring is initially write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoke the + bwriteallow on this struct tagbstring to make it writeable (though this + requires that s be obtained from a function compatible with malloc.) + + .......................................................................... + + void btfromblk (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len. This + action is purely reference oriented; no memory management is done. The + data member of t is just assigned s, and slen is assigned len. Note that + the buffer is not appended with a '\0' character. The s and len + parameters are accessed exactly once each in this macro. + + The resulting struct tagbstring is initially write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoke the + bwriteallow on this struct tagbstring to make it writeable (though this + requires that s be obtained from a function compatible with malloc.) + + .......................................................................... + + void btfromblkltrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been left trimmed. This action is purely reference oriented; no + memory management is done. The data member of t is just assigned to a + pointer inside the buffer s. Note that the buffer is not appended with a + '\0' character. The s and len parameters are accessed exactly once each + in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void btfromblkrtrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been right trimmed. This action is purely reference oriented; no + memory management is done. The data member of t is just assigned to a + pointer inside the buffer s. Note that the buffer is not appended with a + '\0' character. The s and len parameters are accessed exactly once each + in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void btfromblktrimws (struct tagbstring& t, void * s, int len); + + Fill in the tagbstring t with the data buffer s with length len after it + has been left and right trimmed. This action is purely reference + oriented; no memory management is done. The data member of t is just + assigned to a pointer inside the buffer s. Note that the buffer is not + appended with a '\0' character. The s and len parameters are accessed + exactly once each in this macro. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. Invoking the bwriteallow macro onto this struct + tagbstring has no effect. + + .......................................................................... + + void bmid2tbstr (struct tagbstring& t, bstring b, int pos, int len); + + Fill the tagbstring t with the substring from b, starting from position + pos with a length len. The segment is clamped by the boundaries of + the bstring b. This action is purely reference oriented; no memory + management is done. Note that the buffer is not appended with a '\0' + character. Note that the t parameter to this macro may be accessed + multiple times. Note that the contents of t will become undefined + if the contents of b change or are destroyed. + + The resulting struct tagbstring is permanently write protected. Attempts + to write to this struct tagbstring in a write protected state from any + bstrlib function will lead to BSTR_ERR being returned. Invoking the + bwriteallow macro on this struct tagbstring will have no effect. + + .......................................................................... + + void bvformata (int& ret, bstring b, const char * format, lastarg); + + Append the bstring b with printf like formatting with the format control + string, and the arguments taken from the ... list of arguments after + lastarg passed to the containing function. If the containing function + does not have ... parameters or lastarg is not the last named parameter + before the ... then the results are undefined. If successful, the + results are appended to b and BSTR_OK is assigned to ret. Otherwise + BSTR_ERR is assigned to ret. + + Example: + + void dbgerror (FILE * fp, const char * fmt, ...) { + int ret; + bstring b; + bvformata (ret, b = bfromcstr ("DBG: "), fmt, fmt); + if (BSTR_OK == ret) fputs ((char *) bdata (b), fp); + bdestroy (b); + } + + Note that if the BSTRLIB_NOVSNP macro was set when bstrlib had been + compiled the bvformata macro will not link properly. If the + BSTRLIB_NOVSNP macro has been set, the bvformata macro will not be + available. + + .......................................................................... + + void bwriteprotect (struct tagbstring& t); + + Disallow bstring from being written to via the bstrlib API. Attempts to + write to the resulting tagbstring from any bstrlib function will lead to + BSTR_ERR being returned. + + Note: bstrings which are write protected cannot be destroyed via bdestroy. + + Note to C++ users: Setting a CBString as write protected will not prevent + it from being destroyed by the destructor. + + .......................................................................... + + void bwriteallow (struct tagbstring& t); + + Allow bstring to be written to via the bstrlib API. Note that such an + action makes the bstring both writable and destroyable. If the bstring is + not legitimately writable (as is the case for struct tagbstrings + initialized with a bsStatic value), the results of this are undefined. + + Note that invoking the bwriteallow macro may increase the number of + reallocs by one more than necessary for every call to bwriteallow + interleaved with any bstring API which writes to this bstring. + + .......................................................................... + + int biswriteprotected (struct tagbstring& t); + + Returns 1 if the bstring is write protected, otherwise 0 is returned. + +=============================================================================== + +The bstest module +----------------- + +The bstest module is just a unit test for the bstrlib module. For correct +implementations of bstrlib, it should execute with 0 failures being reported. +This test should be utilized if modifications/customizations to bstrlib have +been performed. It tests each core bstrlib function with bstrings of every +mode (read-only, NULL, static and mutable) and ensures that the expected +semantics are observed (including results that should indicate an error). It +also tests for aliasing support. Passing bstest is a necessary but not a +sufficient condition for ensuring the correctness of the bstrlib module. + + +The test module +--------------- + +The test module is just a unit test for the bstrwrap module. For correct +implementations of bstrwrap, it should execute with 0 failures being +reported. This test should be utilized if modifications/customizations to +bstrwrap have been performed. It tests each core bstrwrap function with +CBStrings write protected or not and ensures that the expected semantics are +observed (including expected exceptions.) Note that exceptions cannot be +disabled to run this test. Passing test is a necessary but not a sufficient +condition for ensuring the correctness of the bstrwrap module. + +=============================================================================== + +Using Bstring and CBString as an alternative to the C library +------------------------------------------------------------- + +First let us give a table of C library functions and the alternative bstring +functions and CBString methods that should be used instead of them. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +gets bgets ::gets +strcpy bassign = operator +strncpy bassignmidstr ::midstr +strcat bconcat += operator +strncat bconcat + btrunc += operator + ::trunc +strtok bsplit, bsplits ::split +sprintf b(assign)format ::format +snprintf b(assign)format + btrunc ::format + ::trunc +vsprintf bvformata bvformata + +vsnprintf bvformata + btrunc bvformata + btrunc +vfprintf bvformata + fputs use bvformata + fputs +strcmp biseq, bstrcmp comparison operators. +strncmp bstrncmp, memcmp bstrncmp, memcmp +strlen ->slen, blength ::length +strdup bstrcpy constructor +strset bpattern ::fill +strstr binstr ::find +strpbrk binchr ::findchr +stricmp bstricmp cast & use bstricmp +strlwr btolower cast & use btolower +strupr btoupper cast & use btoupper +strrev bReverse (aux module) cast & use bReverse +strchr bstrchr cast & use bstrchr +strspnp use strspn use strspn +ungetc bsunread bsunread + +The top 9 C functions listed here are troublesome in that they impose memory +management in the calling function. The Bstring and CBstring interfaces have +built-in memory management, so there is far less code with far less potential +for buffer overrun problems. strtok can only be reliably called as a "leaf" +calculation, since it (quite bizarrely) maintains hidden internal state. And +gets is well known to be broken no matter what. The Bstrlib alternatives do +not suffer from those sorts of problems. + +The substitute for strncat can be performed with higher performance by using +the blk2tbstr macro to create a presized second operand for bconcat. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +strspn strspn acceptable strspn acceptable +strcspn strcspn acceptable strcspn acceptable +strnset strnset acceptable strnset acceptable +printf printf acceptable printf acceptable +puts puts acceptable puts acceptable +fprintf fprintf acceptable fprintf acceptable +fputs fputs acceptable fputs acceptable +memcmp memcmp acceptable memcmp acceptable + +Remember that Bstring (and CBstring) functions will automatically append the +'\0' character to the character data buffer. So by simply accessing the data +buffer directly, ordinary C string library functions can be called directly +on them. Note that bstrcmp is not the same as memcmp in exactly the same way +that strcmp is not the same as memcmp. + +C-library Bstring alternative CBString alternative +--------- ------------------- -------------------- +fread balloc + fread ::alloc + fread +fgets balloc + fgets ::alloc + fgets + +These are odd ones because of the exact sizing of the buffer required. The +Bstring and CBString alternatives requires that the buffers are forced to +hold at least the prescribed length, then just use fread or fgets directly. +However, typically the automatic memory management of Bstring and CBstring +will make the typical use of fgets and fread to read specifically sized +strings unnecessary. + +Implementation Choices +---------------------- + +Overhead: +......... + +The bstring library has more overhead versus straight char buffers for most +functions. This overhead is essentially just the memory management and +string header allocation. This overhead usually only shows up for small +string manipulations. The performance loss has to be considered in +light of the following: + +1) What would be the performance loss of trying to write this management + code in one's own application? +2) Since the bstring library source code is given, a sufficiently powerful + modern inlining globally optimizing compiler can remove function call + overhead. + +Since the data type is exposed, a developer can replace any unsatisfactory +function with their own inline implementation. And that is besides the main +point of what the better string library is mainly meant to provide. Any +overhead lost has to be compared against the value of the safe abstraction +for coupling memory management and string functionality. + +Performance of the C interface: +............................... + +The algorithms used have performance advantages versus the analogous C +library functions. For example: + +1. bfromcstr/blk2str/bstrcpy versus strcpy/strdup. By using memmove instead + of strcpy, the break condition of the copy loop is based on an independent + counter (that should be allocated in a register) rather than having to + check the results of the load. Modern out-of-order executing CPUs can + parallelize the final branch mis-predict penality with the loading of the + source string. Some CPUs will also tend to have better built-in hardware + support for counted memory moves than load-compare-store. (This is a + minor, but non-zero gain.) +2. biseq versus strcmp. If the strings are unequal in length, bsiseq will + return in O(1) time. If the strings are aliased, or have aliased data + buffers, biseq will return in O(1) time. strcmp will always be O(k), + where k is the length of the common prefix or the whole string if they are + identical. +3. ->slen versus strlen. ->slen is obviously always O(1), while strlen is + always O(n) where n is the length of the string. +4. bconcat versus strcat. Both rely on precomputing the length of the + destination string argument, which will favor the bstring library. On + iterated concatenations the performance difference can be enormous. +5. bsreadln versus fgets. The bsreadln function reads large blocks at a time + from the given stream, then parses out lines from the buffers directly. + Some C libraries will implement fgets as a loop over single fgetc calls. + Testing indicates that the bsreadln approach can be several times faster + for fast stream devices (such as a file that has been entirely cached.) +6. bsplits/bsplitscb versus strspn. Accelerators for the set of match + characters are generated only once. +7. binstr versus strstr. The binstr implementation unrolls the loops to + help reduce loop overhead. This will matter if the target string is + long and source string is not found very early in the target string. + With strstr, while it is possible to unroll the source contents, it is + not possible to do so with the destination contents in a way that is + effective because every destination character must be tested against + '\0' before proceeding to the next character. +8. bReverse versus strrev. The C function must find the end of the string + first before swaping character pairs. +9. bstrrchr versus no comparable C function. Its not hard to write some C + code to search for a character from the end going backwards. But there + is no way to do this without computing the length of the string with + strlen. + +Practical testing indicates that in general Bstrlib is never signifcantly +slower than the C library for common operations, while very often having a +performance advantage that ranges from significant to massive. Even for +functions like b(n)inchr versus str(c)spn() (where, in theory, there is no +advantage for the Bstrlib architecture) the performance of Bstrlib is vastly +superior to most tested C library implementations. + +Some of Bstrlib's extra functionality also lead to inevitable performance +advantages over typical C solutions. For example, using the blk2tbstr macro, +one can (in O(1) time) generate an internal substring by reference while not +disturbing the original string. If disturbing the original string is not an +option, typically, a comparable char * solution would have to make a copy of +the substring to provide similar functionality. Another example is reverse +character set scanning -- the str(c)spn functions only scan in a forward +direction which can complicate some parsing algorithms. + +Where high performance char * based algorithms are available, Bstrlib can +still leverage them by accessing the ->data field on bstrings. So +realistically Bstrlib can never be significantly slower than any standard +'\0' terminated char * based solutions. + +Performance of the C++ interface: +................................. + +The C++ interface has been designed with an emphasis on abstraction and safety +first. However, since it is substantially a wrapper for the C bstring +functions, for longer strings the performance comments described in the +"Performance of the C interface" section above still apply. Note that the +(CBString *) type can be directly cast to a (bstring) type, and passed as +parameters to the C functions (though a CBString must never be passed to +bdestroy.) + +Probably the most controversial choice is performing full bounds checking on +the [] operator. This decision was made because 1) the fast alternative of +not bounds checking is still available by first casting the CBString to a +(const char *) buffer or to a (struct tagbstring) then derefencing .data and +2) because the lack of bounds checking is seen as one of the main weaknesses +of C/C++ versus other languages. This check being done on every access leads +to individual character extraction being actually slower than other languages +in this one respect (other language's compilers will normally dedicate more +resources on hoisting or removing bounds checking as necessary) but otherwise +bring C++ up to the level of other languages in terms of functionality. + +It is common for other C++ libraries to leverage the abstractions provided by +C++ to use reference counting and "copy on write" policies. While these +techniques can speed up some scenarios, they impose a problem with respect to +thread safety. bstrings and CBStrings can be properly protected with +"per-object" mutexes, meaning that two bstrlib calls can be made and execute +simultaneously, so long as the bstrings and CBstrings are distinct. With a +reference count and alias before copy on write policy, global mutexes are +required that prevent multiple calls to the strings library to execute +simultaneously regardless of whether or not the strings represent the same +string. + +One interesting trade off in CBString is that the default constructor is not +trivial. I.e., it always prepares a ready to use memory buffer. The purpose +is to ensure that there is a uniform internal composition for any functioning +CBString that is compatible with bstrings. It also means that the other +methods in the class are not forced to perform "late initialization" checks. +In the end it means that construction of CBStrings are slower than other +comparable C++ string classes. Initial testing, however, indicates that +CBString outperforms std::string and MFC's CString, for example, in all other +operations. So to work around this weakness it is recommended that CBString +declarations be pushed outside of inner loops. + +Practical testing indicates that with the exception of the caveats given +above (constructors and safe index character manipulations) the C++ API for +Bstrlib generally outperforms popular standard C++ string classes. Amongst +the standard libraries and compilers, the quality of concatenation operations +varies wildly and very little care has gone into search functions. Bstrlib +dominates those performance benchmarks. + +Memory management: +.................. + +The bstring functions which write and modify bstrings will automatically +reallocate the backing memory for the char buffer whenever it is required to +grow. The algorithm for resizing chosen is to snap up to sizes that are a +power of two which are sufficient to hold the intended new size. Memory +reallocation is not performed when the required size of the buffer is +decreased. This behavior can be relied on, and is necessary to make the +behaviour of balloc deterministic. This trades off additional memory usage +for decreasing the frequency for required reallocations: + +1. For any bstring whose size never exceeds n, its buffer is not ever + reallocated more than log_2(n) times for its lifetime. +2. For any bstring whose size never exceeds n, its buffer is never more than + 2*(n+1) in length. (The extra characters beyond 2*n are to allow for the + implicit '\0' which is always added by the bstring modifying functions.) + +Decreasing the buffer size when the string decreases in size would violate 1) +above and in real world case lead to pathological heap thrashing. Similarly, +allocating more tightly than "least power of 2 greater than necessary" would +lead to a violation of 1) and have the same potential for heap thrashing. + +Property 2) needs emphasizing. Although the memory allocated is always a +power of 2, for a bstring that grows linearly in size, its buffer memory also +grows linearly, not exponentially. The reason is that the amount of extra +space increases with each reallocation, which decreases the frequency of +future reallocations. + +Obviously, given that bstring writing functions may reallocate the data +buffer backing the target bstring, one should not attempt to cache the data +buffer address and use it after such bstring functions have been called. +This includes making reference struct tagbstrings which alias to a writable +bstring. + +balloc or bfromcstralloc can be used to preallocate the minimum amount of +space used for a given bstring. This will reduce even further the number of +times the data portion is reallocated. If the length of the string is never +more than one less than the memory length then there will be no further +reallocations. + +Note that invoking the bwriteallow macro may increase the number of reallocs +by one more than necessary for every call to bwriteallow interleaved with any +bstring API which writes to this bstring. + +The library does not use any mechanism for automatic clean up for the C API. +Thus explicit clean up via calls to bdestroy() are required to avoid memory +leaks. + +Constant and static tagbstrings: +................................ + +A struct tagbstring can be write protected from any bstrlib function using +the bwriteprotect macro. A write protected struct tagbstring can then be +reset to being writable via the bwriteallow macro. There is, of course, no +protection from attempts to directly access the bstring members. Modifying a +bstring which is write protected by direct access has undefined behavior. + +static struct tagbstrings can be declared via the bsStatic macro. They are +considered permanently unwritable. Such struct tagbstrings's are declared +such that attempts to write to it are not well defined. Invoking either +bwriteallow or bwriteprotect on static struct tagbstrings has no effect. + +struct tagbstring's initialized via btfromcstr or blk2tbstr are protected by +default but can be made writeable via the bwriteallow macro. If bwriteallow +is called on such struct tagbstring's, it is the programmer's responsibility +to ensure that: + +1) the buffer supplied was allocated from the heap. +2) bdestroy is not called on this tagbstring (unless the header itself has + also been allocated from the heap.) +3) free is called on the buffer to reclaim its memory. + +bwriteallow and bwriteprotect can be invoked on ordinary bstrings (they have +to be dereferenced with the (*) operator to get the levels of indirection +correct) to give them write protection. + +Buffer declaration: +................... + +The memory buffer is actually declared "unsigned char *" instead of "char *". +The reason for this is to trigger compiler warnings whenever uncasted char +buffers are assigned to the data portion of a bstring. This will draw more +diligent programmers into taking a second look at the code where they +have carelessly left off the typically required cast. (Research from +AT&T/Lucent indicates that additional programmer eyeballs is one of the most +effective mechanisms at ferreting out bugs.) + +Function pointers: +.................. + +The bgets, bread and bStream functions use function pointers to obtain +strings from data streams. The function pointer declarations have been +specifically chosen to be compatible with the fgetc and fread functions. +While this may seem to be a convoluted way of implementing fgets and fread +style functionality, it has been specifically designed this way to ensure +that there is no dependency on a single narrowly defined set of device +interfaces, such as just stream I/O. In the embedded world, its quite +possible to have environments where such interfaces may not exist in the +standard C library form. Furthermore, the generalization that this opens up +allows for more sophisticated uses for these functions (performing an fgets +like function on a socket, for example.) By using function pointers, it also +allows such abstract stream interfaces to be created using the bstring library +itself while not creating a circular dependency. + +Use of int's for sizes: +....................... + +This is just a recognition that 16bit platforms with requirements for strings +that are larger than 64K and 32bit+ platforms with requirements for strings +that are larger than 4GB are pretty marginal. The main focus is for 32bit +platforms, and emerging 64bit platforms with reasonable < 4GB string +requirements. Using ints allows for negative values which has meaning +internally to bstrlib. + +Semantic consideration: +....................... + +Certain care needs to be taken when copying and aliasing bstrings. A bstring +is essentially a pointer type which points to a multipart abstract data +structure. Thus usage, and lifetime of bstrings have semantics that follow +these considerations. For example: + + bstring a, b; + struct tagbstring t; + + a = bfromcstr("Hello"); /* Create new bstring and copy "Hello" into it. */ + b = a; /* Alias b to the contents of a. */ + t = *a; /* Create a current instance pseudo-alias of a. */ + bconcat (a, b); /* Double a and b, t is now undefined. */ + bdestroy (a); /* Destroy the contents of both a and b. */ + +Variables of type bstring are really just references that point to real +bstring objects. The equal operator (=) creates aliases, and the asterisk +dereference operator (*) creates a kind of alias to the current instance (which +is generally not useful for any purpose.) Using bstrcpy() is the correct way +of creating duplicate instances. The ampersand operator (&) is useful for +creating aliases to struct tagbstrings (remembering that constructed struct +tagbstrings are not writable by default.) + +CBStrings use complete copy semantics for the equal operator (=), and thus do +not have these sorts of issues. + +Debugging: +.......... + +Bstrings have a simple, exposed definition and construction, and the library +itself is open source. So most debugging is going to be fairly straight- +forward. But the memory for bstrings come from the heap, which can often be +corrupted indirectly, and it might not be obvious what has happened even from +direct examination of the contents in a debugger or a core dump. There are +some tools such as Purify, Insure++ and Electric Fence which can help solve +such problems, however another common approach is to directly instrument the +calls to malloc, realloc, calloc, free, memcpy, memmove and/or other calls +by overriding them with macro definitions. + +Although the user could hack on the Bstrlib sources directly as necessary to +perform such an instrumentation, Bstrlib comes with a built-in mechanism for +doing this. By defining the macro BSTRLIB_MEMORY_DEBUG and providing an +include file named memdbg.h this will force the core Bstrlib modules to +attempt to include this file. In such a file, macros could be defined which +overrides Bstrlib's useage of the C standard library. + +Rather than calling malloc, realloc, free, memcpy or memmove directly, Bstrlib +emits the macros bstr__alloc, bstr__realloc, bstr__free, bstr__memcpy and +bstr__memmove in their place respectively. By default these macros are simply +assigned to be equivalent to their corresponding C standard library function +call. However, if they are given earlier macro definitions (via the back +door include file) they will not be given their default definition. In this +way Bstrlib's interface to the standard library can be changed but without +having to directly redefine or link standard library symbols (both of which +are not strictly ANSI C compliant.) + +An example definition might include: + + #define bstr__alloc(sz) X_malloc ((sz), __LINE__, __FILE__) + +which might help contextualize heap entries in a debugging environment. + +The NULL parameter and sanity checking of bstrings is part of the Bstrlib +API, and thus Bstrlib itself does not present any different modes which would +correspond to "Debug" or "Release" modes. Bstrlib always contains mechanisms +which one might think of as debugging features, but retains the performance +and small memory footprint one would normally associate with release mode +code. + +Integration Microsoft's Visual Studio debugger: +............................................... + +Microsoft's Visual Studio debugger has a capability of customizable mouse +float over data type descriptions. This is accomplished by editting the +AUTOEXP.DAT file to include the following: + + ; new for CBString + tagbstring =slen=<slen> mlen=<mlen> <data,st> + Bstrlib::CBStringList =count=<size()> + +In Visual C++ 6.0 this file is located in the directory: + + C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin + +and in Visual Studio .NET 2003 its located here: + + C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger + +This will improve the ability of debugging with Bstrlib under Visual Studio. + +Security +-------- + +Bstrlib does not come with explicit security features outside of its fairly +comprehensive error detection, coupled with its strict semantic support. +That is to say that certain common security problems, such as buffer overrun, +constant overwrite, arbitrary truncation etc, are far less likely to happen +inadvertently. Where it does help, Bstrlib maximizes its advantage by +providing developers a simple adoption path that lets them leave less secure +string mechanisms behind. The library will not leave developers wanting, so +they will be less likely to add new code using a less secure string library +to add functionality that might be missing from Bstrlib. + +That said there are a number of security ideas not addressed by Bstrlib: + +1. Race condition exploitation (i.e., verifying a string's contents, then +raising the privilege level and execute it as a shell command as two +non-atomic steps) is well beyond the scope of what Bstrlib can provide. It +should be noted that MFC's built-in string mutex actually does not solve this +problem either -- it just removes immediate data corruption as a possible +outcome of such exploit attempts (it can be argued that this is worse, since +it will leave no trace of the exploitation). In general race conditions have +to be dealt with by careful design and implementation; it cannot be assisted +by a string library. + +2. Any kind of access control or security attributes to prevent usage in +dangerous interfaces such as system(). Perl includes a "trust" attribute +which can be endowed upon strings that are intended to be passed to such +dangerous interfaces. However, Perl's solution reflects its own limitations +-- notably that it is not a strongly typed language. In the example code for +Bstrlib, there is a module called taint.cpp. It demonstrates how to write a +simple wrapper class for managing "untainted" or trusted strings using the +type system to prevent questionable mixing of ordinary untrusted strings with +untainted ones then passing them to dangerous interfaces. In this way the +security correctness of the code reduces to auditing the direct usages of +dangerous interfaces or promotions of tainted strings to untainted ones. + +3. Encryption of string contents is way beyond the scope of Bstrlib. +Maintaining encrypted string contents in the futile hopes of thwarting things +like using system-level debuggers to examine sensitive string data is likely +to be a wasted effort (imagine a debugger that runs at a higher level than a +virtual processor where the application runs). For more standard encryption +usages, since the bstring contents are simply binary blocks of data, this +should pose no problem for usage with other standard encryption libraries. + +Compatibility +------------- + +The Better String Library is known to compile and function correctly with the +following compilers: + + - Microsoft Visual C++ + - Watcom C/C++ + - Intel's C/C++ compiler (Windows) + - The GNU C/C++ compiler (cygwin and Linux on PPC64) + - Borland C + - Turbo C + +Setting of configuration options should be unnecessary for these compilers +(unless exceptions are being disabled or STLport has been added to WATCOM +C/C++). Bstrlib has been developed with an emphasis on portability. As such +porting it to other compilers should be straight forward. This package +includes a porting guide (called porting.txt) which explains what issues may +exist for porting Bstrlib to different compilers and environments. + +ANSI issues +----------- + +1. The function pointer types bNgetc and bNread have prototypes which are very +similar to, but not exactly the same as fgetc and fread respectively. +Basically the FILE * parameter is replaced by void *. The purpose of this +was to allow one to create other functions with fgetc and fread like +semantics without being tied to ANSI C's file streaming mechanism. I.e., one +could very easily adapt it to sockets, or simply reading a block of memory, +or procedurally generated strings (for fractal generation, for example.) + +The problem is that invoking the functions (bNgetc)fgetc and (bNread)fread is +not technically legal in ANSI C. The reason being that the compiler is only +able to coerce the function pointers themselves into the target type, however +are unable to perform any cast (implicit or otherwise) on the parameters +passed once invoked. I.e., if internally void * and FILE * need some kind of +mechanical coercion, the compiler will not properly perform this conversion +and thus lead to undefined behavior. + +Apparently a platform from Data General called "Eclipse" and another from +Tandem called "NonStop" have a different representation for pointers to bytes +and pointers to words, for example, where coercion via casting is necessary. +(Actual confirmation of the existence of such machines is hard to come by, so +it is prudent to be skeptical about this information.) However, this is not +an issue for any known contemporary platforms. One may conclude that such +platforms are effectively apocryphal even if they do exist. + +To correctly work around this problem to the satisfaction of the ANSI +limitations, one needs to create wrapper functions for fgets and/or +fread with the prototypes of bNgetc and/or bNread respectively which performs +no other action other than to explicitely cast the void * parameter to a +FILE *, and simply pass the remaining parameters straight to the function +pointer call. + +The wrappers themselves are trivial: + + size_t freadWrap (void * buff, size_t esz, size_t eqty, void * parm) { + return fread (buff, esz, eqty, (FILE *) parm); + } + + int fgetcWrap (void * parm) { + return fgetc ((FILE *) parm); + } + +These have not been supplied in bstrlib or bstraux to prevent unnecessary +linking with file I/O functions. + +2. vsnprintf is not available on all compilers. Because of this, the bformat +and bformata functions (and format and formata methods) are not guaranteed to +work properly. For those compilers that don't have vsnprintf, the +BSTRLIB_NOVSNP macro should be set before compiling bstrlib, and the format +functions/method will be disabled. + +The more recent ANSI C standards have specified the required inclusion of a +vsnprintf function. + +3. The bstrlib function names are not unique in the first 6 characters. This +is only an issue for older C compiler environments which do not store more +than 6 characters for function names. + +4. The bsafe module defines macros and function names which are part of the +C library. This simply overrides the definition as expected on all platforms +tested, however it is not sanctioned by the ANSI standard. This module is +clearly optional and should be omitted on platforms which disallow its +undefined semantics. + +In practice the real issue is that some compilers in some modes of operation +can/will inline these standard library functions on a module by module basis +as they appear in each. The linker will thus have no opportunity to override +the implementation of these functions for those cases. This can lead to +inconsistent behaviour of the bsafe module on different platforms and +compilers. + +=============================================================================== + +Comparison with Microsoft's CString class +----------------------------------------- + +Although developed independently, CBStrings have very similar functionality to +Microsoft's CString class. However, the bstring library has significant +advantages over CString: + +1. Bstrlib is a C-library as well as a C++ library (using the C++ wrapper). + + - Thus it is compatible with more programming environments and + available to a wider population of programmers. + +2. The internal structure of a bstring is considered exposed. + + - A single contiguous block of data can be cut into read-only pieces by + simply creating headers, without allocating additional memory to create + reference copies of each of these sub-strings. + - In this way, using bstrings in a totally abstracted way becomes a choice + rather than an imposition. Further this choice can be made differently + at different layers of applications that use it. + +3. Static declaration support precludes the need for constructor + invocation. + + - Allows for static declarations of constant strings that has no + additional constructor overhead. + +4. Bstrlib is not attached to another library. + + - Bstrlib is designed to be easily plugged into any other library + collection, without dependencies on other libraries or paradigms (such + as "MFC".) + +The bstring library also comes with a few additional functions that are not +available in the CString class: + + - bsetstr + - bsplit + - bread + - breplace (this is different from CString::Replace()) + - Writable indexed characters (for example a[i]='x') + +Interestingly, although Microsoft did implement mid$(), left$() and right$() +functional analogues (these are functions from GWBASIC) they seem to have +forgotten that mid$() could be also used to write into the middle of a string. +This functionality exists in Bstrlib with the bsetstr() and breplace() +functions. + +Among the disadvantages of Bstrlib is that there is no special support for +localization or wide characters. Such things are considered beyond the scope +of what bstrings are trying to deliver. CString essentially supports the +older UCS-2 version of Unicode via widechar_t as an application-wide compile +time switch. + +CString's also use built-in mechanisms for ensuring thread safety under all +situations. While this makes writing thread safe code that much easier, this +built-in safety feature has a price -- the inner loops of each CString method +runs in its own critical section (grabbing and releasing a light weight mutex +on every operation.) The usual way to decrease the impact of a critical +section performance penalty is to amortize more operations per critical +section. But since the implementation of CStrings is fixed as a one critical +section per-operation cost, there is no way to leverage this common +performance enhancing idea. + +The search facilities in Bstrlib are comparable to those in MFC's CString +class, though it is missing locale specific collation. But because Bstrlib +is interoperable with C's char buffers, it will allow programmers to write +their own string searching mechanism (such as Boyer-Moore), or be able to +choose from a variety of available existing string searching libraries (such +as those for regular expressions) without difficulty. + +Microsoft used a very non-ANSI conforming trick in its implementation to +allow printf() to use the "%s" specifier to output a CString correctly. This +can be convenient, but it is inherently not portable. CBString requires an +explicit cast, while bstring requires the data member to be dereferenced. +Microsoft's own documentation recommends casting, instead of relying on this +feature. + +Comparison with C++'s std::string +--------------------------------- + +This is the C++ language's standard STL based string class. + +1. There is no C implementation. +2. The [] operator is not bounds checked. +3. Missing a lot of useful functions like printf-like formatting. +4. Some sub-standard std::string implementations (SGI) are necessarily unsafe + to use with multithreading. +5. Limited by STL's std::iostream which in turn is limited by ifstream which + can only take input from files. (Compare to CBStream's API which can take + abstracted input.) +6. Extremely uneven performance across implementations. + +Comparison with ISO C TR 24731 proposal +--------------------------------------- + +Following the ISO C99 standard, Microsoft has proposed a group of C library +extensions which are supposedly "safer and more secure". This proposal is +expected to be adopted by the ISO C standard which follows C99. + +The proposal reveals itself to be very similar to Microsoft's "StrSafe" +library. The functions are basically the same as other standard C library +string functions except that destination parameters are paired with an +additional length parameter of type rsize_t. rsize_t is the same as size_t, +however, the range is checked to make sure its between 1 and RSIZE_MAX. Like +Bstrlib, the functions perform a "parameter check". Unlike Bstrlib, when a +parameter check fails, rather than simply outputing accumulatable error +statuses, they call a user settable global error function handler, and upon +return of control performs no (additional) detrimental action. The proposal +covers basic string functions as well as a few non-reenterable functions +(asctime, ctime, and strtok). + +1. Still based solely on char * buffers (and therefore strlen() and strcat() + is still O(n), and there are no faster streq() comparison functions.) +2. No growable string semantics. +3. Requires manual buffer length synchronization in the source code. +4. No attempt to enhance functionality of the C library. +5. Introduces a new error scenario (strings exceeding RSIZE_MAX length). + +The hope is that by exposing the buffer length requirements there will be +fewer buffer overrun errors. However, the error modes are really just +transformed, rather than removed. The real problem of buffer overflows is +that they all happen as a result of erroneous programming. So forcing +programmers to manually deal with buffer limits, will make them more aware of +the problem but doesn't remove the possibility of erroneous programming. So +a programmer that erroneously mixes up the rsize_t parameters is no better off +from a programmer that introduces potential buffer overflows through other +more typical lapses. So at best this may reduce the rate of erroneous +programming, rather than making any attempt at removing failure modes. + +The error handler can discriminate between types of failures, but does not +take into account any callsite context. So the problem is that the error is +going to be manifest in a piece of code, but there is no pointer to that +code. It would seem that passing in the call site __FILE__, __LINE__ as +parameters would be very useful, but the API clearly doesn't support such a +thing (it would increase code bloat even more than the extra length +parameter does, and would require macro tricks to implement). + +The Bstrlib C API takes the position that error handling needs to be done at +the callsite, and just tries to make it as painless as possible. Furthermore, +error modes are removed by supporting auto-growing strings and aliasing. For +capturing errors in more central code fragments, Bstrlib's C++ API uses +exception handling extensively, which is superior to the leaf-only error +handler approach. + +Comparison with Managed String Library CERT proposal +---------------------------------------------------- + +The main webpage for the managed string library: +http://www.cert.org/secure-coding/managedstring.html + +Robert Seacord at CERT has proposed a C string library that he calls the +"Managed String Library" for C. Like Bstrlib, it introduces a new type +which is called a managed string. The structure of a managed string +(string_m) is like a struct tagbstring but missing the length field. This +internal structure is considered opaque. The length is, like the C standard +library, always computed on the fly by searching for a terminating NUL on +every operation that requires it. So it suffers from every performance +problem that the C standard library suffers from. Interoperating with C +string APIs (like printf, fopen, or anything else that takes a string +parameter) requires copying to additionally allocating buffers that have to +be manually freed -- this makes this library probably slower and more +cumbersome than any other string library in existence. + +The library gives a fully populated error status as the return value of every +string function. The hope is to be able to diagnose all problems +specifically from the return code alone. Comparing this to Bstrlib, which +aways returns one consistent error message, might make it seem that Bstrlib +would be harder to debug; but this is not true. With Bstrlib, if an error +occurs there is always enough information from just knowing there was an error +and examining the parameters to deduce exactly what kind of error has +happened. The managed string library thus gives up nested function calls +while achieving little benefit, while Bstrlib does not. + +One interesting feature that "managed strings" has is the idea of data +sanitization via character set whitelisting. That is to say, a globally +definable filter that makes any attempt to put invalid characters into strings +lead to an error and not modify the string. The author gives the following +example: + + // create valid char set + if (retValue = strcreate_m(&str1, "abc") ) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + if (retValue = setcharset(str1)) { + fprintf( + stderr, + "Error %d from setcharset().\n", + retValue + ); + } + if (retValue = strcreate_m(&str1, "aabbccabc")) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + // create string with invalid char set + if (retValue = strcreate_m(&str1, "abbccdabc")) { + fprintf( + stderr, + "Error %d from strcreate_m.\n", + retValue + ); + } + +Which we can compare with a more Bstrlib way of doing things: + + bstring bCreateWithFilter (const char * cstr, const_bstring filter) { + bstring b = bfromcstr (cstr); + if (BSTR_ERR != bninchr (b, filter) && NULL != b) { + fprintf (stderr, "Filter violation.\n"); + bdestroy (b); + b = NULL; + } + return b; + } + + struct tagbstring charFilter = bsStatic ("abc"); + bstring str1 = bCreateWithFilter ("aabbccabc", &charFilter); + bstring str2 = bCreateWithFilter ("aabbccdabc", &charFilter); + +The first thing we should notice is that with the Bstrlib approach you can +have different filters for different strings if necessary. Furthermore, +selecting a charset filter in the Managed String Library is uni-contextual. +That is to say, there can only be one such filter active for the entire +program, which means its usage is not well defined for intermediate library +usage (a library that uses it will interfere with user code that uses it, and +vice versa.) It is also likely to be poorly defined in multi-threading +environments. + +There is also a question as to whether the data sanitization filter is checked +on every operation, or just on creation operations. Since the charset can be +set arbitrarily at run time, it might be set *after* some managed strings have +been created. This would seem to imply that all functions should run this +additional check every time if there is an attempt to enforce this. This +would make things tremendously slow. On the other hand, if it is assumed that +only creates and other operations that take char *'s as input need be checked +because the charset was only supposed to be called once at and before any +other managed string was created, then one can see that its easy to cover +Bstrlib with equivalent functionality via a few wrapper calls such as the +example given above. + +And finally we have to question the value of sanitation in the first place. +For example, for httpd servers, there is generally a requirement that the +URLs parsed have some form that avoids undesirable translation to local file +system filenames or resources. The problem is that the way URLs can be +encoded, it must be completely parsed and translated to know if it is using +certain invalid character combinations. That is to say, merely filtering +each character one at a time is not necessarily the right way to ensure that +a string has safe contents. + +In the article that describes this proposal, it is claimed that it fairly +closely approximates the existing C API semantics. On this point we should +compare this "closeness" with Bstrlib: + + Bstrlib Managed String Library + ------- ---------------------- + +Pointer arithmetic Segment arithmetic N/A + +Use in C Std lib ->data, or bdata{e} getstr_m(x,*) ... free(x) + +String literals bsStatic, bsStaticBlk strcreate_m() + +Transparency Complete None + +Its pretty clear that the semantic mapping from C strings to Bstrlib is fairly +straightforward, and that in general semantic capabilities are the same or +superior in Bstrlib. On the other hand the Managed String Library is either +missing semantics or changes things fairly significantly. + +Comparison with Annexia's c2lib library +--------------------------------------- + +This library is available at: +http://www.annexia.org/freeware/c2lib + +1. Still based solely on char * buffers (and therefore strlen() and strcat() + is still O(n), and there are no faster streq() comparison functions.) + Their suggestion that alternatives which wrap the string data type (such as + bstring does) imposes a difficulty in interoperating with the C langauge's + ordinary C string library is not founded. +2. Introduction of memory (and vector?) abstractions imposes a learning + curve, and some kind of memory usage policy that is outside of the strings + themselves (and therefore must be maintained by the developer.) +3. The API is massive, and filled with all sorts of trivial (pjoin) and + controvertial (pmatch -- regular expression are not sufficiently + standardized, and there is a very large difference in performance between + compiled and non-compiled, REs) functions. Bstrlib takes a decidely + minimal approach -- none of the functionality in c2lib is difficult or + challenging to implement on top of Bstrlib (except the regex stuff, which + is going to be difficult, and controvertial no matter what.) +4. Understanding why c2lib is the way it is pretty much requires a working + knowledge of Perl. bstrlib requires only knowledge of the C string library + while providing just a very select few worthwhile extras. +5. It is attached to a lot of cruft like a matrix math library (that doesn't + include any functions for getting the determinant, eigenvectors, + eigenvalues, the matrix inverse, test for singularity, test for + orthogonality, a grahm schmit orthogonlization, LU decomposition ... I + mean why bother?) + +Convincing a development house to use c2lib is likely quite difficult. It +introduces too much, while not being part of any kind of standards body. The +code must therefore be trusted, or maintained by those that use it. While +bstring offers nothing more on this front, since its so much smaller, covers +far less in terms of scope, and will typically improve string performance, +the barrier to usage should be much smaller. + +Comparison with stralloc/qmail +------------------------------ + +More information about this library can be found here: +http://www.canonical.org/~kragen/stralloc.html or here: +http://cr.yp.to/lib/stralloc.html + +1. Library is very very minimal. A little too minimal. +2. Untargetted source parameters are not declared const. +3. Slightly different expected emphasis (like _cats function which takes an + ordinary C string char buffer as a parameter.) Its clear that the + remainder of the C string library is still required to perform more + useful string operations. + +The struct declaration for their string header is essentially the same as that +for bstring. But its clear that this was a quickly written hack whose goals +are clearly a subset of what Bstrlib supplies. For anyone who is served by +stralloc, Bstrlib is complete substitute that just adds more functionality. + +stralloc actually uses the interesting policy that a NULL data pointer +indicates an empty string. In this way, non-static empty strings can be +declared without construction. This advantage is minimal, since static empty +bstrings can be declared inline without construction, and if the string needs +to be written to it should be constructed from an empty string (or its first +initializer) in any event. + +wxString class +-------------- + +This is the string class used in the wxWindows project. A description of +wxString can be found here: +http://www.wxwindows.org/manuals/2.4.2/wx368.htm#wxstring + +This C++ library is similar to CBString. However, it is littered with +trivial functions (IsAscii, UpperCase, RemoveLast etc.) + +1. There is no C implementation. +2. The memory management strategy is to allocate a bounded fixed amount of + additional space on each resize, meaning that it does not have the + log_2(n) property that Bstrlib has (it will thrash very easily, cause + massive fragmentation in common heap implementations, and can easily be a + common source of performance problems). +3. The library uses a "copy on write" strategy, meaning that it has to deal + with multithreading problems. + +Vstr +---- + +This is a highly orthogonal C string library with an emphasis on +networking/realtime programming. It can be found here: +http://www.and.org/vstr/ + +1. The convoluted internal structure does not contain a '\0' char * compatible + buffer, so interoperability with the C library a non-starter. +2. The API and implementation is very large (owing to its orthogonality) and + can lead to difficulty in understanding its exact functionality. +3. An obvious dependency on gnu tools (confusing make configure step) +4. Uses a reference counting system, meaning that it is not likely to be + thread safe. + +The implementation has an extreme emphasis on performance for nontrivial +actions (adds, inserts and deletes are all constant or roughly O(#operations) +time) following the "zero copy" principle. This trades off performance of +trivial functions (character access, char buffer access/coersion, alias +detection) which becomes significantly slower, as well as incremental +accumulative costs for its searching/parsing functions. Whether or not Vstr +wins any particular performance benchmark will depend a lot on the benchmark, +but it should handily win on some, while losing dreadfully on others. + +The learning curve for Vstr is very steep, and it doesn't come with any +obvious way to build for Windows or other platforms without gnu tools. At +least one mechanism (the iterator) introduces a new undefined scenario +(writing to a Vstr while iterating through it.) Vstr has a very large +footprint, and is very ambitious in its total functionality. Vstr has no C++ +API. + +Vstr usage requires context initialization via vstr_init() which must be run +in a thread-local context. Given the totally reference based architecture +this means that sharing Vstrings across threads is not well defined, or at +least not safe from race conditions. This API is clearly geared to the older +standard of fork() style multitasking in UNIX, and is not safely transportable +to modern shared memory multithreading available in Linux and Windows. There +is no portable external solution making the library thread safe (since it +requires a mutex around each Vstr context -- not each string.) + +In the documentation for this library, a big deal is made of its self hosted +s(n)printf-like function. This is an issue for older compilers that don't +include vsnprintf(), but also an issue because Vstr has a slow conversion to +'\0' terminated char * mechanism. That is to say, using "%s" to format data +that originates from Vstr would be slow without some sort of native function +to do so. Bstrlib sidesteps the issue by relying on what snprintf-like +functionality does exist and having a high performance conversion to a char * +compatible string so that "%s" can be used directly. + +Str Library +----------- + +This is a fairly extensive string library, that includes full unicode support +and targetted at the goal of out performing MFC and STL. The architecture, +similarly to MFC's CStrings, is a copy on write reference counting mechanism. + +http://www.utilitycode.com/str/default.aspx + +1. Commercial. +2. C++ only. + +This library, like Vstr, uses a ref counting system. There is only so deeply +I can analyze it, since I don't have a license for it. However, performance +improvements over MFC's and STL, doesn't seem like a sufficient reason to +move your source base to it. For example, in the future, Microsoft may +improve the performance CString. + +It should be pointed out that performance testing of Bstrlib has indicated +that its relative performance advantage versus MFC's CString and STL's +std::string is at least as high as that for the Str library. + +libmib astrings +--------------- + +A handful of functional extensions to the C library that add dynamic string +functionality. +http://www.mibsoftware.com/libmib/astring/ + +This package basically references strings through char ** pointers and assumes +they are pointing to the top of an allocated heap entry (or NULL, in which +case memory will be newly allocated from the heap.) So its still up to user +to mix and match the older C string functions with these functions whenever +pointer arithmetic is used (i.e., there is no leveraging of the type system +to assert semantic differences between references and base strings as Bstrlib +does since no new types are introduced.) Unlike Bstrlib, exact string length +meta data is not stored, thus requiring a strlen() call on *every* string +writing operation. The library is very small, covering only a handful of C's +functions. + +While this is better than nothing, it is clearly slower than even the +standard C library, less safe and less functional than Bstrlib. + +To explain the advantage of using libmib, their website shows an example of +how dangerous C code: + + char buf[256]; + char *pszExtraPath = ";/usr/local/bin"; + + strcpy(buf,getenv("PATH")); /* oops! could overrun! */ + strcat(buf,pszExtraPath); /* Could overrun as well! */ + + printf("Checking...%s\n",buf); /* Some printfs overrun too! */ + +is avoided using libmib: + + char *pasz = 0; /* Must initialize to 0 */ + char *paszOut = 0; + char *pszExtraPath = ";/usr/local/bin"; + + if (!astrcpy(&pasz,getenv("PATH"))) /* malloc error */ exit(-1); + if (!astrcat(&pasz,pszExtraPath)) /* malloc error */ exit(-1); + + /* Finally, a "limitless" printf! we can use */ + asprintf(&paszOut,"Checking...%s\n",pasz);fputs(paszOut,stdout); + + astrfree(&pasz); /* Can use free(pasz) also. */ + astrfree(&paszOut); + +However, compare this to Bstrlib: + + bstring b, out; + + bcatcstr (b = bfromcstr (getenv ("PATH")), ";/usr/local/bin"); + out = bformat ("Checking...%s\n", bdatae (b, "<Out of memory>")); + /* if (out && b) */ fputs (bdatae (out, "<Out of memory>"), stdout); + bdestroy (b); + bdestroy (out); + +Besides being shorter, we can see that error handling can be deferred right +to the very end. Also, unlike the above two versions, if getenv() returns +with NULL, the Bstrlib version will not exhibit undefined behavior. +Initialization starts with the relevant content rather than an extra +autoinitialization step. + +libclc +------ + +An attempt to add to the standard C library with a number of common useful +functions, including additional string functions. +http://libclc.sourceforge.net/ + +1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass + the responsibility to guard against aliasing to the programmer. +2. Adds no safety or memory management whatsoever. +3. Most of the supplied string functions are completely trivial. + +The goals of libclc and Bstrlib are clearly quite different. + +fireString +---------- + +http://firestuff.org/ + +1. Uses standard char * buffer, and adopts C 99's usage of "restrict" to pass + the responsibility to guard against aliasing to the programmer. +2. Mixes char * and length wrapped buffers (estr) functions, doubling the API + size, with safety limited to only half of the functions. + +Firestring was originally just a wrapper of char * functionality with extra +length parameters. However, it has been augmented with the inclusion of the +estr type which has similar functionality to stralloc. But firestring does +not nearly cover the functional scope of Bstrlib. + +Safe C String Library +--------------------- + +A library written for the purpose of increasing safety and power to C's string +handling capabilities. +http://www.zork.org/safestr/safestr.html + +1. While the safestr_* functions are safe in of themselves, interoperating + with char * string has dangerous unsafe modes of operation. +2. The architecture of safestr's causes the base pointer to change. Thus, + its not practical/safe to store a safestr in multiple locations if any + single instance can be manipulated. +3. Dependent on an additional error handling library. +4. Uses reference counting, meaning that it is either not thread safe or + slow and not portable. + +I think the idea of reallocating (and hence potentially changing) the base +pointer is a serious design flaw that is fatal to this architecture. True +safety is obtained by having automatic handling of all common scenarios +without creating implicit constraints on the user. + +Because of its automatic temporary clean up system, it cannot use "const" +semantics on input arguments. Interesting anomolies such as: + + safestr_t s, t; + s = safestr_replace (t = SAFESTR_TEMP ("This is a test"), + SAFESTR_TEMP (" "), SAFESTR_TEMP (".")); + /* t is now undefined. */ + +are possible. If one defines a function which takes a safestr_t as a +parameter, then the function would not know whether or not the safestr_t is +defined after it passes it to a safestr library function. The author +recommended method for working around this problem is to examine the +attributes of the safestr_t within the function which is to modify any of +its parameters and play games with its reference count. I think, therefore, +that the whole SAFESTR_TEMP idea is also fatally broken. + +The library implements immutability, optional non-resizability, and a "trust" +flag. This trust flag is interesting, and suggests that applying any +arbitrary sequence of safestr_* function calls on any set of trusted strings +will result in a trusted string. It seems to me, however, that if one wanted +to implement a trusted string semantic, one might do so by actually creating +a different *type* and only implement the subset of string functions that are +deemed safe (i.e., user input would be excluded, for example.) This, in +essence, would allow the compiler to enforce trust propogation at compile +time rather than run time. Non-resizability is also interesting, however, +it seems marginal (i.e., to want a string that cannot be resized, yet can be +modified and yet where a fixed sized buffer is undesirable.) + +=============================================================================== + +Examples +-------- + + Dumping a line numbered file: + + FILE * fp; + int i, ret; + struct bstrList * lines; + struct tagbstring prefix = bsStatic ("-> "); + + if (NULL != (fp = fopen ("bstrlib.txt", "rb"))) { + bstring b = bread ((bNread) fread, fp); + fclose (fp); + if (NULL != (lines = bsplit (b, '\n'))) { + for (i=0; i < lines->qty; i++) { + binsert (lines->entry[i], 0, &prefix, '?'); + printf ("%04d: %s\n", i, bdatae (lines->entry[i], "NULL")); + } + bstrListDestroy (lines); + } + bdestroy (b); + } + +For numerous other examples, see bstraux.c, bstraux.h and the example archive. + +=============================================================================== + +License +------- + +The Better String Library is available under either the 3 clause BSD license +(see the accompanying license.txt) or the Gnu Public License version 2 (see +the accompanying gpl.txt) at the option of the user. + +=============================================================================== + +Acknowledgements +---------------- + +The following individuals have made significant contributions to the design +and testing of the Better String Library: + +Bjorn Augestad +Clint Olsen +Darryl Bleau +Fabian Cenedese +Graham Wideman +Ignacio Burgueno +International Business Machines Corporation +Ira Mica +John Kortink +Manuel Woelker +Marcel van Kervinck +Michael Hsieh +Richard A. Smith +Simon Ekstrom +Wayne Scott + +=============================================================================== diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt new file mode 100644 index 0000000000..cf78a984cc --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/license.txt @@ -0,0 +1,29 @@ +Copyright (c) 2002-2008 Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + Neither the name of bstrlib nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt new file mode 100644 index 0000000000..11d8d13130 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/porting.txt @@ -0,0 +1,172 @@ +Better String library Porting Guide +----------------------------------- + +by Paul Hsieh + +The bstring library is an attempt to provide improved string processing +functionality to the C and C++ language. At the heart of the bstring library +is the management of "bstring"s which are a significant improvement over '\0' +terminated char buffers. See the accompanying documenation file bstrlib.txt +for more information. + +=============================================================================== + +Identifying the Compiler +------------------------ + +Bstrlib has been tested on the following compilers: + + Microsoft Visual C++ + Watcom C/C++ (32 bit flat) + Intel's C/C++ compiler (on Windows) + The GNU C/C++ compiler (on Windows/Linux on x86 and PPC64) + Borland C++ + Turbo C + +There are slight differences in these compilers which requires slight +differences in the implementation of Bstrlib. These are accomodated in the +same sources using #ifdef/#if defined() on compiler specific macros. To +port Bstrlib to a new compiler not listed above, it is recommended that the +same strategy be followed. If you are unaware of the compiler specific +identifying preprocessor macro for your compiler you might find it here: + +http://predef.sourceforge.net/precomp.html + +Note that Intel C/C++ on Windows sets the Microsoft identifier: _MSC_VER. + +16-bit vs. 32-bit vs. 64-bit Systems +------------------------------------ + +Bstrlib has been architected to deal with strings of length between 0 and +INT_MAX (inclusive). Since the values of int are never higher than size_t +there will be no issue here. Note that on most 64-bit systems int is 32-bit. + +Dependency on The C-Library +--------------------------- + +Bstrlib uses the functions memcpy, memmove, malloc, realloc, free and +vsnprintf. Many free standing C compiler implementations that have a mode in +which the C library is not available will typically not include these +functions which will make porting Bstrlib to it onerous. Bstrlib is not +designed for such bare bones compiler environments. This usually includes +compilers that target ROM environments. + +Porting Issues +-------------- + +Bstrlib has been written completely in ANSI/ISO C and ISO C++, however, there +are still a few porting issues. These are described below. + +1. The vsnprintf () function. + +Unfortunately, the earlier ANSI/ISO C standards did not include this function. +If the compiler of interest does not support this function then the +BSTRLIB_NOVSNP should be defined via something like: + + #if !defined (BSTRLIB_VSNP_OK) && !defined (BSTRLIB_NOVSNP) + # if defined (__TURBOC__) || defined (__COMPILERVENDORSPECIFICMACRO__) + # define BSTRLIB_NOVSNP + # endif + #endif + +which appears at the top of bstrlib.h. Note that the bformat(a) functions +will not be declared or implemented if the BSTRLIB_NOVSNP macro is set. If +the compiler has renamed vsnprintf() to some other named function, then +search for the definition of the exvsnprintf macro in bstrlib.c file and be +sure its defined appropriately: + + #if defined (__COMPILERVENDORSPECIFICMACRO__) + # define exvsnprintf(r,b,n,f,a) {r=__compiler_specific_vsnprintf(b,n,f,a);} + #else + # define exvsnprintf(r,b,n,f,a) {r=vsnprintf(b,n,f,a);} + #endif + +Take notice of the return value being captured in the variable r. It is +assumed that r exceeds n if and only if the underlying vsnprintf function has +determined what the true maximal output length would be for output if the +buffer were large enough to hold it. Non-modern implementations must output a +lesser number (the macro can and should be modified to ensure this). + +2. Weak C++ compiler. + +C++ is a much more complicated language to implement than C. This has lead +to varying quality of compiler implementations. The weaknesses isolated in +the initial ports are inclusion of the Standard Template Library, +std::iostream and exception handling. By default it is assumed that the C++ +compiler supports all of these things correctly. If your compiler does not +support one or more of these define the corresponding macro: + + BSTRLIB_CANNOT_USE_STL + BSTRLIB_CANNOT_USE_IOSTREAM + BSTRLIB_DOESNT_THROW_EXCEPTIONS + +The compiler specific detected macro should be defined at the top of +bstrwrap.h in the Configuration defines section. Note that these disabling +macros can be overrided with the associated enabling macro if a subsequent +version of the compiler gains support. (For example, its possible to rig +up STLport to provide STL support for WATCOM C/C++, so -DBSTRLIB_CAN_USE_STL +can be passed in as a compiler option.) + +3. The bsafe module, and reserved words. + +The bsafe module is in gross violation of the ANSI/ISO C standard in the +sense that it redefines what could be implemented as reserved words on a +given compiler. The typical problem is that a compiler may inline some of the +functions and thus not be properly overridden by the definitions in the bsafe +module. It is also possible that a compiler may prohibit the redefinitions in +the bsafe module. Compiler specific action will be required to deal with +these situations. + +Platform Specific Files +----------------------- + +The makefiles for the examples are basically setup of for particular +environments for each platform. In general these makefiles are not portable +and should be constructed as necessary from scratch for each platform. + +Testing a port +-------------- + +To test that a port compiles correctly do the following: + +1. Build a sample project that includes the bstrlib, bstraux, bstrwrap, and + bsafe modules. +2. Compile bstest against the bstrlib module. +3. Run bstest and ensure that 0 errors are reported. +4. Compile test against the bstrlib and bstrwrap modules. +5. Run test and ensure that 0 errors are reported. +6. Compile each of the examples (except for the "re" example, which may be + complicated and is not a real test of bstrlib and except for the mfcbench + example which is Windows specific.) +7. Run each of the examples. + +The builds must have 0 errors, and should have the absolute minimum number of +warnings (in most cases can be reduced to 0.) The result of execution should +be essentially identical on each platform. + +Performance +----------- + +Different CPU and compilers have different capabilities in terms of +performance. It is possible for Bstrlib to assume performance +characteristics that a platform doesn't have (since it was primarily +developed on just one platform). The goal of Bstrlib is to provide very good +performance on all platforms regardless of this but without resorting to +extreme measures (such as using assembly language, or non-portable intrinsics +or library extensions.) + +There are two performance benchmarks that can be found in the example/ +directory. They are: cbench.c and cppbench.cpp. These are variations and +expansions of a benchmark for another string library. They don't cover all +string functionality, but do include the most basic functions which will be +common in most string manipulation kernels. + +............................................................................... + +Feedback +-------- + +In all cases, you may email issues found to the primary author of Bstrlib at +the email address: websnarf@users.sourceforge.net + +=============================================================================== diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt new file mode 100644 index 0000000000..9761409f56 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/cbstring/security.txt @@ -0,0 +1,221 @@ +Better String library Security Statement +---------------------------------------- + +by Paul Hsieh + +=============================================================================== + +Introduction +------------ + +The Better String library (hereafter referred to as Bstrlib) is an attempt to +provide improved string processing functionality to the C and C++ languages. +At the heart of the Bstrlib is the management of "bstring"s which are a +significant improvement over '\0' terminated char buffers. See the +accompanying documenation file bstrlib.txt for more information. + +DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Like any software, there is always a possibility of failure due to a flawed +implementation. Nevertheless a good faith effort has been made to minimize +such flaws in Bstrlib. Also, use of Bstrlib by itself will not make an +application secure or free from implementation failures. However, it is the +author's conviction that use of Bstrlib can greatly facilitate the creation +of software meeting the highest possible standards of security. + +Part of the reason why this document has been created, is for the purpose of +security auditing, or the creation of further "Statements on Security" for +software that is created that uses Bstrlib. An auditor may check the claims +below against Bstrlib, and use this as a basis for analysis of software which +uses Bstrlib. + +=============================================================================== + +Statement on Security +--------------------- + +This is a document intended to give consumers of the Better String Library +who are interested in security an idea of where the Better String Library +stands on various security issues. Any deviation observed in the actual +library itself from the descriptions below should be considered an +implementation error, not a design flaw. + +This statement is not an analytical proof of correctness or an outline of one +but rather an assertion similar to a scientific claim or hypothesis. By use, +testing and open independent examination (otherwise known as scientific +falsifiability), the credibility of the claims made below can rise to the +level of an established theory. + +Common security issues: +....................... + +1. Buffer Overflows + +The Bstrlib API allows the programmer a way to deal with strings without +having to deal with the buffers containing them. Ordinary usage of the +Bstrlib API itself makes buffer overflows impossible. + +Furthermore, the Bstrlib API has a superset of basic string functionality as +compared to the C library's char * functions, C++'s std::string class and +Microsoft's MFC based CString class. It also has abstracted mechanisms for +dealing with IO. This is important as it gives developers a way of migrating +all their code from a functionality point of view. + +2. Memory size overflow/wrap around attack + +Bstrlib is, by design, impervious to memory size overflow attacks. The +reason is it is resiliant to length overflows is that bstring lengths are +bounded above by INT_MAX, instead of ~(size_t)0. So length addition +overflows cause a wrap around of the integer value making them negative +causing balloc() to fail before an erroneous operation can occurr. Attempted +conversions of char * strings which may have lengths greater than INT_MAX are +detected and the conversion is aborted. + +It is unknown if this property holds on machines that don't represent +integers as 2s complement. It is recommended that Bstrlib be carefully +auditted by anyone using a system which is not 2s complement based. + +3. Constant string protection + +Bstrlib implements runtime enforced constant and read-only string semantics. +I.e., bstrings which are declared as constant via the bsStatic() macro cannot +be modified or deallocated directly through the Bstrlib API, and this cannot +be subverted by casting or other type coercion. This is independent of the +use of the const_bstring data type. + +The Bstrlib C API uses the type const_bstring to specify bstring parameters +whose contents do not change. Although the C language cannot enforce this, +this is nevertheless guaranteed by the implementation of the Bstrlib library +of C functions. The C++ API enforces the const attribute on CBString types +correctly. + +4. Aliased bstring support + +Bstrlib detects and supports aliased parameter management throughout the API. +The kind of aliasing that is allowed is the one where pointers of the same +basic type may be pointing to overlapping objects (this is the assumption the +ANSI C99 specification makes.) Each function behaves as if all read-only +parameters were copied to temporaries which are used in their stead before +the function is enacted (it rarely actually does this). No function in the +Bstrlib uses the "restrict" parameter attribute from the ANSI C99 +specification. + +5. Information leaking + +In bstraux.h, using the semantically equivalent macros bSecureDestroy() and +bSecureWriteProtect() in place of bdestroy() and bwriteprotect() respectively +will ensure that stale data does not linger in the heap's free space after +strings have been released back to memory. Created bstrings or CBStrings +are not linked to anything external to themselves, and thus cannot expose +deterministic data leaking. If a bstring is resized, the preimage may exist +as a copy that is released to the heap. Thus for sensitive data, the bstring +should be sufficiently presized before manipulated so that it is not resized. +bSecureInput() has been supplied in bstraux.c, which can be used to obtain +input securely without any risk of leaving any part of the input image in the +heap except for the allocated bstring that is returned. + +6. Memory leaking + +Bstrlib can be built using memdbg.h enabled via the BSTRLIB_MEMORY_DEBUG +macro. User generated definitions for malloc, realloc and free can then be +supplied which can implement special strategies for memory corruption +detection or memory leaking. Otherwise, bstrlib does not do anything out of +the ordinary to attempt to deal with the standard problem of memory leaking +(i.e., losing references to allocated memory) when programming in the C and +C++ languages. However, it does not compound the problem any more than exists +either, as it doesn't have any intrinsic inescapable leaks in it. Bstrlib +does not preclude the use of automatic garbage collection mechanisms such as +the Boehm garbage collector. + +7. Encryption + +Bstrlib does not present any built-in encryption mechanism. However, it +supports full binary contents in its data buffers, so any standard block +based encryption mechanism can make direct use of bstrings/CBStrings for +buffer management. + +8. Double freeing + +Freeing a pointer that is already free is an extremely rare, but nevertheless +a potentially ruthlessly corrupting operation (its possible to cause Win 98 to +reboot, by calling free mulitiple times on already freed data using the WATCOM +CRT.) Bstrlib invalidates the bstring header data before freeing, so that in +many cases a double free will be detected and an error will be reported +(though this behaviour is not guaranteed and should not be relied on). + +Using bstrFree pervasively (instead of bdestroy) can lead to somewhat +improved invalid free avoidance (it is completely safe whenever bstring +instances are only stored in unique variables). For example: + + struct tagbstring hw = bsStatic ("Hello, world"); + bstring cpHw = bstrcpy (&hw); + + #ifdef NOT_QUITE_AS_SAFE + bdestroy (cpHw); /* Never fail */ + bdestroy (cpHw); /* Error sometimes detected at runtime */ + bdestroy (&hw); /* Error detected at run time */ + #else + bstrFree (cpHw); /* Never fail */ + bstrFree (cpHw); /* Will do nothing */ + bstrFree (&hw); /* Will lead to a compile time error */ + #endif + +9. Resource based denial of service + +bSecureInput() has been supplied in bstraux.c. It has an optional upper limit +for input length. But unlike fgets(), it is also easily determined if the +buffer has been truncated early. In this way, a program can set an upper limit +on input sizes while still allowing for implementing context specific +truncation semantics (i.e., does the program consume but dump the extra +input, or does it consume it in later inputs?) + +10. Mixing char *'s and bstrings + +The bstring and char * representations are not identical. So there is a risk +when converting back and forth that data may lost. Essentially bstrings can +contain '\0' as a valid non-terminating character, while char * strings +cannot and in fact must use the character as a terminator. The risk of data +loss is very low, since: + + A) the simple method of only using bstrings in a char * semantically + compatible way is both easy to achieve and pervasively supported. + B) obtaining '\0' content in a string is either deliberate or indicative + of another, likely more serious problem in the code. + C) the library comes with various functions which deal with this issue + (namely: bfromcstr(), bstr2cstr (), and bSetCstrChar ()) + +Marginal security issues: +......................... + +11. 8-bit versus 9-bit portability + +Bstrlib uses CHAR_BIT and other limits.h constants to the maximum extent +possible to avoid portability problems. However, Bstrlib has not been tested +on any system that does not represent char as 8-bits. So whether or not it +works on 9-bit systems is an open question. It is recommended that Bstrlib be +carefully auditted by anyone using a system in which CHAR_BIT is not 8. + +12. EBCDIC/ASCII/UTF-8 data representation attacks. + +Bstrlib uses ctype.h functions to ensure that it remains portable to non- +ASCII systems. It also checks range to make sure it is well defined even for +data that ANSI does not define for the ctype functions. + +Obscure issues: +............... + +13. Data attributes + +There is no support for a Perl-like "taint" attribute, however, an example of +how to do this using C++'s type system is given as an example. + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c b/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c new file mode 100644 index 0000000000..ce19d481d7 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/decode.c @@ -0,0 +1,1750 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/tokens.h" +#include "internal_includes/structs.h" +#include "internal_includes/decode.h" +#include "stdlib.h" +#include "stdio.h" +#include "internal_includes/reflect.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/toGLSLOperand.h" + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) +enum +{ + FOURCC_DXBC = FOURCC('D', 'X', 'B', 'C') +}; //DirectX byte code +enum +{ + FOURCC_SHDR = FOURCC('S', 'H', 'D', 'R') +}; //Shader model 4 code +enum +{ + FOURCC_SHEX = FOURCC('S', 'H', 'E', 'X') +}; //Shader model 5 code +enum +{ + FOURCC_RDEF = FOURCC('R', 'D', 'E', 'F') +}; //Resource definition (e.g. constant buffers) +enum +{ + FOURCC_ISGN = FOURCC('I', 'S', 'G', 'N') +}; //Input signature +enum +{ + FOURCC_IFCE = FOURCC('I', 'F', 'C', 'E') +}; //Interface (for dynamic linking) +enum +{ + FOURCC_OSGN = FOURCC('O', 'S', 'G', 'N') +}; //Output signature +enum +{ + FOURCC_PSGN = FOURCC('P', 'C', 'S', 'G') +}; //Patch-constant signature +enum +{ + FOURCC_FX10 = FOURCC('F', 'X', '1', '0') +}; //Effects 10 Binary data + +enum +{ + FOURCC_ISG1 = FOURCC('I', 'S', 'G', '1') +}; //Input signature with Stream and MinPrecision +enum +{ + FOURCC_OSG1 = FOURCC('O', 'S', 'G', '1') +}; //Output signature with Stream and MinPrecision +enum +{ + FOURCC_OSG5 = FOURCC('O', 'S', 'G', '5') +}; //Output signature with Stream + +typedef struct DXBCContainerHeaderTAG +{ + unsigned fourcc; + uint32_t unk[4]; + uint32_t one; + uint32_t totalSize; + uint32_t chunkCount; +} DXBCContainerHeader; + +typedef struct DXBCChunkHeaderTAG +{ + unsigned fourcc; + unsigned size; +} DXBCChunkHeader; + +#ifdef _DEBUG +static uint64_t operandID = 0; +static uint64_t instructionID = 0; +#endif + +#if defined(_WIN32) +#define osSprintf(dest, size, src) sprintf_s(dest, size, src) +#else +#define osSprintf(dest, size, src) sprintf(dest, src) +#endif + +void DecodeNameToken(const uint32_t* pui32NameToken, Operand* psOperand) +{ + const size_t MAX_BUFFER_SIZE = sizeof(psOperand->pszSpecialName); + psOperand->eSpecialName = DecodeOperandSpecialName(*pui32NameToken); + switch (psOperand->eSpecialName) + { + case NAME_UNDEFINED: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "undefined"); + break; + } + case NAME_POSITION: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "position"); + break; + } + case NAME_CLIP_DISTANCE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "clipDistance"); + break; + } + case NAME_CULL_DISTANCE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "cullDistance"); + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "renderTargetArrayIndex"); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "viewportArrayIndex"); + break; + } + case NAME_VERTEX_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "vertexID"); + break; + } + case NAME_PRIMITIVE_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "primitiveID"); + break; + } + case NAME_INSTANCE_ID: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "instanceID"); + break; + } + case NAME_IS_FRONT_FACE: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "isFrontFace"); + break; + } + case NAME_SAMPLE_INDEX: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "sampleIndex"); + break; + } + //For the quadrilateral domain, there are 6 factors (4 sides, 2 inner). + case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: + case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: + case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: + + //For the triangular domain, there are 4 factors (3 sides, 1 inner) + case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: + case NAME_FINAL_TRI_INSIDE_TESSFACTOR: + + //For the isoline domain, there are 2 factors (detail and density). + case NAME_FINAL_LINE_DETAIL_TESSFACTOR: + case NAME_FINAL_LINE_DENSITY_TESSFACTOR: + { + osSprintf(psOperand->pszSpecialName, MAX_BUFFER_SIZE, "tessFactor"); + break; + } + default: + { + ASSERT(0); + break; + } + } + + return; +} + +// Find the declaration of the texture described by psTextureOperand and +// mark it as a shadow type. (e.g. accessed via sampler2DShadow rather than sampler2D) +void MarkTextureAsShadow(ShaderInfo* psShaderInfo, Declaration* psDeclList, const uint32_t ui32DeclCount, const Operand* psTextureOperand) +{ + (void)psShaderInfo; + + Declaration* psDecl = psDeclList; + uint32_t i; + + ASSERT(psTextureOperand->eType == OPERAND_TYPE_RESOURCE); + + for (i = 0; i < ui32DeclCount; ++i) + { + if (psDecl->eOpcode == OPCODE_DCL_RESOURCE) + { + if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && + psDecl->asOperands[0].ui32RegisterNumber == psTextureOperand->ui32RegisterNumber) + { + psDecl->ui32IsShadowTex = 1; + break; + } + } + psDecl++; + } +} + +// Search through the list. Return the index if the value is found, return 0xffffffff if not found +static uint32_t Find(uint32_t* psList, uint32_t ui32Count, uint32_t ui32Value) +{ + uint32_t i; + for (i = 0; i < ui32Count; i++) + { + if (psList[i] == ui32Value) + { + return i; + } + } + return 0xffffffff; +} + +void MarkTextureSamplerPair(ShaderInfo* psShaderInfo, Declaration* psDeclList, const uint32_t ui32DeclCount, const Operand* psTextureOperand, const Operand* psSamplerOperand, TextureSamplerInfo* psTextureSamplerInfo) +{ + Declaration* psDecl = psDeclList; + uint32_t i; + bstring combinedname; + const char* cstr; + + ASSERT(psTextureOperand->eType == OPERAND_TYPE_RESOURCE); + ASSERT(psSamplerOperand->eType == OPERAND_TYPE_SAMPLER); + + for (i = 0; i < ui32DeclCount; ++i) + { + if (psDecl->eOpcode == OPCODE_DCL_RESOURCE) + { + if (psDecl->asOperands[0].eType == OPERAND_TYPE_RESOURCE && + psDecl->asOperands[0].ui32RegisterNumber == psTextureOperand->ui32RegisterNumber) + { + // psDecl is the texture resource referenced by psTextureOperand + ASSERT(psDecl->ui32SamplerUsedCount < MAX_TEXTURE_SAMPLERS_PAIRS); + + // add psSamplerOperand->ui32RegisterNumber to list of samplers that use this texture + if (Find(psDecl->ui32SamplerUsed, psDecl->ui32SamplerUsedCount, psSamplerOperand->ui32RegisterNumber) == 0xffffffff) + { + psDecl->ui32SamplerUsed[psDecl->ui32SamplerUsedCount++] = psSamplerOperand->ui32RegisterNumber; + + // Record the texturename_X_samplername string in the TextureSamplerPair array that we return to the client + ASSERT(psTextureSamplerInfo->ui32NumTextureSamplerPairs < MAX_RESOURCE_BINDINGS); + combinedname = TextureSamplerName(psShaderInfo, psTextureOperand->ui32RegisterNumber, psSamplerOperand->ui32RegisterNumber, psDecl->ui32IsShadowTex); + cstr = bstr2cstr(combinedname, '\0'); + bdestroy(combinedname); + strcpy(psTextureSamplerInfo->aTextureSamplerPair[psTextureSamplerInfo->ui32NumTextureSamplerPairs++].Name, cstr); + } + break; + } + } + psDecl++; + } +} + +uint32_t DecodeOperand (const uint32_t* pui32Tokens, Operand* psOperand) +{ + int i; + uint32_t ui32NumTokens = 1; + OPERAND_NUM_COMPONENTS eNumComponents; + +#ifdef _DEBUG + psOperand->id = operandID++; +#endif + + //Some defaults + psOperand->iWriteMaskEnabled = 1; + psOperand->iGSInput = 0; + psOperand->aeDataType[0] = SVT_FLOAT; + psOperand->aeDataType[1] = SVT_FLOAT; + psOperand->aeDataType[2] = SVT_FLOAT; + psOperand->aeDataType[3] = SVT_FLOAT; + + psOperand->iExtended = DecodeIsOperandExtended(*pui32Tokens); + + + psOperand->eModifier = OPERAND_MODIFIER_NONE; + psOperand->psSubOperand[0] = 0; + psOperand->psSubOperand[1] = 0; + psOperand->psSubOperand[2] = 0; + + psOperand->eMinPrecision = OPERAND_MIN_PRECISION_DEFAULT; + + /* Check if this instruction is extended. If it is, + * we need to print the information first */ + if (psOperand->iExtended) + { + /* OperandToken1 is the second token */ + ui32NumTokens++; + + if (DecodeExtendedOperandType(pui32Tokens[1]) == EXTENDED_OPERAND_MODIFIER) + { + psOperand->eModifier = DecodeExtendedOperandModifier(pui32Tokens[1]); + psOperand->eMinPrecision = DecodeOperandMinPrecision(pui32Tokens[1]); + } + } + + psOperand->iIndexDims = DecodeOperandIndexDimension(*pui32Tokens); + psOperand->eType = DecodeOperandType(*pui32Tokens); + + psOperand->ui32RegisterNumber = 0; + + eNumComponents = DecodeOperandNumComponents(*pui32Tokens); + + if (psOperand->eType == OPERAND_TYPE_INPUT_GS_INSTANCE_ID) + { + eNumComponents = OPERAND_1_COMPONENT; + psOperand->aeDataType[0] = SVT_UINT; + } + + switch (eNumComponents) + { + case OPERAND_1_COMPONENT: + { + psOperand->iNumComponents = 1; + break; + } + case OPERAND_4_COMPONENT: + { + psOperand->iNumComponents = 4; + break; + } + default: + { + psOperand->iNumComponents = 0; + break; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + psOperand->eSelMode = DecodeOperand4CompSelMode(*pui32Tokens); + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + psOperand->ui32CompMask = DecodeOperand4CompMask(*pui32Tokens); + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + psOperand->ui32Swizzle = DecodeOperand4CompSwizzle(*pui32Tokens); + + if (psOperand->ui32Swizzle != NO_SWIZZLE) + { + psOperand->aui32Swizzle[0] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 0); + psOperand->aui32Swizzle[1] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 1); + psOperand->aui32Swizzle[2] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 2); + psOperand->aui32Swizzle[3] = DecodeOperand4CompSwizzleSource(*pui32Tokens, 3); + } + else + { + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; + psOperand->aui32Swizzle[1] = OPERAND_4_COMPONENT_Y; + psOperand->aui32Swizzle[2] = OPERAND_4_COMPONENT_Z; + psOperand->aui32Swizzle[3] = OPERAND_4_COMPONENT_W; + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psOperand->aui32Swizzle[0] = DecodeOperand4CompSel1(*pui32Tokens); + } + } + + //Set externally to this function based on the instruction opcode. + psOperand->iIntegerImmediate = 0; + + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) + { + for (i = 0; i < psOperand->iNumComponents; ++i) + { + psOperand->afImmediates[i] = *((float*)(&pui32Tokens[ui32NumTokens])); + ui32NumTokens++; + } + } + else + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + for (i = 0; i < psOperand->iNumComponents; ++i) + { + psOperand->adImmediates[i] = *((double*)(&pui32Tokens[ui32NumTokens])); + ui32NumTokens += 2; + } + } + + if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) + { + psOperand->ui32RegisterNumber = -1; + psOperand->ui32CompMask = -1; + } + + for (i = 0; i < psOperand->iIndexDims; ++i) + { + OPERAND_INDEX_REPRESENTATION eRep = DecodeOperandIndexRepresentation(i, *pui32Tokens); + + psOperand->eIndexRep[i] = eRep; + + psOperand->aui32ArraySizes[i] = 0; + psOperand->ui32RegisterNumber = 0; + + switch (eRep) + { + case OPERAND_INDEX_IMMEDIATE32: + { + psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); + psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; + break; + } + case OPERAND_INDEX_RELATIVE: + { + psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); + DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); + + ui32NumTokens++; + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + psOperand->ui32RegisterNumber = *(pui32Tokens + ui32NumTokens); + psOperand->aui32ArraySizes[i] = psOperand->ui32RegisterNumber; + + ui32NumTokens++; + + psOperand->psSubOperand[i] = hlslcc_malloc(sizeof(Operand)); + DecodeOperand(pui32Tokens + ui32NumTokens, psOperand->psSubOperand[i]); + + ui32NumTokens++; + break; + } + default: + { + ASSERT(0); + break; + } + } + + ui32NumTokens++; + } + + psOperand->pszSpecialName[0] = '\0'; + + return ui32NumTokens; +} + +const uint32_t* DecodeDeclaration(ShaderData* psShader, const uint32_t* pui32Token, Declaration* psDecl) +{ + uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); + const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); + const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); + uint32_t ui32OperandOffset = 1; + + if (eOpcode < NUM_OPCODES && eOpcode >= 0) + { + psShader->aiOpcodeUsed[eOpcode] = 1; + } + + psDecl->eOpcode = eOpcode; + + psDecl->ui32IsShadowTex = 0; + + if (bExtended) + { + ui32OperandOffset = 2; + } + + switch (eOpcode) + { + case OPCODE_DCL_RESOURCE: // DCL* opcodes have + { + psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); + psDecl->ui32NumOperands = 1; + psDecl->ui32SamplerUsedCount = 0; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. + { + psDecl->value.eCBAccessPattern = DecodeConstantBufferAccessPattern(*pui32Token); + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_SAMPLER: + { + ResourceBinding* psBinding = 0; + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_SAMPLER && + GetResourceFromBindingPoint(RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding)) + { + psDecl->bIsComparisonSampler = psBinding->ui32Flags & SHADER_INPUT_FLAG_COMPARISON_SAMPLER; + } + break; + } + case OPCODE_DCL_INDEX_RANGE: + { + psDecl->ui32NumOperands = 1; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + psDecl->value.ui32IndexRange = pui32Token[ui32OperandOffset]; + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) + { + uint32_t i; + const uint32_t indexRange = psDecl->value.ui32IndexRange; + const uint32_t reg = psDecl->asOperands[0].ui32RegisterNumber; + + psShader->aIndexedInput[reg] = indexRange; + psShader->aIndexedInputParents[reg] = reg; + + //-1 means don't declare this input because it falls in + //the range of an already declared array. + for (i = reg + 1; i < reg + indexRange; ++i) + { + psShader->aIndexedInput[i] = -1; + psShader->aIndexedInputParents[i] = reg; + } + } + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) + { + psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.ui32IndexRange; + } + break; + } + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + { + psDecl->value.eOutputPrimitiveTopology = DecodeGSOutputPrimitiveTopology(*pui32Token); + break; + } + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + { + psDecl->value.eInputPrimitive = DecodeGSInputPrimitive(*pui32Token); + break; + } + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + psDecl->value.ui32MaxOutputVertexCount = pui32Token[1]; + break; + } + case OPCODE_DCL_TESS_PARTITIONING: + { + psDecl->value.eTessPartitioning = DecodeTessPartitioning(*pui32Token); + break; + } + case OPCODE_DCL_TESS_DOMAIN: + { + psDecl->value.eTessDomain = DecodeTessDomain(*pui32Token); + break; + } + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + { + psDecl->value.eTessOutPrim = DecodeTessOutPrim(*pui32Token); + break; + } + case OPCODE_DCL_THREAD_GROUP: + { + psDecl->value.aui32WorkGroupSize[0] = pui32Token[1]; + psDecl->value.aui32WorkGroupSize[1] = pui32Token[2]; + psDecl->value.aui32WorkGroupSize[2] = pui32Token[3]; + break; + } + case OPCODE_DCL_INPUT: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_SIV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + if (psShader->eShaderType == PIXEL_SHADER) + { + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + } + break; + } + case OPCODE_DCL_INPUT_PS: + { + psDecl->ui32NumOperands = 1; + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_PS_SGV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_INPUT_PS_SIV: + { + psDecl->ui32NumOperands = 1; + psDecl->value.eInterpolation = DecodeInterpolationMode(*pui32Token); + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_OUTPUT: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_OUTPUT_SGV: + { + break; + } + case OPCODE_DCL_OUTPUT_SIV: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + DecodeNameToken(pui32Token + 3, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_TEMPS: + { + psDecl->value.ui32NumTemps = *(pui32Token + ui32OperandOffset); + break; + } + case OPCODE_DCL_INDEXABLE_TEMP: + { + psDecl->sIdxTemp.ui32RegIndex = *(pui32Token + ui32OperandOffset); + psDecl->sIdxTemp.ui32RegCount = *(pui32Token + ui32OperandOffset + 1); + psDecl->sIdxTemp.ui32RegComponentSize = *(pui32Token + ui32OperandOffset + 2); + break; + } + case OPCODE_DCL_GLOBAL_FLAGS: + { + psDecl->value.ui32GlobalFlags = DecodeGlobalFlags(*pui32Token); + break; + } + case OPCODE_DCL_INTERFACE: + { + uint32_t func = 0, numClassesImplementingThisInterface, arrayLen, interfaceID; + interfaceID = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + psDecl->ui32TableLength = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + + numClassesImplementingThisInterface = DecodeInterfaceTableLength(*(pui32Token + ui32OperandOffset)); + arrayLen = DecodeInterfaceArrayLength(*(pui32Token + ui32OperandOffset)); + + ui32OperandOffset++; + + psDecl->value.interface.ui32InterfaceID = interfaceID; + psDecl->value.interface.ui32NumFuncTables = numClassesImplementingThisInterface; + psDecl->value.interface.ui32ArraySize = arrayLen; + + psShader->funcPointer[interfaceID].ui32NumBodiesPerTable = psDecl->ui32TableLength; + + for (; func < numClassesImplementingThisInterface; ++func) + { + uint32_t ui32FuncTable = *(pui32Token + ui32OperandOffset); + psShader->aui32FuncTableToFuncPointer[ui32FuncTable] = interfaceID; + + psShader->funcPointer[interfaceID].aui32FuncTables[func] = ui32FuncTable; + ui32OperandOffset++; + } + + break; + } + case OPCODE_DCL_FUNCTION_BODY: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_FUNCTION_TABLE: + { + uint32_t ui32Func; + const uint32_t ui32FuncTableID = pui32Token[ui32OperandOffset++]; + const uint32_t ui32NumFuncsInTable = pui32Token[ui32OperandOffset++]; + + for (ui32Func = 0; ui32Func < ui32NumFuncsInTable; ++ui32Func) + { + const uint32_t ui32FuncBodyID = pui32Token[ui32OperandOffset++]; + + psShader->aui32FuncBodyToFuncTable[ui32FuncBodyID] = ui32FuncTableID; + + psShader->funcTable[ui32FuncTableID].aui32FuncBodies[ui32Func] = ui32FuncBodyID; + } + + // OpcodeToken0 is followed by a DWORD that represents the function table + // identifier and another DWORD (TableLength) that gives the number of + // functions in the table. + // + // This is followed by TableLength DWORDs which are function body indices. + // + + break; + } + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_HS_DECLS: + { + break; + } + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + { + psDecl->value.ui32MaxOutputVertexCount = DecodeOutputControlPointCount(*pui32Token); + break; + } + case OPCODE_HS_JOIN_PHASE: + case OPCODE_HS_FORK_PHASE: + case OPCODE_HS_CONTROL_POINT_PHASE: + { + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + ASSERT(psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount != 0); //Check for wrapping when we decrement. + psDecl->value.aui32HullPhaseInstanceInfo[0] = psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount - 1; + psDecl->value.aui32HullPhaseInstanceInfo[1] = pui32Token[1]; + break; + } + case OPCODE_CUSTOMDATA: + { + ui32TokenLength = pui32Token[1]; + { + const uint32_t ui32NumVec4 = (ui32TokenLength - 2) / 4; + uint32_t uIdx = 0; + + ICBVec4 const* pVec4Array = (void*) (pui32Token + 2); + + //The buffer will contain at least one value, but not more than 4096 scalars/1024 vec4's. + ASSERT(ui32NumVec4 < MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE); + + /* must be a multiple of 4 */ + ASSERT(((ui32TokenLength - 2) % 4) == 0); + + for (uIdx = 0; uIdx < ui32NumVec4; uIdx++) + { + psDecl->asImmediateConstBuffer[uIdx] = pVec4Array[uIdx]; + } + + psDecl->ui32NumOperands = ui32NumVec4; + } + break; + } + case OPCODE_DCL_HS_MAX_TESSFACTOR: + { + psDecl->value.fMaxTessFactor = *((float*)&pui32Token[1]); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + { + psDecl->ui32NumOperands = 2; + psDecl->value.eResourceDimension = DecodeResourceDimension(*pui32Token); + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + psDecl->sUAV.Type = DecodeResourceReturnType(0, pui32Token[ui32OperandOffset]); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + { + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + //This should be a RTYPE_UAV_RWBYTEADDRESS buffer. It is memory backed by + //a shader storage buffer whose is unknown at compile time. + psDecl->sUAV.ui32BufferSize = 0; + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + { + ResourceBinding* psBinding = NULL; + ConstantBuffer* psBuffer = NULL; + + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = DecodeAccessCoherencyFlags(*pui32Token); + psDecl->sUAV.bCounter = 0; + psDecl->sUAV.ui32BufferSize = 0; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + GetResourceFromBindingPoint(RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psBinding); + + GetConstantBufferFromBindingPoint(RGROUP_UAV, psBinding->ui32BindPoint, &psShader->sInfo, &psBuffer); + psDecl->sUAV.ui32BufferSize = psBuffer->ui32TotalSizeInBytes; + switch (psBinding->eType) + { + case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: + case RTYPE_UAV_APPEND_STRUCTURED: + case RTYPE_UAV_CONSUME_STRUCTURED: + psDecl->sUAV.bCounter = 1; + break; + default: + break; + } + break; + } + case OPCODE_DCL_RESOURCE_STRUCTURED: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_RESOURCE_RAW: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + { + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = 0; + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + psDecl->sTGSM.ui32Stride = pui32Token[ui32OperandOffset++]; + psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + { + psDecl->ui32NumOperands = 1; + psDecl->sUAV.ui32GloballyCoherentAccess = 0; + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + + psDecl->sTGSM.ui32Stride = 4; + psDecl->sTGSM.ui32Count = pui32Token[ui32OperandOffset++]; + break; + } + case OPCODE_DCL_STREAM: + { + psDecl->ui32NumOperands = 1; + DecodeOperand(pui32Token + ui32OperandOffset, &psDecl->asOperands[0]); + break; + } + case OPCODE_DCL_GS_INSTANCE_COUNT: + { + psDecl->ui32NumOperands = 0; + psDecl->value.ui32GSInstanceCount = pui32Token[1]; + break; + } + default: + { + //Reached end of declarations + return 0; + } + } + + return pui32Token + ui32TokenLength; +} + +const uint32_t* DeocdeInstruction(const uint32_t* pui32Token, Instruction* psInst, ShaderData* psShader) +{ + uint32_t ui32TokenLength = DecodeInstructionLength(*pui32Token); + const uint32_t bExtended = DecodeIsOpcodeExtended(*pui32Token); + const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32Token); + uint32_t ui32OperandOffset = 1; + +#ifdef _DEBUG + psInst->id = instructionID++; +#endif + + psInst->eOpcode = eOpcode; + + psInst->bSaturate = DecodeInstructionSaturate(*pui32Token); + + psInst->bAddressOffset = 0; + + psInst->ui32FirstSrc = 1; + + if (bExtended) + { + do + { + const uint32_t ui32ExtOpcodeToken = pui32Token[ui32OperandOffset]; + const EXTENDED_OPCODE_TYPE eExtType = DecodeExtendedOpcodeType(ui32ExtOpcodeToken); + + if (eExtType == EXTENDED_OPCODE_SAMPLE_CONTROLS) + { + struct + { + int i4 : 4; + } sU; + struct + { + int i4 : 4; + } sV; + struct + { + int i4 : 4; + } sW; + + psInst->bAddressOffset = 1; + + sU.i4 = DecodeImmediateAddressOffset( + IMMEDIATE_ADDRESS_OFFSET_U, ui32ExtOpcodeToken); + sV.i4 = DecodeImmediateAddressOffset( + IMMEDIATE_ADDRESS_OFFSET_V, ui32ExtOpcodeToken); + sW.i4 = DecodeImmediateAddressOffset( + IMMEDIATE_ADDRESS_OFFSET_W, ui32ExtOpcodeToken); + + psInst->iUAddrOffset = sU.i4; + psInst->iVAddrOffset = sV.i4; + psInst->iWAddrOffset = sW.i4; + } + else if (eExtType == EXTENDED_OPCODE_RESOURCE_RETURN_TYPE) + { + psInst->xType = DecodeExtendedResourceReturnType(0, ui32ExtOpcodeToken); + psInst->yType = DecodeExtendedResourceReturnType(1, ui32ExtOpcodeToken); + psInst->zType = DecodeExtendedResourceReturnType(2, ui32ExtOpcodeToken); + psInst->wType = DecodeExtendedResourceReturnType(3, ui32ExtOpcodeToken); + } + else if (eExtType == EXTENDED_OPCODE_RESOURCE_DIM) + { + psInst->eResDim = DecodeExtendedResourceDimension(ui32ExtOpcodeToken); + } + + ui32OperandOffset++; + } + while (DecodeIsOpcodeExtended(pui32Token[ui32OperandOffset - 1])); + } + + if (eOpcode < NUM_OPCODES && eOpcode >= 0) + { + psShader->aiOpcodeUsed[eOpcode] = 1; + } + + switch (eOpcode) + { + //no operands + case OPCODE_CUT: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_RET: + case OPCODE_LOOP: + case OPCODE_ENDLOOP: + case OPCODE_BREAK: + case OPCODE_ELSE: + case OPCODE_ENDIF: + case OPCODE_CONTINUE: + case OPCODE_DEFAULT: + case OPCODE_ENDSWITCH: + case OPCODE_NOP: + case OPCODE_HS_CONTROL_POINT_PHASE: + case OPCODE_HS_FORK_PHASE: + case OPCODE_HS_JOIN_PHASE: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + break; + } + case OPCODE_SYNC: + { + psInst->ui32NumOperands = 0; + psInst->ui32FirstSrc = 0; + psInst->ui32SyncFlags = DecodeSyncFlags(*pui32Token); + break; + } + + //1 operand + case OPCODE_EMIT_STREAM: + case OPCODE_CUT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + case OPCODE_CASE: + case OPCODE_SWITCH: + case OPCODE_LABEL: + { + psInst->ui32NumOperands = 1; + psInst->ui32FirstSrc = 0; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + + if (eOpcode == OPCODE_CASE) + { + psInst->asOperands[0].iIntegerImmediate = 1; + } + break; + } + + case OPCODE_INTERFACE_CALL: + { + psInst->ui32NumOperands = 1; + psInst->ui32FirstSrc = 0; + psInst->ui32FuncIndexWithinInterface = pui32Token[ui32OperandOffset]; + ui32OperandOffset++; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + + break; + } + + /* Floating point instruction decodes */ + + //Instructions with two operands go here + case OPCODE_MOV: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + + //Mov with an integer dest. If src is an immediate then it must be encoded as an integer. + if (psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_SINT_16 || + psInst->asOperands[0].eMinPrecision == OPERAND_MIN_PRECISION_UINT_16) + { + psInst->asOperands[1].iIntegerImmediate = 1; + } + break; + } + case OPCODE_LOG: + case OPCODE_RSQ: + case OPCODE_EXP: + case OPCODE_SQRT: + case OPCODE_ROUND_PI: + case OPCODE_ROUND_NI: + case OPCODE_ROUND_Z: + case OPCODE_ROUND_NE: + case OPCODE_FRC: + case OPCODE_FTOU: + case OPCODE_FTOI: + case OPCODE_UTOF: + case OPCODE_ITOF: + case OPCODE_INEG: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + case OPCODE_DMOV: + case OPCODE_DTOF: + case OPCODE_FTOD: + case OPCODE_DRCP: + case OPCODE_COUNTBITS: + case OPCODE_FIRSTBIT_HI: + case OPCODE_FIRSTBIT_LO: + case OPCODE_FIRSTBIT_SHI: + case OPCODE_BFREV: + case OPCODE_F32TOF16: + case OPCODE_F16TOF32: + case OPCODE_RCP: + case OPCODE_DERIV_RTX: + case OPCODE_DERIV_RTY: + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_NOT: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + + //Instructions with three operands go here + case OPCODE_SINCOS: + { + psInst->ui32FirstSrc = 2; + //Intentional fall-through + } + case OPCODE_IMIN: + case OPCODE_MIN: + case OPCODE_UMIN: + case OPCODE_IMAX: + case OPCODE_MAX: + case OPCODE_UMAX: + case OPCODE_MUL: + case OPCODE_DIV: + case OPCODE_ADD: + case OPCODE_DP2: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_NE: + case OPCODE_OR: + case OPCODE_XOR: + case OPCODE_LT: + case OPCODE_IEQ: + case OPCODE_IADD: + case OPCODE_AND: + case OPCODE_GE: + case OPCODE_IGE: + case OPCODE_EQ: + case OPCODE_USHR: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_LD: + case OPCODE_ILT: + case OPCODE_INE: + case OPCODE_UGE: + case OPCODE_ULT: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_UMIN: + case OPCODE_DADD: + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DDIV: + { + psInst->ui32NumOperands = 3; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + //Instructions with four operands go here + case OPCODE_MAD: + case OPCODE_MOVC: + case OPCODE_IMAD: + case OPCODE_UDIV: + case OPCODE_LOD: + case OPCODE_SAMPLE: + case OPCODE_GATHER4: + case OPCODE_LD_MS: + case OPCODE_UBFE: + case OPCODE_IBFE: + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_DMOVC: + case OPCODE_DFMA: + case OPCODE_IMUL: + { + psInst->ui32NumOperands = 4; + + if (eOpcode == OPCODE_IMUL) + { + psInst->ui32FirstSrc = 2; + } + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + break; + } + case OPCODE_GATHER4_PO: + case OPCODE_SAMPLE_L: + case OPCODE_BFI: + case OPCODE_SWAPC: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + psInst->ui32NumOperands = 5; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + break; + } + case OPCODE_GATHER4_C: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_B: + { + psInst->ui32NumOperands = 5; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + + /* sample_b is not a shadow sampler, others need flagging */ + if (eOpcode != OPCODE_SAMPLE_B) + { + MarkTextureAsShadow(&psShader->sInfo, + psShader->asPhase[MAIN_PHASE].ppsDecl[0], + psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], &psInst->asOperands[2]); + } + + break; + } + case OPCODE_GATHER4_PO_C: + case OPCODE_SAMPLE_D: + { + psInst->ui32NumOperands = 6; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[4]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[5]); + + /* sample_d is not a shadow sampler, others need flagging */ + if (eOpcode != OPCODE_SAMPLE_D) + { + MarkTextureAsShadow(&psShader->sInfo, + psShader->asPhase[MAIN_PHASE].ppsDecl[0], + psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], &psInst->asOperands[2]); + } + break; + } + case OPCODE_IF: + case OPCODE_BREAKC: + case OPCODE_CONTINUEC: + case OPCODE_RETC: + case OPCODE_DISCARD: + { + psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); + psInst->ui32NumOperands = 1; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + break; + } + case OPCODE_CALLC: + { + psInst->eBooleanTestType = DecodeInstrTestBool(*pui32Token); + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + case OPCODE_CUSTOMDATA: + { + psInst->ui32NumOperands = 0; + ui32TokenLength = pui32Token[1]; + break; + } + case OPCODE_EVAL_CENTROID: + { + psInst->ui32NumOperands = 2; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + break; + } + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_SNAPPED: + case OPCODE_STORE_UAV_TYPED: + case OPCODE_LD_UAV_TYPED: + case OPCODE_LD_RAW: + case OPCODE_STORE_RAW: + { + psInst->ui32NumOperands = 3; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + case OPCODE_STORE_STRUCTURED: + case OPCODE_LD_STRUCTURED: + { + psInst->ui32NumOperands = 4; + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[3]); + break; + } + case OPCODE_RESINFO: + { + psInst->ui32NumOperands = 3; + + psInst->eResInfoReturnType = DecodeResInfoReturnType(pui32Token[0]); + + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[0]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[1]); + ui32OperandOffset += DecodeOperand(pui32Token + ui32OperandOffset, &psInst->asOperands[2]); + break; + } + case OPCODE_MSAD: + default: + { + ASSERT(0); + break; + } + } + + // For opcodes that sample textures, mark which samplers are used by each texture + { + uint32_t ui32TextureRegisterNumber; + uint32_t ui32SamplerRegisterNumber; + uint32_t bTextureSampleInstruction = 0; + switch (eOpcode) + { + case OPCODE_GATHER4: + // dest, coords, tex, sampler + ui32TextureRegisterNumber = 2; + ui32SamplerRegisterNumber = 3; + bTextureSampleInstruction = 1; + break; + case OPCODE_GATHER4_PO: + //dest, coords, offset, tex, sampler + ui32TextureRegisterNumber = 3; + ui32SamplerRegisterNumber = 4; + bTextureSampleInstruction = 1; + break; + case OPCODE_GATHER4_C: + //dest, coords, tex, sampler srcReferenceValue + ui32TextureRegisterNumber = 2; + ui32SamplerRegisterNumber = 3; + bTextureSampleInstruction = 1; + break; + case OPCODE_GATHER4_PO_C: + //dest, coords, offset, tex, sampler, srcReferenceValue + ui32TextureRegisterNumber = 3; + ui32SamplerRegisterNumber = 4; + bTextureSampleInstruction = 1; + break; + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_B: + case OPCODE_SAMPLE_D: + // dest, coords, tex, sampler [, reference] + ui32TextureRegisterNumber = 2; + ui32SamplerRegisterNumber = 3; + bTextureSampleInstruction = 1; + break; + } + + if (bTextureSampleInstruction) + { + MarkTextureSamplerPair(&psShader->sInfo, + psShader->asPhase[MAIN_PHASE].ppsDecl[0], + psShader->asPhase[MAIN_PHASE].pui32DeclCount[0], + &psInst->asOperands[ui32TextureRegisterNumber], + &psInst->asOperands[ui32SamplerRegisterNumber], + &psShader->textureSamplerInfo); + } + } + + UpdateOperandReferences(psShader, psInst); + + return pui32Token + ui32TokenLength; +} + +void BindTextureToSampler(ShaderData* psShader, uint32_t ui32TextureRegister, uint32_t ui32SamplerRegister) +{ + ASSERT(ui32TextureRegister < MAX_RESOURCE_BINDINGS && + (psShader->sInfo.aui32SamplerMap[ui32TextureRegister] == MAX_RESOURCE_BINDINGS || + psShader->sInfo.aui32SamplerMap[ui32TextureRegister] == ui32SamplerRegister)); + ASSERT(ui32SamplerRegister < MAX_RESOURCE_BINDINGS); + psShader->sInfo.aui32SamplerMap[ui32TextureRegister] = ui32SamplerRegister; +} + +void UpdateOperandReferences(ShaderData* psShader, Instruction* psInst) +{ + uint32_t ui32Operand; + const uint32_t ui32NumOperands = psInst->ui32NumOperands; + for (ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) + { + Operand* psOperand = &psInst->asOperands[ui32Operand]; + if (psOperand->eType == OPERAND_TYPE_INPUT || + psOperand->eType == OPERAND_TYPE_INPUT_CONTROL_POINT) + { + if (psOperand->iIndexDims == INDEX_2D) + { + if (psOperand->aui32ArraySizes[1] != 0)//gl_in[].gl_Position + { + psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; + } + } + else + { + psShader->abInputReferencedByInstruction[psOperand->ui32RegisterNumber] = 1; + } + } + } + + switch (psInst->eOpcode) + { + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_B: + case OPCODE_SAMPLE_D: + case OPCODE_GATHER4: + case OPCODE_GATHER4_C: + BindTextureToSampler(psShader, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber); + break; + case OPCODE_GATHER4_PO: + case OPCODE_GATHER4_PO_C: + BindTextureToSampler(psShader, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber); + break; + } +} + +const uint32_t* DecodeShaderPhase(const uint32_t* pui32Tokens, + ShaderData* psShader, + const uint32_t ui32Phase) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + const uint32_t ui32InstanceIndex = psShader->asPhase[ui32Phase].ui32InstanceCount; + + Instruction* psInst; + + //Declarations + Declaration* psDecl; + + //Using ui32ShaderLength as the declaration and instruction count + //will allocate more than enough memory. Avoids having to + //traverse the entire shader just to get the real counts. + + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + psShader->asPhase[ui32Phase].ppsDecl[ui32InstanceIndex] = psDecl; + psShader->asPhase[ui32Phase].pui32DeclCount[ui32InstanceIndex] = 0; + + psShader->asPhase[ui32Phase].ui32InstanceCount++; + + while (1) //Keep going until we reach the first non-declaration token, or the end of the shader. + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + psShader->asPhase[ui32Phase].pui32DeclCount[ui32InstanceIndex]++; + psDecl++; + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + + //Instructions + psInst = hlslcc_malloc(sizeof(Instruction) * ui32ShaderLength); + psShader->asPhase[ui32Phase].ppsInst[ui32InstanceIndex] = psInst; + psShader->asPhase[ui32Phase].pui32InstCount[ui32InstanceIndex] = 0; + + while (pui32CurrentToken < (psShader->pui32FirstToken + ui32ShaderLength)) + { + const uint32_t* nextInstr = DeocdeInstruction(pui32CurrentToken, psInst, psShader); + +#ifdef _DEBUG + if (nextInstr == pui32CurrentToken) + { + ASSERT(0); + break; + } +#endif + + if (psInst->eOpcode == OPCODE_HS_FORK_PHASE) + { + return pui32CurrentToken; + } + else if (psInst->eOpcode == OPCODE_HS_JOIN_PHASE) + { + return pui32CurrentToken; + } + pui32CurrentToken = nextInstr; + psShader->asPhase[ui32Phase].pui32InstCount[ui32InstanceIndex]++; + + psInst++; + } + + return pui32CurrentToken; +} + +void AllocateHullPhaseArrays(const uint32_t* pui32Tokens, + ShaderData* psShader, + uint32_t ui32Phase, + OPCODE_TYPE ePhaseOpcode) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + uint32_t ui32InstanceCount = 0; + + while (1) //Keep going until we reach the first non-declaration token, or the end of the shader. + { + uint32_t ui32TokenLength = DecodeInstructionLength(*pui32CurrentToken); + const OPCODE_TYPE eOpcode = DecodeOpcodeType(*pui32CurrentToken); + + if (eOpcode == OPCODE_CUSTOMDATA) + { + ui32TokenLength = pui32CurrentToken[1]; + } + + pui32CurrentToken = pui32CurrentToken + ui32TokenLength; + + if (eOpcode == ePhaseOpcode) + { + ui32InstanceCount++; + } + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + + if (ui32InstanceCount) + { + psShader->asPhase[ui32Phase].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t) * ui32InstanceCount); + psShader->asPhase[ui32Phase].ppsDecl = hlslcc_malloc(sizeof(Declaration*) * ui32InstanceCount); + psShader->asPhase[ui32Phase].pui32DeclCount[0] = 0; + + psShader->asPhase[ui32Phase].pui32InstCount = hlslcc_malloc(sizeof(uint32_t) * ui32InstanceCount); + psShader->asPhase[ui32Phase].ppsInst = hlslcc_malloc(sizeof(Instruction*) * ui32InstanceCount); + psShader->asPhase[ui32Phase].pui32InstCount[0] = 0; + } +} + +const uint32_t* DecodeHullShader(const uint32_t* pui32Tokens, ShaderData* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = psShader->ui32ShaderLength; + Declaration* psDecl; + + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32ShaderLength); + + psShader->asPhase[HS_GLOBAL_DECL].ppsInst = 0; + psShader->asPhase[HS_GLOBAL_DECL].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); + psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0] = psDecl; + psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0] = 0; + psShader->asPhase[HS_GLOBAL_DECL].ui32InstanceCount = 1; + + AllocateHullPhaseArrays(pui32Tokens, psShader, HS_CTRL_POINT_PHASE, OPCODE_HS_CONTROL_POINT_PHASE); + AllocateHullPhaseArrays(pui32Tokens, psShader, HS_FORK_PHASE, OPCODE_HS_FORK_PHASE); + AllocateHullPhaseArrays(pui32Tokens, psShader, HS_JOIN_PHASE, OPCODE_HS_JOIN_PHASE); + + //Keep going until we have done all phases or the end of the shader. + while (1) + { + const uint32_t* pui32Result = DecodeDeclaration(psShader, pui32CurrentToken, psDecl); + + if (pui32Result) + { + pui32CurrentToken = pui32Result; + + if (psDecl->eOpcode == OPCODE_HS_CONTROL_POINT_PHASE) + { + pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_CTRL_POINT_PHASE); + } + else if (psDecl->eOpcode == OPCODE_HS_FORK_PHASE) + { + pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_FORK_PHASE); + } + else if (psDecl->eOpcode == OPCODE_HS_JOIN_PHASE) + { + pui32CurrentToken = DecodeShaderPhase(pui32CurrentToken, psShader, HS_JOIN_PHASE); + } + else + { + psDecl++; + psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]++; + } + + if (pui32CurrentToken >= (psShader->pui32FirstToken + ui32ShaderLength)) + { + break; + } + } + else + { + break; + } + } + + return pui32CurrentToken; +} + +void Decode(const uint32_t* pui32Tokens, ShaderData* psShader) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + const uint32_t ui32ShaderLength = pui32Tokens[1]; + + psShader->ui32MajorVersion = DecodeProgramMajorVersion(*pui32CurrentToken); + psShader->ui32MinorVersion = DecodeProgramMinorVersion(*pui32CurrentToken); + psShader->eShaderType = DecodeShaderType(*pui32CurrentToken); + + pui32CurrentToken++;//Move to shader length + psShader->ui32ShaderLength = ui32ShaderLength; + pui32CurrentToken++;//Move to after shader length (usually a declaration) + + psShader->pui32FirstToken = pui32Tokens; + + if (psShader->eShaderType == HULL_SHADER) + { + pui32CurrentToken = DecodeHullShader(pui32CurrentToken, psShader); + return; + } + + psShader->asPhase[MAIN_PHASE].ui32InstanceCount = 0; + psShader->asPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->asPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); + psShader->asPhase[MAIN_PHASE].pui32DeclCount[0] = 0; + + psShader->asPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->asPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); + psShader->asPhase[MAIN_PHASE].pui32InstCount[0] = 0; + + DecodeShaderPhase(pui32CurrentToken, psShader, MAIN_PHASE); +} + +ShaderData* DecodeDXBC(uint32_t* data) +{ + ShaderData* psShader; + DXBCContainerHeader* header = (DXBCContainerHeader*)data; + uint32_t i; + uint32_t chunkCount; + uint32_t* chunkOffsets; + ReflectionChunks refChunks; + uint32_t* shaderChunk = 0; + + if (header->fourcc != FOURCC_DXBC) + { + //Could be SM1/2/3. If the shader type token + //looks valid then we continue + uint32_t type = DecodeShaderTypeDX9(data[0]); + + if (type != INVALID_SHADER) + { + return DecodeDX9BC(data); + } + return 0; + } + + refChunks.pui32Inputs = NULL; + refChunks.pui32Interfaces = NULL; + refChunks.pui32Outputs = NULL; + refChunks.pui32Resources = NULL; + refChunks.pui32Inputs11 = NULL; + refChunks.pui32Outputs11 = NULL; + refChunks.pui32OutputsWithStreams = NULL; + refChunks.pui32PatchConstants = NULL; + refChunks.pui32Effects10Data = NULL; + + chunkOffsets = (uint32_t*)(header + 1); + + chunkCount = header->chunkCount; + + for (i = 0; i < chunkCount; ++i) + { + uint32_t offset = chunkOffsets[i]; + + DXBCChunkHeader* chunk = (DXBCChunkHeader*)((char*)data + offset); + + switch (chunk->fourcc) + { + case FOURCC_ISGN: + { + refChunks.pui32Inputs = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_ISG1: + { + refChunks.pui32Inputs11 = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_RDEF: + { + refChunks.pui32Resources = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_IFCE: + { + refChunks.pui32Interfaces = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSGN: + { + refChunks.pui32Outputs = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSG1: + { + refChunks.pui32Outputs11 = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_OSG5: + { + refChunks.pui32OutputsWithStreams = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_SHDR: + case FOURCC_SHEX: + { + shaderChunk = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_PSGN: + { + refChunks.pui32PatchConstants = (uint32_t*)(chunk + 1); + break; + } + case FOURCC_FX10: + { + refChunks.pui32Effects10Data = (uint32_t*)(chunk + 1); + break; + } + default: + { + break; + } + } + } + + if (shaderChunk) + { + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + + psShader = hlslcc_calloc(1, sizeof(ShaderData)); + + ui32MajorVersion = DecodeProgramMajorVersion(*shaderChunk); + ui32MinorVersion = DecodeProgramMinorVersion(*shaderChunk); + + LoadShaderInfo(ui32MajorVersion, + ui32MinorVersion, + &refChunks, + &psShader->sInfo); + + Decode(shaderChunk, psShader); + + return psShader; + } + + return 0; +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c b/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c new file mode 100644 index 0000000000..f33c5b4b0e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/decodeDX9.c @@ -0,0 +1,1133 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/debug.h" +#include "internal_includes/decode.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/reflect.h" +#include "internal_includes/structs.h" +#include "internal_includes/tokens.h" +#include "stdio.h" +#include "stdlib.h" + +#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24)) +enum +{ + FOURCC_CTAB = FOURCC('C', 'T', 'A', 'B') +}; // Constant table + +#ifdef _DEBUG +static uint64_t dx9operandID = 0; +static uint64_t dx9instructionID = 0; +#endif + +static uint32_t aui32ImmediateConst[256]; +static uint32_t ui32MaxTemp = 0; + +uint32_t DX9_DECODE_OPERAND_IS_SRC = 0x1; +uint32_t DX9_DECODE_OPERAND_IS_DEST = 0x2; +uint32_t DX9_DECODE_OPERAND_IS_DECL = 0x4; + +uint32_t DX9_DECODE_OPERAND_IS_CONST = 0x8; +uint32_t DX9_DECODE_OPERAND_IS_ICONST = 0x10; +uint32_t DX9_DECODE_OPERAND_IS_BCONST = 0x20; + +#define MAX_INPUTS 64 + +static DECLUSAGE_DX9 aeInputUsage[MAX_INPUTS]; +static uint32_t aui32InputUsageIndex[MAX_INPUTS]; + +static void DecodeOperandDX9(const ShaderData* psShader, const uint32_t ui32Token, const uint32_t ui32Token1, uint32_t ui32Flags, Operand* psOperand) +{ + const uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token); + const uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token); + const uint32_t bRelativeAddr = DecodeOperandIsRelativeAddressModeDX9(ui32Token); + + const uint32_t ui32WriteMask = DecodeDestWriteMaskDX9(ui32Token); + const uint32_t ui32Swizzle = DecodeOperandSwizzleDX9(ui32Token); + + SHADER_VARIABLE_TYPE ConstType; + + psOperand->ui32RegisterNumber = ui32RegNum; + + psOperand->iNumComponents = 4; + +#ifdef _DEBUG + psOperand->id = dx9operandID++; +#endif + + psOperand->iWriteMaskEnabled = 0; + psOperand->iGSInput = 0; + psOperand->iExtended = 0; + psOperand->psSubOperand[0] = 0; + psOperand->psSubOperand[1] = 0; + psOperand->psSubOperand[2] = 0; + + psOperand->iIndexDims = INDEX_0D; + + psOperand->iIntegerImmediate = 0; + + psOperand->pszSpecialName[0] = '\0'; + + psOperand->eModifier = OPERAND_MODIFIER_NONE; + if (ui32Flags & DX9_DECODE_OPERAND_IS_SRC) + { + uint32_t ui32Modifier = DecodeSrcModifierDX9(ui32Token); + + switch (ui32Modifier) + { + case SRCMOD_DX9_NONE: + { + break; + } + case SRCMOD_DX9_NEG: + { + psOperand->eModifier = OPERAND_MODIFIER_NEG; + break; + } + case SRCMOD_DX9_ABS: + { + psOperand->eModifier = OPERAND_MODIFIER_ABS; + break; + } + case SRCMOD_DX9_ABSNEG: + { + psOperand->eModifier = OPERAND_MODIFIER_ABSNEG; + break; + } + default: + { + ASSERT(0); + break; + } + } + } + + if ((ui32Flags & DX9_DECODE_OPERAND_IS_DECL) == 0) + { + if (ui32Flags & DX9_DECODE_OPERAND_IS_DEST) + { + if (ui32WriteMask != DX9_WRITEMASK_ALL) + { + psOperand->iWriteMaskEnabled = 1; + psOperand->eSelMode = OPERAND_4_COMPONENT_MASK_MODE; + + if (ui32WriteMask & DX9_WRITEMASK_0) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_X; + } + if (ui32WriteMask & DX9_WRITEMASK_1) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Y; + } + if (ui32WriteMask & DX9_WRITEMASK_2) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_Z; + } + if (ui32WriteMask & DX9_WRITEMASK_3) + { + psOperand->ui32CompMask |= OPERAND_4_COMPONENT_MASK_W; + } + } + } + else if (ui32Swizzle != NO_SWIZZLE_DX9) + { + uint32_t component; + + psOperand->iWriteMaskEnabled = 1; + psOperand->eSelMode = OPERAND_4_COMPONENT_SWIZZLE_MODE; + + psOperand->ui32Swizzle = 1; + + /* Add the swizzle */ + if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(0)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_X; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(1)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Y; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(2)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_Z; + } + else if (ui32Swizzle == REPLICATE_SWIZZLE_DX9(3)) + { + psOperand->eSelMode = OPERAND_4_COMPONENT_SELECT_1_MODE; + psOperand->aui32Swizzle[0] = OPERAND_4_COMPONENT_W; + } + else + { + for (component = 0; component < 4; component++) + { + uint32_t ui32CompSwiz = ui32Swizzle & (3 << (DX9_SWIZZLE_SHIFT + (component * 2))); + ui32CompSwiz >>= (DX9_SWIZZLE_SHIFT + (component * 2)); + + if (ui32CompSwiz == 0) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_X; + } + else if (ui32CompSwiz == 1) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Y; + } + else if (ui32CompSwiz == 2) + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_Z; + } + else + { + psOperand->aui32Swizzle[component] = OPERAND_4_COMPONENT_W; + } + } + } + } + + if (bRelativeAddr) + { + psOperand->psSubOperand[0] = hlslcc_malloc(sizeof(Operand)); + DecodeOperandDX9(psShader, ui32Token1, 0, ui32Flags, psOperand->psSubOperand[0]); + + psOperand->iIndexDims = INDEX_1D; + + psOperand->eIndexRep[0] = OPERAND_INDEX_RELATIVE; + + psOperand->aui32ArraySizes[0] = 0; + } + } + + if (ui32RegType == OPERAND_TYPE_DX9_CONSTBOOL) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; + ConstType = SVT_BOOL; + } + else if (ui32RegType == OPERAND_TYPE_DX9_CONSTINT) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; + ConstType = SVT_INT; + } + else if (ui32RegType == OPERAND_TYPE_DX9_CONST) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; + ConstType = SVT_FLOAT; + } + + switch (ui32RegType) + { + case OPERAND_TYPE_DX9_TEMP: + { + psOperand->eType = OPERAND_TYPE_TEMP; + + if (ui32MaxTemp < ui32RegNum + 1) + { + ui32MaxTemp = ui32RegNum + 1; + } + break; + } + case OPERAND_TYPE_DX9_INPUT: + { + psOperand->eType = OPERAND_TYPE_INPUT; + + ASSERT(ui32RegNum < MAX_INPUTS); + + if (psShader->eShaderType == PIXEL_SHADER) + { + if (aeInputUsage[ui32RegNum] == DECLUSAGE_TEXCOORD) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + psOperand->ui32RegisterNumber = aui32InputUsageIndex[ui32RegNum]; + } + else + // 0 = base colour, 1 = offset colour. + if (ui32RegNum == 0) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; + } + else + { + ASSERT(ui32RegNum == 1); + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; + } + } + break; + } + // Same value as OPERAND_TYPE_DX9_TEXCRDOUT + // OPERAND_TYPE_DX9_TEXCRDOUT is the pre-SM3 equivalent + case OPERAND_TYPE_DX9_OUTPUT: + { + psOperand->eType = OPERAND_TYPE_OUTPUT; + + if (psShader->eShaderType == VERTEX_SHADER) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + } + break; + } + case OPERAND_TYPE_DX9_RASTOUT: + { + // RegNum: + // 0=POSIION + // 1=FOG + // 2=POINTSIZE + psOperand->eType = OPERAND_TYPE_OUTPUT; + switch (ui32RegNum) + { + case 0: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_POSITION; + break; + } + case 1: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_FOG; + break; + } + case 2: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_POINTSIZE; + psOperand->iNumComponents = 1; + break; + } + } + break; + } + case OPERAND_TYPE_DX9_ATTROUT: + { + ASSERT(psShader->eShaderType == VERTEX_SHADER); + + psOperand->eType = OPERAND_TYPE_OUTPUT; + + // 0 = base colour, 1 = offset colour. + if (ui32RegNum == 0) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTBASECOLOUR; + } + else + { + ASSERT(ui32RegNum == 1); + psOperand->eType = OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR; + } + + break; + } + case OPERAND_TYPE_DX9_COLOROUT: + { + ASSERT(psShader->eShaderType == PIXEL_SHADER); + psOperand->eType = OPERAND_TYPE_OUTPUT; + break; + } + case OPERAND_TYPE_DX9_CONSTBOOL: + case OPERAND_TYPE_DX9_CONSTINT: + case OPERAND_TYPE_DX9_CONST: + { + // c# = constant float + // i# = constant int + // b# = constant bool + + // c0 might be an immediate while i0 is in the constant buffer + if (aui32ImmediateConst[ui32RegNum] & ui32Flags) + { + if (ConstType != SVT_FLOAT) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; + } + else + { + psOperand->eType = OPERAND_TYPE_SPECIAL_IMMCONST; + } + } + else + { + psOperand->eType = OPERAND_TYPE_CONSTANT_BUFFER; + psOperand->aui32ArraySizes[1] = psOperand->ui32RegisterNumber; + } + break; + } + case OPERAND_TYPE_DX9_ADDR: + { + // Vertex shader: address register (only have one of these) + // Pixel shader: texture coordinate register (a few of these) + if (psShader->eShaderType == PIXEL_SHADER) + { + psOperand->eType = OPERAND_TYPE_SPECIAL_TEXCOORD; + } + else + { + psOperand->eType = OPERAND_TYPE_SPECIAL_ADDRESS; + } + break; + } + case OPERAND_TYPE_DX9_SAMPLER: + { + psOperand->eType = OPERAND_TYPE_RESOURCE; + break; + } + case OPERAND_TYPE_DX9_LOOP: + { + psOperand->eType = OPERAND_TYPE_SPECIAL_LOOPCOUNTER; + break; + } + default: + { + ASSERT(0); + break; + } + } +} + +static void DeclareNumTemps(ShaderData* psShader, const uint32_t ui32NumTemps, Declaration* psDecl) +{ + (void)psShader; + + psDecl->eOpcode = OPCODE_DCL_TEMPS; + psDecl->value.ui32NumTemps = ui32NumTemps; +} + +static void SetupRegisterUsage(const ShaderData* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1) +{ + (void)psShader; + + DECLUSAGE_DX9 eUsage = DecodeUsageDX9(ui32Token0); + uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0); + uint32_t ui32RegNum = DecodeOperandRegisterNumberDX9(ui32Token1); + uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); + + if (ui32RegType == OPERAND_TYPE_DX9_INPUT) + { + ASSERT(ui32RegNum < MAX_INPUTS); + aeInputUsage[ui32RegNum] = eUsage; + aui32InputUsageIndex[ui32RegNum] = ui32UsageIndex; + } +} + +// Declaring one constant from a constant buffer will cause all constants in the buffer decalared. +// In dx9 there is only one constant buffer per shader. +static void DeclareConstantBuffer(const ShaderData* psShader, Declaration* psDecl) +{ + // Pick any constant register in the table. Might not start at c0 (e.g. when register(cX) is used). + uint32_t ui32RegNum = psShader->sInfo.psConstantBuffers->asVars[0].ui32StartOffset / 16; + OPERAND_TYPE_DX9 ui32RegType = OPERAND_TYPE_DX9_CONST; + + if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_INT) + { + ui32RegType = OPERAND_TYPE_DX9_CONSTINT; + } + else if (psShader->sInfo.psConstantBuffers->asVars[0].sType.Type == SVT_BOOL) + { + ui32RegType = OPERAND_TYPE_DX9_CONSTBOOL; + } + + if (psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_INPUT; + } + else + { + psDecl->eOpcode = OPCODE_DCL_INPUT_PS; + } + psDecl->ui32NumOperands = 1; + + DecodeOperandDX9(psShader, CreateOperandTokenDX9(ui32RegNum, ui32RegType), 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); + + ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER); + + psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index + psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. +} + +static void DecodeDeclarationDX9(const ShaderData* psShader, const uint32_t ui32Token0, const uint32_t ui32Token1, Declaration* psDecl) +{ + /*uint32_t ui32UsageIndex = DecodeUsageIndexDX9(ui32Token0);*/ + uint32_t ui32RegType = DecodeOperandTypeDX9(ui32Token1); + + if (psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_INPUT; + } + else + { + psDecl->eOpcode = OPCODE_DCL_INPUT_PS; + } + psDecl->ui32NumOperands = 1; + DecodeOperandDX9(psShader, ui32Token1, 0, DX9_DECODE_OPERAND_IS_DECL, &psDecl->asOperands[0]); + + if (ui32RegType == OPERAND_TYPE_DX9_SAMPLER) + { + const RESOURCE_DIMENSION eResDim = DecodeTextureTypeMaskDX9(ui32Token0); + psDecl->value.eResourceDimension = eResDim; + psDecl->ui32IsShadowTex = 0; + psDecl->eOpcode = OPCODE_DCL_RESOURCE; + } + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT) + { + psDecl->eOpcode = OPCODE_DCL_OUTPUT; + + if (psDecl->asOperands[0].ui32RegisterNumber == 0 && psShader->eShaderType == VERTEX_SHADER) + { + psDecl->eOpcode = OPCODE_DCL_OUTPUT_SIV; + // gl_Position + psDecl->asOperands[0].eSpecialName = NAME_POSITION; + } + } + else if (psDecl->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + psDecl->eOpcode = OPCODE_DCL_CONSTANT_BUFFER; + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + psDecl->asOperands[0].aui32ArraySizes[0] = 0; // Const buffer index + psDecl->asOperands[0].aui32ArraySizes[1] = psShader->sInfo.psConstantBuffers[0].ui32TotalSizeInBytes / 16; // Number of vec4 constants. + } +} + +static void DefineDX9(ShaderData* psShader, + const uint32_t ui32RegNum, + const uint32_t ui32Flags, + const uint32_t c0, + const uint32_t c1, + const uint32_t c2, + const uint32_t c3, + Declaration* psDecl) +{ + (void)psShader; + (void)psDecl; + + psDecl->eOpcode = OPCODE_SPECIAL_DCL_IMMCONST; + psDecl->ui32NumOperands = 2; + + memset(&psDecl->asOperands[0], 0, sizeof(Operand)); + psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONST; + + psDecl->asOperands[0].ui32RegisterNumber = ui32RegNum; + + if (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) + { + psDecl->asOperands[0].eType = OPERAND_TYPE_SPECIAL_IMMCONSTINT; + } + + aui32ImmediateConst[ui32RegNum] |= ui32Flags; + + memset(&psDecl->asOperands[1], 0, sizeof(Operand)); + psDecl->asOperands[1].eType = OPERAND_TYPE_IMMEDIATE32; + psDecl->asOperands[1].iNumComponents = 4; + psDecl->asOperands[1].iIntegerImmediate = (ui32Flags & (DX9_DECODE_OPERAND_IS_ICONST | DX9_DECODE_OPERAND_IS_BCONST)) ? 1 : 0; + psDecl->asOperands[1].afImmediates[0] = *((float*)&c0); + psDecl->asOperands[1].afImmediates[1] = *((float*)&c1); + psDecl->asOperands[1].afImmediates[2] = *((float*)&c2); + psDecl->asOperands[1].afImmediates[3] = *((float*)&c3); +} + +static void CreateD3D10Instruction(ShaderData* psShader, + Instruction* psInst, + const OPCODE_TYPE eType, + const uint32_t bHasDest, + const uint32_t ui32SrcCount, + const uint32_t* pui32Tokens) +{ + uint32_t ui32Src; + uint32_t ui32Offset = 1; + + memset(psInst, 0, sizeof(Instruction)); + +#ifdef _DEBUG + psInst->id = dx9instructionID++; +#endif + + psInst->eOpcode = eType; + psInst->ui32NumOperands = ui32SrcCount; + + if (bHasDest) + { + ++psInst->ui32NumOperands; + + DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_DEST, &psInst->asOperands[0]); + + if (DecodeDestModifierDX9(pui32Tokens[ui32Offset]) & DESTMOD_DX9_SATURATE) + { + psInst->bSaturate = 1; + } + + ui32Offset++; + psInst->ui32FirstSrc = 1; + } + + for (ui32Src = 0; ui32Src < ui32SrcCount; ++ui32Src) + { + DecodeOperandDX9(psShader, pui32Tokens[ui32Offset], pui32Tokens[ui32Offset + 1], DX9_DECODE_OPERAND_IS_SRC, &psInst->asOperands[bHasDest + ui32Src]); + + ui32Offset++; + } +} + +ShaderData* DecodeDX9BC(const uint32_t* pui32Tokens) +{ + const uint32_t* pui32CurrentToken = pui32Tokens; + uint32_t ui32NumInstructions = 0; + uint32_t ui32NumDeclarations = 0; + Instruction* psInst; + Declaration* psDecl; + uint32_t decl, inst; + uint32_t bDeclareConstantTable = 0; + ShaderData* psShader = hlslcc_calloc(1, sizeof(ShaderData)); + + memset(aui32ImmediateConst, 0, 256); + + psShader->ui32MajorVersion = DecodeProgramMajorVersionDX9(*pui32CurrentToken); + psShader->ui32MinorVersion = DecodeProgramMinorVersionDX9(*pui32CurrentToken); + psShader->eShaderType = DecodeShaderTypeDX9(*pui32CurrentToken); + + pui32CurrentToken++; + + // Work out how many instructions and declarations we need to allocate memory for. + while (1) + { + OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); + uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); + + if (eOpcode == OPCODE_DX9_END) + { + // SM4+ always end with RET. + // Insert a RET instruction on END to + // replicate this behaviour. + ++ui32NumInstructions; + break; + } + else if (eOpcode == OPCODE_DX9_COMMENT) + { + ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); + if (pui32CurrentToken[1] == FOURCC_CTAB) + { + LoadD3D9ConstantTable((char*)(&pui32CurrentToken[2]), &psShader->sInfo); + + ASSERT(psShader->sInfo.ui32NumConstantBuffers); + + if (psShader->sInfo.psConstantBuffers[0].ui32NumVars) + { + ++ui32NumDeclarations; + bDeclareConstantTable = 1; + } + } + } + else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) + { + ++ui32NumDeclarations; + } + else if (eOpcode == OPCODE_DX9_DCL) + { + const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); + uint32_t ignoreDCL = 0; + + // Inputs and outputs are declared in AddVersionDependentCode + if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) + { + ignoreDCL = 1; + } + if (!ignoreDCL) + { + ++ui32NumDeclarations; + } + } + else + { + switch (eOpcode) + { + case OPCODE_DX9_NRM: + { + // Emulate with dp4 and rsq + ui32NumInstructions += 2; + break; + } + default: + { + ++ui32NumInstructions; + break; + } + } + } + + pui32CurrentToken += ui32InstLen + 1; + } + + psInst = hlslcc_malloc(sizeof(Instruction) * ui32NumInstructions); + psShader->asPhase[MAIN_PHASE].ui32InstanceCount = 1; + psShader->asPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); + psShader->asPhase[MAIN_PHASE].ppsInst[0] = psInst; + psShader->asPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->asPhase[MAIN_PHASE].pui32InstCount[0] = ui32NumInstructions; + + if (psShader->eShaderType == VERTEX_SHADER) + { + // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not + ui32NumDeclarations++; + } + + // For declaring temps. + ui32NumDeclarations++; + + psDecl = hlslcc_malloc(sizeof(Declaration) * ui32NumDeclarations); + psShader->asPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); + psShader->asPhase[MAIN_PHASE].ppsDecl[0] = psDecl; + psShader->asPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->asPhase[MAIN_PHASE].pui32DeclCount[0] = ui32NumDeclarations; + + pui32CurrentToken = pui32Tokens + 1; + + inst = 0; + decl = 0; + while (1) + { + OPCODE_TYPE_DX9 eOpcode = DecodeOpcodeTypeDX9(pui32CurrentToken[0]); + uint32_t ui32InstLen = DecodeInstructionLengthDX9(pui32CurrentToken[0]); + + if (eOpcode == OPCODE_DX9_END) + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); + inst++; + break; + } + else if (eOpcode == OPCODE_DX9_COMMENT) + { + ui32InstLen = DecodeCommentLengthDX9(pui32CurrentToken[0]); + } + else if (eOpcode == OPCODE_DX9_DCL) + { + const OPERAND_TYPE_DX9 eType = DecodeOperandTypeDX9(pui32CurrentToken[2]); + uint32_t ignoreDCL = 0; + // Inputs and outputs are declared in AddVersionDependentCode + if (psShader->eShaderType == PIXEL_SHADER && (OPERAND_TYPE_DX9_CONST != eType && OPERAND_TYPE_DX9_SAMPLER != eType)) + { + ignoreDCL = 1; + } + + SetupRegisterUsage(psShader, pui32CurrentToken[1], pui32CurrentToken[2]); + + if (!ignoreDCL) + { + DecodeDeclarationDX9(psShader, pui32CurrentToken[1], pui32CurrentToken[2], &psDecl[decl]); + decl++; + } + } + else if ((eOpcode == OPCODE_DX9_DEF) || (eOpcode == OPCODE_DX9_DEFI) || (eOpcode == OPCODE_DX9_DEFB)) + { + const uint32_t ui32Const0 = *(pui32CurrentToken + 2); + const uint32_t ui32Const1 = *(pui32CurrentToken + 3); + const uint32_t ui32Const2 = *(pui32CurrentToken + 4); + const uint32_t ui32Const3 = *(pui32CurrentToken + 5); + uint32_t ui32Flags = 0; + + if (eOpcode == OPCODE_DX9_DEF) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_CONST; + } + else if (eOpcode == OPCODE_DX9_DEFI) + { + ui32Flags |= DX9_DECODE_OPERAND_IS_ICONST; + } + else + { + ui32Flags |= DX9_DECODE_OPERAND_IS_BCONST; + } + + DefineDX9(psShader, DecodeOperandRegisterNumberDX9(pui32CurrentToken[1]), ui32Flags, ui32Const0, ui32Const1, ui32Const2, ui32Const3, &psDecl[decl]); + decl++; + } + else + { + switch (eOpcode) + { + case OPCODE_DX9_MOV: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOV, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_LIT: + { + /*Dest.x = 1 + Dest.y = (Src0.x > 0) ? Src0.x : 0 + Dest.z = (Src0.x > 0 && Src0.y > 0) ? pow(Src0.y, Src0.w) : 0 + Dest.w = 1 + */ + ASSERT(0); + break; + } + case OPCODE_DX9_ADD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SUB: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ADD, 1, 2, pui32CurrentToken); + ASSERT(psInst[inst].asOperands[2].eModifier == OPERAND_MODIFIER_NONE); + psInst[inst].asOperands[2].eModifier = OPERAND_MODIFIER_NEG; + break; + } + case OPCODE_DX9_MAD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAD, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_MUL: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MUL, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_RCP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RCP, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_RSQ: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP3: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP3, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP4: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_MIN: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MIN, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_MAX: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MAX, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SLT: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LT, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_SGE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_GE, 1, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_EXP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_EXP, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_LOG: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOG, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_NRM: + { + // Convert NRM RESULT, SRCA into: + // dp4 RESULT, SRCA, SRCA + // rsq RESULT, RESULT + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP4, 1, 1, pui32CurrentToken); + memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); + psInst[inst].ui32NumOperands++; + ++inst; + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RSQ, 0, 0, pui32CurrentToken); + memcpy(&psInst[inst].asOperands[0], &psInst[inst - 1].asOperands[0], sizeof(Operand)); + memcpy(&psInst[inst].asOperands[1], &psInst[inst - 1].asOperands[0], sizeof(Operand)); + psInst[inst].ui32NumOperands++; + psInst[inst].ui32NumOperands++; + break; + } + case OPCODE_DX9_SINCOS: + { + // Before SM3, SINCOS has 2 extra constant sources -D3DSINCOSCONST1 and D3DSINCOSCONST2. + // Ignore them. + + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SINCOS, 1, 1, pui32CurrentToken); + // Pre-SM4: + // If the write mask is .x: dest.x = cos( V ) + // If the write mask is .y: dest.y = sin( V ) + // If the write mask is .xy: + // dest.x = cos( V ) + // dest.y = sin( V ) + + // SM4+ + // destSin destCos Angle + + psInst[inst].ui32NumOperands = 3; + + // Set the angle + memcpy(&psInst[inst].asOperands[2], &psInst[inst].asOperands[1], sizeof(Operand)); + + // Set the cosine dest + memcpy(&psInst[inst].asOperands[1], &psInst[inst].asOperands[0], sizeof(Operand)); + + // Set write masks + psInst[inst].asOperands[0].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_Y; + if (psInst[inst].asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + // Need cosine + } + else + { + psInst[inst].asOperands[0].eType = OPERAND_TYPE_NULL; + } + psInst[inst].asOperands[1].ui32CompMask &= ~OPERAND_4_COMPONENT_MASK_X; + if (psInst[inst].asOperands[1].ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + // Need sine + } + else + { + psInst[inst].asOperands[1].eType = OPERAND_TYPE_NULL; + } + + break; + } + case OPCODE_DX9_FRC: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_FRC, 1, 1, pui32CurrentToken); + break; + } + + case OPCODE_DX9_MOVA: + { + // MOVA preforms RoundToNearest on the src data. + // The only rounding functions available in all GLSL version are ceil and floor. + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ROUND_NI, 1, 1, pui32CurrentToken); + break; + } + + case OPCODE_DX9_TEX: + { + // texld r0, t0, s0 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE, 1, 2, pui32CurrentToken); + psInst[inst].asOperands[2].ui32RegisterNumber = 0; + + break; + } + case OPCODE_DX9_TEXLDL: + { + // texld r0, t0, s0 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_L, 1, 2, pui32CurrentToken); + psInst[inst].asOperands[2].ui32RegisterNumber = 0; + + // Lod comes from fourth coordinate of address. + memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[1], sizeof(Operand)); + + psInst[inst].ui32NumOperands = 5; + + break; + } + + case OPCODE_DX9_IF: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 1, pui32CurrentToken); + psInst[inst].eDX9TestType = D3DSPC_BOOLEAN; + break; + } + + case OPCODE_DX9_IFC: + { + const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_IF, 0, 2, pui32CurrentToken); + psInst[inst].eDX9TestType = eCmpOp; + break; + } + case OPCODE_DX9_ELSE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ELSE, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_CMP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_MOVC, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_REP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_REP, 0, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDREP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDREP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_BREAKC: + { + const COMPARISON_DX9 eCmpOp = DecodeComparisonDX9(pui32CurrentToken[0]); + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAKC, 0, 2, pui32CurrentToken); + psInst[inst].eDX9TestType = eCmpOp; + break; + } + + case OPCODE_DX9_DSX: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTX, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_DSY: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DERIV_RTY, 1, 1, pui32CurrentToken); + break; + } + case OPCODE_DX9_TEXKILL: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DISCARD, 1, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_TEXLDD: + { + // texldd, dst, src0, src1, src2, src3 + // srcAddress[.swizzle], srcResource[.swizzle], srcSampler, XGradient, YGradient + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_SAMPLE_D, 1, 4, pui32CurrentToken); + + // Move the gradients one slot up + memcpy(&psInst[inst].asOperands[5], &psInst[inst].asOperands[4], sizeof(Operand)); + memcpy(&psInst[inst].asOperands[4], &psInst[inst].asOperands[3], sizeof(Operand)); + + // Sampler register + psInst[inst].asOperands[3].ui32RegisterNumber = 0; + psInst[inst].ui32NumOperands = 6; + break; + } + case OPCODE_DX9_LRP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LRP, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_DP2ADD: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_DP2ADD, 1, 3, pui32CurrentToken); + break; + } + case OPCODE_DX9_POW: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_POW, 1, 2, pui32CurrentToken); + break; + } + + case OPCODE_DX9_DST: + case OPCODE_DX9_M4x4: + case OPCODE_DX9_M4x3: + case OPCODE_DX9_M3x4: + case OPCODE_DX9_M3x3: + case OPCODE_DX9_M3x2: + case OPCODE_DX9_CALL: + case OPCODE_DX9_CALLNZ: + case OPCODE_DX9_LABEL: + + case OPCODE_DX9_CRS: + case OPCODE_DX9_SGN: + case OPCODE_DX9_ABS: + + case OPCODE_DX9_TEXCOORD: + case OPCODE_DX9_TEXBEM: + case OPCODE_DX9_TEXBEML: + case OPCODE_DX9_TEXREG2AR: + case OPCODE_DX9_TEXREG2GB: + case OPCODE_DX9_TEXM3x2PAD: + case OPCODE_DX9_TEXM3x2TEX: + case OPCODE_DX9_TEXM3x3PAD: + case OPCODE_DX9_TEXM3x3TEX: + case OPCODE_DX9_TEXM3x3SPEC: + case OPCODE_DX9_TEXM3x3VSPEC: + case OPCODE_DX9_EXPP: + case OPCODE_DX9_LOGP: + case OPCODE_DX9_CND: + case OPCODE_DX9_TEXREG2RGB: + case OPCODE_DX9_TEXDP3TEX: + case OPCODE_DX9_TEXM3x2DEPTH: + case OPCODE_DX9_TEXDP3: + case OPCODE_DX9_TEXM3x3: + case OPCODE_DX9_TEXDEPTH: + case OPCODE_DX9_BEM: + case OPCODE_DX9_SETP: + case OPCODE_DX9_BREAKP: + { + ASSERT(0); + break; + } + case OPCODE_DX9_NOP: + case OPCODE_DX9_PHASE: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_NOP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_LOOP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_LOOP, 0, 2, pui32CurrentToken); + break; + } + case OPCODE_DX9_RET: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_RET, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDLOOP: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDLOOP, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_ENDIF: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_ENDIF, 0, 0, pui32CurrentToken); + break; + } + case OPCODE_DX9_BREAK: + { + CreateD3D10Instruction(psShader, &psInst[inst], OPCODE_BREAK, 0, 0, pui32CurrentToken); + break; + } + default: + { + ASSERT(0); + break; + } + } + + UpdateOperandReferences(psShader, &psInst[inst]); + + inst++; + } + + pui32CurrentToken += ui32InstLen + 1; + } + + DeclareNumTemps(psShader, ui32MaxTemp, &psDecl[decl]); + ++decl; + + if (psShader->eShaderType == VERTEX_SHADER) + { + // Declare gl_Position. vs_3_0 does declare it, SM1/2 do not + if (bDeclareConstantTable) + { + DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl + 1]); + } + else + { + DecodeDeclarationDX9(psShader, 0, CreateOperandTokenDX9(0, OPERAND_TYPE_DX9_RASTOUT), &psDecl[decl]); + } + } + + if (bDeclareConstantTable) + { + DeclareConstantBuffer(psShader, &psDecl[decl]); + } + + return psShader; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h new file mode 100644 index 0000000000..5b071709bc --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/debug.h @@ -0,0 +1,21 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef DEBUG_H_ +#define DEBUG_H_ + +#ifdef _DEBUG +#include "assert.h" +#define ASSERT(expr) CustomAssert(expr) +static void CustomAssert(int expression) +{ + if(!expression) + { + assert(0); + } +} +#else +#define ASSERT(expr) +#endif + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h new file mode 100644 index 0000000000..f0981cb15c --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/decode.h @@ -0,0 +1,18 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef DECODE_H +#define DECODE_H + +#include "internal_includes/structs.h" + +ShaderData* DecodeDXBC(uint32_t* data); + +//You don't need to call this directly because DecodeDXBC +//will call DecodeDX9BC if the shader looks +//like it is SM1/2/3. +ShaderData* DecodeDX9BC(const uint32_t* pui32Tokens); + +void UpdateOperandReferences(ShaderData* psShader, Instruction* psInst); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c new file mode 100644 index 0000000000..57c86655b7 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.c @@ -0,0 +1,37 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include <stdlib.h> + +#ifdef __APPLE_CC__ + #include <malloc/malloc.h> +#else +#include <malloc.h> +#endif + +// Wrapping these functions since we are taking the address of them and the std functions are dllimport which produce +// warning C4232 +void* std_malloc(size_t size) +{ + return malloc(size); +} + +void* std_calloc(size_t num, size_t size) +{ + return calloc(num, size); +} + +void std_free(void* p) +{ + free(p); +} + +void* std_realloc(void* p, size_t size) +{ + return realloc(p, size); +} + +void* (*hlslcc_malloc)(size_t size) = std_malloc; +void* (*hlslcc_calloc)(size_t num,size_t size) = std_calloc; +void (*hlslcc_free)(void *p) = std_free; +void* (*hlslcc_realloc)(void *p,size_t size) = std_realloc; diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h new file mode 100644 index 0000000000..493aa1fe1e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/hlslcc_malloc.h @@ -0,0 +1,15 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef __HLSCC_MALLOC_H +#define __HLSCC_MALLOC_H + +extern void* (*hlslcc_malloc)(size_t size); +extern void* (*hlslcc_calloc)(size_t num,size_t size); +extern void (*hlslcc_free)(void *p); +extern void* (*hlslcc_realloc)(void *p,size_t size); + +#define bstr__alloc hlslcc_malloc +#define bstr__free hlslcc_free +#define bstr__realloc hlslcc_realloc +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h new file mode 100644 index 0000000000..35d7a9b125 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/languages.h @@ -0,0 +1,213 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef LANGUAGES_H +#define LANGUAGES_H + +#include "hlslcc.h" + +static int InOutSupported(const ShaderLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 0; + } + return 1; +} + +static int WriteToFragData(const ShaderLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 1; + } + return 0; +} + +static int ShaderBitEncodingSupported(const ShaderLang eLang) +{ + if( eLang != LANG_ES_300 && + eLang != LANG_ES_310 && + eLang < LANG_330) + { + return 0; + } + return 1; +} + +static int HaveOverloadedTextureFuncs(const ShaderLang eLang) +{ + if(eLang == LANG_ES_100 || eLang == LANG_120) + { + return 0; + } + return 1; +} + +//Only enable for ES. +//Not present in 120, ignored in other desktop languages. +static int HavePrecisionQualifers(const ShaderLang eLang) +{ + if(eLang >= LANG_ES_100 && eLang <= LANG_ES_310) + { + return 1; + } + return 0; +} + +//Only on vertex inputs and pixel outputs. +static int HaveLimitedInOutLocationQualifier(const ShaderLang eLang, unsigned int flags) +{ + (void)flags; + + if(eLang >= LANG_330 || eLang == LANG_ES_300 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveInOutLocationQualifier(const ShaderLang eLang,const struct GlExtensions *extensions, unsigned int flags) +{ + (void)flags; + + if(eLang >= LANG_410 || eLang == LANG_ES_310 || (extensions && ((GlExtensions*)extensions)->ARB_explicit_attrib_location)) + { + return 1; + } + return 0; +} + +//layout(binding = X) uniform {uniformA; uniformB;} +//layout(location = X) uniform uniform_name; +static int HaveUniformBindingsAndLocations(const ShaderLang eLang,const struct GlExtensions *extensions, unsigned int flags) +{ + if (flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS) + return 0; + + if (eLang >= LANG_430 || eLang == LANG_ES_310 || + (extensions && ((GlExtensions*)extensions)->ARB_explicit_uniform_location && ((GlExtensions*)extensions)->ARB_shading_language_420pack)) + { + return 1; + } + return 0; +} + +static int DualSourceBlendSupported(const ShaderLang eLang) +{ + if(eLang >= LANG_330) + { + return 1; + } + return 0; +} + +static int SubroutinesSupported(const ShaderLang eLang) +{ + if(eLang >= LANG_400) + { + return 1; + } + return 0; +} + +//Before 430, flat/smooth/centroid/noperspective must match +//between fragment and its previous stage. +//HLSL bytecode only tells us the interpolation in pixel shader. +static int PixelInterpDependency(const ShaderLang eLang) +{ + if(eLang < LANG_430) + { + return 1; + } + return 0; +} + +static int HaveUVec(const ShaderLang eLang) +{ + switch(eLang) + { + case LANG_ES_100: + case LANG_120: + return 0; + default: + break; + } + return 1; +} + +static int HaveGather(const ShaderLang eLang) +{ + if(eLang >= LANG_400 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveGatherNonConstOffset(const ShaderLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + + +static int HaveQueryLod(const ShaderLang eLang) +{ + if(eLang >= LANG_400) + { + return 1; + } + return 0; +} + +static int HaveQueryLevels(const ShaderLang eLang) +{ + if(eLang >= LANG_430) + { + return 1; + } + return 0; +} + + +static int HaveAtomicCounter(const ShaderLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveAtomicMem(const ShaderLang eLang) +{ + if(eLang >= LANG_430) + { + return 1; + } + return 0; +} + +static int HaveCompute(const ShaderLang eLang) +{ + if(eLang >= LANG_430 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +static int HaveImageLoadStore(const ShaderLang eLang) +{ + if(eLang >= LANG_420 || eLang == LANG_ES_310) + { + return 1; + } + return 0; +} + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h new file mode 100644 index 0000000000..6db63de4ca --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/reflect.h @@ -0,0 +1,73 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef REFLECT_H +#define REFLECT_H + +#include "hlslcc.h" + +ResourceGroup ResourceTypeToResourceGroup(ResourceType); + +int GetResourceFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding); + +void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf); + +int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar); + +int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut); +int GetOutputSignatureFromRegister(const uint32_t currentPhase, + const uint32_t ui32Register, + const uint32_t ui32Stream, + const uint32_t ui32CompMask, + ShaderInfo* psShaderInfo, + InOutSignature** ppsOut); + +int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut); + +int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, + const uint32_t* pui32Swizzle, + ConstantBuffer* psCBuf, + ShaderVarType** ppsShaderVar, + int32_t* pi32Index, + int32_t* pi32Rebase); + +typedef struct +{ + uint32_t* pui32Inputs; + uint32_t* pui32Outputs; + uint32_t* pui32Resources; + uint32_t* pui32Interfaces; + uint32_t* pui32Inputs11; + uint32_t* pui32Outputs11; + uint32_t* pui32OutputsWithStreams; + uint32_t* pui32PatchConstants; + uint32_t* pui32Effects10Data; +} ReflectionChunks; + +void LoadShaderInfo(const uint32_t ui32MajorVersion, + const uint32_t ui32MinorVersion, + const ReflectionChunks* psChunks, + ShaderInfo* psInfo); + +void LoadD3D9ConstantTable(const char* data, + ShaderInfo* psInfo); + +void FreeShaderInfo(ShaderInfo* psShaderInfo); + +#if 0 +//--- Utility functions --- + +//Returns 0 if not found, 1 otherwise. +int GetResourceFromName(const char* name, ShaderInfo* psShaderInfo, ResourceBinding* psBinding); + +//These call into OpenGL and modify the uniforms of the currently bound program. +void SetResourceValueF(ResourceBinding* psBinding, float* value); +void SetResourceValueI(ResourceBinding* psBinding, int* value); +void SetResourceValueStr(ResourceBinding* psBinding, char* value); //Used for interfaces/subroutines. Also for constant buffers? + +void CreateUniformBufferObjectFromResource(ResourceBinding* psBinding, uint32_t* ui32GLHandle); +//------------------------ +#endif + +#endif + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h new file mode 100644 index 0000000000..3561f7c78b --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/shaderLimits.h @@ -0,0 +1,14 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef HLSLCC_SHADER_LIMITS_H +#define HLSLCC_SHADER_LIMITS_H + +static enum {MAX_SHADER_VEC4_OUTPUT = 512}; +static enum {MAX_SHADER_VEC4_INPUT = 512}; +static enum {MAX_TEXTURES = 128}; +static enum {MAX_FUNCTION_BODIES = 1024}; +static enum {MAX_CLASS_TYPES = 1024}; +static enum {MAX_FUNCTION_POINTERS = 128}; + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h new file mode 100644 index 0000000000..541b28d86b --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structs.h @@ -0,0 +1,338 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef STRUCTS_H +#define STRUCTS_H + +#include "hlslcc.h" +#include "bstrlib.h" + +#include "internal_includes/tokens.h" +#include "internal_includes/reflect.h" + +enum +{ + MAX_SUB_OPERANDS = 3 +}; + +typedef struct Operand_TAG +{ + int iExtended; + OPERAND_TYPE eType; + OPERAND_MODIFIER eModifier; + OPERAND_MIN_PRECISION eMinPrecision; + int iIndexDims; + int indexRepresentation[4]; + int writeMask; + int iGSInput; + int iWriteMaskEnabled; + + int iNumComponents; + + OPERAND_4_COMPONENT_SELECTION_MODE eSelMode; + uint32_t ui32CompMask; + uint32_t ui32Swizzle; + uint32_t aui32Swizzle[4]; + + uint32_t aui32ArraySizes[3]; + uint32_t ui32RegisterNumber; + //If eType is OPERAND_TYPE_IMMEDIATE32 + float afImmediates[4]; + //If eType is OPERAND_TYPE_IMMEDIATE64 + double adImmediates[4]; + + int iIntegerImmediate; + + SPECIAL_NAME eSpecialName; + char pszSpecialName[64]; + + OPERAND_INDEX_REPRESENTATION eIndexRep[3]; + + struct Operand_TAG* psSubOperand[MAX_SUB_OPERANDS]; + + //One type for each component. + SHADER_VARIABLE_TYPE aeDataType[4]; + +#ifdef _DEBUG + uint64_t id; +#endif +} Operand; + +typedef struct Instruction_TAG +{ + OPCODE_TYPE eOpcode; + INSTRUCTION_TEST_BOOLEAN eBooleanTestType; + COMPARISON_DX9 eDX9TestType; + uint32_t ui32SyncFlags; + uint32_t ui32NumOperands; + uint32_t ui32FirstSrc; + Operand asOperands[6]; + uint32_t bSaturate; + uint32_t ui32FuncIndexWithinInterface; + RESINFO_RETURN_TYPE eResInfoReturnType; + + int bAddressOffset; + int8_t iUAddrOffset; + int8_t iVAddrOffset; + int8_t iWAddrOffset; + RESOURCE_RETURN_TYPE xType, yType, zType, wType; + RESOURCE_DIMENSION eResDim; + +#ifdef _DEBUG + uint64_t id; +#endif +} Instruction; + +enum +{ + MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE = 1024 +}; +enum +{ + MAX_TEXTURE_SAMPLERS_PAIRS = 32 +}; + +typedef struct ICBVec4_TAG +{ + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; +} ICBVec4; + +typedef struct Declaration_TAG +{ + OPCODE_TYPE eOpcode; + + uint32_t ui32NumOperands; + + Operand asOperands[2]; + + ICBVec4 asImmediateConstBuffer[MAX_IMMEDIATE_CONST_BUFFER_VEC4_SIZE]; + //The declaration can set one of these + //values depending on the opcode. + union + { + uint32_t ui32GlobalFlags; + uint32_t ui32NumTemps; + RESOURCE_DIMENSION eResourceDimension; + CONSTANT_BUFFER_ACCESS_PATTERN eCBAccessPattern; + INTERPOLATION_MODE eInterpolation; + PRIMITIVE_TOPOLOGY eOutputPrimitiveTopology; + PRIMITIVE eInputPrimitive; + uint32_t ui32MaxOutputVertexCount; + TESSELLATOR_DOMAIN eTessDomain; + TESSELLATOR_PARTITIONING eTessPartitioning; + TESSELLATOR_OUTPUT_PRIMITIVE eTessOutPrim; + uint32_t aui32WorkGroupSize[3]; + //Fork phase index followed by the instance count. + uint32_t aui32HullPhaseInstanceInfo[2]; + float fMaxTessFactor; + uint32_t ui32IndexRange; + uint32_t ui32GSInstanceCount; + + struct Interface_TAG + { + uint32_t ui32InterfaceID; + uint32_t ui32NumFuncTables; + uint32_t ui32ArraySize; + } interface; + } value; + + struct UAV_TAG + { + uint32_t ui32GloballyCoherentAccess; + uint32_t ui32BufferSize; + uint8_t bCounter; + RESOURCE_RETURN_TYPE Type; + } sUAV; + + struct TGSM_TAG + { + uint32_t ui32Stride; + uint32_t ui32Count; + } sTGSM; + + struct IndexableTemp_TAG + { + uint32_t ui32RegIndex; + uint32_t ui32RegCount; + uint32_t ui32RegComponentSize; + } sIdxTemp; + + uint32_t ui32TableLength; + + uint32_t ui32IsShadowTex; + + uint32_t ui32SamplerUsed[MAX_TEXTURE_SAMPLERS_PAIRS]; + uint32_t ui32SamplerUsedCount; + + uint32_t bIsComparisonSampler; +} Declaration; + +enum +{ + MAX_TEMP_VEC4 = 512 +}; + +enum +{ + MAX_GROUPSHARED = 8 +}; + +enum +{ + MAX_COLOR_MRT = 8 +}; + +enum +{ + MAX_DX9_IMMCONST = 256 +}; + +static const uint32_t MAIN_PHASE = 0; +static const uint32_t HS_GLOBAL_DECL = 1; +static const uint32_t HS_CTRL_POINT_PHASE = 2; +static const uint32_t HS_FORK_PHASE = 3; +static const uint32_t HS_JOIN_PHASE = 4; +enum +{ + NUM_PHASES = 5 +}; + +typedef struct ShaderPhase_TAG +{ + //How many instances of this phase type are there? + uint32_t ui32InstanceCount; + + uint32_t* pui32DeclCount; + Declaration** ppsDecl; + + uint32_t* pui32InstCount; + Instruction** ppsInst; +} ShaderPhase; + +typedef struct Shader_TAG +{ + uint32_t ui32MajorVersion; + uint32_t ui32MinorVersion; + SHADER_TYPE eShaderType; + + ShaderLang eTargetLanguage; + const struct GlExtensions* extensions; + + int fp64; + + //DWORDs in program code, including version and length tokens. + uint32_t ui32ShaderLength; + + //Instruction* functions;//non-main subroutines + + uint32_t aui32FuncTableToFuncPointer[MAX_FUNCTION_TABLES];//FIXME dynamic alloc + uint32_t aui32FuncBodyToFuncTable[MAX_FUNCTION_BODIES]; + + struct + { + uint32_t aui32FuncBodies[MAX_FUNCTION_BODIES]; + }funcTable[MAX_FUNCTION_TABLES]; + + struct + { + uint32_t aui32FuncTables[MAX_FUNCTION_TABLES]; + uint32_t ui32NumBodiesPerTable; + }funcPointer[MAX_FUNCTION_POINTERS]; + + uint32_t ui32NextClassFuncName[MAX_CLASS_TYPES]; + + const uint32_t* pui32FirstToken;//Reference for calculating current position in token stream. + + ShaderPhase asPhase[NUM_PHASES]; + + ShaderInfo sInfo; + + int abScalarInput[MAX_SHADER_VEC4_INPUT]; + + int aIndexedOutput[MAX_SHADER_VEC4_OUTPUT]; + + int aIndexedInput[MAX_SHADER_VEC4_INPUT]; + int aIndexedInputParents[MAX_SHADER_VEC4_INPUT]; + + RESOURCE_DIMENSION aeResourceDims[MAX_TEXTURES]; + + int aiInputDeclaredSize[MAX_SHADER_VEC4_INPUT]; + + int aiOutputDeclared[MAX_SHADER_VEC4_OUTPUT]; + + //Does not track built-in inputs. + int abInputReferencedByInstruction[MAX_SHADER_VEC4_INPUT]; + + int aiOpcodeUsed[NUM_OPCODES]; + + uint32_t ui32CurrentVertexOutputStream; + + uint32_t ui32NumDx9ImmConst; + uint32_t aui32Dx9ImmConstArrayRemap[MAX_DX9_IMMCONST]; + + ShaderVarType sGroupSharedVarType[MAX_GROUPSHARED]; + + TextureSamplerInfo textureSamplerInfo; +} ShaderData; + +// CONFETTI NOTE: DAVID SROUR +// The following is super sketchy, but at the moment, +// there is no way to figure out the type of a resource +// since HLSL has only register sets for the following: +// bool, int4, float4, sampler. +enum +{ + GMEM_FLOAT4_START_SLOT = 120 +}; +enum +{ + GMEM_FLOAT3_START_SLOT = 112 +}; +enum +{ + GMEM_FLOAT2_START_SLOT = 104 +}; +enum +{ + GMEM_FLOAT_START_SLOT = 96 +}; + +// CONFETTI NOTE +// Set the starting binding point for UAV_Buffer. +// All the binding points after the starting point is reserved for UAV +// only. This apply for both [[texture]] and [[buffer]] +enum +{ + UAV_BUFFER_START_SLOT = 25 +}; + +typedef struct HLSLCrossCompilerContext_TAG +{ + bstring mainShader; + bstring stagedInputDeclarations; // Metal only + bstring parameterDeclarations; // Metal only + bstring declaredOutputs; // Metal only + bstring earlyMain;//Code to be inserted at the start of main() + bstring postShaderCode[NUM_PHASES];//End of main or before emit() + + bstring* currentShaderString;//either mainShader or earlyMain + + int needsFragmentTestHint; // METAL only + + int havePostShaderCode[NUM_PHASES]; + uint32_t currentPhase; + + // GMEM INPUT AND OUTPUT TYPES MUST MATCH! + // THIS TABLE KEEPS TRACK OF WHAT THE OUTPUT TYPE SHOULD + // BE IF GMEM INPUT WAS DECLARED TO THE SAME SLOT # + uint32_t gmemOutputNumElements[MAX_COLOR_MRT]; // Metal only + + int indent; + unsigned int flags; + ShaderData* psShader; +} HLSLCrossCompilerContext; + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c new file mode 100644 index 0000000000..d380100d83 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMETAL.c @@ -0,0 +1,15 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#include "structsMetal.h" + +int IsAtomicVar(const ShaderVarType* const var, AtomicVarList* const list) +{ + for (uint32_t i = 0; i < list->Filled; i++) + { + if (var == list->AtomicVars[i]) + { + return 1; + } + } + return 0; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h new file mode 100644 index 0000000000..cd63921310 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/structsMetal.h @@ -0,0 +1,19 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates + +#ifndef STRUCTSS_METAL_H +#define STRUCTSS_METAL_H + +#include "hlslcc.h" +#include <stdint.h> + +typedef struct AtomicVarList_s +{ + const ShaderVarType** AtomicVars; + uint32_t Filled; + uint32_t Size; +} AtomicVarList; + +int IsAtomicVar(const ShaderVarType* const var, AtomicVarList* const list); + + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h new file mode 100644 index 0000000000..d18ee2c243 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLDeclaration.h @@ -0,0 +1,19 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_DECLARATION_H +#define TO_GLSL_DECLARATION_H + +#include "internal_includes/structs.h" + +void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl); + +const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); +const char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand, int* stream); + +//Hull shaders have multiple phases. +//Each phase has its own temps. +//Convert to global temps for GLSL. +void ConsolidateHullTempVars(ShaderData* psShader); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h new file mode 100644 index 0000000000..34f67cfe46 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLInstruction.h @@ -0,0 +1,18 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_INSTRUCTION_H +#define TO_GLSL_INSTRUCTION_H + +#include "internal_includes/structs.h" + +void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst); + +//For each MOV temp, immediate; check to see if the next instruction +//using that temp has an integer opcode. If so then the immediate value +//is flaged as having an integer encoding. +void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext); + +void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h new file mode 100644 index 0000000000..1d7430504c --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toGLSLOperand.h @@ -0,0 +1,72 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_GLSL_OPERAND_H +#define TO_GLSL_OPERAND_H + +#include "internal_includes/structs.h" + +#define TO_FLAG_NONE 0x0 +#define TO_FLAG_INTEGER 0x1 +#define TO_FLAG_NAME_ONLY 0x2 +#define TO_FLAG_DECLARATION_NAME 0x4 +#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. +#define TO_FLAG_UNSIGNED_INTEGER 0x10 +#define TO_FLAG_DOUBLE 0x20 +#define TO_FLAG_FLOAT16 0x40 +// --- TO_AUTO_BITCAST_TO_FLOAT --- +//If the operand is an integer temp variable then this flag +//indicates that the temp has a valid floating point encoding +//and that the current expression expects the operand to be floating point +//and therefore intBitsToFloat must be applied to that variable. +#define TO_AUTO_BITCAST_TO_FLOAT 0x80 +#define TO_AUTO_BITCAST_TO_INT 0x100 +#define TO_AUTO_BITCAST_TO_UINT 0x200 +#define TO_AUTO_BITCAST_TO_FLOAT16 0x400 +// AUTO_EXPAND flags automatically expand the operand to at least (i/u)vecX +// to match HLSL functionality. +#define TO_AUTO_EXPAND_TO_VEC2 0x800 +#define TO_AUTO_EXPAND_TO_VEC3 0x1000 +#define TO_AUTO_EXPAND_TO_VEC4 0x2000 + + +void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); +// Translate operand but add additional component mask +void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask); + +int GetMaxComponentFromComponentMask(const Operand* psOperand); +void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); +void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); +void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask); + +uint32_t GetNumSwizzleElements(const Operand* psOperand); +uint32_t GetNumSwizzleElementsWithMask(const Operand *psOperand, uint32_t ui32CompMask); +void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count); +int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +uint32_t IsSwizzleReplicated(const Operand* psOperand); + +void ResourceName(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare); + +bstring TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); +void ConcatTextureSamplerName(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); + +//Non-zero means the components overlap +int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB); + +// Returns the write mask for the operand used for destination +uint32_t GetOperandWriteMask(const Operand *psOperand); + +SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates); + +const char * GetConstructorForType(const SHADER_VARIABLE_TYPE eType, + const int components); + +const char * GetConstructorForTypeFlag(const uint32_t ui32Flag, + const int components); + +uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType); +SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h new file mode 100644 index 0000000000..fb10d5b691 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALDeclaration.h @@ -0,0 +1,15 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_DECLARATION_H +#define TO_METAL_DECLARATION_H + +#include "internal_includes/structs.h" +#include "internal_includes/structsMetal.h" + +void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, AtomicVarList* psAtomicList); + +char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); +char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h new file mode 100644 index 0000000000..e5b267cd58 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALInstruction.h @@ -0,0 +1,20 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_INSTRUCTION_H +#define TO_METAL_INSTRUCTION_H + +#include "internal_includes/structs.h" +#include "structsMetal.h" + +void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst); +void DetectAtomicInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst, AtomicVarList* psAtomicList); + +//For each MOV temp, immediate; check to see if the next instruction +//using that temp has an integer opcode. If so then the immediate value +//is flaged as having an integer encoding. +void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext); + +void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h new file mode 100644 index 0000000000..6cebf5bab6 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/toMETALOperand.h @@ -0,0 +1,78 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TO_METAL_OPERAND_H +#define TO_METAL_OPERAND_H + +#include "internal_includes/structs.h" + +#define TO_FLAG_NONE 0x0 +#define TO_FLAG_INTEGER 0x1 +#define TO_FLAG_NAME_ONLY 0x2 +#define TO_FLAG_DECLARATION_NAME 0x4 +#define TO_FLAG_DESTINATION 0x8 //Operand is being written to by assignment. +#define TO_FLAG_UNSIGNED_INTEGER 0x10 +#define TO_FLAG_DOUBLE 0x20 +#define TO_FLAG_FLOAT16 0x40 +// --- TO_AUTO_BITCAST_TO_FLOAT --- +//If the operand is an integer temp variable then this flag +//indicates that the temp has a valid floating point encoding +//and that the current expression expects the operand to be floating point +//and therefore intBitsToFloat must be applied to that variable. +#define TO_AUTO_BITCAST_TO_FLOAT 0x80 +#define TO_AUTO_BITCAST_TO_INT 0x100 +#define TO_AUTO_BITCAST_TO_UINT 0x200 +#define TO_AUTO_BITCAST_TO_FLOAT16 0x400 +// AUTO_EXPAND flags automatically expand the operand to at least (i/u)vecX +// to match HLSL functionality. +#define TO_AUTO_EXPAND_TO_VEC2 0x800 +#define TO_AUTO_EXPAND_TO_VEC3 0x1000 +#define TO_AUTO_EXPAND_TO_VEC4 0x2000 + +void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag); +// Translate operand but add additional component mask +void TranslateOperandWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask); + +int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand); +void TranslateOperandIndexMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index); +void TranslateOperandIndexMADMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add); +void TranslateOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +void TranslateOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask); + +void TranslateGmemOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements); + +uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand); +uint32_t GetNumSwizzleElementsWithMaskMETAL(const Operand *psOperand, uint32_t ui32CompMask); +void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count); +int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +uint32_t IsSwizzleReplicatedMETAL(const Operand* psOperand); + +void ResourceNameMETAL(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare); + +bstring TextureSamplerNameMETAL(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); +void ConcatTextureSamplerNameMETAL(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare); + +//Non-zero means the components overlap +int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB); + +// Returns the write mask for the operand used for destination +uint32_t GetOperandWriteMaskMETAL(const Operand *psOperand); + +SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand); +SHADER_VARIABLE_TYPE GetOperandDataTypeExMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates); + +const char * GetConstructorForTypeMETAL(const SHADER_VARIABLE_TYPE eType, + const int components); + +const char * GetConstructorForTypeFlagMETAL(const uint32_t ui32Flag, + const int components); + +uint32_t SVTTypeToFlagMETAL(const SHADER_VARIABLE_TYPE eType); +SHADER_VARIABLE_TYPE TypeFlagsToSVTTypeMETAL(const uint32_t typeflags); + + +uint32_t GetGmemInputResourceSlotMETAL(uint32_t const slotIn); + +uint32_t GetGmemInputResourceNumElementsMETAL(uint32_t const slotIn); + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h new file mode 100644 index 0000000000..ddf17058cd --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokens.h @@ -0,0 +1,819 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#ifndef TOKENS_H +#define TOKENS_H + +#include "hlslcc.h" + +typedef enum +{ + INVALID_SHADER = -1, + PIXEL_SHADER, + VERTEX_SHADER, + GEOMETRY_SHADER, + HULL_SHADER, + DOMAIN_SHADER, + COMPUTE_SHADER, +} SHADER_TYPE; + +static SHADER_TYPE DecodeShaderType(uint32_t ui32Token) +{ + return (SHADER_TYPE)((ui32Token & 0xffff0000) >> 16); +} + +static uint32_t DecodeProgramMajorVersion(uint32_t ui32Token) +{ + return (ui32Token & 0x000000f0) >> 4; +} + +static uint32_t DecodeProgramMinorVersion(uint32_t ui32Token) +{ + return (ui32Token & 0x0000000f); +} + +static uint32_t DecodeInstructionLength(uint32_t ui32Token) +{ + return (ui32Token & 0x7f000000) >> 24; +} + +static uint32_t DecodeIsOpcodeExtended(uint32_t ui32Token) +{ + return (ui32Token & 0x80000000) >> 31; +} + +typedef enum EXTENDED_OPCODE_TYPE +{ + EXTENDED_OPCODE_EMPTY = 0, + EXTENDED_OPCODE_SAMPLE_CONTROLS = 1, + EXTENDED_OPCODE_RESOURCE_DIM = 2, + EXTENDED_OPCODE_RESOURCE_RETURN_TYPE = 3, +} EXTENDED_OPCODE_TYPE; + +static EXTENDED_OPCODE_TYPE DecodeExtendedOpcodeType(uint32_t ui32Token) +{ + return (EXTENDED_OPCODE_TYPE)(ui32Token & 0x0000003f); +} + +typedef enum RESOURCE_RETURN_TYPE +{ + RETURN_TYPE_UNORM = 1, + RETURN_TYPE_SNORM = 2, + RETURN_TYPE_SINT = 3, + RETURN_TYPE_UINT = 4, + RETURN_TYPE_FLOAT = 5, + RETURN_TYPE_MIXED = 6, + RETURN_TYPE_DOUBLE = 7, + RETURN_TYPE_CONTINUED = 8, + RETURN_TYPE_UNUSED = 9, +} RESOURCE_RETURN_TYPE; + +static RESOURCE_RETURN_TYPE DecodeResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) +{ + return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4))&0xF); +} + +static RESOURCE_RETURN_TYPE DecodeExtendedResourceReturnType(uint32_t ui32Coord, uint32_t ui32Token) +{ + return (RESOURCE_RETURN_TYPE)((ui32Token>>(ui32Coord * 4 + 6))&0xF); +} + +typedef enum +{ + //For DX9 + OPCODE_POW = -6, + OPCODE_DP2ADD = -5, + OPCODE_LRP = -4, + OPCODE_ENDREP = -3, + OPCODE_REP = -2, + OPCODE_SPECIAL_DCL_IMMCONST = -1, + + OPCODE_ADD, + OPCODE_AND, + OPCODE_BREAK, + OPCODE_BREAKC, + OPCODE_CALL, + OPCODE_CALLC, + OPCODE_CASE, + OPCODE_CONTINUE, + OPCODE_CONTINUEC, + OPCODE_CUT, + OPCODE_DEFAULT, + OPCODE_DERIV_RTX, + OPCODE_DERIV_RTY, + OPCODE_DISCARD, + OPCODE_DIV, + OPCODE_DP2, + OPCODE_DP3, + OPCODE_DP4, + OPCODE_ELSE, + OPCODE_EMIT, + OPCODE_EMITTHENCUT, + OPCODE_ENDIF, + OPCODE_ENDLOOP, + OPCODE_ENDSWITCH, + OPCODE_EQ, + OPCODE_EXP, + OPCODE_FRC, + OPCODE_FTOI, + OPCODE_FTOU, + OPCODE_GE, + OPCODE_IADD, + OPCODE_IF, + OPCODE_IEQ, + OPCODE_IGE, + OPCODE_ILT, + OPCODE_IMAD, + OPCODE_IMAX, + OPCODE_IMIN, + OPCODE_IMUL, + OPCODE_INE, + OPCODE_INEG, + OPCODE_ISHL, + OPCODE_ISHR, + OPCODE_ITOF, + OPCODE_LABEL, + OPCODE_LD, + OPCODE_LD_MS, + OPCODE_LOG, + OPCODE_LOOP, + OPCODE_LT, + OPCODE_MAD, + OPCODE_MIN, + OPCODE_MAX, + OPCODE_CUSTOMDATA, + OPCODE_MOV, + OPCODE_MOVC, + OPCODE_MUL, + OPCODE_NE, + OPCODE_NOP, + OPCODE_NOT, + OPCODE_OR, + OPCODE_RESINFO, + OPCODE_RET, + OPCODE_RETC, + OPCODE_ROUND_NE, + OPCODE_ROUND_NI, + OPCODE_ROUND_PI, + OPCODE_ROUND_Z, + OPCODE_RSQ, + OPCODE_SAMPLE, + OPCODE_SAMPLE_C, + OPCODE_SAMPLE_C_LZ, + OPCODE_SAMPLE_L, + OPCODE_SAMPLE_D, + OPCODE_SAMPLE_B, + OPCODE_SQRT, + OPCODE_SWITCH, + OPCODE_SINCOS, + OPCODE_UDIV, + OPCODE_ULT, + OPCODE_UGE, + OPCODE_UMUL, + OPCODE_UMAD, + OPCODE_UMAX, + OPCODE_UMIN, + OPCODE_USHR, + OPCODE_UTOF, + OPCODE_XOR, + OPCODE_DCL_RESOURCE, // DCL* opcodes have + OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats. + OPCODE_DCL_SAMPLER, + OPCODE_DCL_INDEX_RANGE, + OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY, + OPCODE_DCL_GS_INPUT_PRIMITIVE, + OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT, + OPCODE_DCL_INPUT, + OPCODE_DCL_INPUT_SGV, + OPCODE_DCL_INPUT_SIV, + OPCODE_DCL_INPUT_PS, + OPCODE_DCL_INPUT_PS_SGV, + OPCODE_DCL_INPUT_PS_SIV, + OPCODE_DCL_OUTPUT, + OPCODE_DCL_OUTPUT_SGV, + OPCODE_DCL_OUTPUT_SIV, + OPCODE_DCL_TEMPS, + OPCODE_DCL_INDEXABLE_TEMP, + OPCODE_DCL_GLOBAL_FLAGS, + +// ----------------------------------------------- + + OPCODE_RESERVED_10, + +// ---------- DX 10.1 op codes--------------------- + + OPCODE_LOD, + OPCODE_GATHER4, + OPCODE_SAMPLE_POS, + OPCODE_SAMPLE_INFO, + +// ----------------------------------------------- + + // This should be 10.1's version of NUM_OPCODES + OPCODE_RESERVED_10_1, + +// ---------- DX 11 op codes--------------------- + OPCODE_HS_DECLS, // token marks beginning of HS sub-shader + OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader + OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader + OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader + + OPCODE_EMIT_STREAM, + OPCODE_CUT_STREAM, + OPCODE_EMITTHENCUT_STREAM, + OPCODE_INTERFACE_CALL, + + OPCODE_BUFINFO, + OPCODE_DERIV_RTX_COARSE, + OPCODE_DERIV_RTX_FINE, + OPCODE_DERIV_RTY_COARSE, + OPCODE_DERIV_RTY_FINE, + OPCODE_GATHER4_C, + OPCODE_GATHER4_PO, + OPCODE_GATHER4_PO_C, + OPCODE_RCP, + OPCODE_F32TOF16, + OPCODE_F16TOF32, + OPCODE_UADDC, + OPCODE_USUBB, + OPCODE_COUNTBITS, + OPCODE_FIRSTBIT_HI, + OPCODE_FIRSTBIT_LO, + OPCODE_FIRSTBIT_SHI, + OPCODE_UBFE, + OPCODE_IBFE, + OPCODE_BFI, + OPCODE_BFREV, + OPCODE_SWAPC, + + OPCODE_DCL_STREAM, + OPCODE_DCL_FUNCTION_BODY, + OPCODE_DCL_FUNCTION_TABLE, + OPCODE_DCL_INTERFACE, + + OPCODE_DCL_INPUT_CONTROL_POINT_COUNT, + OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT, + OPCODE_DCL_TESS_DOMAIN, + OPCODE_DCL_TESS_PARTITIONING, + OPCODE_DCL_TESS_OUTPUT_PRIMITIVE, + OPCODE_DCL_HS_MAX_TESSFACTOR, + OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT, + OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT, + + OPCODE_DCL_THREAD_GROUP, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, + OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED, + OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW, + OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED, + OPCODE_DCL_RESOURCE_RAW, + OPCODE_DCL_RESOURCE_STRUCTURED, + OPCODE_LD_UAV_TYPED, + OPCODE_STORE_UAV_TYPED, + OPCODE_LD_RAW, + OPCODE_STORE_RAW, + OPCODE_LD_STRUCTURED, + OPCODE_STORE_STRUCTURED, + OPCODE_ATOMIC_AND, + OPCODE_ATOMIC_OR, + OPCODE_ATOMIC_XOR, + OPCODE_ATOMIC_CMP_STORE, + OPCODE_ATOMIC_IADD, + OPCODE_ATOMIC_IMAX, + OPCODE_ATOMIC_IMIN, + OPCODE_ATOMIC_UMAX, + OPCODE_ATOMIC_UMIN, + OPCODE_IMM_ATOMIC_ALLOC, + OPCODE_IMM_ATOMIC_CONSUME, + OPCODE_IMM_ATOMIC_IADD, + OPCODE_IMM_ATOMIC_AND, + OPCODE_IMM_ATOMIC_OR, + OPCODE_IMM_ATOMIC_XOR, + OPCODE_IMM_ATOMIC_EXCH, + OPCODE_IMM_ATOMIC_CMP_EXCH, + OPCODE_IMM_ATOMIC_IMAX, + OPCODE_IMM_ATOMIC_IMIN, + OPCODE_IMM_ATOMIC_UMAX, + OPCODE_IMM_ATOMIC_UMIN, + OPCODE_SYNC, + + OPCODE_DADD, + OPCODE_DMAX, + OPCODE_DMIN, + OPCODE_DMUL, + OPCODE_DEQ, + OPCODE_DGE, + OPCODE_DLT, + OPCODE_DNE, + OPCODE_DMOV, + OPCODE_DMOVC, + OPCODE_DTOF, + OPCODE_FTOD, + + OPCODE_EVAL_SNAPPED, + OPCODE_EVAL_SAMPLE_INDEX, + OPCODE_EVAL_CENTROID, + + OPCODE_DCL_GS_INSTANCE_COUNT, + + OPCODE_ABORT, + OPCODE_DEBUG_BREAK, + +// ----------------------------------------------- + + // This marks the end of D3D11.0 opcodes + OPCODE_RESERVED_11, + + OPCODE_DDIV, + OPCODE_DFMA, + OPCODE_DRCP, + + OPCODE_MSAD, + + OPCODE_DTOI, + OPCODE_DTOU, + OPCODE_ITOD, + OPCODE_UTOD, + +// ----------------------------------------------- + + // This marks the end of D3D11.1 opcodes + OPCODE_RESERVED_11_1, + + NUM_OPCODES, + OPCODE_INVAILD = NUM_OPCODES, +} OPCODE_TYPE; + +static OPCODE_TYPE DecodeOpcodeType(uint32_t ui32Token) +{ + return (OPCODE_TYPE)(ui32Token & 0x00007ff); +} + +typedef enum +{ + INDEX_0D, + INDEX_1D, + INDEX_2D, + INDEX_3D, +} OPERAND_INDEX_DIMENSION; + +static OPERAND_INDEX_DIMENSION DecodeOperandIndexDimension(uint32_t ui32Token) +{ + return (OPERAND_INDEX_DIMENSION)((ui32Token & 0x00300000) >> 20); +} + +typedef enum OPERAND_TYPE +{ + OPERAND_TYPE_SPECIAL_LOOPCOUNTER = -10, + OPERAND_TYPE_SPECIAL_IMMCONSTINT = -9, + OPERAND_TYPE_SPECIAL_TEXCOORD = -8, + OPERAND_TYPE_SPECIAL_POSITION = -7, + OPERAND_TYPE_SPECIAL_FOG = -6, + OPERAND_TYPE_SPECIAL_POINTSIZE = -5, + OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR = -4, + OPERAND_TYPE_SPECIAL_OUTBASECOLOUR = -3, + OPERAND_TYPE_SPECIAL_ADDRESS = -2, + OPERAND_TYPE_SPECIAL_IMMCONST = -1, + OPERAND_TYPE_TEMP = 0, // Temporary Register File + OPERAND_TYPE_INPUT = 1, // General Input Register File + OPERAND_TYPE_OUTPUT = 2, // General Output Register File + OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable) + OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s) + // If for example, operand token bits + // [01:00]==OPERAND_4_COMPONENT, + // this means that the operand type: + // OPERAND_TYPE_IMMEDIATE32 + // results in 4 additional 32bit + // DWORDS present for the operand. + OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO + OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state + OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture) + OPERAND_TYPE_CONSTANT_BUFFER= 8, // Reference to constant buffer + OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER= 9, // Reference to immediate constant buffer + OPERAND_TYPE_LABEL = 10, // Label + OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID + OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth + OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations + // Below Are operands new in DX 10.1 + OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources + OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar) + // Below Are operands new in DX 11 + OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource + OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition + OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class + OPERAND_TYPE_INTERFACE = 19, // Reference to an interface + OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function + OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function + OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is + OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID + OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID + OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them) + OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them) + OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them) + OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point + OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer + OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u# + OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g# + OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID + OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID + OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group + OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input + OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value. + OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID + OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth + OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth + OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter +} OPERAND_TYPE; + +static OPERAND_TYPE DecodeOperandType(uint32_t ui32Token) +{ + return (OPERAND_TYPE)((ui32Token & 0x000ff000) >> 12); +} + +static SPECIAL_NAME DecodeOperandSpecialName(uint32_t ui32Token) +{ + return (SPECIAL_NAME)(ui32Token & 0x0000ffff); +} + +typedef enum OPERAND_INDEX_REPRESENTATION +{ + OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD + OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs + // (HI32:LO32) + OPERAND_INDEX_RELATIVE = 2, // Extra operand + OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by + // extra operand + OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS + // (HI32:LO32) followed + // by extra operand +} OPERAND_INDEX_REPRESENTATION; + +static OPERAND_INDEX_REPRESENTATION DecodeOperandIndexRepresentation(uint32_t ui32Dimension, uint32_t ui32Token) +{ + return (OPERAND_INDEX_REPRESENTATION)((ui32Token & (0x3<<(22+3*((ui32Dimension)&3)))) >> (22+3*((ui32Dimension)&3))); +} + +typedef enum OPERAND_NUM_COMPONENTS +{ + OPERAND_0_COMPONENT = 0, + OPERAND_1_COMPONENT = 1, + OPERAND_4_COMPONENT = 2, + OPERAND_N_COMPONENT = 3 // unused for now +} OPERAND_NUM_COMPONENTS; + +static OPERAND_NUM_COMPONENTS DecodeOperandNumComponents(uint32_t ui32Token) +{ + return (OPERAND_NUM_COMPONENTS)(ui32Token & 0x00000003); +} + +typedef enum OPERAND_4_COMPONENT_SELECTION_MODE +{ + OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components + OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components + OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components +} OPERAND_4_COMPONENT_SELECTION_MODE; + +static OPERAND_4_COMPONENT_SELECTION_MODE DecodeOperand4CompSelMode(uint32_t ui32Token) +{ + return (OPERAND_4_COMPONENT_SELECTION_MODE)((ui32Token & 0x0000000c) >> 2); +} + +#define OPERAND_4_COMPONENT_MASK_X 0x00000001 +#define OPERAND_4_COMPONENT_MASK_Y 0x00000002 +#define OPERAND_4_COMPONENT_MASK_Z 0x00000004 +#define OPERAND_4_COMPONENT_MASK_W 0x00000008 +#define OPERAND_4_COMPONENT_MASK_R OPERAND_4_COMPONENT_MASK_X +#define OPERAND_4_COMPONENT_MASK_G OPERAND_4_COMPONENT_MASK_Y +#define OPERAND_4_COMPONENT_MASK_B OPERAND_4_COMPONENT_MASK_Z +#define OPERAND_4_COMPONENT_MASK_A OPERAND_4_COMPONENT_MASK_W +#define OPERAND_4_COMPONENT_MASK_ALL 0x0000000f + +static uint32_t DecodeOperand4CompMask(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x000000f0) >> 4); +} + +static uint32_t DecodeOperand4CompSwizzle(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x00000ff0) >> 4); +} + +static uint32_t DecodeOperand4CompSel1(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x00000030) >> 4); +} + +#define OPERAND_4_COMPONENT_X 0 +#define OPERAND_4_COMPONENT_Y 1 +#define OPERAND_4_COMPONENT_Z 2 +#define OPERAND_4_COMPONENT_W 3 + +static uint32_t NO_SWIZZLE = (( (OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_W << 6))/*<<4*/); + +static uint32_t XXXX_SWIZZLE = (((OPERAND_4_COMPONENT_X) | (OPERAND_4_COMPONENT_X<<2) | (OPERAND_4_COMPONENT_X << 4) | (OPERAND_4_COMPONENT_X << 6))); +static uint32_t YYYY_SWIZZLE = (((OPERAND_4_COMPONENT_Y) | (OPERAND_4_COMPONENT_Y<<2) | (OPERAND_4_COMPONENT_Y << 4) | (OPERAND_4_COMPONENT_Y << 6))); +static uint32_t ZZZZ_SWIZZLE = (((OPERAND_4_COMPONENT_Z) | (OPERAND_4_COMPONENT_Z<<2) | (OPERAND_4_COMPONENT_Z << 4) | (OPERAND_4_COMPONENT_Z << 6))); +static uint32_t WWWW_SWIZZLE = (((OPERAND_4_COMPONENT_W) | (OPERAND_4_COMPONENT_W<<2) | (OPERAND_4_COMPONENT_W << 4) | (OPERAND_4_COMPONENT_W << 6))); + +static uint32_t DecodeOperand4CompSwizzleSource(uint32_t ui32Token, uint32_t comp) +{ + return (uint32_t)(((ui32Token)>>(4+2*((comp)&3)))&3); +} + +typedef enum RESOURCE_DIMENSION +{ + RESOURCE_DIMENSION_UNKNOWN = 0, + RESOURCE_DIMENSION_BUFFER = 1, + RESOURCE_DIMENSION_TEXTURE1D = 2, + RESOURCE_DIMENSION_TEXTURE2D = 3, + RESOURCE_DIMENSION_TEXTURE2DMS = 4, + RESOURCE_DIMENSION_TEXTURE3D = 5, + RESOURCE_DIMENSION_TEXTURECUBE = 6, + RESOURCE_DIMENSION_TEXTURE1DARRAY = 7, + RESOURCE_DIMENSION_TEXTURE2DARRAY = 8, + RESOURCE_DIMENSION_TEXTURE2DMSARRAY = 9, + RESOURCE_DIMENSION_TEXTURECUBEARRAY = 10, + RESOURCE_DIMENSION_RAW_BUFFER = 11, + RESOURCE_DIMENSION_STRUCTURED_BUFFER = 12, +} RESOURCE_DIMENSION; + +static RESOURCE_DIMENSION DecodeResourceDimension(uint32_t ui32Token) +{ + return (RESOURCE_DIMENSION)((ui32Token & 0x0000f800) >> 11); +} + +static RESOURCE_DIMENSION DecodeExtendedResourceDimension(uint32_t ui32Token) +{ + return (RESOURCE_DIMENSION)((ui32Token & 0x000007C0) >> 6); +} + +static const uint32_t SHADER_INPUT_FLAG_COMPARISON_SAMPLER = (1 << 1); + +static uint32_t DecodeShaderInputFlags(uint32_t ui32Token) +{ + return (uint32_t)(ui32Token & 0x00000002); +} + +typedef enum CONSTANT_BUFFER_ACCESS_PATTERN +{ + CONSTANT_BUFFER_ACCESS_PATTERN_IMMEDIATEINDEXED = 0, + CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED = 1 +} CONSTANT_BUFFER_ACCESS_PATTERN; + +static CONSTANT_BUFFER_ACCESS_PATTERN DecodeConstantBufferAccessPattern(uint32_t ui32Token) +{ + return (CONSTANT_BUFFER_ACCESS_PATTERN)((ui32Token & 0x00000800) >> 11); +} + +typedef enum INSTRUCTION_TEST_BOOLEAN +{ + INSTRUCTION_TEST_ZERO = 0, + INSTRUCTION_TEST_NONZERO = 1 +} INSTRUCTION_TEST_BOOLEAN; + +static INSTRUCTION_TEST_BOOLEAN DecodeInstrTestBool(uint32_t ui32Token) +{ + return (INSTRUCTION_TEST_BOOLEAN)((ui32Token & 0x00040000) >> 18); +} + +static uint32_t DecodeIsOperandExtended(uint32_t ui32Token) +{ + return (ui32Token & 0x80000000) >> 31; +} + +typedef enum EXTENDED_OPERAND_TYPE +{ + EXTENDED_OPERAND_EMPTY = 0, + EXTENDED_OPERAND_MODIFIER = 1, +} EXTENDED_OPERAND_TYPE; + +static EXTENDED_OPERAND_TYPE DecodeExtendedOperandType(uint32_t ui32Token) +{ + return (EXTENDED_OPERAND_TYPE)(ui32Token & 0x0000003f); +} + +typedef enum OPERAND_MODIFIER +{ + OPERAND_MODIFIER_NONE = 0, + OPERAND_MODIFIER_NEG = 1, + OPERAND_MODIFIER_ABS = 2, + OPERAND_MODIFIER_ABSNEG = 3, +} OPERAND_MODIFIER; + +static OPERAND_MODIFIER DecodeExtendedOperandModifier(uint32_t ui32Token) +{ + return (OPERAND_MODIFIER)((ui32Token & 0x00003fc0) >> 6); +} + +static const uint32_t GLOBAL_FLAG_REFACTORING_ALLOWED = (1<<11); +static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS = (1<<12); +static const uint32_t GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL = (1<<13); +static const uint32_t GLOBAL_FLAG_ENABLE_RAW_AND_STRUCTURED_BUFFERS = (1<<14); +static const uint32_t GLOBAL_FLAG_SKIP_OPTIMIZATION = (1<<15); +static const uint32_t GLOBAL_FLAG_ENABLE_MINIMUM_PRECISION = (1<<16); +static const uint32_t GLOBAL_FLAG_ENABLE_DOUBLE_EXTENSIONS = (1<<17); +static const uint32_t GLOBAL_FLAG_ENABLE_SHADER_EXTENSIONS = (1<<18); + +static uint32_t DecodeGlobalFlags(uint32_t ui32Token) +{ + return (uint32_t)(ui32Token & 0x00fff800); +} + +static INTERPOLATION_MODE DecodeInterpolationMode(uint32_t ui32Token) +{ + return (INTERPOLATION_MODE)((ui32Token & 0x00007800) >> 11); +} + + +typedef enum PRIMITIVE_TOPOLOGY +{ + PRIMITIVE_TOPOLOGY_UNDEFINED = 0, + PRIMITIVE_TOPOLOGY_POINTLIST = 1, + PRIMITIVE_TOPOLOGY_LINELIST = 2, + PRIMITIVE_TOPOLOGY_LINESTRIP = 3, + PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4, + PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5, + // 6 is reserved for legacy triangle fans + // Adjacency values should be equal to (0x8 & non-adjacency): + PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10, + PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11, + PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12, + PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13, +} PRIMITIVE_TOPOLOGY; + +static PRIMITIVE_TOPOLOGY DecodeGSOutputPrimitiveTopology(uint32_t ui32Token) +{ + return (PRIMITIVE_TOPOLOGY)((ui32Token & 0x0001f800) >> 11); +} + +typedef enum PRIMITIVE +{ + PRIMITIVE_UNDEFINED = 0, + PRIMITIVE_POINT = 1, + PRIMITIVE_LINE = 2, + PRIMITIVE_TRIANGLE = 3, + // Adjacency values should be equal to (0x4 & non-adjacency): + PRIMITIVE_LINE_ADJ = 6, + PRIMITIVE_TRIANGLE_ADJ = 7, + PRIMITIVE_1_CONTROL_POINT_PATCH = 8, + PRIMITIVE_2_CONTROL_POINT_PATCH = 9, + PRIMITIVE_3_CONTROL_POINT_PATCH = 10, + PRIMITIVE_4_CONTROL_POINT_PATCH = 11, + PRIMITIVE_5_CONTROL_POINT_PATCH = 12, + PRIMITIVE_6_CONTROL_POINT_PATCH = 13, + PRIMITIVE_7_CONTROL_POINT_PATCH = 14, + PRIMITIVE_8_CONTROL_POINT_PATCH = 15, + PRIMITIVE_9_CONTROL_POINT_PATCH = 16, + PRIMITIVE_10_CONTROL_POINT_PATCH = 17, + PRIMITIVE_11_CONTROL_POINT_PATCH = 18, + PRIMITIVE_12_CONTROL_POINT_PATCH = 19, + PRIMITIVE_13_CONTROL_POINT_PATCH = 20, + PRIMITIVE_14_CONTROL_POINT_PATCH = 21, + PRIMITIVE_15_CONTROL_POINT_PATCH = 22, + PRIMITIVE_16_CONTROL_POINT_PATCH = 23, + PRIMITIVE_17_CONTROL_POINT_PATCH = 24, + PRIMITIVE_18_CONTROL_POINT_PATCH = 25, + PRIMITIVE_19_CONTROL_POINT_PATCH = 26, + PRIMITIVE_20_CONTROL_POINT_PATCH = 27, + PRIMITIVE_21_CONTROL_POINT_PATCH = 28, + PRIMITIVE_22_CONTROL_POINT_PATCH = 29, + PRIMITIVE_23_CONTROL_POINT_PATCH = 30, + PRIMITIVE_24_CONTROL_POINT_PATCH = 31, + PRIMITIVE_25_CONTROL_POINT_PATCH = 32, + PRIMITIVE_26_CONTROL_POINT_PATCH = 33, + PRIMITIVE_27_CONTROL_POINT_PATCH = 34, + PRIMITIVE_28_CONTROL_POINT_PATCH = 35, + PRIMITIVE_29_CONTROL_POINT_PATCH = 36, + PRIMITIVE_30_CONTROL_POINT_PATCH = 37, + PRIMITIVE_31_CONTROL_POINT_PATCH = 38, + PRIMITIVE_32_CONTROL_POINT_PATCH = 39, +} PRIMITIVE; + +static PRIMITIVE DecodeGSInputPrimitive(uint32_t ui32Token) +{ + return (PRIMITIVE)((ui32Token & 0x0001f800) >> 11); +} + +static TESSELLATOR_PARTITIONING DecodeTessPartitioning(uint32_t ui32Token) +{ + return (TESSELLATOR_PARTITIONING)((ui32Token & 0x00003800) >> 11); +} + +typedef enum TESSELLATOR_DOMAIN +{ + TESSELLATOR_DOMAIN_UNDEFINED = 0, + TESSELLATOR_DOMAIN_ISOLINE = 1, + TESSELLATOR_DOMAIN_TRI = 2, + TESSELLATOR_DOMAIN_QUAD = 3 +} TESSELLATOR_DOMAIN; + +static TESSELLATOR_DOMAIN DecodeTessDomain(uint32_t ui32Token) +{ + return (TESSELLATOR_DOMAIN)((ui32Token & 0x00001800) >> 11); +} + +static TESSELLATOR_OUTPUT_PRIMITIVE DecodeTessOutPrim(uint32_t ui32Token) +{ + return (TESSELLATOR_OUTPUT_PRIMITIVE)((ui32Token & 0x00003800) >> 11); +} + +static const uint32_t SYNC_THREADS_IN_GROUP = 0x00000800; +static const uint32_t SYNC_THREAD_GROUP_SHARED_MEMORY = 0x00001000; +static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP = 0x00002000; +static const uint32_t SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL = 0x00004000; + +static uint32_t DecodeSyncFlags(uint32_t ui32Token) +{ + return ui32Token & 0x00007800; +} + +// The number of types that implement this interface +static uint32_t DecodeInterfaceTableLength(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0x0000ffff) >> 0); +} + +// The number of interfaces that are defined in this array. +static uint32_t DecodeInterfaceArrayLength(uint32_t ui32Token) +{ + return (uint32_t)((ui32Token & 0xffff0000) >> 16); +} + +typedef enum CUSTOMDATA_CLASS +{ + CUSTOMDATA_COMMENT = 0, + CUSTOMDATA_DEBUGINFO, + CUSTOMDATA_OPAQUE, + CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER, + CUSTOMDATA_SHADER_MESSAGE, +} CUSTOMDATA_CLASS; + +static CUSTOMDATA_CLASS DecodeCustomDataClass(uint32_t ui32Token) +{ + return (CUSTOMDATA_CLASS)((ui32Token & 0xfffff800) >> 11); +} + +static uint32_t DecodeInstructionSaturate(uint32_t ui32Token) +{ + return (ui32Token & 0x00002000) ? 1 : 0; +} + +typedef enum OPERAND_MIN_PRECISION +{ + OPERAND_MIN_PRECISION_DEFAULT = 0, // Default precision + // for the shader model + OPERAND_MIN_PRECISION_FLOAT_16 = 1, // Min 16 bit/component float + OPERAND_MIN_PRECISION_FLOAT_2_8 = 2, // Min 10(2.8)bit/comp. float + OPERAND_MIN_PRECISION_SINT_16 = 4, // Min 16 bit/comp. signed integer + OPERAND_MIN_PRECISION_UINT_16 = 5, // Min 16 bit/comp. unsigned integer +} OPERAND_MIN_PRECISION; + +static uint32_t DecodeOperandMinPrecision(uint32_t ui32Token) +{ + return (ui32Token & 0x0001C000) >> 14; +} + +static uint32_t DecodeOutputControlPointCount(uint32_t ui32Token) +{ + return ((ui32Token & 0x0001f800) >> 11); +} + +typedef enum IMMEDIATE_ADDRESS_OFFSET_COORD +{ + IMMEDIATE_ADDRESS_OFFSET_U = 0, + IMMEDIATE_ADDRESS_OFFSET_V = 1, + IMMEDIATE_ADDRESS_OFFSET_W = 2, +} IMMEDIATE_ADDRESS_OFFSET_COORD; + + +#define IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord) (9+4*((Coord)&3)) +#define IMMEDIATE_ADDRESS_OFFSET_MASK(Coord) (0x0000000f<<IMMEDIATE_ADDRESS_OFFSET_SHIFT(Coord)) + +static uint32_t DecodeImmediateAddressOffset(IMMEDIATE_ADDRESS_OFFSET_COORD eCoord, uint32_t ui32Token) +{ + return ((((ui32Token)&IMMEDIATE_ADDRESS_OFFSET_MASK(eCoord))>>(IMMEDIATE_ADDRESS_OFFSET_SHIFT(eCoord)))); +} + +// UAV access scope flags +static const uint32_t GLOBALLY_COHERENT_ACCESS = 0x00010000; +static uint32_t DecodeAccessCoherencyFlags(uint32_t ui32Token) +{ + return ui32Token & 0x00010000; +} + + +typedef enum RESINFO_RETURN_TYPE +{ + RESINFO_INSTRUCTION_RETURN_FLOAT = 0, + RESINFO_INSTRUCTION_RETURN_RCPFLOAT = 1, + RESINFO_INSTRUCTION_RETURN_UINT = 2 +} RESINFO_RETURN_TYPE; + +static RESINFO_RETURN_TYPE DecodeResInfoReturnType(uint32_t ui32Token) +{ + return (RESINFO_RETURN_TYPE)((ui32Token & 0x00001800) >> 11); +} + +#include "tokensDX9.h" + +#endif diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h new file mode 100644 index 0000000000..1284419ca2 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/internal_includes/tokensDX9.h @@ -0,0 +1,304 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "debug.h" + +static const uint32_t D3D9SHADER_TYPE_VERTEX = 0xFFFE0000; +static const uint32_t D3D9SHADER_TYPE_PIXEL = 0xFFFF0000; + +static SHADER_TYPE DecodeShaderTypeDX9(const uint32_t ui32Token) +{ + uint32_t ui32Type = ui32Token & 0xFFFF0000; + if(ui32Type == D3D9SHADER_TYPE_VERTEX) + return VERTEX_SHADER; + + if(ui32Type == D3D9SHADER_TYPE_PIXEL) + return PIXEL_SHADER; + + return INVALID_SHADER; +} + +static uint32_t DecodeProgramMajorVersionDX9(const uint32_t ui32Token) +{ + return ((ui32Token)>>8)&0xFF; +} + +static uint32_t DecodeProgramMinorVersionDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xFF; +} + +typedef enum +{ + OPCODE_DX9_NOP = 0, + OPCODE_DX9_MOV , + OPCODE_DX9_ADD , + OPCODE_DX9_SUB , + OPCODE_DX9_MAD , + OPCODE_DX9_MUL , + OPCODE_DX9_RCP , + OPCODE_DX9_RSQ , + OPCODE_DX9_DP3 , + OPCODE_DX9_DP4 , + OPCODE_DX9_MIN , + OPCODE_DX9_MAX , + OPCODE_DX9_SLT , + OPCODE_DX9_SGE , + OPCODE_DX9_EXP , + OPCODE_DX9_LOG , + OPCODE_DX9_LIT , + OPCODE_DX9_DST , + OPCODE_DX9_LRP , + OPCODE_DX9_FRC , + OPCODE_DX9_M4x4 , + OPCODE_DX9_M4x3 , + OPCODE_DX9_M3x4 , + OPCODE_DX9_M3x3 , + OPCODE_DX9_M3x2 , + OPCODE_DX9_CALL , + OPCODE_DX9_CALLNZ , + OPCODE_DX9_LOOP , + OPCODE_DX9_RET , + OPCODE_DX9_ENDLOOP , + OPCODE_DX9_LABEL , + OPCODE_DX9_DCL , + OPCODE_DX9_POW , + OPCODE_DX9_CRS , + OPCODE_DX9_SGN , + OPCODE_DX9_ABS , + OPCODE_DX9_NRM , + OPCODE_DX9_SINCOS , + OPCODE_DX9_REP , + OPCODE_DX9_ENDREP , + OPCODE_DX9_IF , + OPCODE_DX9_IFC , + OPCODE_DX9_ELSE , + OPCODE_DX9_ENDIF , + OPCODE_DX9_BREAK , + OPCODE_DX9_BREAKC , + OPCODE_DX9_MOVA , + OPCODE_DX9_DEFB , + OPCODE_DX9_DEFI , + + OPCODE_DX9_TEXCOORD = 64, + OPCODE_DX9_TEXKILL , + OPCODE_DX9_TEX , + OPCODE_DX9_TEXBEM , + OPCODE_DX9_TEXBEML , + OPCODE_DX9_TEXREG2AR , + OPCODE_DX9_TEXREG2GB , + OPCODE_DX9_TEXM3x2PAD , + OPCODE_DX9_TEXM3x2TEX , + OPCODE_DX9_TEXM3x3PAD , + OPCODE_DX9_TEXM3x3TEX , + OPCODE_DX9_RESERVED0 , + OPCODE_DX9_TEXM3x3SPEC , + OPCODE_DX9_TEXM3x3VSPEC , + OPCODE_DX9_EXPP , + OPCODE_DX9_LOGP , + OPCODE_DX9_CND , + OPCODE_DX9_DEF , + OPCODE_DX9_TEXREG2RGB , + OPCODE_DX9_TEXDP3TEX , + OPCODE_DX9_TEXM3x2DEPTH , + OPCODE_DX9_TEXDP3 , + OPCODE_DX9_TEXM3x3 , + OPCODE_DX9_TEXDEPTH , + OPCODE_DX9_CMP , + OPCODE_DX9_BEM , + OPCODE_DX9_DP2ADD , + OPCODE_DX9_DSX , + OPCODE_DX9_DSY , + OPCODE_DX9_TEXLDD , + OPCODE_DX9_SETP , + OPCODE_DX9_TEXLDL , + OPCODE_DX9_BREAKP , + + OPCODE_DX9_PHASE = 0xFFFD, + OPCODE_DX9_COMMENT = 0xFFFE, + OPCODE_DX9_END = 0xFFFF, + + OPCODE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} OPCODE_TYPE_DX9; + +static OPCODE_TYPE_DX9 DecodeOpcodeTypeDX9(const uint32_t ui32Token) +{ + return (OPCODE_TYPE_DX9)(ui32Token & 0x0000FFFF); +} + +static uint32_t DecodeInstructionLengthDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x0F000000)>>24; +} + +static uint32_t DecodeCommentLengthDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x7FFF0000)>>16; +} + +static uint32_t DecodeOperandRegisterNumberDX9(const uint32_t ui32Token) +{ + return ui32Token & 0x000007FF; +} + +typedef enum +{ + OPERAND_TYPE_DX9_TEMP = 0, // Temporary Register File + OPERAND_TYPE_DX9_INPUT = 1, // Input Register File + OPERAND_TYPE_DX9_CONST = 2, // Constant Register File + OPERAND_TYPE_DX9_ADDR = 3, // Address Register (VS) + OPERAND_TYPE_DX9_TEXTURE = 3, // Texture Register File (PS) + OPERAND_TYPE_DX9_RASTOUT = 4, // Rasterizer Register File + OPERAND_TYPE_DX9_ATTROUT = 5, // Attribute Output Register File + OPERAND_TYPE_DX9_TEXCRDOUT = 6, // Texture Coordinate Output Register File + OPERAND_TYPE_DX9_OUTPUT = 6, // Output register file for VS3.0+ + OPERAND_TYPE_DX9_CONSTINT = 7, // Constant Integer Vector Register File + OPERAND_TYPE_DX9_COLOROUT = 8, // Color Output Register File + OPERAND_TYPE_DX9_DEPTHOUT = 9, // Depth Output Register File + OPERAND_TYPE_DX9_SAMPLER = 10, // Sampler State Register File + OPERAND_TYPE_DX9_CONST2 = 11, // Constant Register File 2048 - 4095 + OPERAND_TYPE_DX9_CONST3 = 12, // Constant Register File 4096 - 6143 + OPERAND_TYPE_DX9_CONST4 = 13, // Constant Register File 6144 - 8191 + OPERAND_TYPE_DX9_CONSTBOOL = 14, // Constant Boolean register file + OPERAND_TYPE_DX9_LOOP = 15, // Loop counter register file + OPERAND_TYPE_DX9_TEMPFLOAT16 = 16, // 16-bit float temp register file + OPERAND_TYPE_DX9_MISCTYPE = 17, // Miscellaneous (single) registers. + OPERAND_TYPE_DX9_LABEL = 18, // Label + OPERAND_TYPE_DX9_PREDICATE = 19, // Predicate register + OPERAND_TYPE_DX9_FORCE_DWORD = 0x7fffffff, // force 32-bit size enum +} OPERAND_TYPE_DX9; + +static OPERAND_TYPE_DX9 DecodeOperandTypeDX9(const uint32_t ui32Token) +{ + return (OPERAND_TYPE_DX9)(((ui32Token & 0x70000000) >> 28) | + ((ui32Token & 0x00001800) >> 8)); +} + +static uint32_t CreateOperandTokenDX9(const uint32_t ui32RegNum, const OPERAND_TYPE_DX9 eType) +{ + uint32_t ui32Token = ui32RegNum; + ASSERT(ui32RegNum <2048); + ui32Token |= (eType <<28) & 0x70000000; + ui32Token |= (eType <<8) & 0x00001800; + return ui32Token; +} + +typedef enum { + DECLUSAGE_POSITION = 0, + DECLUSAGE_BLENDWEIGHT = 1, + DECLUSAGE_BLENDINDICES = 2, + DECLUSAGE_NORMAL = 3, + DECLUSAGE_PSIZE = 4, + DECLUSAGE_TEXCOORD = 5, + DECLUSAGE_TANGENT = 6, + DECLUSAGE_BINORMAL = 7, + DECLUSAGE_TESSFACTOR = 8, + DECLUSAGE_POSITIONT = 9, + DECLUSAGE_COLOR = 10, + DECLUSAGE_FOG = 11, + DECLUSAGE_DEPTH = 12, + DECLUSAGE_SAMPLE = 13 +} DECLUSAGE_DX9; + +static DECLUSAGE_DX9 DecodeUsageDX9(const uint32_t ui32Token) +{ + return (DECLUSAGE_DX9) (ui32Token & 0x0000000f); +} + +static uint32_t DecodeUsageIndexDX9(const uint32_t ui32Token) +{ + return (ui32Token & 0x000f0000)>>16; +} + +static uint32_t DecodeOperandIsRelativeAddressModeDX9(const uint32_t ui32Token) +{ + return ui32Token & (1<<13); +} + +static const uint32_t DX9_SWIZZLE_SHIFT = 16; +#define NO_SWIZZLE_DX9 ((0<<DX9_SWIZZLE_SHIFT)|(1<<DX9_SWIZZLE_SHIFT)|(2<<DX9_SWIZZLE_SHIFT)|(3<<DX9_SWIZZLE_SHIFT)) + +#define REPLICATE_SWIZZLE_DX9(CHANNEL) ((CHANNEL<<DX9_SWIZZLE_SHIFT)|(CHANNEL<<(DX9_SWIZZLE_SHIFT+2))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+4))|(CHANNEL<<(DX9_SWIZZLE_SHIFT+6))) + +static uint32_t DecodeOperandSwizzleDX9(const uint32_t ui32Token) +{ + return ui32Token & 0x00FF0000; +} + +static const uint32_t DX9_WRITEMASK_0 = 0x00010000; // Component 0 (X;Red) +static const uint32_t DX9_WRITEMASK_1 = 0x00020000; // Component 1 (Y;Green) +static const uint32_t DX9_WRITEMASK_2 = 0x00040000; // Component 2 (Z;Blue) +static const uint32_t DX9_WRITEMASK_3 = 0x00080000; // Component 3 (W;Alpha) +static const uint32_t DX9_WRITEMASK_ALL = 0x000F0000; // All Components + +static uint32_t DecodeDestWriteMaskDX9(const uint32_t ui32Token) +{ + return ui32Token & DX9_WRITEMASK_ALL; +} + +static RESOURCE_DIMENSION DecodeTextureTypeMaskDX9(const uint32_t ui32Token) +{ + + switch(ui32Token & 0x78000000) + { + case 2 << 27: + return RESOURCE_DIMENSION_TEXTURE2D; + case 3 << 27: + return RESOURCE_DIMENSION_TEXTURECUBE; + case 4 << 27: + return RESOURCE_DIMENSION_TEXTURE3D; + default: + return RESOURCE_DIMENSION_UNKNOWN; + } +} + + + +static const uint32_t DESTMOD_DX9_NONE = 0; +static const uint32_t DESTMOD_DX9_SATURATE = (1 << 20); +static const uint32_t DESTMOD_DX9_PARTIALPRECISION = (2 << 20); +static const uint32_t DESTMOD_DX9_MSAMPCENTROID = (4 << 20); +static uint32_t DecodeDestModifierDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xf00000; +} + +typedef enum +{ + SRCMOD_DX9_NONE = 0 << 24, + SRCMOD_DX9_NEG = 1 << 24, + SRCMOD_DX9_BIAS = 2 << 24, + SRCMOD_DX9_BIASNEG = 3 << 24, + SRCMOD_DX9_SIGN = 4 << 24, + SRCMOD_DX9_SIGNNEG = 5 << 24, + SRCMOD_DX9_COMP = 6 << 24, + SRCMOD_DX9_X2 = 7 << 24, + SRCMOD_DX9_X2NEG = 8 << 24, + SRCMOD_DX9_DZ = 9 << 24, + SRCMOD_DX9_DW = 10 << 24, + SRCMOD_DX9_ABS = 11 << 24, + SRCMOD_DX9_ABSNEG = 12 << 24, + SRCMOD_DX9_NOT = 13 << 24, + SRCMOD_DX9_FORCE_DWORD = 0xffffffff +} SRCMOD_DX9; +static uint32_t DecodeSrcModifierDX9(const uint32_t ui32Token) +{ + return ui32Token & 0xf000000; +} + +typedef enum +{ + D3DSPC_RESERVED0 = 0, + D3DSPC_GT = 1, + D3DSPC_EQ = 2, + D3DSPC_GE = 3, + D3DSPC_LT = 4, + D3DSPC_NE = 5, + D3DSPC_LE = 6, + D3DSPC_BOOLEAN = 7, //Make use of the RESERVED1 bit to indicate if-bool opcode. +} COMPARISON_DX9; + +static COMPARISON_DX9 DecodeComparisonDX9(const uint32_t ui32Token) +{ + return (COMPARISON_DX9)((ui32Token & (0x07<<16))>>16); +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c b/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c new file mode 100644 index 0000000000..03f3388a93 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/reflect.c @@ -0,0 +1,1213 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/reflect.h" +#include "internal_includes/debug.h" +#include "internal_includes/decode.h" +#include "internal_includes/hlslcc_malloc.h" +#include "bstrlib.h" +#include <stdlib.h> +#include <stdio.h> + +static void FormatVariableName(char* Name) +{ + /* MSDN http://msdn.microsoft.com/en-us/library/windows/desktop/bb944006(v=vs.85).aspx + The uniform function parameters appear in the + constant table prepended with a dollar sign ($), + unlike the global variables. The dollar sign is + required to avoid name collisions between local + uniform inputs and global variables of the same name.*/ + + /* Leave $ThisPointer, $Element and $Globals as-is. + Otherwise remove $ character ($ is not a valid character for GLSL variable names). */ + if (Name[0] == '$') + { + if (strcmp(Name, "$Element") != 0 && + strcmp(Name, "$Globals") != 0 && + strcmp(Name, "$ThisPointer") != 0) + { + Name[0] = '_'; + } + } +} + +static void ReadStringFromTokenStream(const uint32_t* tokens, char* str) +{ + char* charTokens = (char*) tokens; + char nextCharacter = *charTokens++; + int length = 0; + + //Add each individual character until + //a terminator is found. + while (nextCharacter != 0) + { + str[length++] = nextCharacter; + + if (length > MAX_REFLECT_STRING_LENGTH) + { + str[length - 1] = '\0'; + return; + } + + nextCharacter = *charTokens++; + } + + str[length] = '\0'; +} + +static void ReadInputSignatures(const uint32_t* pui32Tokens, + ShaderInfo* psShaderInfo, + const int extended) +{ + uint32_t i; + + InOutSignature* psSignatures; + const uint32_t* pui32FirstSignatureToken = pui32Tokens; + const uint32_t ui32ElementCount = *pui32Tokens++; + /*const uint32_t ui32Key =*/ *pui32Tokens++; + + psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); + psShaderInfo->psInputSignatures = psSignatures; + psShaderInfo->ui32NumInputSignatures = ui32ElementCount; + + for (i = 0; i < ui32ElementCount; ++i) + { + uint32_t ui32ComponentMasks; + InOutSignature* psCurrentSignature = psSignatures + i; + uint32_t ui32SemanticNameOffset; + + psCurrentSignature->ui32Stream = 0; + psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; + + if (extended) + { + psCurrentSignature->ui32Stream = *pui32Tokens++; + } + + ui32SemanticNameOffset = *pui32Tokens++; + psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; + psCurrentSignature->eSystemValueType = (SPECIAL_NAME) *pui32Tokens++; + psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; + psCurrentSignature->ui32Register = *pui32Tokens++; + + ui32ComponentMasks = *pui32Tokens++; + psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; + //Shows which components are read + psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; + + if (extended) + { + psCurrentSignature->eMinPrec = *pui32Tokens++; + } + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); + } +} + +static void ReadOutputSignatures(const uint32_t* pui32Tokens, + ShaderInfo* psShaderInfo, + const int minPrec, + const int streams) +{ + uint32_t i; + + InOutSignature* psSignatures; + const uint32_t* pui32FirstSignatureToken = pui32Tokens; + const uint32_t ui32ElementCount = *pui32Tokens++; + /*const uint32_t ui32Key =*/ *pui32Tokens++; + + psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); + psShaderInfo->psOutputSignatures = psSignatures; + psShaderInfo->ui32NumOutputSignatures = ui32ElementCount; + + for (i = 0; i < ui32ElementCount; ++i) + { + uint32_t ui32ComponentMasks; + InOutSignature* psCurrentSignature = psSignatures + i; + uint32_t ui32SemanticNameOffset; + + psCurrentSignature->ui32Stream = 0; + psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; + + if (streams) + { + psCurrentSignature->ui32Stream = *pui32Tokens++; + } + + ui32SemanticNameOffset = *pui32Tokens++; + psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; + psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; + psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; + psCurrentSignature->ui32Register = *pui32Tokens++; + + // Massage some special inputs/outputs to match the types of GLSL counterparts + if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX) + { + psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32; + } + + ui32ComponentMasks = *pui32Tokens++; + psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; + //Shows which components are NEVER written. + psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; + + if (minPrec) + { + psCurrentSignature->eMinPrec = *pui32Tokens++; + } + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); + } +} + +static void ReadPatchConstantSignatures(const uint32_t* pui32Tokens, + ShaderInfo* psShaderInfo, + const int minPrec, + const int streams) +{ + uint32_t i; + + InOutSignature* psSignatures; + const uint32_t* pui32FirstSignatureToken = pui32Tokens; + const uint32_t ui32ElementCount = *pui32Tokens++; + /*const uint32_t ui32Key =*/ *pui32Tokens++; + + psSignatures = hlslcc_malloc(sizeof(InOutSignature) * ui32ElementCount); + psShaderInfo->psPatchConstantSignatures = psSignatures; + psShaderInfo->ui32NumPatchConstantSignatures = ui32ElementCount; + + for (i = 0; i < ui32ElementCount; ++i) + { + uint32_t ui32ComponentMasks; + InOutSignature* psCurrentSignature = psSignatures + i; + uint32_t ui32SemanticNameOffset; + + psCurrentSignature->ui32Stream = 0; + psCurrentSignature->eMinPrec = MIN_PRECISION_DEFAULT; + + if (streams) + { + psCurrentSignature->ui32Stream = *pui32Tokens++; + } + + ui32SemanticNameOffset = *pui32Tokens++; + psCurrentSignature->ui32SemanticIndex = *pui32Tokens++; + psCurrentSignature->eSystemValueType = (SPECIAL_NAME)*pui32Tokens++; + psCurrentSignature->eComponentType = (INOUT_COMPONENT_TYPE) *pui32Tokens++; + psCurrentSignature->ui32Register = *pui32Tokens++; + + // Massage some special inputs/outputs to match the types of GLSL counterparts + if (psCurrentSignature->eSystemValueType == NAME_RENDER_TARGET_ARRAY_INDEX) + { + psCurrentSignature->eComponentType = INOUT_COMPONENT_SINT32; + } + + ui32ComponentMasks = *pui32Tokens++; + psCurrentSignature->ui32Mask = ui32ComponentMasks & 0x7F; + //Shows which components are NEVER written. + psCurrentSignature->ui32ReadWriteMask = (ui32ComponentMasks & 0x7F00) >> 8; + + if (minPrec) + { + psCurrentSignature->eMinPrec = *pui32Tokens++; + } + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstSignatureToken + ui32SemanticNameOffset), psCurrentSignature->SemanticName); + } +} + +static const uint32_t* ReadResourceBinding(const uint32_t* pui32FirstResourceToken, const uint32_t* pui32Tokens, ResourceBinding* psBinding) +{ + uint32_t ui32NameOffset = *pui32Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstResourceToken + ui32NameOffset), psBinding->Name); + FormatVariableName(psBinding->Name); + + psBinding->eType = *pui32Tokens++; + psBinding->ui32ReturnType = *pui32Tokens++; + psBinding->eDimension = (REFLECT_RESOURCE_DIMENSION)*pui32Tokens++; + psBinding->ui32NumSamples = *pui32Tokens++; + psBinding->ui32BindPoint = *pui32Tokens++; + psBinding->ui32BindCount = *pui32Tokens++; + psBinding->ui32Flags = *pui32Tokens++; + psBinding->eBindArea = UAVAREA_INVALID; + + return pui32Tokens; +} + +//Read D3D11_SHADER_TYPE_DESC +static void ReadShaderVariableType(const uint32_t ui32MajorVersion, + const uint32_t* pui32FirstConstBufToken, + const uint32_t* pui32tokens, ShaderVarType* varType) +{ + const uint16_t* pui16Tokens = (const uint16_t*) pui32tokens; + uint16_t ui32MemberCount; + uint32_t ui32MemberOffset; + const uint32_t* pui32MemberTokens; + uint32_t i; + + varType->Class = (SHADER_VARIABLE_CLASS)pui16Tokens[0]; + varType->Type = (SHADER_VARIABLE_TYPE)pui16Tokens[1]; + varType->Rows = pui16Tokens[2]; + varType->Columns = pui16Tokens[3]; + varType->Elements = pui16Tokens[4]; + + varType->MemberCount = ui32MemberCount = pui16Tokens[5]; + varType->Members = 0; + + if (varType->ParentCount) + { + ASSERT((strlen(varType->Parent->FullName) + 1 + strlen(varType->Name) + 1 + 2) < MAX_REFLECT_STRING_LENGTH); + + strcpy(varType->FullName, varType->Parent->FullName); + strcat(varType->FullName, "."); + strcat(varType->FullName, varType->Name); + } + + if (ui32MemberCount) + { + varType->Members = (ShaderVarType*)hlslcc_malloc(sizeof(ShaderVarType) * ui32MemberCount); + + ui32MemberOffset = pui32tokens[3]; + + pui32MemberTokens = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberOffset); + + for (i = 0; i < ui32MemberCount; ++i) + { + uint32_t ui32NameOffset = *pui32MemberTokens++; + uint32_t ui32MemberTypeOffset = *pui32MemberTokens++; + + varType->Members[i].Parent = varType; + varType->Members[i].ParentCount = varType->ParentCount + 1; + + varType->Members[i].Offset = *pui32MemberTokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), varType->Members[i].Name); + + ReadShaderVariableType(ui32MajorVersion, pui32FirstConstBufToken, + (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32MemberTypeOffset), &varType->Members[i]); + } + } +} + +static const uint32_t* ReadConstantBuffer(ShaderInfo* psShaderInfo, + const uint32_t* pui32FirstConstBufToken, const uint32_t* pui32Tokens, ConstantBuffer* psBuffer) +{ + uint32_t i; + uint32_t ui32NameOffset = *pui32Tokens++; + uint32_t ui32VarCount = *pui32Tokens++; + uint32_t ui32VarOffset = *pui32Tokens++; + const uint32_t* pui32VarToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32VarOffset); + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), psBuffer->Name); + FormatVariableName(psBuffer->Name); + + psBuffer->ui32NumVars = ui32VarCount; + psBuffer->asVars = hlslcc_malloc(psBuffer->ui32NumVars * sizeof(ShaderVar)); + + for (i = 0; i < ui32VarCount; ++i) + { + //D3D11_SHADER_VARIABLE_DESC + ShaderVar* const psVar = &psBuffer->asVars[i]; + + uint32_t ui32Flags; + uint32_t ui32TypeOffset; + uint32_t ui32DefaultValueOffset; + + ui32NameOffset = *pui32VarToken++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstConstBufToken + ui32NameOffset), psVar->Name); + FormatVariableName(psVar->Name); + + psVar->ui32StartOffset = *pui32VarToken++; + psVar->ui32Size = *pui32VarToken++; + ui32Flags = *pui32VarToken++; + ui32TypeOffset = *pui32VarToken++; + + strcpy(psVar->sType.Name, psVar->Name); + strcpy(psVar->sType.FullName, psVar->Name); + psVar->sType.Parent = 0; + psVar->sType.ParentCount = 0; + psVar->sType.Offset = 0; + + ReadShaderVariableType(psShaderInfo->ui32MajorVersion, pui32FirstConstBufToken, + (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32TypeOffset), &psVar->sType); + + ui32DefaultValueOffset = *pui32VarToken++; + + + if (psShaderInfo->ui32MajorVersion >= 5) + { + /* uint32_t StartTexture = */ *pui32VarToken++; + /* uint32_t TextureSize = */ *pui32VarToken++; + /* uint32_t StartSampler = */ *pui32VarToken++; + /* uint32_t SamplerSize = */ *pui32VarToken++; + } + + psVar->haveDefaultValue = 0; + + if (ui32DefaultValueOffset) + { + const uint32_t ui32NumDefaultValues = psVar->ui32Size / 4; + const uint32_t* pui32DefaultValToken = (const uint32_t*)((const char*)pui32FirstConstBufToken + ui32DefaultValueOffset); + + //Always a sequence of 4-bytes at the moment. + //bool const becomes 0 or 0xFFFFFFFF int, int & float are 4-bytes. + ASSERT(psVar->ui32Size % 4 == 0); + + psVar->haveDefaultValue = 1; + + psVar->pui32DefaultValues = hlslcc_malloc(psVar->ui32Size); + + for (uint32_t ii = 0; ii < ui32NumDefaultValues; ++ii) + { + psVar->pui32DefaultValues[ii] = pui32DefaultValToken[ii]; + } + } + } + + + { + uint32_t ui32Flags; + uint32_t ui32BufferType; + + psBuffer->ui32TotalSizeInBytes = *pui32Tokens++; + psBuffer->blob = 0; + ui32Flags = *pui32Tokens++; + ui32BufferType = *pui32Tokens++; + } + + return pui32Tokens; +} + +static void ReadResources(const uint32_t* pui32Tokens,//in + ShaderInfo* psShaderInfo) //out +{ + ResourceBinding* psResBindings; + ConstantBuffer* psConstantBuffers; + const uint32_t* pui32ConstantBuffers; + const uint32_t* pui32ResourceBindings; + const uint32_t* pui32FirstToken = pui32Tokens; + uint32_t i; + + const uint32_t ui32NumConstantBuffers = *pui32Tokens++; + const uint32_t ui32ConstantBufferOffset = *pui32Tokens++; + + uint32_t ui32NumResourceBindings = *pui32Tokens++; + uint32_t ui32ResourceBindingOffset = *pui32Tokens++; + /*uint32_t ui32ShaderModel =*/ *pui32Tokens++; + /*uint32_t ui32CompileFlags =*/ *pui32Tokens++;//D3DCompile flags? http://msdn.microsoft.com/en-us/library/gg615083(v=vs.85).aspx + + //Resources + pui32ResourceBindings = (const uint32_t*)((const char*)pui32FirstToken + ui32ResourceBindingOffset); + + psResBindings = hlslcc_malloc(sizeof(ResourceBinding) * ui32NumResourceBindings); + + psShaderInfo->ui32NumResourceBindings = ui32NumResourceBindings; + psShaderInfo->psResourceBindings = psResBindings; + + for (i = 0; i < ui32NumResourceBindings; ++i) + { + pui32ResourceBindings = ReadResourceBinding(pui32FirstToken, pui32ResourceBindings, psResBindings + i); + ASSERT(psResBindings[i].ui32BindPoint < MAX_RESOURCE_BINDINGS); + } + + //Constant buffers + pui32ConstantBuffers = (const uint32_t*)((const char*)pui32FirstToken + ui32ConstantBufferOffset); + + psConstantBuffers = hlslcc_malloc(sizeof(ConstantBuffer) * ui32NumConstantBuffers); + + psShaderInfo->ui32NumConstantBuffers = ui32NumConstantBuffers; + psShaderInfo->psConstantBuffers = psConstantBuffers; + + for (i = 0; i < ui32NumConstantBuffers; ++i) + { + pui32ConstantBuffers = ReadConstantBuffer(psShaderInfo, pui32FirstToken, pui32ConstantBuffers, psConstantBuffers + i); + } + + + //Map resource bindings to constant buffers + if (psShaderInfo->ui32NumConstantBuffers) + { + for (i = 0; i < ui32NumResourceBindings; ++i) + { + ResourceGroup eRGroup; + uint32_t cbufIndex = 0; + + eRGroup = ResourceTypeToResourceGroup(psResBindings[i].eType); + + //Find the constant buffer whose name matches the resource at the given resource binding point + for (cbufIndex = 0; cbufIndex < psShaderInfo->ui32NumConstantBuffers; cbufIndex++) + { + if (strcmp(psConstantBuffers[cbufIndex].Name, psResBindings[i].Name) == 0) + { + psShaderInfo->aui32ResourceMap[eRGroup][psResBindings[i].ui32BindPoint] = cbufIndex; + } + } + } + } +} + +static const uint16_t* ReadClassType(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassType* psClassType) +{ + const uint32_t* pui32Tokens = (const uint32_t*)pui16Tokens; + uint32_t ui32NameOffset = *pui32Tokens; + pui16Tokens += 2; + + psClassType->ui16ID = *pui16Tokens++; + psClassType->ui16ConstBufStride = *pui16Tokens++; + psClassType->ui16Texture = *pui16Tokens++; + psClassType->ui16Sampler = *pui16Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset), psClassType->Name); + + return pui16Tokens; +} + +static const uint16_t* ReadClassInstance(const uint32_t* pui32FirstInterfaceToken, const uint16_t* pui16Tokens, ClassInstance* psClassInstance) +{ + uint32_t ui32NameOffset = *pui16Tokens++ << 16; + ui32NameOffset |= *pui16Tokens++; + + psClassInstance->ui16ID = *pui16Tokens++; + psClassInstance->ui16ConstBuf = *pui16Tokens++; + psClassInstance->ui16ConstBufOffset = *pui16Tokens++; + psClassInstance->ui16Texture = *pui16Tokens++; + psClassInstance->ui16Sampler = *pui16Tokens++; + + ReadStringFromTokenStream((const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32NameOffset), psClassInstance->Name); + + return pui16Tokens; +} + + +static void ReadInterfaces(const uint32_t* pui32Tokens, + ShaderInfo* psShaderInfo) +{ + uint32_t i; + uint32_t ui32StartSlot; + const uint32_t* pui32FirstInterfaceToken = pui32Tokens; + const uint32_t ui32ClassInstanceCount = *pui32Tokens++; + const uint32_t ui32ClassTypeCount = *pui32Tokens++; + const uint32_t ui32InterfaceSlotRecordCount = *pui32Tokens++; + /*const uint32_t ui32InterfaceSlotCount =*/ *pui32Tokens++; + const uint32_t ui32ClassInstanceOffset = *pui32Tokens++; + const uint32_t ui32ClassTypeOffset = *pui32Tokens++; + const uint32_t ui32InterfaceSlotOffset = *pui32Tokens++; + + const uint16_t* pui16ClassTypes = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassTypeOffset); + const uint16_t* pui16ClassInstances = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32ClassInstanceOffset); + const uint32_t* pui32InterfaceSlots = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32InterfaceSlotOffset); + + const uint32_t* pui32InterfaceSlotTokens = pui32InterfaceSlots; + + ClassType* psClassTypes; + ClassInstance* psClassInstances; + + psClassTypes = hlslcc_malloc(sizeof(ClassType) * ui32ClassTypeCount); + for (i = 0; i < ui32ClassTypeCount; ++i) + { + pui16ClassTypes = ReadClassType(pui32FirstInterfaceToken, pui16ClassTypes, psClassTypes + i); + psClassTypes[i].ui16ID = (uint16_t)i; + } + + psClassInstances = hlslcc_malloc(sizeof(ClassInstance) * ui32ClassInstanceCount); + for (i = 0; i < ui32ClassInstanceCount; ++i) + { + pui16ClassInstances = ReadClassInstance(pui32FirstInterfaceToken, pui16ClassInstances, psClassInstances + i); + } + + //Slots map function table to $ThisPointer cbuffer variable index + ui32StartSlot = 0; + for (i = 0; i < ui32InterfaceSlotRecordCount; ++i) + { + uint32_t k; + + const uint32_t ui32SlotSpan = *pui32InterfaceSlotTokens++; + const uint32_t ui32Count = *pui32InterfaceSlotTokens++; + const uint32_t ui32TypeIDOffset = *pui32InterfaceSlotTokens++; + const uint32_t ui32TableIDOffset = *pui32InterfaceSlotTokens++; + + const uint16_t* pui16TypeID = (const uint16_t*)((const char*)pui32FirstInterfaceToken + ui32TypeIDOffset); + const uint32_t* pui32TableID = (const uint32_t*)((const char*)pui32FirstInterfaceToken + ui32TableIDOffset); + + for (k = 0; k < ui32Count; ++k) + { + psShaderInfo->aui32TableIDToTypeID[*pui32TableID++] = *pui16TypeID++; + } + + ui32StartSlot += ui32SlotSpan; + } + + psShaderInfo->ui32NumClassInstances = ui32ClassInstanceCount; + psShaderInfo->psClassInstances = psClassInstances; + + psShaderInfo->ui32NumClassTypes = ui32ClassTypeCount; + psShaderInfo->psClassTypes = psClassTypes; +} + +void GetConstantBufferFromBindingPoint(const ResourceGroup eGroup, const uint32_t ui32BindPoint, const ShaderInfo* psShaderInfo, ConstantBuffer** ppsConstBuf) +{ + if (psShaderInfo->ui32MajorVersion > 3) + { + *ppsConstBuf = psShaderInfo->psConstantBuffers + psShaderInfo->aui32ResourceMap[eGroup][ui32BindPoint]; + } + else + { + ASSERT(psShaderInfo->ui32NumConstantBuffers == 1); + *ppsConstBuf = psShaderInfo->psConstantBuffers; + } +} + +int GetResourceFromBindingPoint(const ResourceGroup eGroup, uint32_t const ui32BindPoint, const ShaderInfo* psShaderInfo, ResourceBinding** ppsOutBinding) +{ + uint32_t i; + const uint32_t ui32NumBindings = psShaderInfo->ui32NumResourceBindings; + ResourceBinding* psBindings = psShaderInfo->psResourceBindings; + + for (i = 0; i < ui32NumBindings; ++i) + { + if (ResourceTypeToResourceGroup(psBindings[i].eType) == eGroup) + { + if (ui32BindPoint >= psBindings[i].ui32BindPoint && ui32BindPoint < (psBindings[i].ui32BindPoint + psBindings[i].ui32BindCount)) + { + *ppsOutBinding = psBindings + i; + return 1; + } + } + } + + return 0; +} + +int GetInterfaceVarFromOffset(uint32_t ui32Offset, ShaderInfo* psShaderInfo, ShaderVar** ppsShaderVar) +{ + uint32_t i; + ConstantBuffer* psThisPointerConstBuffer = psShaderInfo->psThisPointerConstBuffer; + + const uint32_t ui32NumVars = psThisPointerConstBuffer->ui32NumVars; + + for (i = 0; i < ui32NumVars; ++i) + { + if (ui32Offset >= psThisPointerConstBuffer->asVars[i].ui32StartOffset && + ui32Offset < (psThisPointerConstBuffer->asVars[i].ui32StartOffset + psThisPointerConstBuffer->asVars[i].ui32Size)) + { + *ppsShaderVar = &psThisPointerConstBuffer->asVars[i]; + return 1; + } + } + return 0; +} + +int GetInputSignatureFromRegister(const uint32_t ui32Register, const ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +{ + uint32_t i; + const uint32_t ui32NumVars = psShaderInfo->ui32NumInputSignatures; + + for (i = 0; i < ui32NumVars; ++i) + { + InOutSignature* psInputSignatures = psShaderInfo->psInputSignatures; + if (ui32Register == psInputSignatures[i].ui32Register) + { + *ppsOut = psInputSignatures + i; + return 1; + } + } + return 0; +} + +int GetOutputSignatureFromRegister(const uint32_t currentPhase, + const uint32_t ui32Register, + const uint32_t ui32CompMask, + const uint32_t ui32Stream, + ShaderInfo* psShaderInfo, + InOutSignature** ppsOut) +{ + uint32_t i; + + if (currentPhase == HS_JOIN_PHASE || currentPhase == HS_FORK_PHASE) + { + const uint32_t ui32NumVars = psShaderInfo->ui32NumPatchConstantSignatures; + + for (i = 0; i < ui32NumVars; ++i) + { + InOutSignature* psOutputSignatures = psShaderInfo->psPatchConstantSignatures; + if (ui32Register == psOutputSignatures[i].ui32Register && + (ui32CompMask & psOutputSignatures[i].ui32Mask) && + ui32Stream == psOutputSignatures[i].ui32Stream) + { + *ppsOut = psOutputSignatures + i; + return 1; + } + } + } + else + { + const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; + + for (i = 0; i < ui32NumVars; ++i) + { + InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; + if (ui32Register == psOutputSignatures[i].ui32Register && + (ui32CompMask & psOutputSignatures[i].ui32Mask) && + ui32Stream == psOutputSignatures[i].ui32Stream) + { + *ppsOut = psOutputSignatures + i; + return 1; + } + } + } + return 0; +} + +int GetOutputSignatureFromSystemValue(SPECIAL_NAME eSystemValueType, uint32_t ui32SemanticIndex, ShaderInfo* psShaderInfo, InOutSignature** ppsOut) +{ + uint32_t i; + const uint32_t ui32NumVars = psShaderInfo->ui32NumOutputSignatures; + + for (i = 0; i < ui32NumVars; ++i) + { + InOutSignature* psOutputSignatures = psShaderInfo->psOutputSignatures; + if (eSystemValueType == psOutputSignatures[i].eSystemValueType && + ui32SemanticIndex == psOutputSignatures[i].ui32SemanticIndex) + { + *ppsOut = psOutputSignatures + i; + return 1; + } + } + return 0; +} + +static int IsOffsetInType(ShaderVarType* psType, + uint32_t parentOffset, + uint32_t offsetToFind, + const uint32_t* pui32Swizzle, + int32_t* pi32Index, + int32_t* pi32Rebase) +{ + uint32_t thisOffset = parentOffset + psType->Offset; + uint32_t thisSize = psType->Columns * psType->Rows * 4; + + if (psType->Elements) + { + // Everything smaller than vec4 in an array takes the space of vec4, except for the last one + if (thisSize < 4 * 4) + { + thisSize = (4 * 4 * (psType->Elements - 1)) + thisSize; + } + else + { + thisSize *= psType->Elements; + } + } + + //Swizzle can point to another variable. In the example below + //cbUIUpdates.g_uMaxFaces would be cb1[2].z. The scalars are combined + //into vectors. psCBuf->ui32NumVars will be 3. + + // cbuffer cbUIUpdates + // { + // + // float g_fLifeSpan; // Offset: 0 Size: 4 + // float g_fLifeSpanVar; // Offset: 4 Size: 4 [unused] + // float g_fRadiusMin; // Offset: 8 Size: 4 [unused] + // float g_fRadiusMax; // Offset: 12 Size: 4 [unused] + // float g_fGrowTime; // Offset: 16 Size: 4 [unused] + // float g_fStepSize; // Offset: 20 Size: 4 + // float g_fTurnRate; // Offset: 24 Size: 4 + // float g_fTurnSpeed; // Offset: 28 Size: 4 [unused] + // float g_fLeafRate; // Offset: 32 Size: 4 + // float g_fShrinkTime; // Offset: 36 Size: 4 [unused] + // uint g_uMaxFaces; // Offset: 40 Size: 4 + // + // } + + // Name Type Format Dim Slot Elements + // ------------------------------ ---------- ------- ----------- ---- -------- + // cbUIUpdates cbuffer NA NA 1 1 + + if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + offsetToFind += 4; + } + else + if (pui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + offsetToFind += 8; + } + else + if (pui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + offsetToFind += 12; + } + + if ((offsetToFind >= thisOffset) && + offsetToFind < (thisOffset + thisSize)) + { + if (psType->Class == SVC_MATRIX_ROWS || + psType->Class == SVC_MATRIX_COLUMNS) + { + //Matrices are treated as arrays of vectors. + pi32Index[0] = (offsetToFind - thisOffset) / 16; + } + //Check for array of scalars or vectors (both take up 16 bytes per element) + else if ((psType->Class == SVC_SCALAR || psType->Class == SVC_VECTOR) && psType->Elements > 1) + { + pi32Index[0] = (offsetToFind - thisOffset) / 16; + } + else if (psType->Class == SVC_VECTOR && psType->Columns > 1) + { + //Check for vector starting at a non-vec4 offset. + + // cbuffer $Globals + // { + // + // float angle; // Offset: 0 Size: 4 + // float2 angle2; // Offset: 4 Size: 8 + // + // } + + //cb0[0].x = angle + //cb0[0].yzyy = angle2.xyxx + + //Rebase angle2 so that .y maps to .x, .z maps to .y + + pi32Rebase[0] = thisOffset % 16; + } + + return 1; + } + return 0; +} + +int GetShaderVarFromOffset(const uint32_t ui32Vec4Offset, + const uint32_t* pui32Swizzle, + ConstantBuffer* psCBuf, + ShaderVarType** ppsShaderVar, + int32_t* pi32Index, + int32_t* pi32Rebase) +{ + uint32_t i; + + uint32_t ui32ByteOffset = ui32Vec4Offset * 16; + + const uint32_t ui32NumVars = psCBuf->ui32NumVars; + + for (i = 0; i < ui32NumVars; ++i) + { + if (psCBuf->asVars[i].sType.Class == SVC_STRUCT) + { + uint32_t m = 0; + + for (m = 0; m < psCBuf->asVars[i].sType.MemberCount; ++m) + { + ShaderVarType* psMember = psCBuf->asVars[i].sType.Members + m; + + ASSERT(psMember->Class != SVC_STRUCT); + + if (IsOffsetInType(psMember, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) + { + ppsShaderVar[0] = psMember; + return 1; + } + } + } + else + { + if (IsOffsetInType(&psCBuf->asVars[i].sType, psCBuf->asVars[i].ui32StartOffset, ui32ByteOffset, pui32Swizzle, pi32Index, pi32Rebase)) + { + ppsShaderVar[0] = &psCBuf->asVars[i].sType; + return 1; + } + } + } + return 0; +} + +ResourceGroup ResourceTypeToResourceGroup(ResourceType eType) +{ + switch (eType) + { + case RTYPE_CBUFFER: + return RGROUP_CBUFFER; + + case RTYPE_SAMPLER: + return RGROUP_SAMPLER; + + case RTYPE_TEXTURE: + case RTYPE_BYTEADDRESS: + case RTYPE_STRUCTURED: + return RGROUP_TEXTURE; + + case RTYPE_UAV_RWTYPED: + case RTYPE_UAV_RWSTRUCTURED: + case RTYPE_UAV_RWBYTEADDRESS: + case RTYPE_UAV_APPEND_STRUCTURED: + case RTYPE_UAV_CONSUME_STRUCTURED: + case RTYPE_UAV_RWSTRUCTURED_WITH_COUNTER: + return RGROUP_UAV; + + case RTYPE_TBUFFER: + ASSERT(0); // Need to find out which group this belongs to + return RGROUP_TEXTURE; + } + + ASSERT(0); + return RGROUP_CBUFFER; +} + +void LoadShaderInfo(const uint32_t ui32MajorVersion, + const uint32_t ui32MinorVersion, + const ReflectionChunks* psChunks, + ShaderInfo* psInfo) +{ + const uint32_t* pui32Inputs = psChunks->pui32Inputs; + const uint32_t* pui32Inputs11 = psChunks->pui32Inputs11; + const uint32_t* pui32Resources = psChunks->pui32Resources; + const uint32_t* pui32Interfaces = psChunks->pui32Interfaces; + const uint32_t* pui32Outputs = psChunks->pui32Outputs; + const uint32_t* pui32Outputs11 = psChunks->pui32Outputs11; + const uint32_t* pui32OutputsWithStreams = psChunks->pui32OutputsWithStreams; + const uint32_t* pui32PatchConstants = psChunks->pui32PatchConstants; + + psInfo->eTessOutPrim = TESSELLATOR_OUTPUT_UNDEFINED; + psInfo->eTessPartitioning = TESSELLATOR_PARTITIONING_UNDEFINED; + + psInfo->ui32MajorVersion = ui32MajorVersion; + psInfo->ui32MinorVersion = ui32MinorVersion; + + + if (pui32Inputs) + { + ReadInputSignatures(pui32Inputs, psInfo, 0); + } + if (pui32Inputs11) + { + ReadInputSignatures(pui32Inputs11, psInfo, 1); + } + if (pui32Resources) + { + ReadResources(pui32Resources, psInfo); + } + if (pui32Interfaces) + { + ReadInterfaces(pui32Interfaces, psInfo); + } + if (pui32Outputs) + { + ReadOutputSignatures(pui32Outputs, psInfo, 0, 0); + } + if (pui32Outputs11) + { + ReadOutputSignatures(pui32Outputs11, psInfo, 1, 1); + } + if (pui32OutputsWithStreams) + { + ReadOutputSignatures(pui32OutputsWithStreams, psInfo, 0, 1); + } + if (pui32PatchConstants) + { + ReadPatchConstantSignatures(pui32PatchConstants, psInfo, 0, 0); + } + // if(pui32Effects10Data) + // ReadEffectsData(pui32Effects10Data, psInfo); NOT IMPLEMENTED + + uint32_t i; + for (i = 0; i < psInfo->ui32NumConstantBuffers; ++i) + { + bstring cbufName = bfromcstr(&psInfo->psConstantBuffers[i].Name[0]); + bstring cbufThisPointer = bfromcstr("$ThisPointer"); + if (bstrcmp(cbufName, cbufThisPointer) == 0) + { + psInfo->psThisPointerConstBuffer = &psInfo->psConstantBuffers[i]; + } + } + + for (i = 0; i < MAX_RESOURCE_BINDINGS; ++i) + { + psInfo->aui32SamplerMap[i] = MAX_RESOURCE_BINDINGS; + } +} + +void FreeShaderInfo(ShaderInfo* psShaderInfo) +{ + //Free any default values for constants. + uint32_t cbuf; + for (cbuf = 0; cbuf < psShaderInfo->ui32NumConstantBuffers; ++cbuf) + { + ConstantBuffer* psCBuf = &psShaderInfo->psConstantBuffers[cbuf]; + uint32_t var; + if (psCBuf->ui32NumVars) + { + for (var = 0; var < psCBuf->ui32NumVars; ++var) + { + ShaderVar* psVar = &psCBuf->asVars[var]; + if (psVar->haveDefaultValue) + { + hlslcc_free(psVar->pui32DefaultValues); + } + } + hlslcc_free(psCBuf->asVars); + } + } + hlslcc_free(psShaderInfo->psInputSignatures); + hlslcc_free(psShaderInfo->psResourceBindings); + hlslcc_free(psShaderInfo->psConstantBuffers); + hlslcc_free(psShaderInfo->psClassTypes); + hlslcc_free(psShaderInfo->psClassInstances); + hlslcc_free(psShaderInfo->psOutputSignatures); + hlslcc_free(psShaderInfo->psPatchConstantSignatures); + + psShaderInfo->ui32NumInputSignatures = 0; + psShaderInfo->ui32NumResourceBindings = 0; + psShaderInfo->ui32NumConstantBuffers = 0; + psShaderInfo->ui32NumClassTypes = 0; + psShaderInfo->ui32NumClassInstances = 0; + psShaderInfo->ui32NumOutputSignatures = 0; + psShaderInfo->ui32NumPatchConstantSignatures = 0; +} + +typedef struct ConstantTableD3D9_TAG +{ + uint32_t size; + uint32_t creator; + uint32_t version; + uint32_t constants; + uint32_t constantInfos; + uint32_t flags; + uint32_t target; +} ConstantTableD3D9; + +// These enums match those in d3dx9shader.h. +enum RegisterSet +{ + RS_BOOL, + RS_INT4, + RS_FLOAT4, + RS_SAMPLER, +}; + +enum TypeClass +{ + CLASS_SCALAR, + CLASS_VECTOR, + CLASS_MATRIX_ROWS, + CLASS_MATRIX_COLUMNS, + CLASS_OBJECT, + CLASS_STRUCT, +}; + +enum Type +{ + PT_VOID, + PT_BOOL, + PT_INT, + PT_FLOAT, + PT_STRING, + PT_TEXTURE, + PT_TEXTURE1D, + PT_TEXTURE2D, + PT_TEXTURE3D, + PT_TEXTURECUBE, + PT_SAMPLER, + PT_SAMPLER1D, + PT_SAMPLER2D, + PT_SAMPLER3D, + PT_SAMPLERCUBE, + PT_PIXELSHADER, + PT_VERTEXSHADER, + PT_PIXELFRAGMENT, + PT_VERTEXFRAGMENT, + PT_UNSUPPORTED, +}; +typedef struct ConstantInfoD3D9_TAG +{ + uint32_t name; + uint16_t registerSet; + uint16_t registerIndex; + uint16_t registerCount; + uint16_t reserved; + uint32_t typeInfo; + uint32_t defaultValue; +} ConstantInfoD3D9; + +typedef struct TypeInfoD3D9_TAG +{ + uint16_t typeClass; + uint16_t type; + uint16_t rows; + uint16_t columns; + uint16_t elements; + uint16_t structMembers; + uint32_t structMemberInfos; +} TypeInfoD3D9; + +typedef struct StructMemberInfoD3D9_TAG +{ + uint32_t name; + uint32_t typeInfo; +} StructMemberInfoD3D9; + +void LoadD3D9ConstantTable(const char* data, + ShaderInfo* psInfo) +{ + ConstantTableD3D9* ctab; + uint32_t constNum; + ConstantInfoD3D9* cinfos; + ConstantBuffer* psConstantBuffer; + uint32_t ui32ConstantBufferSize = 0; + uint32_t numResourceBindingsNeeded = 0; + ShaderVar* var; + + ctab = (ConstantTableD3D9*)data; + + cinfos = (ConstantInfoD3D9*) (data + ctab->constantInfos); + + psInfo->ui32NumConstantBuffers++; + + //Only 1 Constant Table in d3d9 + ASSERT(psInfo->ui32NumConstantBuffers == 1); + + psConstantBuffer = hlslcc_malloc(sizeof(ConstantBuffer)); + + psInfo->psConstantBuffers = psConstantBuffer; + + psConstantBuffer->ui32NumVars = 0; + strcpy(psConstantBuffer->Name, "$Globals"); + + //Determine how many resource bindings to create + for (constNum = 0; constNum < ctab->constants; ++constNum) + { + if (cinfos[constNum].registerSet == RS_SAMPLER) + { + ++numResourceBindingsNeeded; + } + } + + psInfo->psResourceBindings = hlslcc_malloc(numResourceBindingsNeeded * sizeof(ResourceBinding)); + + psConstantBuffer->asVars = hlslcc_malloc((ctab->constants - numResourceBindingsNeeded) * sizeof(ShaderVar)); + + var = &psConstantBuffer->asVars[0]; + + for (constNum = 0; constNum < ctab->constants; ++constNum) + { + TypeInfoD3D9* typeInfo = (TypeInfoD3D9*) (data + cinfos[constNum].typeInfo); + + if (cinfos[constNum].registerSet != RS_SAMPLER) + { + strcpy(var->Name, data + cinfos[constNum].name); + FormatVariableName(var->Name); + var->ui32Size = cinfos[constNum].registerCount * 16; + var->ui32StartOffset = cinfos[constNum].registerIndex * 16; + var->haveDefaultValue = 0; + + if (ui32ConstantBufferSize < (var->ui32Size + var->ui32StartOffset)) + { + ui32ConstantBufferSize = var->ui32Size + var->ui32StartOffset; + } + + var->sType.Rows = typeInfo->rows; + var->sType.Columns = typeInfo->columns; + var->sType.Elements = typeInfo->elements; + var->sType.MemberCount = typeInfo->structMembers; + var->sType.Members = 0; + var->sType.Offset = 0; + strcpy(var->sType.FullName, var->Name); + var->sType.Parent = 0; + var->sType.ParentCount = 0; + + switch (typeInfo->typeClass) + { + case CLASS_SCALAR: + { + var->sType.Class = SVC_SCALAR; + break; + } + case CLASS_VECTOR: + { + var->sType.Class = SVC_VECTOR; + break; + } + case CLASS_MATRIX_ROWS: + { + var->sType.Class = SVC_MATRIX_ROWS; + break; + } + case CLASS_MATRIX_COLUMNS: + { + var->sType.Class = SVC_MATRIX_COLUMNS; + break; + } + case CLASS_OBJECT: + { + var->sType.Class = SVC_OBJECT; + break; + } + case CLASS_STRUCT: + { + var->sType.Class = SVC_STRUCT; + break; + } + } + + switch (cinfos[constNum].registerSet) + { + case RS_BOOL: + { + var->sType.Type = SVT_BOOL; + break; + } + case RS_INT4: + { + var->sType.Type = SVT_INT; + break; + } + case RS_FLOAT4: + { + var->sType.Type = SVT_FLOAT; + break; + } + } + + var++; + psConstantBuffer->ui32NumVars++; + } + else + { + //Create a resource if it is sampler in order to replicate the d3d10+ + //method of separating samplers from general constants. + uint32_t ui32ResourceIndex = psInfo->ui32NumResourceBindings++; + ResourceBinding* res = &psInfo->psResourceBindings[ui32ResourceIndex]; + + strcpy(res->Name, data + cinfos[constNum].name); + FormatVariableName(res->Name); + + res->ui32BindPoint = cinfos[constNum].registerIndex; + res->ui32BindCount = cinfos[constNum].registerCount; + res->ui32Flags = 0; + res->ui32NumSamples = 1; + res->ui32ReturnType = 0; + + res->eType = RTYPE_TEXTURE; + + switch (typeInfo->type) + { + case PT_SAMPLER: + case PT_SAMPLER1D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE1D; + break; + case PT_SAMPLER2D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE2D; + break; + case PT_SAMPLER3D: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURE3D; + break; + case PT_SAMPLERCUBE: + res->eDimension = REFLECT_RESOURCE_DIMENSION_TEXTURECUBE; + break; + } + } + } + psConstantBuffer->ui32TotalSizeInBytes = ui32ConstantBufferSize; +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c new file mode 100644 index 0000000000..6c9d02015e --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSL.c @@ -0,0 +1,851 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/tokens.h" +#include "internal_includes/structs.h" +#include "internal_includes/decode.h" +#include "stdlib.h" +#include "stdio.h" +#include "bstrlib.h" +#include "internal_includes/toGLSLInstruction.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/toGLSLDeclaration.h" +#include "internal_includes/languages.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" + +#ifndef GL_VERTEX_SHADER_ARB +#define GL_VERTEX_SHADER_ARB 0x8B31 +#endif +#ifndef GL_FRAGMENT_SHADER_ARB +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#endif +#ifndef GL_GEOMETRY_SHADER +#define GL_GEOMETRY_SHADER 0x8DD9 +#endif +#ifndef GL_TESS_EVALUATION_SHADER +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#endif +#ifndef GL_TESS_CONTROL_SHADER +#define GL_TESS_CONTROL_SHADER 0x8E88 +#endif +#ifndef GL_COMPUTE_SHADER +#define GL_COMPUTE_SHADER 0x91B9 +#endif + + +HLSLCC_API void HLSLCC_APIENTRY HLSLcc_SetMemoryFunctions(void* (*malloc_override)(size_t),void* (*calloc_override)(size_t,size_t),void (*free_override)(void *),void* (*realloc_override)(void*,size_t)) +{ + hlslcc_malloc = malloc_override; + hlslcc_calloc = calloc_override; + hlslcc_free = free_override; + hlslcc_realloc = realloc_override; +} + +void AddIndentation(HLSLCrossCompilerContext* psContext) +{ + int i; + int indent = psContext->indent; + bstring glsl = *psContext->currentShaderString; + for(i=0; i < indent; ++i) + { + bcatcstr(glsl, " "); + } +} + +void AddVersionDependentCode(HLSLCrossCompilerContext* psContext) +{ + bstring glsl = *psContext->currentShaderString; + + if(psContext->psShader->ui32MajorVersion > 3 && psContext->psShader->eTargetLanguage != LANG_ES_300 && psContext->psShader->eTargetLanguage != LANG_ES_310 && !(psContext->psShader->eTargetLanguage >= LANG_330)) + { + //DX10+ bycode format requires the ability to treat registers + //as raw bits. ES3.0+ has that built-in, also 330 onwards + bcatcstr(glsl,"#extension GL_ARB_shader_bit_encoding : require\n"); + } + + if(!HaveCompute(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->eShaderType == COMPUTE_SHADER) + { + bcatcstr(glsl,"#extension GL_ARB_compute_shader : enable\n"); + bcatcstr(glsl,"#extension GL_ARB_shader_storage_buffer_object : enable\n"); + } + } + + if (!HaveAtomicMem(psContext->psShader->eTargetLanguage) || + !HaveAtomicCounter(psContext->psShader->eTargetLanguage)) + { + if( psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_ALLOC] || + psContext->psShader->aiOpcodeUsed[OPCODE_IMM_ATOMIC_CONSUME] || + psContext->psShader->aiOpcodeUsed[OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED]) + { + bcatcstr(glsl,"#extension GL_ARB_shader_atomic_counters : enable\n"); + + bcatcstr(glsl,"#extension GL_ARB_shader_storage_buffer_object : enable\n"); + } + } + + if(!HaveGather(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_C]) + { + bcatcstr(glsl,"#extension GL_ARB_texture_gather : enable\n"); + } + } + + if(!HaveGatherNonConstOffset(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO_C] || + psContext->psShader->aiOpcodeUsed[OPCODE_GATHER4_PO]) + { + bcatcstr(glsl,"#extension GL_ARB_gpu_shader5 : enable\n"); + } + } + + if(!HaveQueryLod(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->aiOpcodeUsed[OPCODE_LOD]) + { + bcatcstr(glsl,"#extension GL_ARB_texture_query_lod : enable\n"); + } + } + + if(!HaveQueryLevels(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->aiOpcodeUsed[OPCODE_RESINFO]) + { + bcatcstr(glsl,"#extension GL_ARB_texture_query_levels : enable\n"); + } + } + + if(!HaveImageLoadStore(psContext->psShader->eTargetLanguage)) + { + if(psContext->psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] || + psContext->psShader->aiOpcodeUsed[OPCODE_STORE_RAW] || + psContext->psShader->aiOpcodeUsed[OPCODE_STORE_STRUCTURED]) + { + bcatcstr(glsl,"#extension GL_ARB_shader_image_load_store : enable\n"); + bcatcstr(glsl,"#extension GL_ARB_shader_bit_encoding : enable\n"); + } + else + if(psContext->psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] || + psContext->psShader->aiOpcodeUsed[OPCODE_LD_RAW] || + psContext->psShader->aiOpcodeUsed[OPCODE_LD_STRUCTURED]) + { + bcatcstr(glsl,"#extension GL_ARB_shader_image_load_store : enable\n"); + } + } + + //The fragment language has no default precision qualifier for floating point types. + if (psContext->psShader->eShaderType == PIXEL_SHADER && + psContext->psShader->eTargetLanguage == LANG_ES_100 || psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision highp float;\n"); + } + + /* There is no default precision qualifier for the following sampler types in either the vertex or fragment language: */ + if (psContext->psShader->eTargetLanguage == LANG_ES_300 || psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision lowp sampler3D;\n"); + bcatcstr(glsl, "precision lowp samplerCubeShadow;\n"); + bcatcstr(glsl, "precision lowp sampler2DShadow;\n"); + bcatcstr(glsl, "precision lowp sampler2DArray;\n"); + bcatcstr(glsl, "precision lowp sampler2DArrayShadow;\n"); + bcatcstr(glsl, "precision lowp isampler2D;\n"); + bcatcstr(glsl, "precision lowp isampler3D;\n"); + bcatcstr(glsl, "precision lowp isamplerCube;\n"); + bcatcstr(glsl, "precision lowp isampler2DArray;\n"); + bcatcstr(glsl, "precision lowp usampler2D;\n"); + bcatcstr(glsl, "precision lowp usampler3D;\n"); + bcatcstr(glsl, "precision lowp usamplerCube;\n"); + bcatcstr(glsl, "precision lowp usampler2DArray;\n"); + + if (psContext->psShader->eTargetLanguage == LANG_ES_310) + { + bcatcstr(glsl, "precision lowp isampler2DMS;\n"); + bcatcstr(glsl, "precision lowp usampler2D;\n"); + bcatcstr(glsl, "precision lowp usampler3D;\n"); + bcatcstr(glsl, "precision lowp usamplerCube;\n"); + bcatcstr(glsl, "precision lowp usampler2DArray;\n"); + bcatcstr(glsl, "precision lowp usampler2DMS;\n"); + bcatcstr(glsl, "precision lowp image2D;\n"); + bcatcstr(glsl, "precision lowp image3D;\n"); + bcatcstr(glsl, "precision lowp imageCube;\n"); + bcatcstr(glsl, "precision lowp image2DArray;\n"); + bcatcstr(glsl, "precision lowp iimage2D;\n"); + bcatcstr(glsl, "precision lowp iimage3D;\n"); + bcatcstr(glsl, "precision lowp iimageCube;\n"); + bcatcstr(glsl, "precision lowp uimage2DArray;\n"); + } + bcatcstr(glsl, "\n"); + } + + if (SubroutinesSupported(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "subroutine void SubroutineType();\n"); + } + + if (psContext->psShader->ui32MajorVersion <= 3) + { + bcatcstr(glsl, "int RepCounter;\n"); + bcatcstr(glsl, "int LoopCounter;\n"); + bcatcstr(glsl, "int ZeroBasedCounter;\n"); + if (psContext->psShader->eShaderType == VERTEX_SHADER) + { + uint32_t texCoord; + bcatcstr(glsl, "ivec4 Address;\n"); + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "out vec4 OffsetColour;\n"); + bcatcstr(glsl, "out vec4 BaseColour;\n"); + + bcatcstr(glsl, "out vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "out vec4 TexCoord%d;\n", texCoord); + } + } + else + { + bcatcstr(glsl, "varying vec4 OffsetColour;\n"); + bcatcstr(glsl, "varying vec4 BaseColour;\n"); + + bcatcstr(glsl, "varying vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); + } + } + } + else + { + uint32_t renderTargets, texCoord; + + if (InOutSupported(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "in vec4 OffsetColour;\n"); + bcatcstr(glsl, "in vec4 BaseColour;\n"); + + bcatcstr(glsl, "in vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "in vec4 TexCoord%d;\n", texCoord); + } + } + else + { + bcatcstr(glsl, "varying vec4 OffsetColour;\n"); + bcatcstr(glsl, "varying vec4 BaseColour;\n"); + + bcatcstr(glsl, "varying vec4 Fog;\n"); + + for (texCoord = 0; texCoord < 8; ++texCoord) + { + bformata(glsl, "varying vec4 TexCoord%d;\n", texCoord); + } + } + + if (psContext->psShader->eTargetLanguage > LANG_120) + { + bcatcstr(glsl, "out vec4 outFragData[8];\n"); + for (renderTargets = 0; renderTargets < 8; ++renderTargets) + { + bformata(glsl, "#define Output%d outFragData[%d]\n", renderTargets, renderTargets); + } + } + else if (psContext->psShader->eTargetLanguage >= LANG_ES_300 && psContext->psShader->eTargetLanguage < LANG_120) + { + // ES 3 supports min 4 rendertargets, I guess this is reasonable lower limit for DX9 shaders + bcatcstr(glsl, "out vec4 outFragData[4];\n"); + for (renderTargets = 0; renderTargets < 4; ++renderTargets) + { + bformata(glsl, "#define Output%d outFragData[%d]\n", renderTargets, renderTargets); + } + } + else if (psContext->psShader->eTargetLanguage == LANG_ES_100) + { + bcatcstr(glsl, "#define Output0 gl_FragColor;\n"); + } + else + { + for (renderTargets = 0; renderTargets < 8; ++renderTargets) + { + bformata(glsl, "#define Output%d gl_FragData[%d]\n", renderTargets, renderTargets); + } + } + } + } + + if((psContext->flags & HLSLCC_FLAG_ORIGIN_UPPER_LEFT) + && (psContext->psShader->eTargetLanguage >= LANG_150)) + { + bcatcstr(glsl,"layout(origin_upper_left) in vec4 gl_FragCoord;\n"); + } + + if((psContext->flags & HLSLCC_FLAG_PIXEL_CENTER_INTEGER) + && (psContext->psShader->eTargetLanguage >= LANG_150)) + { + bcatcstr(glsl,"layout(pixel_center_integer) in vec4 gl_FragCoord;\n"); + } + + /* For versions which do not support a vec1 (currently all versions) */ + bcatcstr(glsl,"struct vec1 {\n"); + bcatcstr(glsl,"\tfloat x;\n"); + bcatcstr(glsl,"};\n"); + + if(HaveUVec(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl,"struct uvec1 {\n"); + bcatcstr(glsl,"\tuint x;\n"); + bcatcstr(glsl,"};\n"); + } + + bcatcstr(glsl,"struct ivec1 {\n"); + bcatcstr(glsl,"\tint x;\n"); + bcatcstr(glsl,"};\n"); + + /* + OpenGL 4.1 API spec: + To use any built-in input or output in the gl_PerVertex block in separable + program objects, shader code must redeclare that block prior to use. + */ + if(psContext->psShader->eShaderType == VERTEX_SHADER && psContext->psShader->eTargetLanguage >= LANG_410) + { + bcatcstr(glsl, "out gl_PerVertex {\n"); + bcatcstr(glsl, "vec4 gl_Position;\n"); + bcatcstr(glsl, "float gl_PointSize;\n"); + bcatcstr(glsl, "float gl_ClipDistance[];"); + bcatcstr(glsl, "};\n"); + } +} + +ShaderLang ChooseLanguage(ShaderData* psShader) +{ + // Depends on the HLSL shader model extracted from bytecode. + switch(psShader->ui32MajorVersion) + { + case 5: + { + return LANG_430; + } + case 4: + { + return LANG_330; + } + default: + { + return LANG_120; + } + } +} + +const char* GetVersionString(ShaderLang language) +{ + switch(language) + { + case LANG_ES_100: + { + return "#version 100\n"; + break; + } + case LANG_ES_300: + { + return "#version 300 es\n"; + break; + } + case LANG_ES_310: + { + return "#version 310 es\n"; + break; + } + case LANG_120: + { + return "#version 120\n"; + break; + } + case LANG_130: + { + return "#version 130\n"; + break; + } + case LANG_140: + { + return "#version 140\n"; + break; + } + case LANG_150: + { + return "#version 150\n"; + break; + } + case LANG_330: + { + return "#version 330\n"; + break; + } + case LANG_400: + { + return "#version 400\n"; + break; + } + case LANG_410: + { + return "#version 410\n"; + break; + } + case LANG_420: + { + return "#version 420\n"; + break; + } + case LANG_430: + { + return "#version 430\n"; + break; + } + case LANG_440: + { + return "#version 440\n"; + break; + } + default: + { + return ""; + break; + } + } +} + +void TranslateToGLSL(HLSLCrossCompilerContext* psContext, ShaderLang* planguage,const GlExtensions *extensions) +{ + bstring glsl; + uint32_t i; + ShaderData* psShader = psContext->psShader; + ShaderLang language = *planguage; + uint32_t ui32InstCount = 0; + uint32_t ui32DeclCount = 0; + + psContext->indent = 0; + + /*psShader->sPhase[MAIN_PHASE].ui32InstanceCount = 1; + psShader->sPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); + psShader->sPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); + psShader->sPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->sPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t));*/ + + if(language == LANG_DEFAULT) + { + language = ChooseLanguage(psShader); + *planguage = language; + } + + glsl = bfromcstralloc (1024, GetVersionString(language)); + + psContext->mainShader = glsl; + psContext->earlyMain = bfromcstralloc (1024, ""); + for(i=0; i<NUM_PHASES;++i) + { + psContext->postShaderCode[i] = bfromcstralloc (1024, ""); + } + psContext->currentShaderString = &glsl; + psShader->eTargetLanguage = language; + psShader->extensions = (const struct GlExtensions*)extensions; + psContext->currentPhase = MAIN_PHASE; + + if(extensions) + { + if(extensions->ARB_explicit_attrib_location) + bcatcstr(glsl,"#extension GL_ARB_explicit_attrib_location : require\n"); + if(extensions->ARB_explicit_uniform_location) + bcatcstr(glsl,"#extension GL_ARB_explicit_uniform_location : require\n"); + if(extensions->ARB_shading_language_420pack) + bcatcstr(glsl,"#extension GL_ARB_shading_language_420pack : require\n"); + } + + AddVersionDependentCode(psContext); + + if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) + { + bcatcstr(glsl, "layout(std140) uniform;\n"); + } + + //Special case. Can have multiple phases. + if(psShader->eShaderType == HULL_SHADER) + { + int haveInstancedForkPhase = 0; // Do we have an instanced fork phase? + int isCurrentForkPhasedInstanced = 0; // Is the current fork phase instanced? + const char* asPhaseFuncNames[NUM_PHASES]; + uint32_t ui32PhaseFuncCallOrder[3]; + uint32_t ui32PhaseCallIndex; + + uint32_t ui32Phase; + uint32_t ui32Instance; + + asPhaseFuncNames[MAIN_PHASE] = ""; + asPhaseFuncNames[HS_GLOBAL_DECL] = ""; + asPhaseFuncNames[HS_FORK_PHASE] = "fork_phase"; + asPhaseFuncNames[HS_CTRL_POINT_PHASE] = "control_point_phase"; + asPhaseFuncNames[HS_JOIN_PHASE] = "join_phase"; + + ConsolidateHullTempVars(psShader); + + for(i=0; i < psShader->asPhase[HS_GLOBAL_DECL].pui32DeclCount[0]; ++i) + { + TranslateDeclaration(psContext, psShader->asPhase[HS_GLOBAL_DECL].ppsDecl[0]+i); + } + + for(ui32Phase=HS_CTRL_POINT_PHASE; ui32Phase<NUM_PHASES; ui32Phase++) + { + psContext->currentPhase = ui32Phase; + for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) + { + isCurrentForkPhasedInstanced = 0; //reset for each fork phase for cases we don't have a fork phase instance count opcode. + bformata(glsl, "//%s declarations\n", asPhaseFuncNames[ui32Phase]); + for(i=0; i < psShader->asPhase[ui32Phase].pui32DeclCount[ui32Instance]; ++i) + { + TranslateDeclaration(psContext, psShader->asPhase[ui32Phase].ppsDecl[ui32Instance]+i); + if(psShader->asPhase[ui32Phase].ppsDecl[ui32Instance][i].eOpcode == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT) + { + haveInstancedForkPhase = 1; + isCurrentForkPhasedInstanced = 1; + } + } + + bformata(glsl, "void %s%d()\n{\n", asPhaseFuncNames[ui32Phase], ui32Instance); + psContext->indent++; + + SetDataTypes(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance], psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1); + + if(isCurrentForkPhasedInstanced) + { + AddIndentation(psContext); + bformata(glsl, "for(int forkInstanceID = 0; forkInstanceID < HullPhase%dInstanceCount; ++forkInstanceID) {\n", ui32Instance); + psContext->indent++; + } + + //The minus one here is remove the return statement at end of phases. + //This is needed otherwise the for loop will only run once. + ASSERT(psShader->asPhase[ui32Phase].ppsInst[ui32Instance] [psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1].eOpcode == OPCODE_RET); + for(i=0; i < psShader->asPhase[ui32Phase].pui32InstCount[ui32Instance]-1; ++i) + { + TranslateInstruction(psContext, psShader->asPhase[ui32Phase].ppsInst[ui32Instance]+i, NULL); + } + + if(haveInstancedForkPhase) + { + psContext->indent--; + AddIndentation(psContext); + + if(isCurrentForkPhasedInstanced) + { + bcatcstr(glsl, "}\n"); + } + + if(psContext->havePostShaderCode[psContext->currentPhase]) + { + #ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); + #endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); + #ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); + #endif + } + } + + psContext->indent--; + bcatcstr(glsl, "}\n"); + } + } + + bcatcstr(glsl, "void main()\n{\n"); + + psContext->indent++; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Start Early Main ---\n"); +#endif + bconcat(glsl, psContext->earlyMain); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End Early Main ---\n"); +#endif + + ui32PhaseFuncCallOrder[0] = HS_CTRL_POINT_PHASE; + ui32PhaseFuncCallOrder[1] = HS_FORK_PHASE; + ui32PhaseFuncCallOrder[2] = HS_JOIN_PHASE; + + for(ui32PhaseCallIndex=0; ui32PhaseCallIndex<3; ui32PhaseCallIndex++) + { + ui32Phase = ui32PhaseFuncCallOrder[ui32PhaseCallIndex]; + for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) + { + AddIndentation(psContext); + bformata(glsl, "%s%d();\n", asPhaseFuncNames[ui32Phase], ui32Instance); + + if(ui32Phase == HS_FORK_PHASE) + { + if(psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount || + (ui32Instance+1 < psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount)) + { + AddIndentation(psContext); + bcatcstr(glsl, "barrier();\n"); + } + } + } + } + + psContext->indent--; + + bcatcstr(glsl, "}\n"); + + return; + } + + + ui32InstCount = psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; + ui32DeclCount = psShader->asPhase[MAIN_PHASE].pui32DeclCount[0]; + + for(i=0; i < ui32DeclCount; ++i) + { + TranslateDeclaration(psContext, psShader->asPhase[MAIN_PHASE].ppsDecl[0]+i); + } + + if(psContext->psShader->ui32NumDx9ImmConst) + { + bformata(psContext->mainShader, "vec4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); + } + + bcatcstr(glsl, "void main()\n{\n"); + + psContext->indent++; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Start Early Main ---\n"); +#endif + bconcat(glsl, psContext->earlyMain); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End Early Main ---\n"); +#endif + + MarkIntegerImmediates(psContext); + + SetDataTypes(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0], ui32InstCount); + + for(i=0; i < ui32InstCount; ++i) + { + TranslateInstruction(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0]+i, i+1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0]+i+1 : 0); + } + + psContext->indent--; + + bcatcstr(glsl, "}\n"); +} + +static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) +{ + uint32_t ui32Inst; + for(ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) + { + Instruction* psCurrentInst = &psInst[ui32Inst]; + const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; + uint32_t ui32Operand; + + for(ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) + { + uint32_t ui32SubOperand; + for(ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) + { + if(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) + { + hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); + psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; + } + } + } + } +} + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToGLSL(const char* shader, + unsigned int flags, + ShaderLang language, + const GlExtensions *extensions, + Shader* result) +{ + uint32_t* tokens; + ShaderData* psShader; + char* glslcstr = NULL; + int GLSLShaderType = GL_FRAGMENT_SHADER_ARB; + int success = 0; + uint32_t i; + + tokens = (uint32_t*)shader; + + psShader = DecodeDXBC(tokens); + + if(psShader) + { + HLSLCrossCompilerContext sContext; + + if(psShader->ui32MajorVersion <= 3) + { + flags &= ~HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS; + } + + sContext.psShader = psShader; + sContext.flags = flags; + + for(i=0; i<NUM_PHASES;++i) + { + sContext.havePostShaderCode[i] = 0; + } + + TranslateToGLSL(&sContext, &language,extensions); + + switch(psShader->eShaderType) + { + case VERTEX_SHADER: + { + GLSLShaderType = GL_VERTEX_SHADER_ARB; + break; + } + case GEOMETRY_SHADER: + { + GLSLShaderType = GL_GEOMETRY_SHADER; + break; + } + case DOMAIN_SHADER: + { + GLSLShaderType = GL_TESS_EVALUATION_SHADER; + break; + } + case HULL_SHADER: + { + GLSLShaderType = GL_TESS_CONTROL_SHADER; + break; + } + case COMPUTE_SHADER: + { + GLSLShaderType = GL_COMPUTE_SHADER; + break; + } + default: + { + break; + } + } + + glslcstr = bstr2cstr(sContext.mainShader, '\0'); + + bdestroy(sContext.mainShader); + bdestroy(sContext.earlyMain); + for(i=0; i<NUM_PHASES; ++i) + { + bdestroy(sContext.postShaderCode[i]); + } + + for(i=0; i<NUM_PHASES;++i) + { + if(psShader->asPhase[i].ppsDecl != 0) + { + uint32_t k; + for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) + { + hlslcc_free(psShader->asPhase[i].ppsDecl[k]); + } + hlslcc_free(psShader->asPhase[i].ppsDecl); + } + if(psShader->asPhase[i].ppsInst != 0) + { + uint32_t k; + for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) + { + FreeSubOperands(psShader->asPhase[i].ppsInst[k], psShader->asPhase[i].pui32InstCount[k]); + hlslcc_free(psShader->asPhase[i].ppsInst[k]); + } + hlslcc_free(psShader->asPhase[i].ppsInst); + } + } + + memcpy(&result->reflection,&psShader->sInfo,sizeof(psShader->sInfo)); + + result->textureSamplerInfo.ui32NumTextureSamplerPairs = psShader->textureSamplerInfo.ui32NumTextureSamplerPairs; + for (i=0; i<result->textureSamplerInfo.ui32NumTextureSamplerPairs; i++) + strcpy(result->textureSamplerInfo.aTextureSamplerPair[i].Name, psShader->textureSamplerInfo.aTextureSamplerPair[i].Name); + + hlslcc_free(psShader); + + success = 1; + } + + shader = 0; + tokens = 0; + + /* Fill in the result struct */ + + result->shaderType = GLSLShaderType; + result->sourceCode = glslcstr; + result->GLSLLanguage = language; + + return success; +} + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToGLSL(const char* filename, + unsigned int flags, + ShaderLang language, + const GlExtensions *extensions, + Shader* result) +{ + FILE* shaderFile; + int length; + size_t readLength; + char* shader; + int success = 0; + + shaderFile = fopen(filename, "rb"); + + if(!shaderFile) + { + return 0; + } + + fseek(shaderFile, 0, SEEK_END); + length = ftell(shaderFile); + fseek(shaderFile, 0, SEEK_SET); + + shader = (char*)hlslcc_malloc(length+1); + + readLength = fread(shader, 1, length, shaderFile); + + fclose(shaderFile); + shaderFile = 0; + + shader[readLength] = '\0'; + + success = TranslateHLSLFromMemToGLSL(shader, flags, language, extensions, result); + + hlslcc_free(shader); + + return success; +} + +HLSLCC_API void HLSLCC_APIENTRY FreeShader(Shader* s) +{ + bcstrfree(s->sourceCode); + s->sourceCode = NULL; + FreeShaderInfo(&s->reflection); +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c new file mode 100644 index 0000000000..4d9195339f --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLDeclaration.c @@ -0,0 +1,2678 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "hlslcc.h" +#include "internal_includes/toGLSLDeclaration.h" +#include "internal_includes/toGLSLOperand.h" +#include "internal_includes/languages.h" +#include "bstrlib.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include <math.h> +#include <float.h> + +#ifdef _MSC_VER + #ifndef isnan + #define isnan(x) _isnan(x) + #endif + + #ifndef isinf + #define isinf(x) (!_finite(x)) + #endif +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) + +typedef enum { + GLVARTYPE_FLOAT, + GLVARTYPE_INT, + GLVARTYPE_FLOAT4, +} GLVARTYPE; + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +const char* GetTypeString(GLVARTYPE eType) +{ + switch(eType) + { + case GLVARTYPE_FLOAT: + { + return "float"; + } + case GLVARTYPE_INT: + { + return "int"; + } + case GLVARTYPE_FLOAT4: + { + return "vec4"; + } + default: + { + return ""; + } + } +} +const uint32_t GetTypeElementCount(GLVARTYPE eType) +{ + switch(eType) + { + case GLVARTYPE_FLOAT: + case GLVARTYPE_INT: + { + return 1; + } + case GLVARTYPE_FLOAT4: + { + return 4; + } + default: + { + return 0; + } + } +} + +void AddToDx9ImmConstIndexableArray(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + bstring* savedStringPtr = psContext->currentShaderString; + + psContext->currentShaderString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; + bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); + TranslateOperand(psContext, psOperand, TO_FLAG_NONE); + bcatcstr(psContext->earlyMain, ";\n"); + psContext->indent--; + psContext->psShader->ui32NumDx9ImmConst++; + + psContext->currentShaderString = savedStringPtr; +} + +void DeclareConstBufferShaderVariable(bstring glsl, const char* Name, const struct ShaderVarType_TAG* psType, int unsizedArray) + //const SHADER_VARIABLE_CLASS eClass, const SHADER_VARIABLE_TYPE eType, + //const char* pszName) +{ + if(psType->Class == SVC_STRUCT) + { + bformata(glsl, "\t%s_Type %s", Name, Name); + } + else if(psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) + { + switch(psType->Type) + { + case SVT_FLOAT: + { + bformata(glsl, "\tmat4 %s", Name); + break; + } + default: + { + ASSERT(0); + break; + } + } + if(psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + else + if(psType->Class == SVC_VECTOR) + { + switch(psType->Type) + { + case SVT_FLOAT: + { + bformata(glsl, "\tvec%d %s", psType->Columns, Name); + break; + } + case SVT_UINT: + { + bformata(glsl, "\tuvec%d %s", psType->Columns, Name); + break; + } + case SVT_INT: + { + bformata(glsl, "\tivec%d %s", psType->Columns, Name); + break; + } + case SVT_DOUBLE: + { + bformata(glsl, "\tdvec%d %s", psType->Columns, Name); + break; + } + case SVT_BOOL: + { + bformata(glsl, "\tbvec%d %s", psType->Columns, Name); + break; + } + default: + { + ASSERT(0); + break; + } + } + + if(psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + else + if(psType->Class == SVC_SCALAR) + { + switch(psType->Type) + { + case SVT_FLOAT: + { + bformata(glsl, "\tfloat %s", Name); + break; + } + case SVT_UINT: + { + bformata(glsl, "\tuint %s", Name); + break; + } + case SVT_INT: + { + bformata(glsl, "\tint %s", Name); + break; + } + case SVT_DOUBLE: + { + bformata(glsl, "\tdouble %s", Name); + break; + } + case SVT_BOOL: + { + //Use int instead of bool. + //Allows implicit conversions to integer and + //bool consumes 4-bytes in HLSL and GLSL anyway. + bformata(glsl, "\tint %s", Name); + // Also change the definition in the type tree. + ((ShaderVarType *)psType)->Type = SVT_INT; + break; + } + default: + { + ASSERT(0); + break; + } + } + + if(psType->Elements > 1) + { + bformata(glsl, "[%d]", psType->Elements); + } + } + if(unsizedArray) + bformata(glsl, "[]"); + bformata(glsl, ";\n"); +} + +//In GLSL embedded structure definitions are not supported. +void PreDeclareStructType(bstring glsl, const char* Name, const struct ShaderVarType_TAG* psType) +{ + uint32_t i; + + for(i=0; i<psType->MemberCount; ++i) + { + if(psType->Members[i].Class == SVC_STRUCT) + { + PreDeclareStructType(glsl, psType->Members[i].Name, &psType->Members[i]); + } + } + + if(psType->Class == SVC_STRUCT) + { +#if defined(_DEBUG) + uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; +#endif + //Not supported at the moment + ASSERT(!unnamed_struct); + + bformata(glsl, "struct %s_Type {\n", Name); + + for(i=0; i<psType->MemberCount; ++i) + { + ASSERT(psType->Members != 0); + + DeclareConstBufferShaderVariable(glsl, psType->Members[i].Name, &psType->Members[i], 0); + } + + bformata(glsl, "};\n"); + } +} + +const char* GetDeclaredInputName(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) +{ + bstring inputName; + char* cstr; + InOutSignature* psIn; + int found = GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn); + + if((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && found) + { + if (eShaderType == VERTEX_SHADER) /* We cannot have input and output names conflict, but vs output must match ps input. Prefix vs input. */ + inputName = bformat("in_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + else + inputName = bformat("%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + } + else if(eShaderType == GEOMETRY_SHADER) + { + inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else if(eShaderType == HULL_SHADER) + { + inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + else if(eShaderType == DOMAIN_SHADER) + { + inputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); + } + else if(eShaderType == PIXEL_SHADER) + { + if(psContext->flags & HLSLCC_FLAG_TESS_ENABLED) + { + inputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); + } + else + { + inputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + } + else + { + ASSERT(eShaderType == VERTEX_SHADER); + inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); + } + if((psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) && found) + { + bformata(inputName,"_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + } + + cstr = bstr2cstr(inputName, '\0'); + bdestroy(inputName); + return cstr; +} + +const char* GetDeclaredOutputName(const HLSLCrossCompilerContext* psContext, + const SHADER_TYPE eShaderType, + const Operand* psOperand, + int* piStream) +{ + bstring outputName; + char* cstr; + InOutSignature* psOut; + +#if defined(_DEBUG) + int foundOutput = +#endif + GetOutputSignatureFromRegister( + psContext->currentPhase, + psOperand->ui32RegisterNumber, + psOperand->ui32CompMask, + psContext->psShader->ui32CurrentVertexOutputStream, + &psContext->psShader->sInfo, + &psOut); + + ASSERT(foundOutput); + + if(psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) + { + outputName = bformat("%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); + } + else if(eShaderType == GEOMETRY_SHADER) + { + if(psOut->ui32Stream != 0) + { + outputName = bformat("VtxGeoOutput%d_S%d", psOperand->ui32RegisterNumber, psOut->ui32Stream); + piStream[0] = psOut->ui32Stream; + } + else + { + outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + + } + else if(eShaderType == DOMAIN_SHADER) + { + outputName = bformat("DomOutput%d", psOperand->ui32RegisterNumber); + } + else if(eShaderType == VERTEX_SHADER) + { + if(psContext->flags & HLSLCC_FLAG_GS_ENABLED) + { + outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else + { + outputName = bformat("VtxGeoOutput%d", psOperand->ui32RegisterNumber); + } + } + else if(eShaderType == PIXEL_SHADER) + { + outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); + } + else + { + ASSERT(eShaderType == HULL_SHADER); + outputName = bformat("HullOutput%d", psOperand->ui32RegisterNumber); + } + if(psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) + { + bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); + } + + cstr = bstr2cstr(outputName, '\0'); + bdestroy(outputName); + return cstr; +} + +const char* GetInterpolationString(INTERPOLATION_MODE eMode) +{ + switch(eMode) + { + case INTERPOLATION_CONSTANT: + { + return "flat"; + } + case INTERPOLATION_LINEAR: + { + return ""; + } + case INTERPOLATION_LINEAR_CENTROID: + { + return "centroid"; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE: + { + return "noperspective"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: + { + return "noperspective centroid"; + } + case INTERPOLATION_LINEAR_SAMPLE: + { + return "sample"; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: + { + return "noperspective sample"; + } + default: + { + return ""; + } + } +} + +static void DeclareInput( + HLSLCrossCompilerContext* psContext, + const Declaration* psDecl, + const char* Interpolation, const char* StorageQualifier, const char* Precision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) +{ + ShaderData* psShader = psContext->psShader; + bstring glsl = *psContext->currentShaderString; + + // This falls within the specified index ranges. The default is 0 if no input range is specified + if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + return; + + if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + const char* vecType = "vec"; + const char* scalarType = "float"; + InOutSignature* psSignature = NULL; + + if( GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature) ) + { + switch(psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + vecType = "uvec"; + scalarType = "uint"; + break; + } + case INOUT_COMPONENT_SINT32: + { + vecType = "ivec"; + scalarType = "int"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + } + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || + (psShader->eShaderType == VERTEX_SHADER && HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags))) + { + // Skip location if requested by the flags. + if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + switch(eIndexDim) + { + case INDEX_2D: + { + if(iNumComponents == 1) + { + const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; + + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; + + bformata(glsl, "%s %s %s %s [%d];\n", StorageQualifier, Precision, scalarType, InputName, + arraySize); + + bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; + } + else + { + bformata(glsl, "%s %s %s%d %s [%d];\n", StorageQualifier, Precision, vecType, iNumComponents, InputName, + psDecl->asOperands[0].aui32ArraySizes[0]); + + bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].aui32ArraySizes[0]); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->asOperands[0].aui32ArraySizes[0]; + } + break; + } + default: + { + + if(psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) + { + InputName = "TexCoord"; + } + + if(iNumComponents == 1) + { + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; + + bformata(glsl, "%s %s %s %s %s;\n", Interpolation, StorageQualifier, Precision, scalarType, InputName); + bformata(glsl, "%s1 Input%d;\n", vecType, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + else + { + if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) + { + bformata(glsl, "%s %s %s %s%d %s", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "[%d];\n", psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + bformata(glsl, "%s%d Input%d[%d];\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, + psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; + } + else + { + bformata(glsl, "%s %s %s %s%d %s;\n", Interpolation, StorageQualifier, Precision, vecType, iNumComponents, InputName); + bformata(glsl, "%s%d Input%d;\n", vecType, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + } + break; + } + } + } + + if(psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) + { + psContext->currentShaderString = &psContext->earlyMain; + psContext->indent++; + + if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array + { + AddIndentation(psContext); + bformata(psContext->earlyMain, "Input%d = %s;\n", psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else + { + int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; + + while(arrayIndex) + { + AddIndentation(psContext); + bformata(psContext->earlyMain, "Input%d[%d] = %s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex-1, + InputName, arrayIndex-1); + + arrayIndex--; + } + } + psContext->indent--; + psContext->currentShaderString = &psContext->mainShader; + } +} + +void AddBuiltinInput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName) +{ + bstring glsl = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + if(psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + SHADER_VARIABLE_TYPE eType = GetOperandDataType(psContext, &psDecl->asOperands[0]); + switch(eType) + { + case SVT_INT: + bformata(glsl, "ivec4 "); + break; + case SVT_UINT: + bformata(glsl, "uvec4 "); + break; + case SVT_BOOL: + bformata(glsl, "bvec4 "); + break; + default: + bformata(glsl, "vec4 "); + break; + } + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, ";\n"); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; + } + else + { + //This register has already been declared. The HLSL bytecode likely looks + //something like this then: + // dcl_input_ps constant v3.x + // dcl_input_ps_sgv v3.y, primitive_id + + //GLSL does not allow assignment to a varying! + } + + psContext->currentShaderString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_DESTINATION); + + bformata(psContext->earlyMain, " = %s", builtinName); + + switch(psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); + break; + default: + //Scalar built-in. Don't apply swizzle. + break; + } + bcatcstr(psContext->earlyMain, ";\n"); + + psContext->indent--; + psContext->currentShaderString = &psContext->mainShader; +} + +int OutputNeedsDeclaring(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) +{ + ShaderData* psShader = psContext->psShader; + const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; + if(psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) + { + int offset; + + for(offset = 0; offset < count; offset++) + { + psShader->aiOutputDeclared[psOperand->ui32RegisterNumber+offset] = declared; + } + return 1; + } + + if(psShader->eShaderType == PIXEL_SHADER) + { + if(psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL) + { + return 1; + } + } + + return 0; +} + +void AddBuiltinOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) +{ + bstring glsl = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) + { + InOutSignature* psSignature = NULL; + + GetOutputSignatureFromRegister( + psContext->currentPhase, + psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].ui32CompMask, + 0, + &psShader->sInfo, &psSignature); + + bcatcstr(glsl, "#undef "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "\n"); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, " phase%d_", psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "\n"); + + switch (type) + { + case GLVARTYPE_INT: + bcatcstr(glsl, "ivec4 "); + break; + default: + bcatcstr(glsl, "vec4 "); + } + + bformata(glsl, "phase%d_", psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + if(arrayElements) + bformata(glsl, "[%d];\n", arrayElements); + else + bcatcstr(glsl, ";\n"); + + psContext->currentShaderString = &psContext->postShaderCode[psContext->currentPhase]; + glsl = *psContext->currentShaderString; + psContext->indent++; + if(arrayElements) + { + int elem; + for(elem = 0; elem < arrayElements; elem++) + { + AddIndentation(psContext); + bformata(glsl, "%s[%d] = %s(phase%d_", builtinName, elem, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NAME_ONLY); + bformata(glsl, "[%d]", elem); + TranslateOperandSwizzle(psContext, &psDecl->asOperands[0]); + bformata(glsl, ");\n"); + } + } + else + { + + if(psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) + { + int max = GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + + int applySiwzzle = GetNumSwizzleElements(&psDecl->asOperands[0]) > 1 ? 1 : 0; + int index; + int i; + int multiplier = 1; + char* swizzle[] = {".x", ".y", ".z", ".w"}; + + ASSERT(psSignature!=NULL); + + index = psSignature->ui32SemanticIndex; + + //Clip distance can be spread across 1 or 2 outputs (each no more than a vec4). + //Some examples: + //float4 clip[2] : SV_ClipDistance; //8 clip distances + //float3 clip[2] : SV_ClipDistance; //6 clip distances + //float4 clip : SV_ClipDistance; //4 clip distances + //float clip : SV_ClipDistance; //1 clip distance. + + //In GLSL the clip distance built-in is an array of up to 8 floats. + //So vector to array conversion needs to be done here. + if(index == 1) + { + InOutSignature* psFirstClipSignature; + if(GetOutputSignatureFromSystemValue(NAME_CLIP_DISTANCE, 1, &psShader->sInfo, &psFirstClipSignature)) + { + if(psFirstClipSignature->ui32Mask & (1 << 3)) + { + multiplier = 4; + } + else + if(psFirstClipSignature->ui32Mask & (1 << 2)) + { + multiplier = 3; + } + else + if(psFirstClipSignature->ui32Mask & (1 << 1)) + { + multiplier = 2; + } + } + } + + for(i=0; i<max; ++i) + { + AddIndentation(psContext); + bformata(glsl, "%s[%d] = (phase%d_", builtinName, i + multiplier*index, psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + if(applySiwzzle) + { + bformata(glsl, ")%s;\n", swizzle[i]); + } + else + { + bformata(glsl, ");\n"); + } + } + } + else + { + uint32_t elements = GetNumSwizzleElements(&psDecl->asOperands[0]); + + if(elements != GetTypeElementCount(type)) + { + //This is to handle float3 position seen in control point phases + //struct HS_OUTPUT + //{ + // float3 vPosition : POSITION; + //}; -> dcl_output o0.xyz + //gl_Position is vec4. + AddIndentation(psContext); + bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, ", 1);\n"); + } + else + { + AddIndentation(psContext); + bformata(glsl, "%s = %s(phase%d_", builtinName, GetTypeString(type), psContext->currentPhase); + TranslateOperand(psContext, &psDecl->asOperands[0], type == GLVARTYPE_INT ? TO_FLAG_INTEGER : TO_FLAG_NONE); + bformata(glsl, ");\n"); + } + } + } + psContext->indent--; + psContext->currentShaderString = &psContext->mainShader; + } +} + +void AddUserOutput(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) +{ + bstring glsl = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + if(OutputNeedsDeclaring(psContext, &psDecl->asOperands[0], 1)) + { + const Operand* psOperand = &psDecl->asOperands[0]; + const char* Precision = ""; + const char* type = "vec"; + + InOutSignature* psSignature = NULL; + + GetOutputSignatureFromRegister( + psContext->currentPhase, + psDecl->asOperands[0].ui32RegisterNumber, + psDecl->asOperands[0].ui32CompMask, + psShader->ui32CurrentVertexOutputStream, + &psShader->sInfo, + &psSignature); + + switch(psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uvec"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "ivec"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + + if(HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch(psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + //type = "ivec"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + //type = "uvec"; + break; + } + } + } + + switch(psShader->eShaderType) + { + case PIXEL_SHADER: + { + switch(psDecl->asOperands[0].eType) + { + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + { + bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); + bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); + bcatcstr(glsl, "layout (depth_greater) out float gl_FragDepth;\n"); + bcatcstr(glsl, "#endif\n"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bcatcstr(glsl, "#ifdef GL_ARB_conservative_depth\n"); + bcatcstr(glsl, "#extension GL_ARB_conservative_depth : enable\n"); + bcatcstr(glsl, "layout (depth_less) out float gl_FragDepth;\n"); + bcatcstr(glsl, "#endif\n"); + break; + } + default: + { + if(WriteToFragData(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "#define Output%d gl_FragData[%d]\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); + } + else + { + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, PIXEL_SHADER, psOperand, &stream); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags) || HaveLimitedInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->flags)) + { + uint32_t index = 0; + uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; + + if((psContext->flags & HLSLCC_FLAG_DUAL_SOURCE_BLENDING) && DualSourceBlendSupported(psContext->psShader->eTargetLanguage)) + { + if(renderTarget > 0) + { + renderTarget = 0; + index = 1; + } + bformata(glsl, "layout(location = %d, index = %d) ", renderTarget, index); + } + else + { + bformata(glsl, "layout(location = %d) ", renderTarget); + } + } + + bformata(glsl, "out %s %s4 %s;\n", Precision, type, OutputName); + if(stream) + { + bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); + } + else + { + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + } + } + break; + } + } + break; + } + case VERTEX_SHADER: + { + int iNumComponents = 4;//GetMaxComponentFromComponentMask(&psDecl->asOperands[0]); + const char* Interpolation = ""; + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, VERTEX_SHADER, psOperand, &stream); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + if (!(psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS)) + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + if(InOutSupported(psContext->psShader->eTargetLanguage)) + { + bformata(glsl, "%s out %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); + } + else + { + bformata(glsl, "%s varying %s %s%d %s;\n", Interpolation, Precision, type, iNumComponents, OutputName); + } + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + + break; + } + case GEOMETRY_SHADER: + { + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, GEOMETRY_SHADER, psOperand, &stream); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + bformata(glsl, "out %s4 %s;\n", type, OutputName); + if(stream) + { + bformata(glsl, "#define Output%d_S%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, stream, OutputName); + } + else + { + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + } + break; + } + case HULL_SHADER: + { + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, HULL_SHADER, psOperand, &stream); + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber!=0);//Reg 0 should be gl_out[gl_InvocationID].gl_Position. + + if(psContext->currentPhase == HS_JOIN_PHASE) + { + bformata(glsl, "out patch %s4 %s[];\n", type, OutputName); + } + else + { + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + bformata(glsl, "out %s4 %s[];\n", type, OutputName); + } + bformata(glsl, "#define Output%d %s[gl_InvocationID]\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + break; + } + case DOMAIN_SHADER: + { + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, DOMAIN_SHADER, psOperand, &stream); + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + bformata(glsl, "out %s4 %s;\n", type, OutputName); + bformata(glsl, "#define Output%d %s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + break; + } + } + } + else + { + /* + Multiple outputs can be packed into one register. e.g. + // Name Index Mask Register SysValue Format Used + // -------------------- ----- ------ -------- -------- ------- ------ + // FACTOR 0 x 3 NONE int x + // MAX 0 y 3 NONE int y + + We want unique outputs to make it easier to use transform feedback. + + out ivec4 FACTOR0; + #define Output3 FACTOR0 + out ivec4 MAX0; + + MAIN SHADER CODE. Writes factor and max to Output3 which aliases FACTOR0. + + MAX0.x = FACTOR0.y; + + This unpacking of outputs is only done when using HLSLCC_FLAG_INOUT_SEMANTIC_NAMES/HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES. + When not set the application will be using HLSL reflection information to discover + what the input and outputs mean if need be. + */ + + // + + if((psContext->flags & (HLSLCC_FLAG_INOUT_SEMANTIC_NAMES|HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES)) && (psDecl->asOperands[0].eType == OPERAND_TYPE_OUTPUT)) + { + const Operand* psOperand = &psDecl->asOperands[0]; + InOutSignature* psSignature = NULL; + const char* type = "vec"; + int stream = 0; + const char* OutputName = GetDeclaredOutputName(psContext, psShader->eShaderType, psOperand, &stream); + + GetOutputSignatureFromRegister( + psContext->currentPhase, + psOperand->ui32RegisterNumber, + psOperand->ui32CompMask, + 0, + &psShader->sInfo, + &psSignature); + + if (HaveInOutLocationQualifier(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + if (!((psShader->eShaderType == VERTEX_SHADER) && (psContext->flags & HLSLCC_FLAG_DISABLE_EXPLICIT_LOCATIONS))) + bformata(glsl, "layout(location = %d) ", psDecl->asOperands[0].ui32RegisterNumber); + } + + switch(psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uvec"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "ivec"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + bformata(glsl, "out %s4 %s;\n", type, OutputName); + + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + psContext->currentShaderString = &psContext->postShaderCode[psContext->currentPhase]; + glsl = *psContext->currentShaderString; + + bcatcstr(glsl, OutputName); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(psOperand)); + bformata(glsl, " = Output%d", psOperand->ui32RegisterNumber); + TranslateOperandSwizzle(psContext, psOperand); + bcatcstr(glsl, ";\n"); + + psContext->currentShaderString = &psContext->mainShader; + glsl = *psContext->currentShaderString; + } + } +} + +void DeclareUBOConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, + ConstantBuffer* psCBuf, + bstring glsl) +{ + uint32_t i; + const char* Name = psCBuf->Name; + if(psCBuf->Name[0] == '$') //For $Globals + { + Name++; + } + + for(i=0; i < psCBuf->ui32NumVars; ++i) + { + PreDeclareStructType(glsl, + psCBuf->asVars[i].Name, + &psCBuf->asVars[i].sType); + } + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); + + bformata(glsl, "uniform %s {\n ", Name); + + for(i=0; i < psCBuf->ui32NumVars; ++i) + { + DeclareConstBufferShaderVariable(glsl, + psCBuf->asVars[i].Name, + &psCBuf->asVars[i].sType, 0); + } + + bcatcstr(glsl, "};\n"); +} + +void DeclareBufferVariable(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, + ConstantBuffer* psCBuf, const Operand* psOperand, + const uint32_t ui32GloballyCoherentAccess, + const ResourceType eResourceType, + bstring glsl) +{ + bstring StructName; +#if defined(_DEBUG) + uint32_t unnamed_struct = +#endif + strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; + + ASSERT(psCBuf->ui32NumVars == 1); + ASSERT(unnamed_struct); + + StructName = bfromcstr(""); + + //TranslateOperand(psContext, psOperand, TO_FLAG_NAME_ONLY); + if(psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) + { + bformata(StructName, "StructuredRes%d", psOperand->ui32RegisterNumber); + } + else if(psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) + { + bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); + } + else + { + ResourceName(StructName, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); + } + + PreDeclareStructType(glsl, + bstr2cstr(StructName, '\0'), + &psCBuf->asVars[0].sType); + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + bformata(glsl, "layout(binding = %d) ", ui32BindingPoint); + + if(ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) + { + bcatcstr(glsl, "coherent "); + } + + if(eResourceType == RTYPE_STRUCTURED) + { + bcatcstr(glsl, "readonly "); + } + + bformata(glsl, "buffer Block%d {\n", psOperand->ui32RegisterNumber); + + DeclareConstBufferShaderVariable(glsl, + bstr2cstr(StructName, '\0'), + &psCBuf->asVars[0].sType, + 1); + + bcatcstr(glsl, "};\n"); + + bdestroy(StructName); +} + + +void DeclareStructConstants(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, + ConstantBuffer* psCBuf, const Operand* psOperand, + bstring glsl) +{ + uint32_t i; + int useGlobalsStruct = 1; + + if(psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT && psCBuf->Name[0] == '$') + useGlobalsStruct = 0; + + if(useGlobalsStruct) + { + for(i=0; i < psCBuf->ui32NumVars; ++i) + { + PreDeclareStructType(glsl, + psCBuf->asVars[i].Name, + &psCBuf->asVars[i].sType); + } + } + + /* [layout (location = X)] uniform vec4 HLSLConstantBufferName[numConsts]; */ + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + bformata(glsl, "layout(location = %d) ", ui32BindingPoint); + if(useGlobalsStruct) + { + bcatcstr(glsl, "uniform struct "); + TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); + + bcatcstr(glsl, "_Type {\n"); + } + + for(i=0; i < psCBuf->ui32NumVars; ++i) + { + if(!useGlobalsStruct) + bcatcstr(glsl, "uniform "); + + DeclareConstBufferShaderVariable(glsl, + psCBuf->asVars[i].Name, + &psCBuf->asVars[i].sType, 0); + } + + if(useGlobalsStruct) + { + bcatcstr(glsl, "} "); + + TranslateOperand(psContext, psOperand, TO_FLAG_DECLARATION_NAME); + + bcatcstr(glsl, ";\n"); +} +} + +char* GetSamplerType(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eDimension, + const uint32_t ui32RegisterNumber) +{ + ResourceBinding* psBinding = 0; + RESOURCE_RETURN_TYPE eType = RETURN_TYPE_UNORM; + int found; + found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + if(found) + { + eType = (RESOURCE_RETURN_TYPE)psBinding->ui32ReturnType; + } + switch(eDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isamplerBuffer"; + case RETURN_TYPE_UINT: + return "usamplerBuffer"; + default: + return "samplerBuffer"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler1D"; + case RETURN_TYPE_UINT: + return "usampler1D"; + default: + return "sampler1D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler2D"; + case RETURN_TYPE_UINT: + return "usampler2D"; + default: + return "sampler2D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler2DMS"; + case RETURN_TYPE_UINT: + return "usampler2DMS"; + default: + return "sampler2DMS"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler3D"; + case RETURN_TYPE_UINT: + return "usampler3D"; + default: + return "sampler3D"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBE: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isamplerCube"; + case RETURN_TYPE_UINT: + return "usamplerCube"; + default: + return "samplerCube"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler1DArray"; + case RETURN_TYPE_UINT: + return "usampler1DArray"; + default: + return "sampler1DArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler2DArray"; + case RETURN_TYPE_UINT: + return "usampler2DArray"; + default: + return "sampler2DArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isampler2DMSArray"; + case RETURN_TYPE_UINT: + return "usampler2DMSArray"; + default: + return "sampler2DMSArray"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + switch(eType) + { + case RETURN_TYPE_SINT: + return "isamplerCubeArray"; + case RETURN_TYPE_UINT: + return "usamplerCubeArray"; + default: + return "samplerCubeArray"; + } + break; + } + } + + return "sampler2D"; +} + +static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, uint32_t samplerCanDoShadowCmp) +{ + bstring glsl = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + uint32_t i; + + const char* samplerTypeName = GetSamplerType(psContext, + psDecl->value.eResourceDimension, + psDecl->asOperands[0].ui32RegisterNumber); + + if (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) + { + if(samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) + { + for (i = 0; i < psDecl->ui32SamplerUsedCount; i++) + { + bcatcstr(glsl, "uniform "); + bcatcstr(glsl, samplerTypeName); + bcatcstr(glsl, "Shadow "); + ConcatTextureSamplerName(glsl, &psShader->sInfo, psDecl->asOperands[0].ui32RegisterNumber, psDecl->ui32SamplerUsed[i], 1); + bcatcstr(glsl, ";\n"); + } + } + for (i = 0; i < psDecl->ui32SamplerUsedCount; i++) + { + bcatcstr(glsl, "uniform "); + bcatcstr(glsl, samplerTypeName); + bcatcstr(glsl, " "); + ConcatTextureSamplerName(glsl, &psShader->sInfo, psDecl->asOperands[0].ui32RegisterNumber, psDecl->ui32SamplerUsed[i], 0); + bcatcstr(glsl, ";\n"); + } + } + + if(samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) + { + //Create shadow and non-shadow sampler. + //HLSL does not have separate types for depth compare, just different functions. + + bcatcstr(glsl, "uniform "); + bcatcstr(glsl, samplerTypeName); + bcatcstr(glsl, "Shadow "); + ResourceName(glsl, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 1); + bcatcstr(glsl, ";\n"); + } + + bcatcstr(glsl, "uniform "); + bcatcstr(glsl, samplerTypeName); + bcatcstr(glsl, " "); + ResourceName(glsl, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 0); + bcatcstr(glsl, ";\n"); +} + +void TranslateDeclaration(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) +{ + bstring glsl = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + switch(psDecl->eOpcode) + { + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_PS_SGV: + { + const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; + switch(eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinInput(psContext, psDecl, "gl_Position"); + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_Layer"); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinInput(psContext, psDecl, "gl_ClipDistance"); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_ViewportIndex"); + break; + } + case NAME_INSTANCE_ID: + { + AddBuiltinInput(psContext, psDecl, "gl_InstanceID"); + break; + } + case NAME_IS_FRONT_FACE: + { + /* + Cast to int used because + if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. + Suggests no implicit conversion for bool<->int. + */ + + AddBuiltinInput(psContext, psDecl, "int(gl_FrontFacing)"); + break; + } + case NAME_SAMPLE_INDEX: + { + AddBuiltinInput(psContext, psDecl, "gl_SampleID"); + break; + } + case NAME_VERTEX_ID: + { + AddBuiltinInput(psContext, psDecl, "gl_VertexID"); + break; + } + case NAME_PRIMITIVE_ID: + { + AddBuiltinInput(psContext, psDecl, "gl_PrimitiveID"); + break; + } + default: + { + bformata(glsl, "in vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); + break; + } + } + break; + } + + case OPCODE_DCL_OUTPUT_SIV: + { + switch(psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_Position"); + break; + } + case NAME_RENDER_TARGET_ARRAY_INDEX: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_Layer"); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_ClipDistance"); + break; + } + case NAME_VIEWPORT_ARRAY_INDEX: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_ViewportIndex"); + break; + } + case NAME_VERTEX_ID: + { + ASSERT(0); //VertexID is not an output + break; + } + case NAME_PRIMITIVE_ID: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_INT, 0, "gl_PrimitiveID"); + break; + } + case NAME_INSTANCE_ID: + { + ASSERT(0); //InstanceID is not an output + break; + } + case NAME_IS_FRONT_FACE: + { + ASSERT(0); //FrontFacing is not an output + break; + } + case NAME_FINAL_QUAD_U_EQ_0_EDGE_TESSFACTOR: + { + if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 4, "gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_QUAD_V_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_QUAD_U_EQ_1_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); + break; + } + case NAME_FINAL_QUAD_V_EQ_1_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[3]"); + break; + } + case NAME_FINAL_TRI_U_EQ_0_EDGE_TESSFACTOR: + { + if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 3,"gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_TRI_V_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_TRI_W_EQ_0_EDGE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[2]"); + break; + } + case NAME_FINAL_LINE_DENSITY_TESSFACTOR: + { + if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelOuter"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[0]"); + } + break; + } + case NAME_FINAL_LINE_DETAIL_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelOuter[1]"); + break; + } + case NAME_FINAL_TRI_INSIDE_TESSFACTOR: + case NAME_FINAL_QUAD_U_INSIDE_TESSFACTOR: + { + if(psContext->psShader->aIndexedOutput[psDecl->asOperands[0].ui32RegisterNumber]) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 2, "gl_TessLevelInner"); + } + else + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[0]"); + } + break; + } + case NAME_FINAL_QUAD_V_INSIDE_TESSFACTOR: + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT, 0, "gl_TessLevelInner[1]"); + break; + } + default: + { + bformata(glsl, "out vec4 %s;\n", psDecl->asOperands[0].pszSpecialName); + + bcatcstr(glsl, "#define "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, " %s\n", psDecl->asOperands[0].pszSpecialName); + break; + } + } + break; + } + case OPCODE_DCL_INPUT: + { + const Operand* psOperand = &psDecl->asOperands[0]; + //Force the number of components to be 4. +/*dcl_output o3.xy + dcl_output o3.z + +Would generate a vec2 and a vec3. We discard the second one making .z invalid! + +*/ + int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); + const char* StorageQualifier = "attribute"; + const char* InputName; + const char* Precision = ""; + + if((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT)|| + (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID)|| + (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK)|| + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID)|| + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID)|| + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP)|| + (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED) || + (psOperand->eType == OPERAND_TYPE_INPUT_FORK_INSTANCE_ID)) + { + break; + } + + //Already declared as part of an array. + if(psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + break; + } + + InputName = GetDeclaredInputName(psContext, psShader->eShaderType, psOperand); + + if(InOutSupported(psContext->psShader->eTargetLanguage)) + { + StorageQualifier = "in"; + } + + if(HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch(psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + break; + } + } + } + + DeclareInput(psContext, psDecl, + "", StorageQualifier, Precision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); + + break; + } + case OPCODE_DCL_INPUT_PS_SIV: + { + switch(psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinInput(psContext, psDecl, "gl_FragCoord"); + break; + } + } + break; + } + case OPCODE_DCL_INPUT_SIV: + { + break; + } + case OPCODE_DCL_INPUT_PS: + { + const Operand* psOperand = &psDecl->asOperands[0]; + int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); + const char* StorageQualifier = "varying"; + const char* Precision = ""; + const char* InputName = GetDeclaredInputName(psContext, PIXEL_SHADER, psOperand); + const char* Interpolation = ""; + + if(InOutSupported(psContext->psShader->eTargetLanguage)) + { + StorageQualifier = "in"; + } + + switch(psDecl->value.eInterpolation) + { + case INTERPOLATION_CONSTANT: + { + Interpolation = "flat"; + break; + } + case INTERPOLATION_LINEAR: + { + break; + } + case INTERPOLATION_LINEAR_CENTROID: + { + Interpolation = "centroid"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE: + { + Interpolation = "noperspective"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: + { + Interpolation = "noperspective centroid"; + break; + } + case INTERPOLATION_LINEAR_SAMPLE: + { + Interpolation = "sample"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: + { + Interpolation = "noperspective sample"; + break; + } + } + + if(HavePrecisionQualifers(psShader->eTargetLanguage)) + { + switch(psOperand->eMinPrecision) + { + case OPERAND_MIN_PRECISION_DEFAULT: + { + Precision = "highp"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_FLOAT_2_8: + { + Precision = "lowp"; + break; + } + case OPERAND_MIN_PRECISION_SINT_16: + { + Precision = "mediump"; + break; + } + case OPERAND_MIN_PRECISION_UINT_16: + { + Precision = "mediump"; + break; + } + } + } + + DeclareInput(psContext, psDecl, + Interpolation, StorageQualifier, Precision, iNumComponents, INDEX_1D, InputName); + + break; + } + case OPCODE_DCL_TEMPS: + { + const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; + + if(ui32NumTemps > 0) + { + bformata(glsl, "vec4 Temp[%d];\n", ui32NumTemps); + + bformata(glsl, "ivec4 Temp_int[%d];\n", ui32NumTemps); + if(HaveUVec(psShader->eTargetLanguage)) + { + bformata(glsl, "uvec4 Temp_uint[%d];\n", ui32NumTemps); + } + if(psShader->fp64) + { + bformata(glsl, "dvec4 Temp_double[%d];\n", ui32NumTemps); + } + } + + break; + } + case OPCODE_SPECIAL_DCL_IMMCONST: + { + const Operand* psDest = &psDecl->asOperands[0]; + const Operand* psSrc = &psDecl->asOperands[1]; + + ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); + if(psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) + { + bformata(glsl, "const ivec4 IntImmConst%d = ", psDest->ui32RegisterNumber); + } + else + { + bformata(glsl, "const vec4 ImmConst%d = ", psDest->ui32RegisterNumber); + AddToDx9ImmConstIndexableArray(psContext, psDest); + } + TranslateOperand(psContext, psSrc, psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT ? TO_FLAG_INTEGER : TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(glsl, ";\n"); + + break; + } + case OPCODE_DCL_CONSTANT_BUFFER: + { + const Operand* psOperand = &psDecl->asOperands[0]; + const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; + + const char* StageName = "VS"; + + switch(psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + StageName = "PS"; + break; + } + case HULL_SHADER: + { + StageName = "HS"; + break; + } + case DOMAIN_SHADER: + { + StageName = "DS"; + break; + } + case GEOMETRY_SHADER: + { + StageName = "GS"; + break; + } + case COMPUTE_SHADER: + { + StageName = "CS"; + break; + } + default: + { + break; + } + } + + ConstantBuffer* psCBuf = NULL; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + if (psCBuf) + { + // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. + // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads + // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. + psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; + } + + // We don't have a original resource name, maybe generate one??? + if(!psCBuf) + { + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + bformata(glsl, "layout(location = %d) ",ui32BindingPoint); + + bformata(glsl, "layout(std140) uniform ConstantBuffer%d {\n\tvec4 data[%d];\n} cb%d;\n", ui32BindingPoint,psOperand->aui32ArraySizes[1],ui32BindingPoint); + break; + } + else if (psCBuf->blob) + { + bformata(glsl, "layout(std140) uniform %s%s {\n\tvec4 %s%s_data[%d];\n};\n", psCBuf->Name, StageName, psCBuf->Name, StageName, psOperand->aui32ArraySizes[1]); + break; + } + + if(psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) + { + if(psContext->flags & HLSLCC_FLAG_GLOBAL_CONSTS_NEVER_IN_UBO && psCBuf->Name[0] == '$') + { + DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand, glsl); + } + else + { + DeclareUBOConstants(psContext, ui32BindingPoint, psCBuf, glsl); + } + } + else + { + DeclareStructConstants(psContext, ui32BindingPoint, psCBuf, psOperand, glsl); + } + break; + } + case OPCODE_DCL_RESOURCE: + { + if (HaveUniformBindingsAndLocations(psContext->psShader->eTargetLanguage, psContext->psShader->extensions, psContext->flags)) + { + // Explicit layout bindings are not currently compatible with combined texture samplers. The layout below assumes there is exactly one GLSL sampler + // for each HLSL texture declaration, but when combining textures+samplers, there can be multiple OGL samplers for each HLSL texture declaration. + if((psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) != HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) + { + //Constant buffer locations start at 0. Resource locations start at ui32NumConstantBuffers. + bformata(glsl, "layout(location = %d) ", + psContext->psShader->sInfo.ui32NumConstantBuffers + psDecl->asOperands[0].ui32RegisterNumber); + } + } + + switch(psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + bformata(glsl, "uniform %s ", GetSamplerType(psContext, + RESOURCE_DIMENSION_BUFFER, + psDecl->asOperands[0].ui32RegisterNumber)); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + break; + } + case RESOURCE_DIMENSION_TEXTURE1D: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + TranslateResourceTexture(psContext, psDecl, 0); + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + TranslateResourceTexture(psContext, psDecl, 0); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + TranslateResourceTexture(psContext, psDecl, 0); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + } + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); + psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; + break; + } + case OPCODE_DCL_OUTPUT: + { + if(psShader->eShaderType == HULL_SHADER && psDecl->asOperands[0].ui32RegisterNumber==0) + { + AddBuiltinOutput(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "gl_out[gl_InvocationID].gl_Position"); + } + else + { + AddUserOutput(psContext, psDecl); + } + break; + } + case OPCODE_DCL_GLOBAL_FLAGS: + { + uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; + + if(ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL) + { + bcatcstr(glsl, "layout(early_fragment_tests) in;\n"); + } + if(!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) + { + //TODO add precise + //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx + } + if(ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) + { + bcatcstr(glsl, "#extension GL_ARB_gpu_shader_fp64 : enable\n"); + psShader->fp64 = 1; + } + break; + } + + case OPCODE_DCL_THREAD_GROUP: + { + bformata(glsl, "layout(local_size_x = %d, local_size_y = %d, local_size_z = %d) in;\n", + psDecl->value.aui32WorkGroupSize[0], + psDecl->value.aui32WorkGroupSize[1], + psDecl->value.aui32WorkGroupSize[2]); + break; + } + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + { + if(psContext->psShader->eShaderType == HULL_SHADER) + { + psContext->psShader->sInfo.eTessOutPrim = psDecl->value.eTessOutPrim; + } + break; + } + case OPCODE_DCL_TESS_DOMAIN: + { + if(psContext->psShader->eShaderType == DOMAIN_SHADER) + { + switch(psDecl->value.eTessDomain) + { + case TESSELLATOR_DOMAIN_ISOLINE: + { + bcatcstr(glsl, "layout(isolines) in;\n"); + break; + } + case TESSELLATOR_DOMAIN_TRI: + { + bcatcstr(glsl, "layout(triangles) in;\n"); + break; + } + case TESSELLATOR_DOMAIN_QUAD: + { + bcatcstr(glsl, "layout(quads) in;\n"); + break; + } + default: + { + break; + } + } + } + break; + } + case OPCODE_DCL_TESS_PARTITIONING: + { + if(psContext->psShader->eShaderType == HULL_SHADER) + { + psContext->psShader->sInfo.eTessPartitioning = psDecl->value.eTessPartitioning; + } + break; + } + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + { + switch(psDecl->value.eOutputPrimitiveTopology) + { + case PRIMITIVE_TOPOLOGY_POINTLIST: + { + bcatcstr(glsl, "layout(points) out;\n"); + break; + } + case PRIMITIVE_TOPOLOGY_LINELIST_ADJ: + case PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ: + case PRIMITIVE_TOPOLOGY_LINELIST: + case PRIMITIVE_TOPOLOGY_LINESTRIP: + { + bcatcstr(glsl, "layout(line_strip) out;\n"); + break; + } + + case PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ: + case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ: + case PRIMITIVE_TOPOLOGY_TRIANGLESTRIP: + case PRIMITIVE_TOPOLOGY_TRIANGLELIST: + { + bcatcstr(glsl, "layout(triangle_strip) out;\n"); + break; + } + default: + { + break; + } + } + break; + } + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + bformata(glsl, "layout(max_vertices = %d) out;\n", psDecl->value.ui32MaxOutputVertexCount); + break; + } + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + { + switch(psDecl->value.eInputPrimitive) + { + case PRIMITIVE_POINT: + { + bcatcstr(glsl, "layout(points) in;\n"); + break; + } + case PRIMITIVE_LINE: + { + bcatcstr(glsl, "layout(lines) in;\n"); + break; + } + case PRIMITIVE_LINE_ADJ: + { + bcatcstr(glsl, "layout(lines_adjacency) in;\n"); + break; + } + case PRIMITIVE_TRIANGLE: + { + bcatcstr(glsl, "layout(triangles) in;\n"); + break; + } + case PRIMITIVE_TRIANGLE_ADJ: + { + bcatcstr(glsl, "layout(triangles_adjacency) in;\n"); + break; + } + default: + { + break; + } + } + break; + } + case OPCODE_DCL_INTERFACE: + { + const uint32_t interfaceID = psDecl->value.interface.ui32InterfaceID; + const uint32_t numUniforms = psDecl->value.interface.ui32ArraySize; + const uint32_t ui32NumBodiesPerTable = psContext->psShader->funcPointer[interfaceID].ui32NumBodiesPerTable; + ShaderVar* psVar; + uint32_t varFound; + + const char* uniformName; + + varFound = GetInterfaceVarFromOffset(interfaceID, &psContext->psShader->sInfo, &psVar); + ASSERT(varFound); + uniformName = &psVar->Name[0]; + + bformata(glsl, "subroutine uniform SubroutineType %s[%d*%d];\n", uniformName, numUniforms, ui32NumBodiesPerTable); + break; + } + case OPCODE_DCL_FUNCTION_BODY: + { + //bformata(glsl, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); + break; + } + case OPCODE_DCL_FUNCTION_TABLE: + { + break; + } + case OPCODE_CUSTOMDATA: + { + const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; + const uint32_t ui32NumVec4Minus1 = (ui32NumVec4-1); + uint32_t ui32ConstIndex = 0; + float x, y, z, w; + + //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. + //else 2 buffers - one integer and one float. - More data + + if(ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) + { + bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(glsl, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); + + bformata(glsl, "vec4 immediateConstBuffer[%d] = vec4[%d] (\n", ui32NumVec4, ui32NumVec4); + for(;ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) + { + float loopLocalX, loopLocalY, loopLocalZ, loopLocalW; + loopLocalX = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + loopLocalY = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + loopLocalZ = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + loopLocalW = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + + //A single vec4 can mix integer and float types. + //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. + if(fpcheck(loopLocalX)) + { + loopLocalX = 0; + } + if(fpcheck(loopLocalY)) + { + loopLocalY = 0; + } + if(fpcheck(loopLocalZ)) + { + loopLocalZ = 0; + } + if(fpcheck(loopLocalW)) + { + loopLocalW = 0; + } + + bformata(glsl, "\tvec4(%f, %f, %f, %f), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); + } + //No trailing comma on this one + x = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + y = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + z = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + w = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + if(fpcheck(x)) + { + x = 0; + } + if(fpcheck(y)) + { + y = 0; + } + if(fpcheck(z)) + { + z = 0; + } + if(fpcheck(w)) + { + w = 0; + } + bformata(glsl, "\tvec4(%f, %f, %f, %f)\n", x, y, z, w); + bcatcstr(glsl, ");\n"); + } + else + { + bcatcstr(glsl, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(glsl, "#define immediateConstBufferF(idx) intBitsToFloat(immediateConstBufferInt[idx])\n"); + } + + { + uint32_t ui32ConstIndex2 = 0; + int x2, y2, z2, w2; + + bformata(glsl, "ivec4 immediateConstBufferInt[%d] = ivec4[%d] (\n", ui32NumVec4, ui32NumVec4); + for (; ui32ConstIndex2 < ui32NumVec4Minus1; ui32ConstIndex2++) + { + int loopLocalX, loopLocalY, loopLocalZ, loopLocalW; + loopLocalX = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; + loopLocalY = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; + loopLocalZ = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; + loopLocalW = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; + + bformata(glsl, "\tivec4(%d, %d, %d, %d), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); + } + //No trailing comma on this one + x2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; + y2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; + z2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; + w2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; + + bformata(glsl, "\tivec4(%d, %d, %d, %d)\n", x2, y2, z2, w2); + bcatcstr(glsl, ");\n"); + } + + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + const uint32_t forkPhaseNum = psDecl->value.aui32HullPhaseInstanceInfo[0]; + const uint32_t instanceCount = psDecl->value.aui32HullPhaseInstanceInfo[1]; + bformata(glsl, "const int HullPhase%dInstanceCount = %d;\n", forkPhaseNum, instanceCount); + break; + } + case OPCODE_DCL_INDEXABLE_TEMP: + { + const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; + const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; + const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; + bformata(glsl, "vec%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + bformata(glsl, "ivec%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + if(HaveUVec(psShader->eTargetLanguage)) + { + bformata(glsl, "uvec%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + } + if(psShader->fp64) + { + bformata(glsl, "dvec%d TempArray%d_double[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + } + break; + } + case OPCODE_DCL_INDEX_RANGE: + { + break; + } + case OPCODE_HS_DECLS: + { + break; + } + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + { + if(psContext->psShader->eShaderType == HULL_SHADER) + { + bformata(glsl, "layout(vertices=%d) out;\n", psDecl->value.ui32MaxOutputVertexCount); + } + break; + } + case OPCODE_HS_FORK_PHASE: + { + break; + } + case OPCODE_HS_JOIN_PHASE: + { + break; + } + case OPCODE_DCL_SAMPLER: + { + break; + } + case OPCODE_DCL_HS_MAX_TESSFACTOR: + { + //For GLSL the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + { + // non-float images need either 'i' or 'u' prefix. + char imageTypePrefix[2] = { 0, 0 }; + if(psDecl->sUAV.ui32GloballyCoherentAccess & GLOBALLY_COHERENT_ACCESS) + { + bcatcstr(glsl, "coherent "); + } + + if(psShader->aiOpcodeUsed[OPCODE_LD_UAV_TYPED] == 0) + { + bcatcstr(glsl, "writeonly "); + } + else + { + if(psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) + { + bcatcstr(glsl, "readonly "); + } + + switch(psDecl->sUAV.Type) + { + case RETURN_TYPE_FLOAT: + bcatcstr(glsl, "layout(rgba32f) "); + break; + case RETURN_TYPE_UNORM: + bcatcstr(glsl, "layout(rgba8) "); + break; + case RETURN_TYPE_SNORM: + bcatcstr(glsl, "layout(rgba8_snorm) "); + break; + case RETURN_TYPE_UINT: + bcatcstr(glsl, "layout(rgba32ui) "); + imageTypePrefix[0] = 'u'; + break; + case RETURN_TYPE_SINT: + bcatcstr(glsl, "layout(rgba32i) "); + imageTypePrefix[0] = 'i'; + break; + default: + ASSERT(0); + } + } + + switch(psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + bformata(glsl, "uniform %simageBuffer ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE1D: + { + bformata(glsl, "uniform %simage1D ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + bformata(glsl, "uniform %simage2D ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + bformata(glsl, "uniform %simage2DMS ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + bformata(glsl, "uniform %simage3D ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + bformata(glsl, "uniform %simageCube ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + bformata(glsl, "uniform %simage1DArray ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + bformata(glsl, "uniform %simage2DArray ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + bformata(glsl, "uniform %simage3DArray ", imageTypePrefix); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + bformata(glsl, "uniform %simageCubeArray ", imageTypePrefix); + break; + } + } + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + { + const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; + ConstantBuffer* psCBuf = NULL; + + if(psDecl->sUAV.bCounter) + { + bformata(glsl, "layout (binding = 1) uniform atomic_uint "); + ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(glsl, "_counter; \n"); + } + + GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + DeclareBufferVariable(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], + psDecl->sUAV.ui32GloballyCoherentAccess, RTYPE_UAV_RWSTRUCTURED, glsl); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + { + if(psDecl->sUAV.bCounter) + { + bformata(glsl, "layout (binding = 1) uniform atomic_uint "); + ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(glsl, "_counter; \n"); + } + + bformata(glsl, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); + ResourceName(glsl, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bcatcstr(glsl, "[];\n};\n"); + + break; + } + case OPCODE_DCL_RESOURCE_STRUCTURED: + { + ConstantBuffer* psCBuf = NULL; + + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + DeclareBufferVariable(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], + 0, RTYPE_STRUCTURED, glsl); + break; + } + case OPCODE_DCL_RESOURCE_RAW: + { + bformata(glsl, "buffer Block%d {\n\tuint RawRes%d[];\n};\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + { + ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); + + bcatcstr(glsl, "shared struct {\n"); + bformata(glsl, "uint value[%d];\n", psDecl->sTGSM.ui32Stride/4); + bcatcstr(glsl, "} "); + TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(glsl, "[%d];\n", + psDecl->sTGSM.ui32Count); + + memset(psVarType, 0, sizeof(ShaderVarType)); + strcpy(psVarType->Name, "$Element"); + + psVarType->Columns = psDecl->sTGSM.ui32Stride/4; + psVarType->Elements = psDecl->sTGSM.ui32Count; + break; + } + case OPCODE_DCL_STREAM: + { + ASSERT(psDecl->asOperands[0].eType == OPERAND_TYPE_STREAM); + + psShader->ui32CurrentVertexOutputStream = psDecl->asOperands[0].ui32RegisterNumber; + + bformata(glsl, "layout(stream = %d) out;\n", psShader->ui32CurrentVertexOutputStream); + + break; + } + case OPCODE_DCL_GS_INSTANCE_COUNT: + { + bformata(glsl, "layout(invocations = %d) in;\n", psDecl->value.ui32GSInstanceCount); + break; + } + default: + { + ASSERT(0); + break; + } + } +} + +//Convert from per-phase temps to global temps for GLSL. +void ConsolidateHullTempVars(ShaderData* psShader) +{ + uint32_t i, k; + uint32_t ui32Phase, ui32Instance; + const uint32_t ui32NumDeclLists = psShader->asPhase[HS_FORK_PHASE].ui32InstanceCount + + psShader->asPhase[HS_CTRL_POINT_PHASE].ui32InstanceCount + + psShader->asPhase[HS_JOIN_PHASE].ui32InstanceCount + + psShader->asPhase[HS_GLOBAL_DECL].ui32InstanceCount; + + Declaration** pasDeclArray = hlslcc_malloc(sizeof(Declaration*) * ui32NumDeclLists); + + uint32_t* pui32DeclCounts = hlslcc_malloc(sizeof(uint32_t) * ui32NumDeclLists); + uint32_t ui32NumTemps = 0; + + i=0; + for(ui32Phase = HS_GLOBAL_DECL; ui32Phase < NUM_PHASES; ui32Phase++) + { + for(ui32Instance = 0; ui32Instance < psShader->asPhase[ui32Phase].ui32InstanceCount; ++ui32Instance) + { + pasDeclArray[i] = psShader->asPhase[ui32Phase].ppsDecl[ui32Instance]; + pui32DeclCounts[i++] = psShader->asPhase[ui32Phase].pui32DeclCount[ui32Instance]; + } + } + + for(k = 0; k < ui32NumDeclLists; ++k) + { + for(i=0; i < pui32DeclCounts[k]; ++i) + { + Declaration* psDecl = pasDeclArray[k]+i; + + if(psDecl->eOpcode == OPCODE_DCL_TEMPS) + { + if(ui32NumTemps < psDecl->value.ui32NumTemps) + { + //Find the total max number of temps needed by the entire + //shader. + ui32NumTemps = psDecl->value.ui32NumTemps; + } + //Only want one global temp declaration. + psDecl->value.ui32NumTemps = 0; + } + } + } + + //Find the first temp declaration and make it + //declare the max needed amount of temps. + for(k = 0; k < ui32NumDeclLists; ++k) + { + for(i=0; i < pui32DeclCounts[k]; ++i) + { + Declaration* psDecl = pasDeclArray[k]+i; + + if(psDecl->eOpcode == OPCODE_DCL_TEMPS) + { + psDecl->value.ui32NumTemps = ui32NumTemps; + return; + } + } + } + + hlslcc_free(pasDeclArray); + hlslcc_free(pui32DeclCounts); +} + diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c new file mode 100644 index 0000000000..cb72838092 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLInstruction.c @@ -0,0 +1,4576 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toGLSLInstruction.h" +#include <stdlib.h> +#include "bstrlib.h" +#include "hlslcc.h" +#include "internal_includes/debug.h" +#include "internal_includes/languages.h" +#include "internal_includes/toGLSLOperand.h" +#include "stdio.h" + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); +static int GLSLIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode); + +// Calculate the bits set in mask +static int GLSLWriteMaskToComponentCount(uint32_t writeMask) +{ + uint32_t count; + // In HLSL bytecode writemask 0 also means everything + if (writeMask == 0) + return 4; + + // Count bits set + // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 + count = (writeMask * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; + + return (int)count; +} + +static uint32_t GLSLBuildComponentMaskFromElementCount(int count) +{ + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + return (1 << count) - 1; +} + +// This function prints out the destination name, possible destination writemask, assignment operator +// and any possible conversions needed based on the eSrcType+ui32SrcElementCount (type and size of data expected to be coming in) +// As an output, pNeedsParenthesis will be filled with the amount of closing parenthesis needed +// and pSrcCount will be filled with the number of components expected +// ui32CompMask can be used to only write to 1 or more components (used by MOVC) +static void GLSLAddOpAssignToDestWithMask(HLSLCrossCompilerContext* psContext, + const Operand* psDest, + SHADER_VARIABLE_TYPE eSrcType, + uint32_t ui32SrcElementCount, + const char* szAssignmentOp, + int* pNeedsParenthesis, + uint32_t ui32CompMask) +{ + uint32_t ui32DestElementCount = GetNumSwizzleElementsWithMask(psDest, ui32CompMask); + bstring glsl = *psContext->currentShaderString; + SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataType(psContext, psDest); + ASSERT(pNeedsParenthesis != NULL); + + *pNeedsParenthesis = 0; + + TranslateOperandWithMask(psContext, psDest, TO_FLAG_DESTINATION, ui32CompMask); + + // Simple path: types match. + if (eDestDataType == eSrcType) + { + // Cover cases where the HLSL language expects the rest of the components to be default-filled + // eg. MOV r0, c0.x => Temp[0] = vec4(c0.x); + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); + *pNeedsParenthesis = 1; + } + else + bformata(glsl, " %s ", szAssignmentOp); + return; + } + + switch (eDestDataType) + { + case SVT_INT: + if (eSrcType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) + { + bformata(glsl, " %s floatBitsToInt(", szAssignmentOp); + // Cover cases where the HLSL language expects the rest of the components to be default-filled + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); + (*pNeedsParenthesis)++; + } + } + else + bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); + break; + case SVT_UINT: + if (eSrcType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) + { + bformata(glsl, " %s floatBitsToUint(", szAssignmentOp); + // Cover cases where the HLSL language expects the rest of the components to be default-filled + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); + (*pNeedsParenthesis)++; + } + } + else + bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); + break; + + case SVT_FLOAT: + if (psContext->psShader->ui32MajorVersion > 3) + { + if (eSrcType == SVT_INT) + bformata(glsl, " %s intBitsToFloat(", szAssignmentOp); + else + bformata(glsl, " %s uintBitsToFloat(", szAssignmentOp); + // Cover cases where the HLSL language expects the rest of the components to be default-filled + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(glsl, "%s(", GetConstructorForType(eSrcType, ui32DestElementCount)); + (*pNeedsParenthesis)++; + } + } + else + bformata(glsl, " %s %s(", szAssignmentOp, GetConstructorForType(eDestDataType, ui32DestElementCount)); + break; + default: + // TODO: Handle bools? + break; + } + (*pNeedsParenthesis)++; + return; +} + +static void GLSLMETALAddAssignToDest(HLSLCrossCompilerContext* psContext, + const Operand* psDest, + SHADER_VARIABLE_TYPE eSrcType, + uint32_t ui32SrcElementCount, + int* pNeedsParenthesis) +{ + GLSLAddOpAssignToDestWithMask(psContext, psDest, eSrcType, ui32SrcElementCount, "=", pNeedsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); +} + +static void GLSLAddAssignPrologue(HLSLCrossCompilerContext* psContext, int numParenthesis) +{ + bstring glsl = *psContext->currentShaderString; + while (numParenthesis != 0) + { + bcatcstr(glsl, ")"); + numParenthesis--; + } + bcatcstr(glsl, ";\n"); +} +static uint32_t GLSLResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType) +{ + if (eType == RETURN_TYPE_SINT) + { + return TO_FLAG_INTEGER; + } + else if (eType == RETURN_TYPE_UINT) + { + return TO_FLAG_UNSIGNED_INTEGER; + } + else + { + return TO_FLAG_NONE; + } +} + +typedef enum +{ + GLSL_CMP_EQ, + GLSL_CMP_LT, + GLSL_CMP_GE, + GLSL_CMP_NE, +} GLSLComparisonType; + +static void GLSLAddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, GLSLComparisonType eType, uint32_t typeFlag, Instruction* psNextInst) +{ + // Multiple cases to consider here: + // For shader model <=3: all comparisons are floats + // otherwise: + // OPCODE_LT, _GT, _NE etc: inputs are floats, outputs UINT 0xffffffff or 0. typeflag: TO_FLAG_NONE + // OPCODE_ILT, _IGT etc: comparisons are signed ints, outputs UINT 0xffffffff or 0 typeflag TO_FLAG_INTEGER + // _ULT, UGT etc: inputs unsigned ints, outputs UINTs typeflag TO_FLAG_UNSIGNED_INTEGER + // + // Additional complexity: if dest swizzle element count is 1, we can use normal comparison operators, otherwise glsl intrinsics. + + bstring glsl = *psContext->currentShaderString; + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + const uint32_t s1ElemCount = GetNumSwizzleElements(&psInst->asOperands[2]); + + int floatResult = 0; + int needsParenthesis = 0; + + ASSERT(s0ElemCount == s1ElemCount || s1ElemCount == 1 || s0ElemCount == 1); + if (s0ElemCount != s1ElemCount) + { + // Set the proper auto-expand flag is either argument is scalar + typeFlag |= (TO_AUTO_EXPAND_TO_VEC2 << (max(s0ElemCount, s1ElemCount) - 2)); + } + + if (psContext->psShader->ui32MajorVersion < 4) + { + floatResult = 1; + } + + if (destElemCount > 1) + { + const char* glslOpcode[] = { + "equal", + "lessThan", + "greaterThanEqual", + "notEqual", + }; + + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], floatResult ? SVT_FLOAT : SVT_UINT, destElemCount, &needsParenthesis); + + bcatcstr(glsl, GetConstructorForType(floatResult ? SVT_FLOAT : SVT_UINT, destElemCount)); + bformata(glsl, "(%s(", glslOpcode[eType]); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(glsl, "))"); + if (!floatResult) + { + bcatcstr(glsl, " * 0xFFFFFFFFu"); + } + + GLSLAddAssignPrologue(psContext, needsParenthesis); + } + else + { + const char* glslOpcode[] = { + "==", + "<", + ">=", + "!=", + }; + + // Scalar compare + + // Optimization shortcut for the IGE+BREAKC_NZ combo: + // First print out the if(cond)->break directly, and then + // to guarantee correctness with side-effects, re-run + // the actual comparison. In most cases, the second run will + // be removed by the shader compiler optimizer pass (dead code elimination) + // This also makes it easier for some GLSL optimizers to recognize the for loop. + + if (psInst->eOpcode == OPCODE_IGE && psNextInst && psNextInst->eOpcode == OPCODE_BREAKC && + (psInst->asOperands[0].ui32RegisterNumber == psNextInst->asOperands[0].ui32RegisterNumber)) + { + AddIndentation(psContext); + bcatcstr(glsl, "// IGE+BREAKC opt\n"); + AddIndentation(psContext); + + if (psNextInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO) + bcatcstr(glsl, "if (("); + else + bcatcstr(glsl, "if (!("); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bformata(glsl, "%s ", glslOpcode[eType]); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(glsl, ")) { break; }\n"); + + // Mark the BREAKC instruction as already handled + psNextInst->eOpcode = OPCODE_NOP; + + // Continue as usual + } + + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], floatResult ? SVT_FLOAT : SVT_UINT, destElemCount, &needsParenthesis); + + bcatcstr(glsl, "("); + TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + bformata(glsl, "%s", glslOpcode[eType]); + TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + if (floatResult) + { + bcatcstr(glsl, ") ? 1.0 : 0.0"); + } + else + { + bcatcstr(glsl, ") ? 0xFFFFFFFFu : 0u"); + } + GLSLAddAssignPrologue(psContext, needsParenthesis); + } +} + +static void GLSLAddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, Operand* pSrc) +{ + int numParenthesis = 0; + int srcSwizzleCount = GetNumSwizzleElements(pSrc); + uint32_t writeMask = GetOperandWriteMask(pDest); + + const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataTypeEx(psContext, pSrc, GetOperandDataType(psContext, pDest)); + uint32_t flags = SVTTypeToFlag(eSrcType); + + GLSLMETALAddAssignToDest(psContext, pDest, eSrcType, srcSwizzleCount, &numParenthesis); + TranslateOperandWithMask(psContext, pSrc, flags, writeMask); + + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static uint32_t GLSLElemCountToAutoExpandFlag(uint32_t elemCount) +{ + return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2); +} + +static void GLSLAddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, const Operand* src0, Operand* src1, Operand* src2) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t destElemCount = GetNumSwizzleElements(pDest); + uint32_t s0ElemCount = GetNumSwizzleElements(src0); + uint32_t s1ElemCount = GetNumSwizzleElements(src1); + uint32_t s2ElemCount = GetNumSwizzleElements(src2); + uint32_t destWriteMask = GetOperandWriteMask(pDest); + uint32_t destElem; + + const SHADER_VARIABLE_TYPE eDestType = GetOperandDataType(psContext, pDest); + /* + for each component in dest[.mask] + if the corresponding component in src0 (POS-swizzle) + has any bit set + { + copy this component (POS-swizzle) from src1 into dest + } + else + { + copy this component (POS-swizzle) from src2 into dest + } + endfor + */ + + /* Single-component conditional variable (src0) */ + if (s0ElemCount == 1 || IsSwizzleReplicated(src0)) + { + int numParenthesis = 0; + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); + bcatcstr(glsl, "("); + TranslateOperand(psContext, src0, TO_AUTO_BITCAST_TO_INT); + if (s0ElemCount > 1) + bcatcstr(glsl, ".x"); + if (psContext->psShader->ui32MajorVersion < 4) + { + // cmp opcode uses >= 0 + bcatcstr(glsl, " >= 0) ? "); + } + else + { + bcatcstr(glsl, " != 0) ? "); + } + + if (s1ElemCount == 1 && destElemCount > 1) + TranslateOperand(psContext, src1, SVTTypeToFlag(eDestType) | GLSLElemCountToAutoExpandFlag(destElemCount)); + else + TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), destWriteMask); + + bcatcstr(glsl, " : "); + if (s2ElemCount == 1 && destElemCount > 1) + TranslateOperand(psContext, src2, SVTTypeToFlag(eDestType) | GLSLElemCountToAutoExpandFlag(destElemCount)); + else + TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), destWriteMask); + + GLSLAddAssignPrologue(psContext, numParenthesis); + } + else + { + // TODO: We can actually do this in one op using mix(). + int srcElem = 0; + for (destElem = 0; destElem < 4; ++destElem) + { + int numParenthesis = 0; + if (pDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && pDest->ui32CompMask != 0 && !(pDest->ui32CompMask & (1 << destElem))) + continue; + + AddIndentation(psContext); + GLSLAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); + bcatcstr(glsl, "("); + TranslateOperandWithMask(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << srcElem); + if (psContext->psShader->ui32MajorVersion < 4) + { + // cmp opcode uses >= 0 + bcatcstr(glsl, " >= 0) ? "); + } + else + { + bcatcstr(glsl, " != 0) ? "); + } + + TranslateOperandWithMask(psContext, src1, SVTTypeToFlag(eDestType), 1 << srcElem); + bcatcstr(glsl, " : "); + TranslateOperandWithMask(psContext, src2, SVTTypeToFlag(eDestType), 1 << srcElem); + + GLSLAddAssignPrologue(psContext, numParenthesis); + + srcElem++; + } + } +} + +// Returns nonzero if operands are identical, only cares about temp registers currently. +static int GLSLAreTempOperandsIdentical(const Operand* psA, const Operand* psB) +{ + if (!psA || !psB) + return 0; + + if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP) + return 0; + + if (psA->eModifier != psB->eModifier) + return 0; + + if (psA->iNumComponents != psB->iNumComponents) + return 0; + + if (psA->ui32RegisterNumber != psB->ui32RegisterNumber) + return 0; + + if (psA->eSelMode != psB->eSelMode) + return 0; + + if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask) + return 0; + + if (psA->eSelMode != OPERAND_4_COMPONENT_MASK_MODE && psA->ui32Swizzle != psB->ui32Swizzle) + return 0; + + return 1; +} + +// Returns nonzero if the operation is commutative +static int GLSLIsOperationCommutative(OPCODE_TYPE eOpCode) +{ + switch (eOpCode) + { + case OPCODE_DADD: + case OPCODE_IADD: + case OPCODE_ADD: + case OPCODE_MUL: + case OPCODE_IMUL: + case OPCODE_OR: + case OPCODE_AND: + return 1; + default: + return 0; + }; +} + +static void +GLSLCallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t src1SwizCount = GetNumSwizzleElements(&psInst->asOperands[src1]); + uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = GetOperandWriteMask(&psInst->asOperands[dest]); + int needsParenthesis = 0; + + AddIndentation(psContext); + + if (src1SwizCount == src0SwizCount == dstSwizCount) + { + // Optimization for readability (and to make for loops in WebGL happy): detect cases where either src == dest and emit +=, -= etc. instead. + if (GLSLAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src0]) != 0) + { + GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); + TranslateOperand(psContext, &psInst->asOperands[src1], SVTTypeToFlag(eDataType)); + GLSLAddAssignPrologue(psContext, needsParenthesis); + return; + } + else if (GLSLAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src1]) != 0 && (GLSLIsOperationCommutative(psInst->eOpcode) != 0)) + { + GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); + TranslateOperand(psContext, &psInst->asOperands[src0], SVTTypeToFlag(eDataType)); + GLSLAddAssignPrologue(psContext, needsParenthesis); + return; + } + } + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, &needsParenthesis); + + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], SVTTypeToFlag(eDataType), destMask); + bformata(glsl, " %s ", name); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], SVTTypeToFlag(eDataType), destMask); + GLSLAddAssignPrologue(psContext, needsParenthesis); +} + +static void GLSLCallTernaryOp(HLSLCrossCompilerContext* psContext, + const char* op1, + const char* op2, + Instruction* psInst, + int dest, + int src0, + int src1, + int src2, + uint32_t dataType) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = GetOperandWriteMask(&psInst->asOperands[dest]); + + uint32_t ui32Flags = dataType; + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], TypeFlagsToSVTType(dataType), dstSwizCount, &numParenthesis); + + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bformata(glsl, " %s ", op1); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + bformata(glsl, " %s ", op2); + TranslateOperandWithMask(psContext, &psInst->asOperands[src2], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void GLSLCallHelper3(HLSLCrossCompilerContext* psContext, + const char* name, + Instruction* psInst, + int dest, + int src0, + int src1, + int src2, + int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; + bstring glsl = *psContext->currentShaderString; + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[src2], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void +GLSLCallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; + bstring glsl = *psContext->currentShaderString; + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + + int isDotProduct = (strncmp(name, "dot", 3) == 0) ? 1 : 0; + int numParenthesis = 0; + + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, isDotProduct ? 1 : dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void +GLSLCallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void +GLSLCallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_UINT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_UINT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void GLSLCallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, int dest, int src0, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +// Result is an int. +static void GLSLCallHelper1Int(HLSLCrossCompilerContext* psContext, + const char* name, + Instruction* psInst, + const int dest, + const int src0, + int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void GLSLTranslateTexelFetch(HLSLCrossCompilerContext* psContext, Instruction* psInst, ResourceBinding* psBinding, bstring glsl) +{ + int numParenthesis = 0; + uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(GLSLResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, + &numParenthesis); + bcatcstr(glsl, "texelFetch("); + + switch (psBinding->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + case REFLECT_RESOURCE_DIMENSION_BUFFER: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + if (psBinding->eDimension != REFLECT_RESOURCE_DIMENSION_BUFFER) + bcatcstr(glsl, ", 0"); // Buffers don't have LOD + bcatcstr(glsl, ")"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); + bcatcstr(glsl, ", 0)"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); + bcatcstr(glsl, ", 0)"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: // TODO does this make any sense at all? + { + ASSERT(psInst->eOpcode == OPCODE_LD_MS); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(glsl, ")"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + ASSERT(psInst->eOpcode == OPCODE_LD_MS); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[3], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(glsl, ")"); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + case REFLECT_RESOURCE_DIMENSION_BUFFEREX: + default: + { + ASSERT(0); + break; + } + } + + AddSwizzleUsingElementCount(psContext, destCount); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static void GLSLTranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, Instruction* psInst, ResourceBinding* psBinding, bstring glsl) +{ + int numParenthesis = 0; + uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(GLSLResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, + &numParenthesis); + + bcatcstr(glsl, "texelFetchOffset("); + + switch (psBinding->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bformata(glsl, ", 0, %d)", psInst->iUAddrOffset); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); + bformata(glsl, ", 0, ivec2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); + bformata(glsl, ", 0, ivec3(%d, %d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset, psInst->iWAddrOffset); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); + bformata(glsl, ", 0, ivec2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); + bformata(glsl, ", 0, int(%d))", psInst->iUAddrOffset); + break; + } + case REFLECT_RESOURCE_DIMENSION_BUFFER: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + case REFLECT_RESOURCE_DIMENSION_BUFFEREX: + default: + { + ASSERT(0); + break; + } + } + + AddSwizzleUsingElementCount(psContext, destCount); + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +// Makes sure the texture coordinate swizzle is appropriate for the texture type. +// i.e. vecX for X-dimension texture. +// Currently supports floating point coord only, so not used for texelFetch. +static void GLSLTranslateTexCoord(HLSLCrossCompilerContext* psContext, const RESOURCE_DIMENSION eResDim, Operand* psTexCoordOperand) +{ + uint32_t flags = TO_AUTO_BITCAST_TO_FLOAT; + uint32_t opMask = OPERAND_4_COMPONENT_MASK_ALL; + + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + // Vec1 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X; + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + // Vec2 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; + flags |= TO_AUTO_EXPAND_TO_VEC2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + // Vec3 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z; + flags |= TO_AUTO_EXPAND_TO_VEC3; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + flags |= TO_AUTO_EXPAND_TO_VEC4; + break; + } + default: + { + ASSERT(0); + break; + } + } + + // FIXME detect when integer coords are needed. + TranslateOperandWithMask(psContext, psTexCoordOperand, flags, opMask); +} + +static int GLSLGetNumTextureDimensions(HLSLCrossCompilerContext* psContext, const RESOURCE_DIMENSION eResDim) +{ + (void)psContext; + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + return 1; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBE: + { + return 2; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + return 3; + } + default: + { + ASSERT(0); + break; + } + } + return 0; +} + +void GetResInfoData(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index, int destElem) +{ + bstring glsl = *psContext->currentShaderString; + int numParenthesis = 0; + const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + AddIndentation(psContext); + GLSLAddOpAssignToDestWithMask(psContext, &psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", + &numParenthesis, 1 << destElem); + + //[width, height, depth or array size, total-mip-count] + if (index < 3) + { + int dim = GLSLGetNumTextureDimensions(psContext, eResDim); + bcatcstr(glsl, "("); + if (dim < (index + 1)) + { + bcatcstr(glsl, eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? "0u" : "0.0"); + } + else + { + if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + { + bformata(glsl, "uvec%d(textureSize(", dim); + } + else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) + { + bformata(glsl, "vec%d(1.0) / vec%d(textureSize(", dim, dim); + } + else + { + bformata(glsl, "vec%d(textureSize(", dim); + } + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, "))"); + + switch (index) + { + case 0: + bcatcstr(glsl, ".x"); + break; + case 1: + bcatcstr(glsl, ".y"); + break; + case 2: + bcatcstr(glsl, ".z"); + break; + } + } + + bcatcstr(glsl, ")"); + } + else + { + if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + bcatcstr(glsl, "uint("); + else + bcatcstr(glsl, "float("); + bcatcstr(glsl, "textureQueryLevels("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + } + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +#define TEXSMP_FLAG_NONE 0x0 +#define TEXSMP_FLAG_LOD 0x1 // LOD comes from operand +#define TEXSMP_FLAG_DEPTHCOMPARE 0x2 +#define TEXSMP_FLAG_FIRSTLOD 0x4 // LOD is 0 +#define TEXSMP_FLAG_BIAS 0x8 +#define TEXSMP_FLAGS_GRAD 0x10 + +// TODO FIXME: non-float samplers! +static void GLSLTranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, uint32_t ui32Flags) +{ + bstring glsl = *psContext->currentShaderString; + int numParenthesis = 0; + + const char* funcName = "texture"; + const char* offset = ""; + const char* depthCmpCoordType = ""; + const char* gradSwizzle = ""; + + uint32_t ui32NumOffsets = 0; + + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + const int iHaveOverloadedTexFuncs = HaveOverloadedTextureFuncs(psContext->psShader->eTargetLanguage); + + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; + + ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); + + if (psInst->bAddressOffset) + { + offset = "Offset"; + } + + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + depthCmpCoordType = "vec2"; + gradSwizzle = ".x"; + ui32NumOffsets = 1; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture1D"; + if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) + { + funcName = "shadow1D"; + } + } + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture2D"; + if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) + { + funcName = "shadow2D"; + } + } + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (!iHaveOverloadedTexFuncs) + { + funcName = "textureCube"; + } + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + depthCmpCoordType = "vec4"; + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (!iHaveOverloadedTexFuncs) + { + funcName = "texture3D"; + } + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + depthCmpCoordType = "vec3"; + gradSwizzle = ".x"; + ui32NumOffsets = 1; + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + depthCmpCoordType = "vec4"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) + { + SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! + // Special. Reference is a separate argument. + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, 1, &numParenthesis); + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bcatcstr(glsl, "textureLod("); + } + else + { + bcatcstr(glsl, "texture("); + } + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0); + else + bconcat(glsl, TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, + psInst->asOperands[3].ui32RegisterNumber, (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) ? 1 : 0)); + bcatcstr(glsl, ","); + GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ","); + //.z = reference. + TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + + bcatcstr(glsl, ")"); + // Doesn't make any sense to do swizzles here, depth comparison returns a scalar. + GLSLAddAssignPrologue(psContext, numParenthesis); + return; + } + + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) + { + // For non-cubeMap Arrays the reference value comes from the + // texture coord vector in GLSL. For cubmap arrays there is a + // separate parameter. + // It is always separate paramter in HLSL. + SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bformata(glsl, "%sLod%s(", funcName, offset); + } + else + { + bformata(glsl, "%s%s(", funcName, offset); + } + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); + bformata(glsl, ", %s(", depthCmpCoordType); + GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ","); + //.z = reference. + TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(glsl, ")"); + + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + + bcatcstr(glsl, ")"); + } + else + { + SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + + if (ui32Flags & (TEXSMP_FLAG_LOD | TEXSMP_FLAG_FIRSTLOD)) + { + bformata(glsl, "%sLod%s(", funcName, offset); + } + else if (ui32Flags & TEXSMP_FLAGS_GRAD) + { + bformata(glsl, "%sGrad%s(", funcName, offset); + } + else + { + bformata(glsl, "%s%s(", funcName, offset); + } + if (!useCombinedTextureSamplers) + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); // resource + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); + bcatcstr(glsl, ", "); + GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + if (ui32Flags & (TEXSMP_FLAG_LOD)) + { + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + if (psContext->psShader->ui32MajorVersion < 4) + { + bcatcstr(glsl, ".w"); + } + } + else if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(glsl, ", 0.0"); + } + else if (ui32Flags & TEXSMP_FLAGS_GRAD) + { + bcatcstr(glsl, ", vec4("); + TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); // dx + bcatcstr(glsl, ")"); + bcatcstr(glsl, gradSwizzle); + bcatcstr(glsl, ", vec4("); + TranslateOperand(psContext, &psInst->asOperands[5], TO_AUTO_BITCAST_TO_FLOAT); // dy + bcatcstr(glsl, ")"); + bcatcstr(glsl, gradSwizzle); + } + + if (psInst->bAddressOffset) + { + if (ui32NumOffsets == 1) + { + bformata(glsl, ", %d", psInst->iUAddrOffset); + } + else if (ui32NumOffsets == 2) + { + bformata(glsl, ", ivec2(%d, %d)", psInst->iUAddrOffset, psInst->iVAddrOffset); + } + else if (ui32NumOffsets == 3) + { + bformata(glsl, ", ivec3(%d, %d, %d)", psInst->iUAddrOffset, psInst->iVAddrOffset, psInst->iWAddrOffset); + } + } + + if (ui32Flags & (TEXSMP_FLAG_BIAS)) + { + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + } + + bcatcstr(glsl, ")"); + } + + if (!(ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE)) + { + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[2], GetOperandWriteMask(&psInst->asOperands[0])); + } + GLSLAddAssignPrologue(psContext, numParenthesis); +} + +static ShaderVarType* GLSLLookupStructuredVar(HLSLCrossCompilerContext* psContext, Operand* psResource, Operand* psByteOffset, uint32_t ui32Component) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = {OPERAND_4_COMPONENT_X}; + int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; + int vec4Offset = 0; + int32_t index = -1; + int32_t rebase = -1; + int found; + + ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); + // TODO: multi-component stores and vector writes need testing. + + // aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; + + switch (byteOffset % 16) + { + case 0: + aui32Swizzle[0] = 0; + break; + case 4: + aui32Swizzle[0] = 1; + break; + case 8: + aui32Swizzle[0] = 2; + break; + case 12: + aui32Swizzle[0] = 3; + break; + } + + switch (psResource->eType) + { + case OPERAND_TYPE_RESOURCE: + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + // dcl_tgsm_structured defines the amount of memory and a stride. + ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); + return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; + } + default: + ASSERT(0); + break; + } + + found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + ASSERT(found); + + return psVarType; +} + +static void GLSLTranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentShaderString; + ShaderVarType* psVarType = NULL; + int component; + int srcComponent = 0; + + Operand* psDest = 0; + Operand* psDestAddr = 0; + Operand* psDestByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_STORE_STRUCTURED: + psDest = &psInst->asOperands[0]; + psDestAddr = &psInst->asOperands[1]; + psDestByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + + break; + case OPCODE_STORE_RAW: + psDest = &psInst->asOperands[0]; + psDestByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + for (component = 0; component < 4; component++) + { + ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psInst->asOperands[0].ui32CompMask & (1 << component)) + { + + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + psVarType = GLSLLookupStructuredVar(psContext, psDest, psDestByteOff, component); + } + + AddIndentation(psContext); + + if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) + { + bformata(glsl, "StructuredRes%d", psDest->ui32RegisterNumber); + } + else + { + TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + } + bformata(glsl, "["); + if (structured) // Dest address and dest byte offset + { + if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, "].value["); + TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, "/4u "); // bytes to floats + } + else + { + TranslateOperand(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + } + else + { + TranslateOperand(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + + // RAW: change component using index offset + if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(glsl, " + %d", component); + } + + bformata(glsl, "]"); + + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + if (strcmp(psVarType->Name, "$Element") != 0) + { + bformata(glsl, ".%s", psVarType->Name); + } + } + + if (structured) + { + uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; + if (psVarType) + { + if (psVarType->Type == SVT_INT) + { + flags = TO_FLAG_INTEGER; + } + else if (psVarType->Type == SVT_FLOAT) + { + flags = TO_FLAG_NONE; + } + } + // TGSM always uint + bformata(glsl, " = ("); + if (GetNumSwizzleElements(psSrc) > 1) + TranslateOperandWithMask(psContext, psSrc, flags, 1 << (srcComponent++)); + else + TranslateOperandWithMask(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); + } + else + { + // Dest type is currently always a uint array. + bformata(glsl, " = ("); + if (GetNumSwizzleElements(psSrc) > 1) + TranslateOperandWithMask(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); + else + TranslateOperandWithMask(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); + } + + // Double takes an extra slot. + if (psVarType && psVarType->Type == SVT_DOUBLE) + { + if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + bcatcstr(glsl, ")"); + component++; + } + + bformata(glsl, ");\n"); + } + } +} +static void GLSLTranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentShaderString; + int component; + Operand* psDest = 0; + Operand* psSrcAddr = 0; + Operand* psSrcByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_LD_STRUCTURED: + psDest = &psInst->asOperands[0]; + psSrcAddr = &psInst->asOperands[1]; + psSrcByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + break; + case OPCODE_LD_RAW: + psDest = &psInst->asOperands[0]; + psSrcByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + if (psInst->eOpcode == OPCODE_LD_RAW) + { + int numParenthesis = 0; + int firstItemAdded = 0; + uint32_t destCount = GetNumSwizzleElements(psDest); + uint32_t destMask = GetOperandWriteMask(psDest); + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); + if (destCount > 1) + { + bformata(glsl, "%s(", GetConstructorForType(SVT_UINT, destCount)); + numParenthesis++; + } + for (component = 0; component < 4; component++) + { + if (!(destMask & (1 << component))) + continue; + + if (firstItemAdded) + bcatcstr(glsl, ", "); + else + firstItemAdded = 1; + + bformata(glsl, "RawRes%d[((", psSrc->ui32RegisterNumber); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(glsl, ") >> 2)"); + if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) + { + bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); + } + bcatcstr(glsl, "]"); + } + GLSLAddAssignPrologue(psContext, numParenthesis); + } + else + { + int numParenthesis = 0; + int firstItemAdded = 0; + uint32_t destCount = GetNumSwizzleElements(psDest); + uint32_t destMask = GetOperandWriteMask(psDest); + ASSERT(psInst->eOpcode == OPCODE_LD_STRUCTURED); + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); + if (destCount > 1) + { + bformata(glsl, "%s(", GetConstructorForType(SVT_UINT, destCount)); + numParenthesis++; + } + for (component = 0; component < 4; component++) + { + ShaderVarType* psVar = NULL; + int addedBitcast = 0; + if (!(destMask & (1 << component))) + continue; + + if (firstItemAdded) + bcatcstr(glsl, ", "); + else + firstItemAdded = 1; + + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + // input already in uints + TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "["); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "].value[("); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, " >> 2u) + %d]", psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + } + else + { + ConstantBuffer* psCBuf = NULL; + psVar = GLSLLookupStructuredVar(psContext, psSrc, psSrcByteOff, + psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + if (psVar->Type == SVT_FLOAT) + { + bcatcstr(glsl, "floatBitsToUint("); + addedBitcast = 1; + } + else if (psVar->Type == SVT_DOUBLE) + { + bcatcstr(glsl, "unpackDouble2x32("); + addedBitcast = 1; + } + if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) + { + bformata(glsl, "%s[", psCBuf->Name); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + if (strcmp(psVar->Name, "$Element") != 0) + { + bcatcstr(glsl, "."); + bcatcstr(glsl, psVar->Name); + } + } + else + { + bformata(glsl, "StructuredRes%d[", psSrc->ui32RegisterNumber); + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(glsl, "]."); + + bcatcstr(glsl, psVar->Name); + } + + if (addedBitcast) + bcatcstr(glsl, ")"); + if (psVar->Type == SVT_DOUBLE) + component++; // doubles take up 2 slots + } + } + GLSLAddAssignPrologue(psContext, numParenthesis); + + return; + } + +#if 0 + + //(int)GetNumSwizzleElements(&psInst->asOperands[0]) + for (component = 0; component < 4; component++) + { + const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; + ASSERT(psDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psDest->ui32CompMask & (1 << component)) + { + if (structured && psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + psVarType = GLSLLookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->aui32Swizzle[component]); + } + + AddIndentation(psContext); + + aui32Swizzle[0] = psSrc->aui32Swizzle[component]; + + TranslateOperand(psContext, psDest, TO_FLAG_DESTINATION); + if (GetNumSwizzleElements(psDest) > 1) + bformata(glsl, swizzleString[destComponent++]); + + if (psVarType) + { + // TODO completely broken now after GLSLMETALAddAssignToDest refactorings. + GLSLMETALAddAssignToDest(psContext, psDest, SVTTypeToFlag(psVarType->Type), GetNumSwizzleElements(psDest), &numParenthesis); + } + else + { + GLSLMETALAddAssignToDest(psContext, psDest, TO_FLAG_NONE, GetNumSwizzleElements(psDest), &numParenthesis); + } + + if (psSrc->eType == OPERAND_TYPE_RESOURCE) + { + if (structured) + bformata(glsl, "(StructuredRes%d[", psSrc->ui32RegisterNumber); + else + bformata(glsl, "(RawRes%d[", psSrc->ui32RegisterNumber); + } + else + { + bformata(glsl, "("); + TranslateOperand(psContext, psSrc, TO_FLAG_NAME_ONLY); + bformata(glsl, "["); + Translate + } + + if (structured) //src address and src byte offset + { + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, "].value["); + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(glsl, "/4u ");//bytes to floats + } + else + { + TranslateOperand(psContext, psSrcAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + } + else + { + TranslateOperand(psContext, psSrcByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + + //RAW: change component using index offset + if (!structured || (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(glsl, " + %d", psSrc->aui32Swizzle[component]); + } + + bformata(glsl, "]"); + if (structured && psSrc->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + if (strcmp(psVarType->Name, "$Element") != 0) + { + bformata(glsl, ".%s", psVarType->Name); + } + + if (psVarType->Type == SVT_DOUBLE) + { + //Double takes an extra slot. + component++; + } + } + + bformata(glsl, ");\n"); + } + } +#endif +} + +void TranslateAtomicMemOp(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring glsl = *psContext->currentShaderString; + int numParenthesis = 0; + ShaderVarType* psVarType = NULL; + uint32_t ui32DataTypeFlag = TO_FLAG_INTEGER; + const char* func = ""; + Operand* dest = 0; + Operand* previousValue = 0; + Operand* destAddr = 0; + Operand* src = 0; + Operand* compare = 0; + + switch (psInst->eOpcode) + { + case OPCODE_IMM_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IADD\n"); +#endif + func = "atomicAdd"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IADD\n"); +#endif + func = "atomicAdd"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_AND\n"); +#endif + func = "atomicAnd"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_AND\n"); +#endif + func = "atomicAnd"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_OR\n"); +#endif + func = "atomicOr"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_OR\n"); +#endif + func = "atomicOr"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_XOR\n"); +#endif + func = "atomicXor"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_XOR\n"); +#endif + func = "atomicXor"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + + case OPCODE_IMM_ATOMIC_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_EXCH\n"); +#endif + func = "atomicExchange"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_CMP_EXC\n"); +#endif + func = "atomicCompSwap"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + compare = &psInst->asOperands[3]; + src = &psInst->asOperands[4]; + break; + } + case OPCODE_ATOMIC_CMP_STORE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_CMP_STORE\n"); +#endif + func = "atomicCompSwap"; + previousValue = 0; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + compare = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_UMIN\n"); +#endif + func = "atomicMin"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_UMIN\n"); +#endif + func = "atomicMin"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IMIN\n"); +#endif + func = "atomicMin"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IMIN\n"); +#endif + func = "atomicMin"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_UMAX\n"); +#endif + func = "atomicMax"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_UMAX\n"); +#endif + func = "atomicMax"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_IMAX\n"); +#endif + func = "atomicMax"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ATOMIC_IMAX\n"); +#endif + func = "atomicMax"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + } + + AddIndentation(psContext); + + psVarType = GLSLLookupStructuredVar(psContext, dest, destAddr, 0); + if (psVarType->Type == SVT_UINT) + { + ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT; + } + else + { + ui32DataTypeFlag = TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT; + } + + if (previousValue) + { + GLSLMETALAddAssignToDest(psContext, previousValue, psVarType->Type, 1, &numParenthesis); + } + bcatcstr(glsl, func); + bformata(glsl, "("); + ResourceName(glsl, psContext, RGROUP_UAV, dest->ui32RegisterNumber, 0); + bformata(glsl, "[0]"); + if (strcmp(psVarType->Name, "$Element") != 0) + { + bformata(glsl, ".%s", psVarType->Name); + } + + bcatcstr(glsl, ", "); + + if (compare) + { + TranslateOperand(psContext, compare, ui32DataTypeFlag); + bcatcstr(glsl, ", "); + } + + TranslateOperand(psContext, src, ui32DataTypeFlag); + bcatcstr(glsl, ")"); + if (previousValue) + { + GLSLAddAssignPrologue(psContext, numParenthesis); + } + else + bcatcstr(glsl, ";\n"); +} + +static void GLSLTranslateConditional(HLSLCrossCompilerContext* psContext, Instruction* psInst, bstring glsl) +{ + const char* statement = ""; + if (psInst->eOpcode == OPCODE_BREAKC) + { + statement = "break"; + } + else if (psInst->eOpcode == OPCODE_CONTINUEC) + { + statement = "continue"; + } + else if (psInst->eOpcode == OPCODE_RETC) + { + statement = "return"; + } + + if (psContext->psShader->ui32MajorVersion < 4) + { + bcatcstr(glsl, "if("); + + TranslateOperand(psContext, &psInst->asOperands[0], SVTTypeToFlag(GetOperandDataType(psContext, &psInst->asOperands[0]))); + switch (psInst->eDX9TestType) + { + case D3DSPC_GT: + { + bcatcstr(glsl, " > "); + break; + } + case D3DSPC_EQ: + { + bcatcstr(glsl, " == "); + break; + } + case D3DSPC_GE: + { + bcatcstr(glsl, " >= "); + break; + } + case D3DSPC_LT: + { + bcatcstr(glsl, " < "); + break; + } + case D3DSPC_NE: + { + bcatcstr(glsl, " != "); + break; + } + case D3DSPC_LE: + { + bcatcstr(glsl, " <= "); + break; + } + case D3DSPC_BOOLEAN: + { + bcatcstr(glsl, " != 0"); + break; + } + default: + { + break; + } + } + + if (psInst->eDX9TestType != D3DSPC_BOOLEAN) + { + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + } + + if (psInst->eOpcode != OPCODE_IF) + { + bformata(glsl, "){ %s; }\n", statement); + } + else + { + bcatcstr(glsl, "){\n"); + } + } + else + { + if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF) + { + bformata(glsl, ")==0u){%s;}\n", statement); + } + else + { + bcatcstr(glsl, ")==0u){\n"); + } + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF) + { + bformata(glsl, ")!=0u){%s;}\n", statement); + } + else + { + bcatcstr(glsl, ")!=0u){\n"); + } + } + } +} + +// Returns the "more important" type of a and b, currently int < uint < float +static SHADER_VARIABLE_TYPE GLSLSelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b) +{ + if (a == SVT_FLOAT || b == SVT_FLOAT) + return SVT_FLOAT; + // Apart from floats, the enum values are fairly well-ordered, use that directly. + return a > b ? a : b; +} + +// Helper function to set the vector type of 1 or more components in a vector +// If the existing values (that we're writing to) are all SVT_VOID, just upgrade the value and we're done +// Otherwise, set all the components in the vector that currently are set to that same value OR are now being written to +// to the "highest" type value (ordering int->uint->float) +static void GLSLSetVectorType(SHADER_VARIABLE_TYPE* aeTempVecType, uint32_t regBaseIndex, uint32_t componentMask, SHADER_VARIABLE_TYPE eType) +{ + int existingTypesFound = 0; + int i = 0; + for (i = 0; i < 4; i++) + { + if (componentMask & (1 << i)) + { + if (aeTempVecType[regBaseIndex + i] != SVT_VOID) + { + existingTypesFound = 1; + break; + } + } + } + + if (existingTypesFound != 0) + { + // Expand the mask to include all components that are used, also upgrade type + for (i = 0; i < 4; i++) + { + if (aeTempVecType[regBaseIndex + i] != SVT_VOID) + { + componentMask |= (1 << i); + eType = GLSLSelectHigherType(eType, aeTempVecType[regBaseIndex + i]); + } + } + } + + // Now componentMask contains the components we actually need to update and eType may have been changed to something else. + // Write the results + for (i = 0; i < 4; i++) + { + if (componentMask & (1 << i)) + { + aeTempVecType[regBaseIndex + i] = eType; + } + } +} + +static void GLSLMarkOperandAs(Operand* psOperand, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) +{ + if (psOperand->eType == OPERAND_TYPE_INDEXABLE_TEMP || psOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + GLSLSetVectorType(aeTempVecType, ui32RegIndex, 1 << psOperand->aui32Swizzle[0], eType); + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + // 0xf == all components, swizzle order doesn't matter. + GLSLSetVectorType(aeTempVecType, ui32RegIndex, 0xf, eType); + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + GLSLSetVectorType(aeTempVecType, ui32RegIndex, ui32CompMask, eType); + } + } +} + +static void GLSLMarkAllOperandsAs(Instruction* psInst, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) +{ + uint32_t i = 0; + for (i = 0; i < psInst->ui32NumOperands; i++) + { + GLSLMarkOperandAs(&psInst->asOperands[i], eType, aeTempVecType); + } +} + +static void GLSLWriteOperandTypes(Operand* psOperand, const SHADER_VARIABLE_TYPE* aeTempVecType) +{ + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eType != OPERAND_TYPE_TEMP) + return; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; + psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex + 1]; + psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex + 2]; + psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex + 3]; + } + else + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + psOperand->aeDataType[psOperand->aui32Swizzle[1]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[1]]; + psOperand->aeDataType[psOperand->aui32Swizzle[2]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[2]]; + psOperand->aeDataType[psOperand->aui32Swizzle[3]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[3]]; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; + } + } + } +} + +// Mark scalars from CBs. TODO: Do we need to do the same for vec2/3's as well? There may be swizzles involved which make it vec4 or something else again. +static void GLSLSetCBOperandComponents(HLSLCrossCompilerContext* psContext, Operand* psOperand) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + int rebase = 0; + + if (psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER) + return; + + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + + if (psVarType->Class == SVC_SCALAR) + psOperand->iNumComponents = 1; +} + +void SetDataTypes(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount) +{ + int32_t i; + Instruction* psFirstInst = psInst; + + SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; + + if (psContext->psShader->ui32MajorVersion <= 3) + { + for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) + { + aeTempVecType[i] = SVT_FLOAT; + } + } + else + { + // Start with void, then move up the chain void->int->uint->float + for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) + { + aeTempVecType[i] = SVT_VOID; + } + } + + // if (psContext->psShader->ui32MajorVersion <= 3) + { + // First pass, do analysis: deduce the data type based on opcodes, fill out aeTempVecType table + // Only ever to int->float promotion (or int->uint), never the other way around + for (i = 0; i < i32InstCount; ++i, psInst++) + { + if (psInst->ui32NumOperands == 0) + continue; + + switch (psInst->eOpcode) + { + // All float-only ops + case OPCODE_ADD: + case OPCODE_DERIV_RTX: + case OPCODE_DERIV_RTY: + case OPCODE_DIV: + case OPCODE_DP2: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_EQ: + case OPCODE_EXP: + case OPCODE_FRC: + case OPCODE_LOG: + case OPCODE_MAD: + case OPCODE_MIN: + case OPCODE_MAX: + case OPCODE_MUL: + case OPCODE_NE: + case OPCODE_ROUND_NE: + case OPCODE_ROUND_NI: + case OPCODE_ROUND_PI: + case OPCODE_ROUND_Z: + case OPCODE_RSQ: + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_D: + case OPCODE_SAMPLE_B: + case OPCODE_SQRT: + case OPCODE_SINCOS: + case OPCODE_LOD: + case OPCODE_GATHER4: + + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_GATHER4_C: + case OPCODE_GATHER4_PO: + case OPCODE_GATHER4_PO_C: + case OPCODE_RCP: + + GLSLMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); + break; + + // Int-only ops, no need to do anything + case OPCODE_AND: + case OPCODE_BREAKC: + case OPCODE_CALLC: + case OPCODE_CONTINUEC: + case OPCODE_IADD: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_IF: + case OPCODE_NOT: + case OPCODE_OR: + case OPCODE_RETC: + case OPCODE_XOR: + case OPCODE_BUFINFO: + case OPCODE_COUNTBITS: + case OPCODE_FIRSTBIT_HI: + case OPCODE_FIRSTBIT_LO: + case OPCODE_FIRSTBIT_SHI: + case OPCODE_UBFE: + case OPCODE_IBFE: + case OPCODE_BFI: + case OPCODE_BFREV: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_MOV: + case OPCODE_MOVC: + case OPCODE_SWAPC: + GLSLMarkAllOperandsAs(psInst, SVT_INT, aeTempVecType); + break; + // uint ops + case OPCODE_UDIV: + case OPCODE_ULT: + case OPCODE_UGE: + case OPCODE_UMUL: + case OPCODE_UMAD: + case OPCODE_UMAX: + case OPCODE_UMIN: + case OPCODE_USHR: + case OPCODE_UADDC: + case OPCODE_USUBB: + GLSLMarkAllOperandsAs(psInst, SVT_UINT, aeTempVecType); + break; + + // Need special handling + case OPCODE_FTOI: + case OPCODE_FTOU: + GLSLMarkOperandAs(&psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOI ? SVT_INT : SVT_UINT, aeTempVecType); + GLSLMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_GE: + case OPCODE_LT: + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_UINT, aeTempVecType); + GLSLMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); + GLSLMarkOperandAs(&psInst->asOperands[2], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_ITOF: + case OPCODE_UTOF: + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + GLSLMarkOperandAs(&psInst->asOperands[1], psInst->eOpcode == OPCODE_ITOF ? SVT_INT : SVT_UINT, aeTempVecType); + break; + + case OPCODE_LD: + case OPCODE_LD_MS: + // TODO: Would need to know the sampler return type + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_RESINFO: + { + if (psInst->eResInfoReturnType != RESINFO_INSTRUCTION_RETURN_UINT) + GLSLMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); + break; + } + + case OPCODE_SAMPLE_INFO: + // TODO decode the _uint flag + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_SAMPLE_POS: + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_LD_UAV_TYPED: + case OPCODE_STORE_UAV_TYPED: + case OPCODE_LD_RAW: + case OPCODE_STORE_RAW: + case OPCODE_LD_STRUCTURED: + case OPCODE_STORE_STRUCTURED: + GLSLMarkOperandAs(&psInst->asOperands[0], SVT_INT, aeTempVecType); + break; + + case OPCODE_F32TOF16: + case OPCODE_F16TOF32: + // TODO + break; + + // No-operands, should never get here anyway + /* case OPCODE_BREAK: + case OPCODE_CALL: + case OPCODE_CASE: + case OPCODE_CONTINUE: + case OPCODE_CUT: + case OPCODE_DEFAULT: + case OPCODE_DISCARD: + case OPCODE_ELSE: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_ENDIF: + case OPCODE_ENDLOOP: + case OPCODE_ENDSWITCH: + + case OPCODE_LABEL: + case OPCODE_LOOP: + case OPCODE_CUSTOMDATA: + case OPCODE_NOP: + case OPCODE_RET: + case OPCODE_SWITCH: + case OPCODE_DCL_RESOURCE: // DCL* opcodes have + case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. + case OPCODE_DCL_SAMPLER: + case OPCODE_DCL_INDEX_RANGE: + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + case OPCODE_DCL_INPUT: + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_SIV: + case OPCODE_DCL_INPUT_PS: + case OPCODE_DCL_INPUT_PS_SGV: + case OPCODE_DCL_INPUT_PS_SIV: + case OPCODE_DCL_OUTPUT: + case OPCODE_DCL_OUTPUT_SGV: + case OPCODE_DCL_OUTPUT_SIV: + case OPCODE_DCL_TEMPS: + case OPCODE_DCL_INDEXABLE_TEMP: + case OPCODE_DCL_GLOBAL_FLAGS: + + + case OPCODE_HS_DECLS: // token marks beginning of HS sub-shader + case OPCODE_HS_CONTROL_POINT_PHASE: // token marks beginning of HS sub-shader + case OPCODE_HS_FORK_PHASE: // token marks beginning of HS sub-shader + case OPCODE_HS_JOIN_PHASE: // token marks beginning of HS sub-shader + + case OPCODE_EMIT_STREAM: + case OPCODE_CUT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + case OPCODE_INTERFACE_CALL: + + + case OPCODE_DCL_STREAM: + case OPCODE_DCL_FUNCTION_BODY: + case OPCODE_DCL_FUNCTION_TABLE: + case OPCODE_DCL_INTERFACE: + + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + case OPCODE_DCL_TESS_DOMAIN: + case OPCODE_DCL_TESS_PARTITIONING: + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + case OPCODE_DCL_HS_MAX_TESSFACTOR: + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + case OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: + + case OPCODE_DCL_THREAD_GROUP: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + case OPCODE_DCL_RESOURCE_RAW: + case OPCODE_DCL_RESOURCE_STRUCTURED: + case OPCODE_SYNC: + + // TODO + case OPCODE_DADD: + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_DTOF: + case OPCODE_FTOD: + + case OPCODE_EVAL_SNAPPED: + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_CENTROID: + + case OPCODE_DCL_GS_INSTANCE_COUNT: + + case OPCODE_ABORT: + case OPCODE_DEBUG_BREAK:*/ + + default: + break; + } + } + } + + // Fill the rest of aeTempVecType, just in case. + for (i = 0; i < MAX_TEMP_VEC4 * 4; i++) + { + if (aeTempVecType[i] == SVT_VOID) + aeTempVecType[i] = SVT_INT; + } + + // Now the aeTempVecType table has been filled with (mostly) valid data, write it back to all operands + psInst = psFirstInst; + for (i = 0; i < i32InstCount; ++i, psInst++) + { + int k = 0; + + if (psInst->ui32NumOperands == 0) + continue; + + // Preserve the current type on dest array index + if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) + { + Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; + if (psSubOperand != 0) + { + GLSLWriteOperandTypes(psSubOperand, aeTempVecType); + } + } + if (psInst->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) + GLSLSetCBOperandComponents(psContext, &psInst->asOperands[0]); + + // Preserve the current type on sources. + for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) + { + int32_t subOperand; + Operand* psOperand = &psInst->asOperands[k]; + + GLSLWriteOperandTypes(psOperand, aeTempVecType); + if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + GLSLSetCBOperandComponents(psContext, psOperand); + + for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) + { + if (psOperand->psSubOperand[subOperand] != 0) + { + Operand* psSubOperand = psOperand->psSubOperand[subOperand]; + GLSLWriteOperandTypes(psSubOperand, aeTempVecType); + if (psSubOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + GLSLSetCBOperandComponents(psContext, psSubOperand); + } + } + + // Set immediates + if (GLSLIsIntegerImmediateOpcode(psInst->eOpcode)) + { + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) + { + psOperand->iIntegerImmediate = 1; + } + } + } + + // Process the destination last in order to handle instructions + // where the destination register is also used as a source. + for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) + { + Operand* psOperand = &psInst->asOperands[k]; + GLSLWriteOperandTypes(psOperand, aeTempVecType); + } + } +} + +void TranslateInstruction(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst) +{ + bstring glsl = *psContext->currentShaderString; + int numParenthesis = 0; + +#ifdef _DEBUG + AddIndentation(psContext); + bformata(glsl, "//Instruction %d\n", psInst->id); +#if 0 + if(psInst->id == 73) + { + ASSERT(1); //Set breakpoint here to debug an instruction from its ID. + } +#endif +#endif + + switch (psInst->eOpcode) + { + case OPCODE_FTOI: + case OPCODE_FTOU: + { + uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_FTOU) + bcatcstr(glsl, "//FTOU\n"); + else + bcatcstr(glsl, "//FTOI\n"); +#endif + + AddIndentation(psContext); + + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); + bcatcstr(glsl, GetConstructorForType(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); + bcatcstr(glsl, "("); // 1 + TranslateOperand(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(glsl, ")"); // 1 + // Add destination writemask if the component counts do not match + if (srcCount != dstCount) + AddSwizzleUsingElementCount(psContext, dstCount); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + + case OPCODE_MOV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MOV\n"); +#endif + AddIndentation(psContext); + GLSLAddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1]); + break; + } + case OPCODE_ITOF: // signed to float + case OPCODE_UTOF: // unsigned to float + { + uint32_t dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElements(&psInst->asOperands[1]); + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_ITOF) + { + bcatcstr(glsl, "//ITOF\n"); + } + else + { + bcatcstr(glsl, "//UTOF\n"); + } +#endif + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, srcCount, &numParenthesis); + bcatcstr(glsl, GetConstructorForType(SVT_FLOAT, srcCount == dstCount ? dstCount : 4)); + bcatcstr(glsl, "("); // 1 + TranslateOperand(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT); + bcatcstr(glsl, ")"); // 1 + // Add destination writemask if the component counts do not match + if (srcCount != dstCount) + AddSwizzleUsingElementCount(psContext, dstCount); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_MAD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MAD\n"); +#endif + GLSLCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_NONE); + break; + } + case OPCODE_IMAD: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMAD\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + GLSLCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); + break; + } + case OPCODE_DADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DADD\n"); +#endif + GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_DOUBLE); + break; + } + case OPCODE_IADD: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IADD\n"); +#endif + // Is this a signed or unsigned add? + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ADD\n"); +#endif + GLSLCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_OR: + { + /*Todo: vector version */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//OR\n"); +#endif + GLSLCallBinaryOp(psContext, "|", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//AND\n"); +#endif + GLSLCallBinaryOp(psContext, "&", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_GE: + { + /* + dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); + Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. + */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GE\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_MUL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MUL\n"); +#endif + GLSLCallBinaryOp(psContext, "*", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_IMUL: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMUL\n"); +#endif + if (GetOperandDataType(psContext, &psInst->asOperands[1]) == SVT_UINT) + { + eType = SVT_UINT; + } + + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); + + GLSLCallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); + break; + } + case OPCODE_UDIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UDIV\n"); +#endif + // destQuotient, destRemainder, src0, src1 + GLSLCallBinaryOp(psContext, "/", psInst, 0, 2, 3, SVT_UINT); + GLSLCallBinaryOp(psContext, "%", psInst, 1, 2, 3, SVT_UINT); + break; + } + case OPCODE_DIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DIV\n"); +#endif + GLSLCallBinaryOp(psContext, "/", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_SINCOS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SINCOS\n"); +#endif + // Need careful ordering if src == dest[0], as then the cos() will be reading from wrong value + if (psInst->asOperands[0].eType == psInst->asOperands[2].eType && + psInst->asOperands[0].ui32RegisterNumber == psInst->asOperands[2].ui32RegisterNumber) + { + // sin() result overwrites source, do cos() first. + // The case where both write the src shouldn't really happen anyway. + if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) + { + GLSLCallHelper1(psContext, "cos", psInst, 1, 2, 1); + } + + if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) + { + GLSLCallHelper1(psContext, "sin", psInst, 0, 2, 1); + } + } + else + { + if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) + { + GLSLCallHelper1(psContext, "sin", psInst, 0, 2, 1); + } + + if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) + { + GLSLCallHelper1(psContext, "cos", psInst, 1, 2, 1); + } + } + break; + } + + case OPCODE_DP2: + { + int numParenthesis2 = 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP2\n"); +#endif + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); + bcatcstr(glsl, "dot("); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT, 3 /* .xy */); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT, 3 /* .xy */); + bcatcstr(glsl, ")"); + GLSLAddAssignPrologue(psContext, numParenthesis2); + break; + } + case OPCODE_DP3: + { + int numParenthesis2 = 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP3\n"); +#endif + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); + bcatcstr(glsl, "dot("); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT, 7 /* .xyz */); + bcatcstr(glsl, ", "); + TranslateOperandWithMask(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT, 7 /* .xyz */); + bcatcstr(glsl, ")"); + GLSLAddAssignPrologue(psContext, numParenthesis2); + break; + } + case OPCODE_DP4: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP4\n"); +#endif + GLSLCallHelper2(psContext, "dot", psInst, 0, 1, 2, 0); + break; + } + case OPCODE_INE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INE\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_NE, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//NE\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_NE, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_IGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IGE\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_INTEGER, psNextInst); + break; + } + case OPCODE_ILT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ILT\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_LT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LT\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_IEQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IEQ\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_EQ, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_ULT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ULT\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_LT, TO_FLAG_UNSIGNED_INTEGER, NULL); + break; + } + case OPCODE_UGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//UGE\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_GE, TO_FLAG_UNSIGNED_INTEGER, NULL); + break; + } + case OPCODE_MOVC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MOVC\n"); +#endif + GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); + break; + } + case OPCODE_SWAPC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SWAPC\n"); +#endif + // TODO needs temps!! + GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); + GLSLAddMOVCBinaryOp(psContext, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); + break; + } + + case OPCODE_LOG: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOG\n"); +#endif + GLSLCallHelper1(psContext, "log2", psInst, 0, 1, 1); + break; + } + case OPCODE_RSQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RSQ\n"); +#endif + GLSLCallHelper1(psContext, "inversesqrt", psInst, 0, 1, 1); + break; + } + case OPCODE_EXP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EXP\n"); +#endif + GLSLCallHelper1(psContext, "exp2", psInst, 0, 1, 1); + break; + } + case OPCODE_SQRT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SQRT\n"); +#endif + GLSLCallHelper1(psContext, "sqrt", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_PI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_PI\n"); +#endif + GLSLCallHelper1(psContext, "ceil", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_NI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_NI\n"); +#endif + GLSLCallHelper1(psContext, "floor", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_Z: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_Z\n"); +#endif + GLSLCallHelper1(psContext, "trunc", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ROUND_NE\n"); +#endif + GLSLCallHelper1(psContext, "roundEven", psInst, 0, 1, 1); + break; + } + case OPCODE_FRC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FRC\n"); +#endif + GLSLCallHelper1(psContext, "fract", psInst, 0, 1, 1); + break; + } + case OPCODE_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMAX\n"); +#endif + GLSLCallHelper2Int(psContext, "max", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_MAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MAX\n"); +#endif + GLSLCallHelper2(psContext, "max", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMIN\n"); +#endif + GLSLCallHelper2Int(psContext, "min", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_MIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//MIN\n"); +#endif + GLSLCallHelper2(psContext, "min", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_GATHER4: + { + // dest, coords, tex, sampler + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4\n"); +#endif + // gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x + AddIndentation(psContext); // TODO FIXME integer samplers + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(glsl, "textureGather("); + + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); + + bcatcstr(glsl, ", "); + GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(glsl, ")"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_GATHER4_PO_C: + { + // dest, coords, offset, tex, sampler, srcReferenceValue + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[3].ui32RegisterNumber]; + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_PO_C\n"); +#endif + + AddIndentation(psContext); // TODO FIXME integer samplers + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(glsl, "textureGatherOffset("); + + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 1); + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); + + bcatcstr(glsl, ", "); + + GLSLTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[5], TO_FLAG_NONE); + + bcatcstr(glsl, ", ivec2("); + // ivec2 offset + psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_GATHER4_PO: + { + // dest, coords, offset, tex, sampler + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_PO\n"); +#endif + + AddIndentation(psContext); // TODO FIXME integer samplers + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(glsl, "textureGatherOffset("); + + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 0); + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, 0)); + + bcatcstr(glsl, ", "); + // Texture coord cannot be vec4 + // Determining if it is a vec3 for vec2 yet to be done. + psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + + bcatcstr(glsl, ", ivec2("); + // ivec2 offset + psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[3]); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_GATHER4_C: + { + // dest, coords, tex, sampler srcReferenceValue + const int useCombinedTextureSamplers = (psContext->flags & HLSLCC_FLAG_COMBINE_TEXTURE_SAMPLERS) ? 1 : 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//GATHER4_C\n"); +#endif + + AddIndentation(psContext); // TODO FIXME integer samplers + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElements(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(glsl, "textureGather("); + + if (!useCombinedTextureSamplers) + ResourceName(glsl, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 1); + else + bconcat(glsl, + TextureSamplerName(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); + + bcatcstr(glsl, ", "); + // Texture coord cannot be vec4 + // Determining if it is a vec3 for vec2 yet to be done. + psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[4], TO_FLAG_NONE); + bcatcstr(glsl, ")"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzle(psContext, &psInst->asOperands[2]); + AddSwizzleUsingElementCount(psContext, GetNumSwizzleElements(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_SAMPLE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE\n"); +#endif + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); + break; + } + case OPCODE_SAMPLE_L: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_L\n"); +#endif + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); + break; + } + case OPCODE_SAMPLE_C: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_C\n"); +#endif + + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE); + break; + } + case OPCODE_SAMPLE_C_LZ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_C_LZ\n"); +#endif + + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE | TEXSMP_FLAG_FIRSTLOD); + break; + } + case OPCODE_SAMPLE_D: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_D\n"); +#endif + + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); + break; + } + case OPCODE_SAMPLE_B: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SAMPLE_B\n"); +#endif + + GLSLTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); + break; + } + case OPCODE_RET: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RET\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + } + AddIndentation(psContext); + bcatcstr(glsl, "return;\n"); + break; + } + case OPCODE_INTERFACE_CALL: + { + const char* name; + ShaderVar* psVar; + uint32_t varFound; + + uint32_t funcPointer; + uint32_t funcTableIndex; + uint32_t funcTable; + uint32_t funcBodyIndex; + uint32_t funcBody; + uint32_t ui32NumBodiesPerTable; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INTERFACE_CALL\n"); +#endif + + ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); + + funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; + funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; + funcBodyIndex = psInst->ui32FuncIndexWithinInterface; + + ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; + + funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; + + funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; + + varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); + + ASSERT(varFound); + + name = &psVar->Name[0]; + + AddIndentation(psContext); + bcatcstr(glsl, name); + TranslateOperandIndexMAD(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); + // bformata(glsl, "[%d]", funcBodyIndex); + bcatcstr(glsl, "();\n"); + break; + } + case OPCODE_LABEL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LABEL\n"); +#endif + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); // Closing brace ends the previous function. + AddIndentation(psContext); + + bcatcstr(glsl, "subroutine(SubroutineType)\n"); + bcatcstr(glsl, "void "); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, "(){\n"); + ++psContext->indent; + break; + } + case OPCODE_COUNTBITS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//COUNTBITS\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(glsl, " = bitCount("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_FIRSTBIT_HI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_HI\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(glsl, " = findMSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_FIRSTBIT_LO: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_LO\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(glsl, " = findLSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_FIRSTBIT_SHI: // signed high + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//FIRSTBIT_SHI\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(glsl, " = findMSB("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_BFREV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BFREV\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(glsl, " = bitfieldReverse("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_BFI: + { + uint32_t numelements_width = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t numelements_offset = GetNumSwizzleElements(&psInst->asOperands[2]); + uint32_t numelements_dest = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t numoverall_elements = min(min(numelements_width, numelements_offset), numelements_dest); + uint32_t i, j; + static const char* bfi_elementidx[] = {"x", "y", "z", "w"}; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BFI\n"); +#endif + + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bformata(glsl, " = ivec%d(", numoverall_elements); + for (i = 0; i < numoverall_elements; ++i) + { + bcatcstr(glsl, "bitfieldInsert("); + + for (j = 4; j >= 1; --j) + { + uint32_t opSwizzleCount = GetNumSwizzleElements(&psInst->asOperands[j]); + + if (opSwizzleCount != 1) + bcatcstr(glsl, " ("); + TranslateOperand(psContext, &psInst->asOperands[j], TO_FLAG_INTEGER); + if (opSwizzleCount != 1) + bformata(glsl, " ).%s", bfi_elementidx[i]); + if (j != 1) + bcatcstr(glsl, ","); + } + + bcatcstr(glsl, ") "); + if (i + 1 != numoverall_elements) + bcatcstr(glsl, ", "); + } + + bcatcstr(glsl, ")."); + for (i = 0; i < numoverall_elements; ++i) + bformata(glsl, "%s", bfi_elementidx[i]); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_CUT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EndPrimitive();\n"); + break; + } + case OPCODE_EMIT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMIT\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + } + + AddIndentation(psContext); + bcatcstr(glsl, "EmitVertex();\n"); + break; + } + case OPCODE_EMITTHENCUT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMITTHENCUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EmitVertex();\nEndPrimitive();\n"); + break; + } + + case OPCODE_CUT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EndStreamPrimitive("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + + break; + } + case OPCODE_EMIT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMIT_STREAM\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- Post shader code ---\n"); +#endif + bconcat(glsl, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//--- End post shader code ---\n"); +#endif + } + + AddIndentation(psContext); + bcatcstr(glsl, "EmitStreamVertex("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_EMITTHENCUT_STREAM: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EMITTHENCUT\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "EmitStreamVertex("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + bcatcstr(glsl, "EndStreamPrimitive("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_REP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//REP\n"); +#endif + // Need to handle nesting. + // Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx + + AddIndentation(psContext); + bcatcstr(glsl, "RepCounter = "); + TranslateOperandWithMask(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(glsl, ";\n"); + + AddIndentation(psContext); + bcatcstr(glsl, "while(RepCounter!=0){\n"); + ++psContext->indent; + break; + } + case OPCODE_ENDREP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ENDREP\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "RepCounter--;\n"); + + --psContext->indent; + + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_LOOP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOOP\n"); +#endif + AddIndentation(psContext); + + if (psInst->ui32NumOperands == 2) + { + // DX9 version + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); + bcatcstr(glsl, "for("); + bcatcstr(glsl, "LoopCounter = "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".y, ZeroBasedCounter = 0;"); + bcatcstr(glsl, "ZeroBasedCounter < "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".x;"); + + bcatcstr(glsl, "LoopCounter += "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ".z, ZeroBasedCounter++){\n"); + ++psContext->indent; + } + else + { + bcatcstr(glsl, "while(true){\n"); + ++psContext->indent; + } + break; + } + case OPCODE_ENDLOOP: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ENDLOOP\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_BREAK: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BREAK\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "break;\n"); + break; + } + case OPCODE_BREAKC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//BREAKC\n"); +#endif + AddIndentation(psContext); + + GLSLTranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_CONTINUEC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//CONTINUEC\n"); +#endif + AddIndentation(psContext); + + GLSLTranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_IF: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IF\n"); +#endif + AddIndentation(psContext); + + GLSLTranslateConditional(psContext, psInst, glsl); + ++psContext->indent; + break; + } + case OPCODE_RETC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RETC\n"); +#endif + AddIndentation(psContext); + + GLSLTranslateConditional(psContext, psInst, glsl); + break; + } + case OPCODE_ELSE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ELSE\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "} else {\n"); + psContext->indent++; + break; + } + case OPCODE_ENDSWITCH: + case OPCODE_ENDIF: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "//ENDIF\n"); + AddIndentation(psContext); + bcatcstr(glsl, "}\n"); + break; + } + case OPCODE_CONTINUE: + { + AddIndentation(psContext); + bcatcstr(glsl, "continue;\n"); + break; + } + case OPCODE_DEFAULT: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(glsl, "default:\n"); + ++psContext->indent; + break; + } + case OPCODE_NOP: + { + break; + } + case OPCODE_SYNC: + { + const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SYNC\n"); +#endif + + if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) + { + AddIndentation(psContext); + bcatcstr(glsl, "groupMemoryBarrier();\n"); + } + if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) + { + AddIndentation(psContext); + bcatcstr(glsl, "memoryBarrierShared();\n"); + } + if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) + { + AddIndentation(psContext); + bcatcstr(glsl, "memoryBarrier();\n"); + } + break; + } + case OPCODE_SWITCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//SWITCH\n"); +#endif + AddIndentation(psContext); + bcatcstr(glsl, "switch(int("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")){\n"); + + psContext->indent += 2; + break; + } + case OPCODE_CASE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//case\n"); +#endif + AddIndentation(psContext); + + bcatcstr(glsl, "case "); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ":\n"); + + ++psContext->indent; + break; + } + case OPCODE_EQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EQ\n"); +#endif + GLSLAddComparision(psContext, psInst, GLSL_CMP_EQ, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_USHR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//USHR\n"); +#endif + GLSLCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_ISHL: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ISHL\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + + GLSLCallBinaryOp(psContext, "<<", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_ISHR: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//ISHR\n"); +#endif + + if (GetOperandDataType(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + + GLSLCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_LD: + case OPCODE_LD_MS: + { + ResourceBinding* psBinding = 0; +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_LD) + bcatcstr(glsl, "//LD\n"); + else + bcatcstr(glsl, "//LD_MS\n"); +#endif + + GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + + if (psInst->bAddressOffset) + { + GLSLTranslateTexelFetchOffset(psContext, psInst, psBinding, glsl); + } + else + { + GLSLTranslateTexelFetch(psContext, psInst, psBinding, glsl); + } + break; + } + case OPCODE_DISCARD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DISCARD\n"); +#endif + AddIndentation(psContext); + if (psContext->psShader->ui32MajorVersion <= 3) + { + bcatcstr(glsl, "if(any(lessThan(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NONE); + + if (psContext->psShader->ui32MajorVersion == 1) + { + /* SM1.X only kills based on the rgb channels */ + bcatcstr(glsl, ").xyz, vec3(0)))){discard;}\n"); + } + else + { + bcatcstr(glsl, "), vec4(0)))){discard;}\n"); + } + } + else if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")==0){discard;}\n"); + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(glsl, "if(("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")!=0){discard;}\n"); + } + break; + } + case OPCODE_LOD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LOD\n"); +#endif + // LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) + + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 4, &numParenthesis); + + // If the core language does not have query-lod feature, + // then the extension is used. The name of the function + // changed between extension and core. + if (HaveQueryLod(psContext->psShader->eTargetLanguage)) + { + bcatcstr(glsl, "textureQueryLod("); + } + else + { + bcatcstr(glsl, "textureQueryLOD("); + } + + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ","); + GLSLTranslateTexCoord(psContext, psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], &psInst->asOperands[1]); + bcatcstr(glsl, ")"); + + // The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. + + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleWithMask(psContext, &psInst->asOperands[2], GetOperandWriteMask(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_EVAL_CENTROID: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_CENTROID\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = interpolateAtCentroid("); + // interpolateAtCentroid accepts in-qualified variables. + // As long as bytecode only writes vX registers in declarations + // we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_EVAL_SAMPLE_INDEX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_SAMPLE_INDEX\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = interpolateAtSample("); + // interpolateAtSample accepts in-qualified variables. + // As long as bytecode only writes vX registers in declarations + // we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_EVAL_SNAPPED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//EVAL_SNAPPED\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = interpolateAtOffset("); + // interpolateAtOffset accepts in-qualified variables. + // As long as bytecode only writes vX registers in declarations + // we should be able to use the declared name directly. + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_DECLARATION_NAME); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_INTEGER); + bcatcstr(glsl, ".xy);\n"); + break; + } + case OPCODE_LD_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_STRUCTURED\n"); +#endif + GLSLTranslateShaderStorageLoad(psContext, psInst); + break; + } + case OPCODE_LD_UAV_TYPED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_UAV_TYPED\n"); +#endif + switch (psInst->eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = imageLoad("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").x)"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + bcatcstr(glsl, ";\n"); + break; + case RESOURCE_DIMENSION_TEXTURECUBE: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE2DMS: + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = imageLoad("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").xy)"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + bcatcstr(glsl, ";\n"); + break; + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = imageLoad("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ", ("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bformata(glsl, ").xyz)"); + TranslateOperandSwizzle(psContext, &psInst->asOperands[0]); + bcatcstr(glsl, ";\n"); + break; + } + break; + } + case OPCODE_STORE_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_RAW\n"); +#endif + GLSLTranslateShaderStorageStore(psContext, psInst); + break; + } + case OPCODE_STORE_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_STRUCTURED\n"); +#endif + GLSLTranslateShaderStorageStore(psContext, psInst); + break; + } + + case OPCODE_STORE_UAV_TYPED: + { + ResourceBinding* psRes; + int foundResource; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//STORE_UAV_TYPED\n"); +#endif + AddIndentation(psContext); + + foundResource = GetResourceFromBindingPoint(RGROUP_UAV, psInst->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psRes); + + ASSERT(foundResource); + + bcatcstr(glsl, "imageStore("); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); + switch (psRes->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + bcatcstr(glsl, ", int("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, "), "); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + bcatcstr(glsl, ", ivec2("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ".xy), "); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + bcatcstr(glsl, ", ivec3("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ".xyz), "); + break; + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + bcatcstr(glsl, ", ivec4("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(glsl, ".xyzw) "); + break; + }; + + TranslateOperand(psContext, &psInst->asOperands[2], GLSLResourceReturnTypeToFlag(psRes->ui32ReturnType)); + bformata(glsl, ");\n"); + + break; + } + case OPCODE_LD_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LD_RAW\n"); +#endif + + GLSLTranslateShaderStorageLoad(psContext, psInst); + break; + } + + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + TranslateAtomicMemOp(psContext, psInst); + break; + } + case OPCODE_UBFE: + case OPCODE_IBFE: + { +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_UBFE) + bcatcstr(glsl, "//OPCODE_UBFE\n"); + else + bcatcstr(glsl, "//OPCODE_IBFE\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = bitfieldExtract("); + TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ", "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, ");\n"); + break; + } + case OPCODE_RCP: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RCP\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = (vec4(1.0) / vec4("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, "))"); + AddSwizzleUsingElementCount(psContext, destElemCount); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_F32TOF16: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//F32TOF16\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = {".x", ".y", ".z", ".w"}; + + // unpackHalf2x16 converts two f16s packed into uint to two f32s. + + // dest.swiz.x = unpackHalf2x16(src.swiz.x).x + // dest.swiz.y = unpackHalf2x16(src.swiz.y).x + // dest.swiz.z = unpackHalf2x16(src.swiz.z).x + // dest.swiz.w = unpackHalf2x16(src.swiz.w).x + + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + if (destElemCount > 1) + bcatcstr(glsl, swizzle[destElem]); + + bcatcstr(glsl, " = unpackHalf2x16("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + if (s0ElemCount > 1) + bcatcstr(glsl, swizzle[destElem]); + bcatcstr(glsl, ").x;\n"); + } + break; + } + case OPCODE_F16TOF32: + { + const uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElements(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//F16TOF32\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = {".x", ".y", ".z", ".w"}; + + // packHalf2x16 converts two f32s to two f16s packed into a uint. + + // dest.swiz.x = packHalf2x16(vec2(src.swiz.x)) & 0xFFFF + // dest.swiz.y = packHalf2x16(vec2(src.swiz.y)) & 0xFFFF + // dest.swiz.z = packHalf2x16(vec2(src.swiz.z)) & 0xFFFF + // dest.swiz.w = packHalf2x16(vec2(src.swiz.w)) & 0xFFFF + + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_UNSIGNED_INTEGER); + if (destElemCount > 1) + bcatcstr(glsl, swizzle[destElem]); + + bcatcstr(glsl, " = packHalf2x16(vec2("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + if (s0ElemCount > 1) + bcatcstr(glsl, swizzle[destElem]); + bcatcstr(glsl, ")) & 0xFFFF;\n"); + } + break; + } + case OPCODE_INEG: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INEG\n"); +#endif + // dest = 0 - src0 + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_INTEGER); + bcatcstr(glsl, " = 0 - "); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DERIV_RTX\n"); +#endif + GLSLCallHelper1(psContext, "dFdx", psInst, 0, 1, 1); + break; + } + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_DERIV_RTY: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DERIV_RTY\n"); +#endif + GLSLCallHelper1(psContext, "dFdy", psInst, 0, 1, 1); + break; + } + case OPCODE_LRP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//LRP\n"); +#endif + GLSLCallHelper3(psContext, "mix", psInst, 0, 2, 3, 1, 1); + break; + } + case OPCODE_DP2ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//DP2ADD\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = dot(vec2("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, "), vec2("); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ")) + "); + TranslateOperand(psContext, &psInst->asOperands[3], TO_FLAG_NONE); + bcatcstr(glsl, ";\n"); + break; + } + case OPCODE_POW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//POW\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = pow(abs("); + TranslateOperand(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(glsl, "), "); + TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(glsl, ");\n"); + break; + } + + case OPCODE_IMM_ATOMIC_ALLOC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_ALLOC\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(glsl, " = int(atomicCounterIncrement("); + ResourceName(glsl, psContext, RGROUP_UAV, psInst->asOperands[1].ui32RegisterNumber, 0); + bformata(glsl, "_counter"); + bcatcstr(glsl, "));\n"); + break; + } + case OPCODE_IMM_ATOMIC_CONSUME: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//IMM_ATOMIC_CONSUME\n"); +#endif + AddIndentation(psContext); + TranslateOperand(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + // Temps are always signed and atomci counters are always unsigned + // at the moment. + bcatcstr(glsl, " = int(atomicCounterDecrement("); + ResourceName(glsl, psContext, RGROUP_UAV, psInst->asOperands[1].ui32RegisterNumber, 0); + bformata(glsl, "_counter"); + bcatcstr(glsl, "));\n"); + break; + } + + case OPCODE_NOT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//INOT\n"); +#endif + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, GetNumSwizzleElements(&psInst->asOperands[1]), &numParenthesis); + + bcatcstr(glsl, "~"); + TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, GetOperandWriteMask(&psInst->asOperands[0])); + GLSLAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//XOR\n"); +#endif + + GLSLCallBinaryOp(psContext, "^", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_RESINFO: + { + uint32_t destElemCount = GetNumSwizzleElements(&psInst->asOperands[0]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(glsl, "//RESINFO\n"); +#endif + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + + GetResInfoData(psContext, psInst, psInst->asOperands[2].aui32Swizzle[destElem], destElem); + } + + break; + } + + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_DTOF: + case OPCODE_FTOD: + case OPCODE_DDIV: + case OPCODE_DFMA: + case OPCODE_DRCP: + case OPCODE_MSAD: + case OPCODE_DTOI: + case OPCODE_DTOU: + case OPCODE_ITOD: + case OPCODE_UTOD: + default: + { + ASSERT(0); + break; + } + } + + if (psInst->bSaturate) // Saturate is only for floating point data (float opcodes or MOV) + { + int dstCount = GetNumSwizzleElements(&psInst->asOperands[0]); + AddIndentation(psContext); + GLSLMETALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, dstCount, &numParenthesis); + bcatcstr(glsl, "clamp("); + + TranslateOperand(psContext, &psInst->asOperands[0], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(glsl, ", 0.0, 1.0)"); + GLSLAddAssignPrologue(psContext, numParenthesis); + } +} + +static int GLSLIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode) +{ + switch (eOpcode) + { + case OPCODE_IADD: + case OPCODE_IF: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_ITOF: + case OPCODE_USHR: + case OPCODE_AND: + case OPCODE_OR: + case OPCODE_XOR: + case OPCODE_BREAKC: + case OPCODE_CONTINUEC: + case OPCODE_RETC: + case OPCODE_DISCARD: + // MOV is typeless. + // Treat immediates as int, bitcast to float if necessary + case OPCODE_MOV: + case OPCODE_MOVC: + { + return 1; + } + default: + { + return 0; + } + } +} + +int InstructionUsesRegister(const Instruction* psInst, const Operand* psOperand) +{ + uint32_t operand; + for (operand = 0; operand < psInst->ui32NumOperands; ++operand) + { + if (psInst->asOperands[operand].eType == psOperand->eType) + { + if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) + { + if (CompareOperandSwizzles(&psInst->asOperands[operand], psOperand)) + { + return 1; + } + } + } + } + return 0; +} + +void MarkIntegerImmediates(HLSLCrossCompilerContext* psContext) +{ + const uint32_t count = psContext->psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; + Instruction* psInst = psContext->psShader->asPhase[MAIN_PHASE].ppsInst[0]; + uint32_t i; + + for (i = 0; i < count;) + { + if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) + { + uint32_t k; + + for (k = i + 1; k < count; ++k) + { + if (psInst[k].eOpcode == OPCODE_ILT) + { + k = k; + } + if (InstructionUsesRegister(&psInst[k], &psInst[i].asOperands[0])) + { + if (GLSLIsIntegerImmediateOpcode(psInst[k].eOpcode)) + { + psInst[i].asOperands[1].iIntegerImmediate = 1; + } + + goto next_iteration; + } + } + } + next_iteration: + ++i; + } +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c new file mode 100644 index 0000000000..f6595ad2cf --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toGLSLOperand.c @@ -0,0 +1,1869 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toGLSLOperand.h" +#include "bstrlib.h" +#include "hlslcc.h" +#include "internal_includes/debug.h" +#include "internal_includes/toGLSLDeclaration.h" + +#include <float.h> +#include <stdlib.h> + +#ifdef _MSC_VER +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +uint32_t SVTTypeToFlag(const SHADER_VARIABLE_TYPE eType) +{ + if (eType == SVT_UINT) + { + return TO_FLAG_UNSIGNED_INTEGER; + } + else if (eType == SVT_INT) + { + return TO_FLAG_INTEGER; + } + else if (eType == SVT_BOOL) + { + return TO_FLAG_INTEGER; // TODO bools? + } + else + { + return TO_FLAG_NONE; + } +} + +SHADER_VARIABLE_TYPE TypeFlagsToSVTType(const uint32_t typeflags) +{ + if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT)) + return SVT_INT; + if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT)) + return SVT_UINT; + return SVT_FLOAT; +} + +uint32_t GetOperandWriteMask(const Operand* psOperand) +{ + if (psOperand->eSelMode != OPERAND_4_COMPONENT_MASK_MODE || psOperand->ui32CompMask == 0) + return OPERAND_4_COMPONENT_MASK_ALL; + + return psOperand->ui32CompMask; +} + +const char* GetConstructorForType(const SHADER_VARIABLE_TYPE eType, const int components) +{ + static const char* const uintTypes[] = {" ", "uint", "uvec2", "uvec3", "uvec4"}; + static const char* const intTypes[] = {" ", "int", "ivec2", "ivec3", "ivec4"}; + static const char* const floatTypes[] = {" ", "float", "vec2", "vec3", "vec4"}; + + if (components < 1 || components > 4) + return "ERROR TOO MANY COMPONENTS IN VECTOR"; + + switch (eType) + { + case SVT_UINT: + return uintTypes[components]; + case SVT_INT: + return intTypes[components]; + case SVT_FLOAT: + return floatTypes[components]; + default: + return "ERROR UNSUPPORTED TYPE"; + } +} + +const char* GetConstructorForTypeFlag(const uint32_t ui32Flag, const int components) +{ + if (ui32Flag & TO_FLAG_UNSIGNED_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_UINT) + { + return GetConstructorForType(SVT_UINT, components); + } + else if (ui32Flag & TO_FLAG_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_INT) + { + return GetConstructorForType(SVT_INT, components); + } + else + { + return GetConstructorForType(SVT_FLOAT, components); + } +} + +int GetMaxComponentFromComponentMask(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) + { + // Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && + psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 4; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 3; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 1; + } + } + } + else + // Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + return 4; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return 1; + } + } + + return 4; +} + +// Single component repeated +// e..g .wwww +uint32_t IsSwizzleReplicated(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) + { + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == WWWW_SWIZZLE || psOperand->ui32Swizzle == ZZZZ_SWIZZLE || psOperand->ui32Swizzle == YYYY_SWIZZLE || + psOperand->ui32Swizzle == XXXX_SWIZZLE) + { + return 1; + } + } + } + return 0; +} + +static uint32_t GLSLGetNumberBitsSet(uint32_t a) +{ + // Calculate number of bits in a + // Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 + // Works only up to 14 bits (we're only using up to 4) + return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; +} + +// e.g. +//.z = 1 +//.x = 1 +//.yw = 2 +uint32_t GetNumSwizzleElements(const Operand* psOperand) +{ + return GetNumSwizzleElementsWithMask(psOperand, OPERAND_4_COMPONENT_MASK_ALL); +} + +// Get the number of elements returned by operand, taking additional component mask into account +uint32_t GetNumSwizzleElementsWithMask(const Operand* psOperand, uint32_t ui32CompMask) +{ + uint32_t count = 0; + + switch (psOperand->eType) + { + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + return 1; // TODO: does mask make any sense here? + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + // Adjust component count and break to more processing + ((Operand*)psOperand)->iNumComponents = 3; + break; + case OPERAND_TYPE_IMMEDIATE32: + case OPERAND_TYPE_IMMEDIATE64: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return GLSLGetNumberBitsSet(compMask); + } + default: + { + break; + } + } + + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents != 1) + { + // Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t compMask = psOperand->ui32CompMask; + if (compMask == 0) + compMask = OPERAND_4_COMPONENT_MASK_ALL; + compMask &= ui32CompMask; + + if (compMask == OPERAND_4_COMPONENT_MASK_ALL) + return 4; + + if (compMask & OPERAND_4_COMPONENT_MASK_X) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_Y) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_Z) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_W) + { + count++; + } + } + else + // Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if ((ui32CompMask & (1 << i)) == 0) + continue; + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + count++; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + count++; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + count++; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + count++; + } + } + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && (ui32CompMask & OPERAND_4_COMPONENT_MASK_X)) + { + count++; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y && (ui32CompMask & OPERAND_4_COMPONENT_MASK_Y)) + { + count++; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z && (ui32CompMask & OPERAND_4_COMPONENT_MASK_Z)) + { + count++; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W && (ui32CompMask & OPERAND_4_COMPONENT_MASK_W)) + { + count++; + } + } + + // Component Select 1 + } + + if (!count) + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return GLSLGetNumberBitsSet(compMask); + } + + return count; +} + +void AddSwizzleUsingElementCount(HLSLCrossCompilerContext* psContext, uint32_t count) +{ + bstring glsl = *psContext->currentShaderString; + if (count == 4) + return; + if (count) + { + bcatcstr(glsl, "."); + bcatcstr(glsl, "x"); + count--; + } + if (count) + { + bcatcstr(glsl, "y"); + count--; + } + if (count) + { + bcatcstr(glsl, "z"); + count--; + } + if (count) + { + bcatcstr(glsl, "w"); + count--; + } +} + +static uint32_t GLSLConvertOperandSwizzleToComponentMask(const Operand* psOperand) +{ + uint32_t mask = 0; + + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) + { + // Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + mask = psOperand->ui32CompMask; + } + else + // Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + + // Component Select 1 + } + + return mask; +} + +// Non-zero means the components overlap +int CompareOperandSwizzles(const Operand* psOperandA, const Operand* psOperandB) +{ + uint32_t maskA = GLSLConvertOperandSwizzleToComponentMask(psOperandA); + uint32_t maskB = GLSLConvertOperandSwizzleToComponentMask(psOperandB); + + return maskA & maskB; +} + +void TranslateOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + TranslateOperandSwizzleWithMask(psContext, psOperand, OPERAND_4_COMPONENT_MASK_ALL); +} + +void TranslateOperandSwizzleWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask) +{ + bstring glsl = *psContext->currentShaderString; + + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return; + } + } + + if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + /*ConstantBuffer* psCBuf = NULL; + ShaderVar* psVar = NULL; + int32_t index = -1; + GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) + //then apply the sizzle. + + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); + + bformata(glsl, ".%s", psVar->Name); + if(index != -1) + { + bformata(glsl, "[%d]", index); + }*/ + + // return; + } + + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents != 1) + { + // Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t mask; + if (psOperand->ui32CompMask != 0) + mask = psOperand->ui32CompMask & ui32ComponentMask; + else + mask = ui32ComponentMask; + + if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) + { + bcatcstr(glsl, "."); + if (mask & OPERAND_4_COMPONENT_MASK_X) + { + bcatcstr(glsl, "x"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Y) + { + bcatcstr(glsl, "y"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Z) + { + bcatcstr(glsl, "z"); + } + if (mask & OPERAND_4_COMPONENT_MASK_W) + { + bcatcstr(glsl, "w"); + } + } + } + else + // Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || + !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && + psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W)) + { + uint32_t i; + + bcatcstr(glsl, "."); + + for (i = 0; i < 4; ++i) + { + if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) + continue; + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + bcatcstr(glsl, "x"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(glsl, "y"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(glsl, "z"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + bcatcstr(glsl, "w"); + } + } + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case + { + bcatcstr(glsl, "."); + + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + bcatcstr(glsl, "x"); + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(glsl, "y"); + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(glsl, "z"); + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + bcatcstr(glsl, "w"); + } + } + + // Component Select 1 + } +} + +int GetFirstOperandSwizzle(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return -1; + } + } + + if (psOperand->iWriteMaskEnabled && psOperand->iNumComponents == 4) + { + // Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && + psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 0; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 1; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 3; + } + } + } + else + // Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + + // Component Select 1 + } + + return -1; +} + +void TranslateOperandIndex(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) +{ + int i = index; + int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; + + bstring glsl = *psContext->currentShaderString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0 || isGeoShader) + { + bformata(glsl, "[%d]", psOperand->aui32ArraySizes[i]); + } + else + { + bformata(glsl, "%d", psOperand->aui32ArraySizes[i]); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(glsl, "["); // Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bformata(glsl, " + %d]", psOperand->aui32ArraySizes[i]); + break; + } + default: + { + break; + } + } +} + +void TranslateOperandIndexMAD(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) +{ + int i = index; + int isGeoShader = psContext->psShader->eShaderType == GEOMETRY_SHADER ? 1 : 0; + + bstring glsl = *psContext->currentShaderString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0 || isGeoShader) + { + bformata(glsl, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + } + else + { + bformata(glsl, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(glsl, "[int("); // Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); + bformata(glsl, ")*%d+%d]", multiply, add); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(glsl, "[(int("); // Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); + bformata(glsl, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + break; + } + default: + { + break; + } + } +} + +// Returns nonzero if a direct constructor can convert src->dest +static int GLSLCanDoDirectCast(HLSLCrossCompilerContext* psContext, SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) +{ + // Only option on pre-SM4 stuff + if (psContext->psShader->ui32MajorVersion < 4) + return 1; + + // uint<->int<->bool conversions possible + if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL) && (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL)) + return 1; + + // float<->double possible + if ((src == SVT_FLOAT || src == SVT_DOUBLE) && (dest == SVT_FLOAT || dest == SVT_DOUBLE)) + return 1; + + return 0; +} + +static const char* GetBitcastOp(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) +{ + if (to == SVT_FLOAT && from == SVT_INT) + return "intBitsToFloat"; + else if (to == SVT_FLOAT && from == SVT_UINT) + return "uintBitsToFloat"; + else if (to == SVT_INT && from == SVT_FLOAT) + return "floatBitsToInt"; + else if (to == SVT_UINT && from == SVT_FLOAT) + return "floatBitsToUint"; + + return "ERROR missing components in GetBitcastOp()"; +} + +// Helper function to print out a single 32-bit immediate value in desired format +static void GLSLprintImmediate32(HLSLCrossCompilerContext* psContext, uint32_t value, SHADER_VARIABLE_TYPE eType) +{ + bstring glsl = *psContext->currentShaderString; + int needsParenthesis = 0; + + // Print floats as bit patterns. + if (eType == SVT_FLOAT && psContext->psShader->ui32MajorVersion > 3) + { + bcatcstr(glsl, "intBitsToFloat("); + eType = SVT_INT; + needsParenthesis = 1; + } + + switch (eType) + { + default: + case SVT_INT: + // Need special handling for anything >= uint 0x3fffffff + if (value > 0x3ffffffe) + bformata(glsl, "int(0x%Xu)", value); + else + bformata(glsl, "0x%X", value); + break; + case SVT_UINT: + bformata(glsl, "%uu", value); + break; + case SVT_FLOAT: + bformata(glsl, "%f", *((float*)(&value))); + break; + } + if (needsParenthesis) + bcatcstr(glsl, ")"); +} + +static void GLSLGLSLTranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, + const Operand* psOperand, + uint32_t ui32TOFlag, + uint32_t* pui32IgnoreSwizzle, + uint32_t ui32CompMask) +{ + int numParenthesis = 0; + int hasCtor = 0; + bstring glsl = *psContext->currentShaderString; + SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTType(ui32TOFlag); + SHADER_VARIABLE_TYPE eType = GetOperandDataTypeEx(psContext, psOperand, requestedType); + int numComponents = GetNumSwizzleElementsWithMask(psOperand, ui32CompMask); + int requestedComponents = 0; + + if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC2) + requestedComponents = 2; + else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC3) + requestedComponents = 3; + else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC4) + requestedComponents = 4; + + requestedComponents = max(requestedComponents, numComponents); + + *pui32IgnoreSwizzle = 0; + + if (!(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) + { + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32 || psOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + // Mark the operand type to match whatever we're asking for in the flags. + ((Operand*)psOperand)->aeDataType[0] = requestedType; + ((Operand*)psOperand)->aeDataType[1] = requestedType; + ((Operand*)psOperand)->aeDataType[2] = requestedType; + ((Operand*)psOperand)->aeDataType[3] = requestedType; + } + + if (eType != requestedType) + { + if (GLSLCanDoDirectCast(psContext, eType, requestedType)) + { + bformata(glsl, "%s(", GetConstructorForType(requestedType, requestedComponents)); + numParenthesis++; + hasCtor = 1; + } + else + { + // Direct cast not possible, need to do bitcast. + bformata(glsl, "%s(", GetBitcastOp(eType, requestedType)); + numParenthesis++; + } + } + + // Add ctor if needed (upscaling) + if (numComponents < requestedComponents && (hasCtor == 0)) + { + ASSERT(numComponents == 1); + bformata(glsl, "%s(", GetConstructorForType(requestedType, requestedComponents)); + numParenthesis++; + hasCtor = 1; + } + } + + switch (psOperand->eType) + { + case OPERAND_TYPE_IMMEDIATE32: + { + if (psOperand->iNumComponents == 1) + { + GLSLprintImmediate32(psContext, *((unsigned int*)(&psOperand->afImmediates[0])), requestedType); + } + else + { + int i; + int firstItemAdded = 0; + if (hasCtor == 0) + { + bformata(glsl, "%s(", GetConstructorForType(requestedType, numComponents)); + numParenthesis++; + hasCtor = 1; + } + for (i = 0; i < 4; i++) + { + uint32_t uval; + if (!(ui32CompMask & (1 << i))) + continue; + + if (firstItemAdded) + bcatcstr(glsl, ", "); + uval = *((uint32_t*)(&psOperand->afImmediates[i])); + GLSLprintImmediate32(psContext, uval, requestedType); + firstItemAdded = 1; + } + bcatcstr(glsl, ")"); + *pui32IgnoreSwizzle = 1; + numParenthesis--; + } + break; + } + case OPERAND_TYPE_IMMEDIATE64: + { + if (psOperand->iNumComponents == 1) + { + bformata(glsl, "%f", psOperand->adImmediates[0]); + } + else + { + bformata(glsl, "dvec4(%f, %f, %f, %f)", psOperand->adImmediates[0], psOperand->adImmediates[1], psOperand->adImmediates[2], + psOperand->adImmediates[3]); + if (psOperand->iNumComponents != 4) + { + AddSwizzleUsingElementCount(psContext, psOperand->iNumComponents); + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + switch (psOperand->iIndexDims) + { + case INDEX_2D: + { + if (psOperand->aui32ArraySizes[1] == 0) // Input index zero - position. + { + bcatcstr(glsl, "gl_in"); + TranslateOperandIndex(psContext, psOperand, 0); // Vertex index + bcatcstr(glsl, ".gl_Position"); + } + else + { + const char* name = "Input"; + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); + } + + bformata(glsl, "%s%d", name, psOperand->aui32ArraySizes[1]); + TranslateOperandIndex(psContext, psOperand, 0); // Vertex index + } + break; + } + default: + { + if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) + { + bformata(glsl, "Input%d[", psOperand->ui32RegisterNumber); + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + } + else + { + if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) + { + const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; + bformata(glsl, "Input%d[%d]", parentIndex, psOperand->ui32RegisterNumber - parentIndex); + } + else + { + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + const char* name = GetDeclaredInputName(psContext, psContext->psShader->eShaderType, psOperand); + bcatcstr(glsl, name); + } + else + { + bformata(glsl, "Input%d", psOperand->ui32RegisterNumber); + } + } + } + break; + } + } + break; + } + case OPERAND_TYPE_OUTPUT: + { + bformata(glsl, "Output%d", psOperand->ui32RegisterNumber); + if (psOperand->psSubOperand[0]) + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_AUTO_BITCAST_TO_INT); + bcatcstr(glsl, "]"); + } + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bcatcstr(glsl, "gl_FragDepth"); + break; + } + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eType2 = GetOperandDataType(psContext, psOperand); + bcatcstr(glsl, "Temp"); + + if (eType2 == SVT_INT) + { + bcatcstr(glsl, "_int"); + } + else if (eType2 == SVT_UINT) + { + bcatcstr(glsl, "_uint"); + } + else if (eType2 == SVT_DOUBLE) + { + bcatcstr(glsl, "_double"); + } + else if (eType2 == SVT_VOID && (ui32TOFlag & TO_FLAG_DESTINATION)) + { + ASSERT(0 && "Should never get here!"); + /* if(ui32TOFlag & TO_FLAG_INTEGER) + { + bcatcstr(glsl, "_int"); + } + else + if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(glsl, "_uint"); + }*/ + } + + bformata(glsl, "[%d]", psOperand->ui32RegisterNumber); + + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONSTINT: + { + bformata(glsl, "IntImmConst%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONST: + { + if (psOperand->psSubOperand[0] != NULL) + { + if (psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] != 0) + bformata(glsl, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); + else + bcatcstr(glsl, "ImmConstArray["); + TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(glsl, "]"); + } + else + { + bformata(glsl, "ImmConst%d", psOperand->ui32RegisterNumber); + } + break; + } + case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: + { + bcatcstr(glsl, "BaseColour"); + break; + } + case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: + { + bcatcstr(glsl, "OffsetColour"); + break; + } + case OPERAND_TYPE_SPECIAL_POSITION: + { + bcatcstr(glsl, "gl_Position"); + break; + } + case OPERAND_TYPE_SPECIAL_FOG: + { + bcatcstr(glsl, "Fog"); + break; + } + case OPERAND_TYPE_SPECIAL_POINTSIZE: + { + bcatcstr(glsl, "gl_PointSize"); + break; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + { + bcatcstr(glsl, "Address"); + break; + } + case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: + { + bcatcstr(glsl, "LoopCounter"); + pui32IgnoreSwizzle[0] = 1; + break; + } + case OPERAND_TYPE_SPECIAL_TEXCOORD: + { + bformata(glsl, "TexCoord%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + const char* StageName = "VS"; + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + StageName = "PS"; + break; + } + case HULL_SHADER: + { + StageName = "HS"; + break; + } + case DOMAIN_SHADER: + { + StageName = "DS"; + break; + } + case GEOMETRY_SHADER: + { + StageName = "GS"; + break; + } + case COMPUTE_SHADER: + { + StageName = "CS"; + break; + } + default: + { + break; + } + } + + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + pui32IgnoreSwizzle[0] = 1; + } + + // FIXME: With ES 3.0 the buffer name is often not prepended to variable names + if (((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) && + ((psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT) != HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT)) + { + if (psCBuf) + { + //$Globals. + if (psCBuf->Name[0] == '$') + { + bformata(glsl, "Globals%s", StageName); + } + else + { + bformata(glsl, "%s%s", psCBuf->Name, StageName); + } + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(glsl, "."); + } + } + else + { + // bformata(glsl, "cb%d", psOperand->aui32ArraySizes[0]); + } + } + + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + // Work out the variable name. Don't apply swizzle to that variable yet. + int32_t rebase = 0; + + if (psCBuf && !psCBuf->blob) + { + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + + bformata(glsl, "%s", psVarType->FullName); + } + else if (psCBuf) + { + bformata(glsl, "%s%s_data", psCBuf->Name, StageName); + index = psOperand->aui32ArraySizes[1]; + } + else // We don't have a semantic for this variable, so try the raw dump appoach. + { + bformata(glsl, "cb%d.data", psOperand->aui32ArraySizes[0]); // + index = psOperand->aui32ArraySizes[1]; + } + + // Dx9 only? + if (psOperand->psSubOperand[0] != NULL) + { + // Array of matrices is treated as array of vec4s in HLSL, + // but that would mess up uniform types in GLSL. Do gymnastics. + uint32_t opFlags = TO_FLAG_INTEGER; + + if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays + bcatcstr(glsl, "[("); + TranslateOperand(psContext, psOperand->psSubOperand[0], opFlags); + bformata(glsl, ") / 4]"); + if (psContext->psShader->eTargetLanguage <= LANG_120) + { + bcatcstr(glsl, "[int(mod(float("); + TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); + bformata(glsl, "), 4.0))]"); + } + else + { + bcatcstr(glsl, "[(("); + TranslateOperandWithMask(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); + bformata(glsl, ") %% 4)]"); + } + } + else + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[0], opFlags); + bformata(glsl, "]"); + } + } + else if (index != -1 && psOperand->psSubOperand[1] != NULL) + { + // Array of matrices is treated as array of vec4s in HLSL, + // but that would mess up uniform types in GLSL. Do gymnastics. + SHADER_VARIABLE_TYPE eType2 = GetOperandDataType(psContext, psOperand->psSubOperand[1]); + uint32_t opFlags = TO_FLAG_INTEGER; + if (eType2 != SVT_INT && eType2 != SVT_UINT) + opFlags = TO_AUTO_BITCAST_TO_INT; + + if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays + bcatcstr(glsl, "[("); + TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); + bformata(glsl, " + %d) / 4]", index); + if (psContext->psShader->eTargetLanguage <= LANG_120) + { + bcatcstr(glsl, "[int(mod(float("); + TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); + bformata(glsl, " + %d), 4.0))]", index); + } + else + { + bcatcstr(glsl, "[(("); + TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); + bformata(glsl, " + %d) %% 4)]", index); + } + } + else + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[1], opFlags); + bformata(glsl, " + %d]", index); + } + } + else if (index != -1) + { + if ((psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays, open them up into vec4's + size_t matidx = index / 4; + size_t rowidx = index - (matidx * 4); + bformata(glsl, "[%d][%d]", matidx, rowidx); + } + else + { + bformata(glsl, "[%d]", index); + } + } + else if (psOperand->psSubOperand[1] != NULL) + { + bcatcstr(glsl, "["); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bcatcstr(glsl, "]"); + } + + if (psVarType && psVarType->Class == SVC_VECTOR) + { + switch (rebase) + { + case 4: + { + if (psVarType->Columns == 2) + { + //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) + bcatcstr(glsl, ".xxyx"); + } + else if (psVarType->Columns == 3) + { + //.x(GLSL) is .y(HLSL). .y(GLSL) is .z(HLSL) .z(GLSL) is .w(HLSL) + bcatcstr(glsl, ".xxyz"); + } + break; + } + case 8: + { + if (psVarType->Columns == 2) + { + //.x(GLSL) is .z(HLSL). .y(GLSL) is .w(HLSL) + bcatcstr(glsl, ".xxxy"); + } + break; + } + case 0: + default: + { + // No rebase, but extend to vec4. + if (psVarType->Columns == 2) + { + bcatcstr(glsl, ".xyxx"); + } + else if (psVarType->Columns == 3) + { + bcatcstr(glsl, ".xyzx"); + } + break; + } + } + } + + if (psVarType && psVarType->Class == SVC_SCALAR) + { + *pui32IgnoreSwizzle = 1; + } + } + break; + } + case OPERAND_TYPE_RESOURCE: + { + ResourceName(glsl, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_SAMPLER: + { + bformata(glsl, "Sampler%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_FUNCTION_BODY: + { + const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; + const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; + // const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; + const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; + const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; + const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; + + bformata(glsl, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); + break; + } + case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: + { + bcatcstr(glsl, "forkInstanceID"); + *pui32IgnoreSwizzle = 1; + return; + } + case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + { + bcatcstr(glsl, "immediateConstBufferF"); + + if (psOperand->psSubOperand[0]) + { + bcatcstr(glsl, "("); // Indexes must be integral. + TranslateOperand(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(glsl, ")"); + } + break; + } + case OPERAND_TYPE_INPUT_DOMAIN_POINT: + { + bcatcstr(glsl, "gl_TessCoord"); + break; + } + case OPERAND_TYPE_INPUT_CONTROL_POINT: + { + if (psOperand->aui32ArraySizes[1] == 0) // Input index zero - position. + { + bformata(glsl, "gl_in[%d].gl_Position", psOperand->aui32ArraySizes[0]); + } + else + { + bformata(glsl, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); + } + break; + } + case OPERAND_TYPE_NULL: + { + // Null register, used to discard results of operations + bcatcstr(glsl, "//null"); + break; + } + case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: + { + bcatcstr(glsl, "gl_InvocationID"); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + bcatcstr(glsl, "gl_SampleMask[0]"); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_COVERAGE_MASK: + { + bcatcstr(glsl, "gl_SampleMaskIn[0]"); + // Skip swizzle on scalar types. + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID: // SV_DispatchThreadID + { + bcatcstr(glsl, "gl_GlobalInvocationID"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: // SV_GroupThreadID + { + bcatcstr(glsl, "gl_LocalInvocationID"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: // SV_GroupID + { + bcatcstr(glsl, "gl_WorkGroupID"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: // SV_GroupIndex + { + bcatcstr(glsl, "gl_LocalInvocationIndex"); + *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. + break; + } + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + { + ResourceName(glsl, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); + break; + } + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + bformata(glsl, "TGSM%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_PRIMITIVEID: + { + bcatcstr(glsl, "gl_PrimitiveID"); + break; + } + case OPERAND_TYPE_INDEXABLE_TEMP: + { + bformata(glsl, "TempArray%d", psOperand->aui32ArraySizes[0]); + bcatcstr(glsl, "["); + if (psOperand->aui32ArraySizes[1] != 0 || !psOperand->psSubOperand[1]) + bformata(glsl, "%d", psOperand->aui32ArraySizes[1]); + + if (psOperand->psSubOperand[1]) + { + if (psOperand->aui32ArraySizes[1] != 0) + bcatcstr(glsl, "+"); + TranslateOperand(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + } + bcatcstr(glsl, "]"); + break; + } + case OPERAND_TYPE_STREAM: + { + bformata(glsl, "%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: + { + // In HLSL the instance id is uint, so cast here. + bcatcstr(glsl, "uint(gl_InvocationID)"); + break; + } + case OPERAND_TYPE_THIS_POINTER: + { + /* + The "this" register is a register that provides up to 4 pieces of information: + X: Which CB holds the instance data + Y: Base element offset of the instance data within the instance CB + Z: Base sampler index + W: Base Texture index + + Can be different for each function call + */ + break; + } + case OPERAND_TYPE_INPUT_PATCH_CONSTANT: + { + bformata(glsl, "myPatchConst%d", psOperand->ui32RegisterNumber); + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (hasCtor && (*pui32IgnoreSwizzle == 0)) + { + TranslateOperandSwizzleWithMask(psContext, psOperand, ui32CompMask); + *pui32IgnoreSwizzle = 1; + } + + while (numParenthesis != 0) + { + bcatcstr(glsl, ")"); + numParenthesis--; + } +} + +static void GLSLTranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) +{ + GLSLGLSLTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL); +} + +SHADER_VARIABLE_TYPE GetOperandDataType(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + return GetOperandDataTypeEx(psContext, psOperand, SVT_INT); +} + +SHADER_VARIABLE_TYPE GetOperandDataTypeEx(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates) +{ + switch (psOperand->eType) + { + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; + int i = 0; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + return psOperand->aeDataType[0]; + } + + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + for (; i < 4; ++i) + { + if (ui32CompMask & (1 << i)) + { + eCurrentType = psOperand->aeDataType[i]; + break; + } + } + +#ifdef _DEBUG + // Check if all elements have the same basic type. + for (; i < 4; ++i) + { + if (psOperand->ui32CompMask & (1 << i)) + { + if (eCurrentType != psOperand->aeDataType[i]) + { + ASSERT(0); + } + } + } +#endif + return eCurrentType; + } + + ASSERT(0); + + break; + } + case OPERAND_TYPE_OUTPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psOut; + + if (GetOutputSignatureFromRegister(psContext->currentPhase, ui32Register, psOperand->ui32CompMask, 0, &psContext->psShader->sInfo, &psOut)) + { + if (psOut->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psIn; + + // UINT in DX, INT in GL. + if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) + { + return SVT_INT; + } + + if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) + { + if (psIn->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + int32_t rebase = -1; + int foundVar; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + if (psCBuf && !psCBuf->blob) + { + foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) + { + return psVarType->Type; + } + } + else + { + // Todo: this isn't correct yet. + return SVT_FLOAT; + } + break; + } + case OPERAND_TYPE_IMMEDIATE32: + { + return ePreferredTypeForImmediates; + } + + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + { + return SVT_UINT; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: + { + return SVT_INT; + } + case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: + { + return SVT_UINT; + } + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + return SVT_INT; + } + case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: + { + return SVT_INT; + } + default: + { + return SVT_FLOAT; + } + } + + return SVT_FLOAT; +} + +void TranslateOperand(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) +{ + TranslateOperandWithMask(psContext, psOperand, ui32TOFlag, OPERAND_4_COMPONENT_MASK_ALL); +} + +void TranslateOperandWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t ui32IgnoreSwizzle = 0; + + if (psContext->psShader->ui32MajorVersion <= 3) + { + ui32TOFlag &= ~(TO_AUTO_BITCAST_TO_FLOAT | TO_AUTO_BITCAST_TO_INT | TO_AUTO_BITCAST_TO_UINT); + } + + if (ui32TOFlag & TO_FLAG_NAME_ONLY) + { + GLSLTranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); + return; + } + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + bcatcstr(glsl, "(-"); + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(glsl, "abs("); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(glsl, "-abs("); + break; + } + } + + GLSLGLSLTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask); + + if (!ui32IgnoreSwizzle) + { + TranslateOperandSwizzleWithMask(psContext, psOperand, ui32ComponentMask); + } + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + bcatcstr(glsl, ")"); + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(glsl, ")"); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(glsl, ")"); + break; + } + } +} + +void ResourceName(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare) +{ + bstring glsl = (targetStr == NULL) ? *psContext->currentShaderString : targetStr; + ResourceBinding* psBinding = 0; + int found; + + found = GetResourceFromBindingPoint(group, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + + if (bZCompare) + { + bcatcstr(glsl, "hlslcc_zcmp"); + } + + if (found) + { + int i = 0; + char name[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32ArrayOffset = ui32RegisterNumber - psBinding->ui32BindPoint; + + while (psBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) + { + name[i] = psBinding->Name[i]; + + // array syntax [X] becomes _0_ + // Otherwise declarations could end up as: + // uniform sampler2D SomeTextures[0]; + // uniform sampler2D SomeTextures[1]; + if (name[i] == '[' || name[i] == ']') + name[i] = '_'; + + ++i; + } + + name[i] = '\0'; + + if (ui32ArrayOffset) + { + bformata(glsl, "%s%d", name, ui32ArrayOffset); + } + else + { + bformata(glsl, "%s", name); + } + } + else + { + bformata(glsl, "UnknownResource%d", ui32RegisterNumber); + } +} + +bstring TextureSamplerName(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) +{ + bstring result; + ResourceBinding* psTextureBinding = 0; + ResourceBinding* psSamplerBinding = 0; + int foundTexture, foundSampler; + uint32_t i = 0; + char textureName[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32ArrayOffset; + + foundTexture = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegisterNumber, psShaderInfo, &psTextureBinding); + foundSampler = GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegisterNumber, psShaderInfo, &psSamplerBinding); + + if (!foundTexture || !foundSampler) + { + result = bformat("UnknownResource%d_%d", ui32TextureRegisterNumber, ui32SamplerRegisterNumber); + return result; + } + + ui32ArrayOffset = ui32TextureRegisterNumber - psTextureBinding->ui32BindPoint; + + while (psTextureBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) + { + textureName[i] = psTextureBinding->Name[i]; + + // array syntax [X] becomes _0_ + // Otherwise declarations could end up as: + // uniform sampler2D SomeTextures[0]; + // uniform sampler2D SomeTextures[1]; + if (textureName[i] == '[' || textureName[i] == ']') + { + textureName[i] = '_'; + } + + ++i; + } + textureName[i] = '\0'; + + result = bfromcstr(""); + + if (bZCompare) + { + bcatcstr(result, "hlslcc_zcmp"); + } + + if (ui32ArrayOffset) + { + bformata(result, "%s%d_X_%s", textureName, ui32ArrayOffset, psSamplerBinding->Name); + } + else + { + if ((i > 0) && (textureName[i - 1] == '_')) // Prevent double underscore which is reserved + { + bformata(result, "%sX_%s", textureName, psSamplerBinding->Name); + } + else + { + bformata(result, "%s_X_%s", textureName, psSamplerBinding->Name); + } + } + + return result; +} + +void ConcatTextureSamplerName(bstring str, + ShaderInfo* psShaderInfo, + const uint32_t ui32TextureRegisterNumber, + const uint32_t ui32SamplerRegisterNumber, + const int bZCompare) +{ + bstring texturesamplername = TextureSamplerName(psShaderInfo, ui32TextureRegisterNumber, ui32SamplerRegisterNumber, bZCompare); + bconcat(str, texturesamplername); + bdestroy(texturesamplername); +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c new file mode 100644 index 0000000000..8e3a719950 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETAL.c @@ -0,0 +1,440 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/tokens.h" +#include "internal_includes/structs.h" +#include "internal_includes/decode.h" +#include "stdlib.h" +#include "stdio.h" +#include "bstrlib.h" +#include "internal_includes/toMETALInstruction.h" +#include "internal_includes/toMETALOperand.h" +#include "internal_includes/toMETALDeclaration.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/structsMetal.h" + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); +extern void UpdateFullName(ShaderVarType* psParentVarType); +extern void MangleIdentifiersPerStage(ShaderData* psShader); + + +void TranslateToMETAL(HLSLCrossCompilerContext* psContext, ShaderLang* planguage) +{ + bstring metal; + uint32_t i; + ShaderData* psShader = psContext->psShader; + ShaderLang language = *planguage; + uint32_t ui32InstCount = 0; + uint32_t ui32DeclCount = 0; + + psContext->indent = 0; + + /*psShader->sPhase[MAIN_PHASE].ui32InstanceCount = 1; + psShader->sPhase[MAIN_PHASE].ppsDecl = hlslcc_malloc(sizeof(Declaration*)); + psShader->sPhase[MAIN_PHASE].ppsInst = hlslcc_malloc(sizeof(Instruction*)); + psShader->sPhase[MAIN_PHASE].pui32DeclCount = hlslcc_malloc(sizeof(uint32_t)); + psShader->sPhase[MAIN_PHASE].pui32InstCount = hlslcc_malloc(sizeof(uint32_t));*/ + + if(language == LANG_DEFAULT) + { + language = LANG_METAL; + *planguage = language; + } + + metal = bfromcstralloc (1024, ""); + + psContext->mainShader = metal; + psContext->stagedInputDeclarations = bfromcstralloc(1024, ""); + psContext->parameterDeclarations = bfromcstralloc(1024, ""); + psContext->declaredOutputs = bfromcstralloc(1024, ""); + psContext->earlyMain = bfromcstralloc (1024, ""); + for(i=0; i<NUM_PHASES;++i) + { + psContext->postShaderCode[i] = bfromcstralloc (1024, ""); + } + + psContext->needsFragmentTestHint = 0; + + for (i = 0; i < MAX_COLOR_MRT; i++) + psContext->gmemOutputNumElements[i] = 0; + + psContext->currentShaderString = &metal; + psShader->eTargetLanguage = language; + psContext->currentPhase = MAIN_PHASE; + + bcatcstr(metal, "#include <metal_stdlib>\n"); + bcatcstr(metal, "using namespace metal;\n"); + + + bcatcstr(metal, "struct float1 {\n"); + bcatcstr(metal, "\tfloat x;\n"); + bcatcstr(metal, "};\n"); + + bcatcstr(metal, "struct uint1 {\n"); + bcatcstr(metal, "\tuint x;\n"); + bcatcstr(metal, "};\n"); + + bcatcstr(metal, "struct int1 {\n"); + bcatcstr(metal, "\tint x;\n"); + bcatcstr(metal, "};\n"); + + + ui32InstCount = psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; + ui32DeclCount = psShader->asPhase[MAIN_PHASE].pui32DeclCount[0]; + + AtomicVarList atomicList; + atomicList.Filled = 0; + atomicList.Size = ui32InstCount; + atomicList.AtomicVars = (const ShaderVarType**)hlslcc_malloc(ui32InstCount * sizeof(ShaderVarType*)); + + for (i = 0; i < ui32InstCount; ++i) + { + DetectAtomicInstructionMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0] + i, i + 1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0] + i + 1 : 0, &atomicList); + } + + for(i=0; i < ui32DeclCount; ++i) + { + TranslateDeclarationMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsDecl[0] + i, &atomicList); + } + + if(psContext->psShader->ui32NumDx9ImmConst) + { + bformata(psContext->mainShader, "float4 ImmConstArray [%d];\n", psContext->psShader->ui32NumDx9ImmConst); + } + + MarkIntegerImmediatesMETAL(psContext); + + SetDataTypesMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0], ui32InstCount); + + switch (psShader->eShaderType) + { + case VERTEX_SHADER: + { + int hasStageInput = 0; + int hasOutput = 0; + if (blength(psContext->stagedInputDeclarations) > 0) + { + hasStageInput = 1; + bcatcstr(metal, "struct metalVert_stageIn\n{\n"); + bconcat(metal, psContext->stagedInputDeclarations); + bcatcstr(metal, "};\n"); + } + if (blength(psContext->declaredOutputs) > 0) + { + hasOutput = 1; + bcatcstr(metal, "struct metalVert_out\n{\n"); + bconcat(metal, psContext->declaredOutputs); + bcatcstr(metal, "};\n"); + } + + bformata(metal, "vertex %s metalMain(\n%s", + hasOutput ? "metalVert_out" : "void", + hasStageInput ? "\tmetalVert_stageIn stageIn [[ stage_in ]]" : ""); + + int userInputDeclLength = blength(psContext->parameterDeclarations); + if (userInputDeclLength > 2) + { + if (hasStageInput) + bformata(metal, ",\n"); + bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove ",\n" + } + + bconcat(metal, psContext->parameterDeclarations); + bcatcstr(metal, hasOutput ? "\t)\n{\n\tmetalVert_out output;\n" : ")\n{\n"); + break; + } + case PIXEL_SHADER: + { + int hasStageInput = 0; + int hasOutput = 0; + int userInputDeclLength = blength(psContext->parameterDeclarations); + if (blength(psContext->stagedInputDeclarations) > 0) + { + hasStageInput = 1; + bcatcstr(metal, "struct metalFrag_stageIn\n{\n"); + bconcat(metal, psContext->stagedInputDeclarations); + bcatcstr(metal, "};\n"); + } + if (blength(psContext->declaredOutputs) > 0) + { + hasOutput = 1; + bcatcstr(metal, "struct metalFrag_out\n{\n"); + bconcat(metal, psContext->declaredOutputs); + bcatcstr(metal, "};\n"); + } + + bcatcstr(metal, "fragment "); + if (psContext->needsFragmentTestHint) + { + bcatcstr(metal, "\n#ifndef MTLLanguage1_1\n"); + bcatcstr(metal, "[[ early_fragment_tests ]]\n"); + bcatcstr(metal, "#endif\n"); + } + + bformata(metal, "%s metalMain(\n%s", hasOutput ? "metalFrag_out" : "void", + hasStageInput ? "\tmetalFrag_stageIn stageIn [[ stage_in ]]" : ""); + if (userInputDeclLength > 2) + { + if (hasStageInput) + bcatcstr(metal, ",\n"); + bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space + } + bconcat(metal, psContext->parameterDeclarations); + bcatcstr(metal, hasOutput ? ")\n{\n\tmetalFrag_out output;\n" : ")\n{\n"); + break; + } + case COMPUTE_SHADER: + { + int hasStageInput = 0; + int hasOutput = 0; + if (blength(psContext->stagedInputDeclarations) > 0) + { + hasStageInput = 1; + bcatcstr(metal, "struct metalCompute_stageIn\n{\n"); + bconcat(metal, psContext->stagedInputDeclarations); + bcatcstr(metal, "};\n"); + } + if (blength(psContext->declaredOutputs) > 0) + { + hasOutput = 1; + bcatcstr(metal, "struct metalCompute_out\n{\n"); + bconcat(metal, psContext->declaredOutputs); + bcatcstr(metal, "};\n"); + } + + bformata(metal, "kernel %s metalMain(\n%s", + hasOutput ? "metalCompute_out" : "void", + hasStageInput ? "\tmetalCompute_stageIn stageIn [[ stage_in ]]" : ""); + + int userInputDeclLength = blength(psContext->parameterDeclarations); + if (userInputDeclLength > 2) + { + if (hasStageInput) + bformata(metal, ",\n"); + bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove ",\n" + } + + bconcat(metal, psContext->parameterDeclarations); + bcatcstr(metal, hasOutput ? "\t)\n{\n\tmetalCompute_out output;\n" : ")\n{\n"); + break; + } + default: + { + ASSERT(0); + // Geometry, Hull, and Domain shaders unsupported by Metal + // int userInputDeclLength = blength(psContext->parameterDeclarations); + // if (blength(psContext->outputDeclarations) > 0) + // { + // bcatcstr(metal, "struct metalComp_out\n{\n"); + // bconcat(metal, psContext->outputDeclarations); + // bcatcstr(metal, "};\n"); + // if (userInputDeclLength > 2) + // bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space + // bformata(metal, "kernel metalComp_out metalMain(%s)\n{\n\tmetalComp_out output;\n", psContext->parameterDeclarations); + // } + // else + // { + // if (userInputDeclLength > 2) + // bdelete(psContext->parameterDeclarations, userInputDeclLength - 2, 2); // remove the trailing comma and space + // bformata(metal, "kernel void metalMain(%s)\n{\n", psContext->parameterDeclarations); + // } + break; + } + } + + psContext->indent++; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//--- Start Early Main ---\n"); +#endif + bconcat(metal, psContext->earlyMain); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//--- End Early Main ---\n"); +#endif + + + for(i=0; i < ui32InstCount; ++i) + { + TranslateInstructionMETAL(psContext, psShader->asPhase[MAIN_PHASE].ppsInst[0]+i, i+1 < ui32InstCount ? psShader->asPhase[MAIN_PHASE].ppsInst[0]+i+1 : 0); + } + + hlslcc_free((void*)atomicList.AtomicVars); + + psContext->indent--; + + bcatcstr(metal, "}\n"); +} + +static void FreeSubOperands(Instruction* psInst, const uint32_t ui32NumInsts) +{ + uint32_t ui32Inst; + for(ui32Inst = 0; ui32Inst < ui32NumInsts; ++ui32Inst) + { + Instruction* psCurrentInst = &psInst[ui32Inst]; + const uint32_t ui32NumOperands = psCurrentInst->ui32NumOperands; + uint32_t ui32Operand; + + for(ui32Operand = 0; ui32Operand < ui32NumOperands; ++ui32Operand) + { + uint32_t ui32SubOperand; + for(ui32SubOperand = 0; ui32SubOperand < MAX_SUB_OPERANDS; ++ui32SubOperand) + { + if(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]) + { + hlslcc_free(psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand]); + psCurrentInst->asOperands[ui32Operand].psSubOperand[ui32SubOperand] = NULL; + } + } + } + } +} + +typedef enum { + MTLFunctionTypeVertex = 1, + MTLFunctionTypeFragment = 2, + MTLFunctionTypeKernel = 3 +} MTLFunctionType; + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromMemToMETAL(const char* shader, + unsigned int flags, + ShaderLang language, + Shader* result) +{ + uint32_t* tokens; + ShaderData* psShader; + char* glslcstr = NULL; + int ShaderType = MTLFunctionTypeFragment; + int success = 0; + uint32_t i; + + tokens = (uint32_t*)shader; + + psShader = DecodeDXBC(tokens); + + if(psShader) + { + HLSLCrossCompilerContext sContext; + + sContext.psShader = psShader; + sContext.flags = flags; + + for(i=0; i<NUM_PHASES;++i) + { + sContext.havePostShaderCode[i] = 0; + } + + TranslateToMETAL(&sContext, &language); + + switch(psShader->eShaderType) + { + case VERTEX_SHADER: + { + ShaderType = MTLFunctionTypeVertex; + break; + } + case COMPUTE_SHADER: + { + ShaderType = MTLFunctionTypeKernel; + break; + } + default: + { + break; + } + } + + glslcstr = bstr2cstr(sContext.mainShader, '\0'); + + bdestroy(sContext.mainShader); + bdestroy(sContext.earlyMain); + for(i=0; i<NUM_PHASES; ++i) + { + bdestroy(sContext.postShaderCode[i]); + } + + for(i=0; i<NUM_PHASES;++i) + { + if(psShader->asPhase[i].ppsDecl != 0) + { + uint32_t k; + for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) + { + hlslcc_free(psShader->asPhase[i].ppsDecl[k]); + } + hlslcc_free(psShader->asPhase[i].ppsDecl); + } + if(psShader->asPhase[i].ppsInst != 0) + { + uint32_t k; + for(k=0; k < psShader->asPhase[i].ui32InstanceCount; ++k) + { + FreeSubOperands(psShader->asPhase[i].ppsInst[k], psShader->asPhase[i].pui32InstCount[k]); + hlslcc_free(psShader->asPhase[i].ppsInst[k]); + } + hlslcc_free(psShader->asPhase[i].ppsInst); + } + } + + memcpy(&result->reflection,&psShader->sInfo,sizeof(psShader->sInfo)); + + result->textureSamplerInfo.ui32NumTextureSamplerPairs = psShader->textureSamplerInfo.ui32NumTextureSamplerPairs; + for (i=0; i<result->textureSamplerInfo.ui32NumTextureSamplerPairs; i++) + strcpy(result->textureSamplerInfo.aTextureSamplerPair[i].Name, psShader->textureSamplerInfo.aTextureSamplerPair[i].Name); + + hlslcc_free(psShader); + + success = 1; + } + + shader = 0; + tokens = 0; + + /* Fill in the result struct */ + + result->shaderType = ShaderType; + result->sourceCode = glslcstr; + result->GLSLLanguage = language; + + return success; +} + +HLSLCC_API int HLSLCC_APIENTRY TranslateHLSLFromFileToMETAL(const char* filename, + unsigned int flags, + ShaderLang language, + Shader* result) +{ + FILE* shaderFile; + int length; + size_t readLength; + char* shader; + int success = 0; + + shaderFile = fopen(filename, "rb"); + + if(!shaderFile) + { + return 0; + } + + fseek(shaderFile, 0, SEEK_END); + length = ftell(shaderFile); + fseek(shaderFile, 0, SEEK_SET); + + shader = (char*)hlslcc_malloc(length+1); + + readLength = fread(shader, 1, length, shaderFile); + + fclose(shaderFile); + shaderFile = 0; + + shader[readLength] = '\0'; + + success = TranslateHLSLFromMemToMETAL(shader, flags, language, result); + + hlslcc_free(shader); + + return success; +} \ No newline at end of file diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c new file mode 100644 index 0000000000..79dcb809fd --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALDeclaration.c @@ -0,0 +1,2281 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "hlslcc.h" +#include "internal_includes/toMETALDeclaration.h" +#include "internal_includes/toMETALOperand.h" +#include "internal_includes/languages.h" +#include "bstrlib.h" +#include "internal_includes/debug.h" +#include "internal_includes/hlslcc_malloc.h" +#include "internal_includes/structsMetal.h" +#include <math.h> +#include <float.h> + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wpointer-sign" +#endif + +#ifdef _MSC_VER +#ifndef isnan +#define isnan(x) _isnan(x) +#endif + +#ifndef isinf +#define isinf(x) (!_finite(x)) +#endif +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) + +typedef enum +{ + GLVARTYPE_FLOAT, + GLVARTYPE_INT, + GLVARTYPE_FLOAT4, +} GLVARTYPE; + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +const char* GetTypeStringMETAL(GLVARTYPE eType) +{ + switch (eType) + { + case GLVARTYPE_FLOAT: + { + return "float"; + } + case GLVARTYPE_INT: + { + return "int"; + } + case GLVARTYPE_FLOAT4: + { + return "float4"; + } + default: + { + return ""; + } + } +} +const uint32_t GetTypeElementCountMETAL(GLVARTYPE eType) +{ + switch (eType) + { + case GLVARTYPE_FLOAT: + case GLVARTYPE_INT: + { + return 1; + } + case GLVARTYPE_FLOAT4: + { + return 4; + } + default: + { + return 0; + } + } +} + +void AddToDx9ImmConstIndexableArrayMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + bstring* savedStringPtr = psContext->currentShaderString; + + psContext->currentShaderString = &psContext->earlyMain; + psContext->indent++; + AddIndentation(psContext); + psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] = psContext->psShader->ui32NumDx9ImmConst; + bformata(psContext->earlyMain, "ImmConstArray[%d] = ", psContext->psShader->ui32NumDx9ImmConst); + TranslateOperandMETAL(psContext, psOperand, TO_FLAG_NONE); + bcatcstr(psContext->earlyMain, ";\n"); + psContext->indent--; + psContext->psShader->ui32NumDx9ImmConst++; + + psContext->currentShaderString = savedStringPtr; +} + +void DeclareConstBufferShaderVariableMETAL(bstring metal, const char* Name, const struct ShaderVarType_TAG* psType, int pointerType, int const createDummyAlignment, AtomicVarList* psAtomicList) +//const SHADER_VARIABLE_CLASS eClass, const SHADER_VARIABLE_TYPE eType, +//const char* pszName) +{ + if (psType->Class == SVC_STRUCT) + { + bformata(metal, "%s_Type %s%s", Name, pointerType ? "*" : "", Name); + if (psType->Elements > 1) + { + bformata(metal, "[%d]", psType->Elements); + } + } + else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) + { + switch (psType->Type) + { + case SVT_FLOAT: + { + bformata(metal, "\tfloat%d %s%s[%d", psType->Columns, pointerType ? "*" : "", Name, psType->Rows); + break; + } + case SVT_FLOAT16: + { + bformata(metal, "\thalf%d %s%s[%d", psType->Columns, pointerType ? "*" : "", Name, psType->Rows); + break; + } + default: + { + ASSERT(0); + break; + } + } + if (psType->Elements > 1) + { + bformata(metal, " * %d", psType->Elements); + } + bformata(metal, "]"); + } + else + if (psType->Class == SVC_VECTOR) + { + switch (psType->Type) + { + case SVT_DOUBLE: + case SVT_FLOAT: + { + bformata(metal, "\tfloat%d %s%s", psType->Columns, pointerType ? "*" : "", Name); + break; + } + case SVT_FLOAT16: + { + bformata(metal, "\thalf%d %s%s", psType->Columns, pointerType ? "*" : "", Name); + break; + } + case SVT_UINT: + { + bformata(metal, "\tuint%d %s%s", psType->Columns, pointerType ? "*" : "", Name); + break; + } + case SVT_INT: + case SVT_BOOL: + { + bformata(metal, "\tint%d %s%s", psType->Columns, pointerType ? "*" : "", Name); + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (psType->Elements > 1) + { + bformata(metal, "[%d]", psType->Elements); + } + } + else + if (psType->Class == SVC_SCALAR) + { + switch (psType->Type) + { + case SVT_DOUBLE: + case SVT_FLOAT: + { + bformata(metal, "\tfloat %s%s", pointerType ? "*" : "", Name); + break; + } + case SVT_FLOAT16: + { + bformata(metal, "\thalf %s%s", pointerType ? "*" : "", Name); + break; + } + case SVT_UINT: + { + if (IsAtomicVar(psType, psAtomicList)) + { + bformata(metal, "\tvolatile atomic_uint %s%s", pointerType ? "*" : "", Name); + } + else + { + bformata(metal, "\tuint %s%s", pointerType ? "*" : "", Name); + } + break; + } + case SVT_INT: + { + if (IsAtomicVar(psType, psAtomicList)) + { + bformata(metal, "\tvolatile atomic_int %s%s", pointerType ? "*" : "", Name); + } + else + { + bformata(metal, "\tint %s%s", pointerType ? "*" : "", Name); + } + break; + } + case SVT_BOOL: + { + //Use int instead of bool. + //Allows implicit conversions to integer and + //bool consumes 4-bytes in HLSL and metal anyway. + bformata(metal, "\tint %s%s", pointerType ? "*" : "", Name); + // Also change the definition in the type tree. + ((ShaderVarType*)psType)->Type = SVT_INT; + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (psType->Elements > 1) + { + bformata(metal, "[%d]", psType->Elements); + } + } + if (!pointerType) + { + bformata(metal, ";\n"); + } + + // We need to add more dummies if float2 or less since they are not 16 bytes aligned + // float = 4 + // float2 = 8 + // float3 = float4 = 16 + // https://developer.apple.com/library/ios/documentation/Metal/Reference/MetalShadingLanguageGuide/data-types/data-types.html + if (createDummyAlignment) + { + uint16_t sizeInBytes = 16; + if (1 == psType->Columns) + { + sizeInBytes = 4; + } + else if (2 == psType->Columns) + { + sizeInBytes = 8; + } + + if (4 == sizeInBytes) + { + bformata(metal, "\tfloat offsetDummy_4Bytes_%s;\n", Name); + bformata(metal, "\tfloat2 offsetDummy_8Bytes_%s;\n", Name); + } + else if (8 == sizeInBytes) + { + bformata(metal, "\tfloat2 offsetDummy_8Bytes_%s;\n", Name); + } + } +} + +//In metal embedded structure definitions are not supported. +void PreDeclareStructTypeMETAL(bstring metal, const char* Name, const struct ShaderVarType_TAG* psType, AtomicVarList* psAtomicList) +{ + uint32_t i; + + for (i = 0; i < psType->MemberCount; ++i) + { + if (psType->Members[i].Class == SVC_STRUCT) + { + PreDeclareStructTypeMETAL(metal, psType->Members[i].Name, &psType->Members[i], psAtomicList); + } + } + + if (psType->Class == SVC_STRUCT) + { +#if defined(_DEBUG) + uint32_t unnamed_struct = strcmp(Name, "$Element") == 0 ? 1 : 0; +#endif + + //Not supported at the moment + ASSERT(!unnamed_struct); + + bformata(metal, "struct %s_Type {\n", Name); + + for (i = 0; i < psType->MemberCount; ++i) + { + ASSERT(psType->Members != 0); + + DeclareConstBufferShaderVariableMETAL(metal, psType->Members[i].Name, &psType->Members[i], 0, 0, psAtomicList); + } + + bformata(metal, "};\n"); + } +} + +char* GetDeclaredInputNameMETAL(const HLSLCrossCompilerContext* psContext, const SHADER_TYPE eShaderType, const Operand* psOperand) +{ + bstring inputName; + char* cstr; + InOutSignature* psIn; + + if (eShaderType == PIXEL_SHADER) + { + inputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else + { + ASSERT(eShaderType == VERTEX_SHADER); + inputName = bformat("dcl_Input%d", psOperand->ui32RegisterNumber); + } + if ((psContext->flags & HLSLCC_FLAG_INOUT_SEMANTIC_NAMES) && GetInputSignatureFromRegister(psOperand->ui32RegisterNumber, &psContext->psShader->sInfo, &psIn)) + { + bformata(inputName, "_%s%d", psIn->SemanticName, psIn->ui32SemanticIndex); + } + + cstr = bstr2cstr(inputName, '\0'); + bdestroy(inputName); + return cstr; +} + +char* GetDeclaredOutputNameMETAL(const HLSLCrossCompilerContext* psContext, + const SHADER_TYPE eShaderType, + const Operand* psOperand) +{ + bstring outputName = bformat(""); + char* cstr; + InOutSignature* psOut; + +#if defined(_DEBUG) + int foundOutput = +#endif + GetOutputSignatureFromRegister( + psContext->currentPhase, + psOperand->ui32RegisterNumber, + psOperand->ui32CompMask, + psContext->psShader->ui32CurrentVertexOutputStream, + &psContext->psShader->sInfo, + &psOut); + + ASSERT(foundOutput); + + if (eShaderType == VERTEX_SHADER) + { + outputName = bformat("VtxOutput%d", psOperand->ui32RegisterNumber); + } + else if (eShaderType == PIXEL_SHADER) + { + outputName = bformat("PixOutput%d", psOperand->ui32RegisterNumber); + } + + if (psContext->flags & HLSLCC_FLAG_INOUT_APPEND_SEMANTIC_NAMES) + { + bformata(outputName, "_%s%d", psOut->SemanticName, psOut->ui32SemanticIndex); + } + + cstr = bstr2cstr(outputName, '\0'); + bdestroy(outputName); + return cstr; +} + +const char* GetInterpolationStringMETAL(INTERPOLATION_MODE eMode) +{ + switch (eMode) + { + case INTERPOLATION_CONSTANT: + { + return "flat"; + } + case INTERPOLATION_LINEAR: + { + return "center_perspective"; + } + case INTERPOLATION_LINEAR_CENTROID: + { + return "centroid_perspective"; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE: + { + return "center_no_perspective"; + break; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_CENTROID: + { + return "centroid_no_perspective"; + } + case INTERPOLATION_LINEAR_SAMPLE: + { + return "sample_perspective"; + } + case INTERPOLATION_LINEAR_NOPERSPECTIVE_SAMPLE: + { + return "sample_no_perspective"; + } + default: + { + return ""; + } + } +} + +static void DeclareInput( + HLSLCrossCompilerContext* psContext, + const Declaration* psDecl, const char* StorageQualifier, OPERAND_MIN_PRECISION minPrecision, int iNumComponents, OPERAND_INDEX_DIMENSION eIndexDim, const char* InputName) +{ + ShaderData* psShader = psContext->psShader; + psContext->currentShaderString = &psContext->parameterDeclarations; + bstring metal = *psContext->currentShaderString; + + // This falls within the specified index ranges. The default is 0 if no input range is specified + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + return; + } + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + + InOutSignature* psSignature = NULL; + + const char* type = "float"; + if (minPrecision == OPERAND_MIN_PRECISION_FLOAT_16) + { + type = "half"; + } + if (GetInputSignatureFromRegister(psDecl->asOperands[0].ui32RegisterNumber, &psShader->sInfo, &psSignature)) + { + switch (psSignature->eComponentType) + { + case INOUT_COMPONENT_UINT32: + { + type = "uint"; + break; + } + case INOUT_COMPONENT_SINT32: + { + type = "int"; + break; + } + case INOUT_COMPONENT_FLOAT32: + { + break; + } + } + } + + bstring qual = bfromcstralloc(256, StorageQualifier); + + if (biseqcstr(qual, "attribute")) + { + bformata(qual, "(%d)", psDecl->asOperands[0].ui32RegisterNumber); + psContext->currentShaderString = &psContext->stagedInputDeclarations; + metal = *psContext->currentShaderString; + } + else if (biseqcstr(qual, "user")) + { + bformata(qual, "(varying%d)", psDecl->asOperands[0].ui32RegisterNumber); + psContext->currentShaderString = &psContext->stagedInputDeclarations; + metal = *psContext->currentShaderString; + } + else if (biseqcstr(qual, "buffer")) + { + bformata(qual, "(%d)", psDecl->asOperands[0].ui32RegisterNumber); + } + + if (metal == psContext->stagedInputDeclarations) + { + bformata(metal, "\t%s", type); + if (iNumComponents > 1) + { + bformata(metal, "%d", iNumComponents); + } + } + else + { + if (iNumComponents > 1) + { + bformata(metal, "\tdevice %s%d*", type, iNumComponents); + } + else + { + bformata(metal, "\tdevice %s*", type, iNumComponents); + } + } + + + if (psDecl->asOperands[0].eType == OPERAND_TYPE_SPECIAL_TEXCOORD) + { + InputName = "TexCoord"; + } + + bformata(metal, " %s", InputName); + + switch (eIndexDim) + { + case INDEX_2D: + { + if (iNumComponents == 1) + { + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + + const uint32_t arraySize = psDecl->asOperands[0].aui32ArraySizes[0]; + + bformata(metal, " [%d]", arraySize); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = arraySize; + break; + } + default: + { + if (iNumComponents == 1) + { + psContext->psShader->abScalarInput[psDecl->asOperands[0].ui32RegisterNumber] = 1; + } + else + { + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] > 0) + { + bformata(metal, "[%d]", type, iNumComponents, InputName, + psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]; + } + else + { + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = -1; + } + } + break; + } + } + + if (blength(qual) > 0) + { + bformata(metal, " [[ %s ]]", bdata(qual)); + } + bdestroy(qual); + + bformata(metal, "%c\n", (metal == psContext->stagedInputDeclarations) ? ';' : ','); + + if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) + { + const char* stageInString = (metal == psContext->stagedInputDeclarations) ? "stageIn." : ""; + const char* bufferAccessString = (metal == psContext->stagedInputDeclarations) ? "" : "[vId]"; + + psContext->currentShaderString = &psContext->earlyMain; + metal = *psContext->currentShaderString; + psContext->indent++; + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == -1) //Not an array + { + AddIndentation(psContext); + bformata(metal, "%s%d Input%d = %s%s%s;\n", type, iNumComponents, + psDecl->asOperands[0].ui32RegisterNumber, stageInString, InputName, bufferAccessString); + } + else + { + int arrayIndex = psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber]; + bformata(metal, "%s%d Input%d[%d];\n", type, iNumComponents, psDecl->asOperands[0].ui32RegisterNumber, + psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber]); + + while (arrayIndex) + { + AddIndentation(psContext); + bformata(metal, "Input%d[%d] = %s%s%s[%d];\n", psDecl->asOperands[0].ui32RegisterNumber, arrayIndex - 1, + stageInString, InputName, bufferAccessString, arrayIndex - 1); + + arrayIndex--; + } + } + psContext->indent--; + } + } + psContext->currentShaderString = &psContext->mainShader; +} + +static void AddBuiltinInputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const char* builtinName, const char* type) +{ + psContext->currentShaderString = &psContext->stagedInputDeclarations; + bstring metal = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + char* InputName = GetDeclaredInputNameMETAL(psContext, PIXEL_SHADER, &psDecl->asOperands[0]); + + if (psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] == 0) + { + // CONFETTI NOTE: DAVID SROUR + // vertex_id and instance_id must be part of the function's params -- not part of stage_in! + if (psDecl->asOperands[0].eSpecialName == NAME_INSTANCE_ID || psDecl->asOperands[0].eSpecialName == NAME_VERTEX_ID) + { + bformata(psContext->parameterDeclarations, "\t%s %s [[ %s ]],\n", type, &psDecl->asOperands[0].pszSpecialName, builtinName); + } + else + { + bformata(metal, "\t%s %s [[ %s ]];\n", type, InputName, builtinName); + } + + psShader->aiInputDeclaredSize[psDecl->asOperands[0].ui32RegisterNumber] = 1; + } + + if (psShader->abInputReferencedByInstruction[psDecl->asOperands[0].ui32RegisterNumber]) + { + psContext->currentShaderString = &psContext->earlyMain; + metal = *psContext->currentShaderString; + psContext->indent++; + AddIndentation(psContext); + + if (psDecl->asOperands[0].eSpecialName == NAME_INSTANCE_ID || psDecl->asOperands[0].eSpecialName == NAME_VERTEX_ID) + { + bformata(metal, "uint4 "); + bformata(metal, "Input%d; Input%d.x = %s;\n", + psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, &psDecl->asOperands[0].pszSpecialName); + } + else if (!strcmp(type, "bool")) + { + bformata(metal, "int4 "); + bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", + psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else if (!strcmp(type, "float")) + { + bformata(metal, "float4 "); + bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", + psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else if (!strcmp(type, "int")) + { + bformata(metal, "int4 "); + bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", + psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else if (!strcmp(type, "uint")) + { + bformata(metal, "uint4 "); + bformata(metal, "Input%d; Input%d.x = stageIn.%s;\n", + psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + else + { + bformata(metal, "%s Input%d = stageIn.%s;\n", type, + psDecl->asOperands[0].ui32RegisterNumber, InputName); + } + + if (psDecl->asOperands[0].eSpecialName == NAME_POSITION) + { + if (psContext->psShader->eShaderType == PIXEL_SHADER) + { + if (psDecl->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE && + psDecl->asOperands[0].eType == OPERAND_TYPE_INPUT) + { + if (psDecl->asOperands[0].ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + bformata(metal, "Input%d.w = 1.0 / Input%d.w;", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); + } + } + } + } + + psContext->indent--; + } + bcstrfree(InputName); + + psContext->currentShaderString = &psContext->mainShader; +} + +int OutputNeedsDeclaringMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, const int count) +{ + ShaderData* psShader = psContext->psShader; + + // Depth Output operands are a special case and won't have a ui32RegisterNumber, + // so first we have to check if the output operand is depth. + if (psShader->eShaderType == PIXEL_SHADER) + { + if (psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL || + psOperand->eType == OPERAND_TYPE_OUTPUT_DEPTH) + { + return 1; + } + } + + const uint32_t declared = ((psContext->currentPhase + 1) << 3) | psShader->ui32CurrentVertexOutputStream; + ASSERT(psOperand->ui32RegisterNumber >= 0); + ASSERT(psOperand->ui32RegisterNumber < MAX_SHADER_VEC4_OUTPUT); + if (psShader->aiOutputDeclared[psOperand->ui32RegisterNumber] != declared) + { + int offset; + + for (offset = 0; offset < count; offset++) + { + psShader->aiOutputDeclared[psOperand->ui32RegisterNumber + offset] = declared; + } + return 1; + } + + return 0; +} + +void AddBuiltinOutputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, const GLVARTYPE type, int arrayElements, const char* builtinName) +{ + (void)type; + + bstring metal = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + psContext->havePostShaderCode[psContext->currentPhase] = 1; + + if (OutputNeedsDeclaringMETAL(psContext, &psDecl->asOperands[0], arrayElements ? arrayElements : 1)) + { + psContext->currentShaderString = &psContext->declaredOutputs; + metal = *psContext->currentShaderString; + InOutSignature* psSignature = NULL; + + int regNum = psDecl->asOperands[0].ui32RegisterNumber; + + GetOutputSignatureFromRegister(psContext->currentPhase, regNum, + psDecl->asOperands[0].ui32CompMask, + 0, + &psShader->sInfo, &psSignature); + + if (psDecl->asOperands[0].eSpecialName == NAME_CLIP_DISTANCE) + { + int max = GetMaxComponentFromComponentMaskMETAL(&psDecl->asOperands[0]); + bformata(metal, "\tfloat %s [%d] [[ %s ]];\n", builtinName, max, builtinName); + } + else + { + bformata(metal, "\tfloat4 %s [[ %s ]];\n", builtinName, builtinName); + } + bformata(metal, "#define Output%d output.%s\n", regNum, builtinName); + + psContext->currentShaderString = &psContext->mainShader; + } +} + +void AddUserOutputMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl) +{ + psContext->currentShaderString = &psContext->declaredOutputs; + bstring metal = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + if (OutputNeedsDeclaringMETAL(psContext, &psDecl->asOperands[0], 1)) + { + const Operand* psOperand = &psDecl->asOperands[0]; + const char* type = "\tfloat"; + const SHADER_VARIABLE_TYPE eOutType = GetOperandDataTypeMETAL(psContext, &psDecl->asOperands[0]); + + switch (eOutType) + { + case SVT_UINT: + { + type = "\tuint"; + break; + } + case SVT_INT: + { + type = "\tint"; + break; + } + case SVT_FLOAT16: + { + type = "\thalf"; + break; + } + case SVT_FLOAT: + { + break; + } + } + + switch (psShader->eShaderType) + { + case PIXEL_SHADER: + { + switch (psDecl->asOperands[0].eType) + { + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH: + { + bformata(metal, "%s PixOutDepthAny [[ depth(any) ]];\n", type); + bformata(metal, "#define DepthAny output.PixOutDepthAny\n"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + { + bformata(metal, "%s PixOutDepthGreater [[ depth(greater) ]];\n", type); + bformata(metal, "#define DepthGreater output.PixOutDepthGreater\n"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bformata(metal, "%s PixOutDepthLess [[ depth(less) ]];\n", type); + bformata(metal, "#define DepthLess output.PixOutDepthLess\n"); + break; + } + default: + { + uint32_t renderTarget = psDecl->asOperands[0].ui32RegisterNumber; + + if (!psContext->gmemOutputNumElements[psDecl->asOperands[0].ui32RegisterNumber]) + { + bformata(metal, "%s4 PixOutColor%d [[ color(%d) ]];\n", type, renderTarget, renderTarget); + } + else // GMEM output type must match the input! + { + bformata(metal, "float%d PixOutColor%d [[ color(%d) ]];\n", psContext->gmemOutputNumElements[psDecl->asOperands[0].ui32RegisterNumber], renderTarget, renderTarget); + } + bformata(metal, "#define Output%d output.PixOutColor%d\n", psDecl->asOperands[0].ui32RegisterNumber, renderTarget); + + break; + } + } + break; + } + case VERTEX_SHADER: + { + int iNumComponents = 4;//GetMaxComponentFromComponentMaskMETAL(&psDecl->asOperands[0]); + char* OutputName = GetDeclaredOutputNameMETAL(psContext, VERTEX_SHADER, psOperand); + + bformata(metal, "%s%d %s [[ user(varying%d) ]];\n", type, iNumComponents, OutputName, psDecl->asOperands[0].ui32RegisterNumber); + bformata(metal, "#define Output%d output.%s\n", psDecl->asOperands[0].ui32RegisterNumber, OutputName); + bcstrfree(OutputName); + + break; + } + } + } + + psContext->currentShaderString = &psContext->mainShader; +} + +void DeclareBufferVariableMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, + ConstantBuffer* psCBuf, const Operand* psOperand, + const ResourceType eResourceType, + bstring metal, AtomicVarList* psAtomicList) +{ + (void)ui32BindingPoint; + + bstring StructName; +#if !defined(NDEBUG) + uint32_t unnamed_struct = strcmp(psCBuf->asVars[0].Name, "$Element") == 0 ? 1 : 0; +#endif + + ASSERT(psCBuf->ui32NumVars == 1); + ASSERT(unnamed_struct); + + StructName = bfromcstr(""); + + //TranslateOperandMETAL(psContext, psOperand, TO_FLAG_NAME_ONLY); + if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_STRUCTURED) + { + ResourceNameMETAL(StructName, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); + } + else if (psOperand->eType == OPERAND_TYPE_RESOURCE && eResourceType == RTYPE_UAV_RWBYTEADDRESS) + { + bformata(StructName, "RawRes%d", psOperand->ui32RegisterNumber); + } + else + { + ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); + } + + PreDeclareStructTypeMETAL(metal, + bstr2cstr(StructName, '\0'), + &psCBuf->asVars[0].sType, psAtomicList); + + + bcatcstr(psContext->parameterDeclarations, "\t"); + if (eResourceType == RTYPE_STRUCTURED) + { + bcatcstr(psContext->parameterDeclarations, "constant "); + } + else + { + bcatcstr(psContext->parameterDeclarations, "device "); + } + + + DeclareConstBufferShaderVariableMETAL(psContext->parameterDeclarations, + bstr2cstr(StructName, '\0'), + &psCBuf->asVars[0].sType, + 1, 0, psAtomicList); + if (eResourceType == RTYPE_UAV_RWSTRUCTURED) + { + //If it is UAV raw structured, let Metal compiler assign it with the first available location index + bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", psOperand->ui32RegisterNumber + UAV_BUFFER_START_SLOT); + //modify the reflection data to match the binding index + int count = 0; + for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) + { + if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) + { + count++; + //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; + psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_CBUFFER; + } + } + //If count >2, the logic here is wrong and need to be modified. + ASSERT(count < 2); + } + else + { + bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", psOperand->ui32RegisterNumber); + } + + bdestroy(StructName); +} + +static uint32_t ComputeVariableTypeSize(const ShaderVarType* psType) +{ + if (psType->Class == SVC_STRUCT) + { + uint32_t i; + uint32_t size = 0; + for (i = 0; i < psType->MemberCount; ++i) + { + size += ComputeVariableTypeSize(&psType->Members[i]); + } + + if (psType->Elements > 1) + { + return size * psType->Elements; + } + else + { + return size; + } + } + else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) + { + if (psType->Elements > 1) + { + return psType->Rows * psType->Elements; + } + else + { + return psType->Rows; + } + } + else + if (psType->Class == SVC_VECTOR) + { + if (psType->Elements > 1) + { + return psType->Elements; + } + else + { + return 1; + } + } + + return 1; +} + + +void DeclareStructConstantsMETAL(HLSLCrossCompilerContext* psContext, const uint32_t ui32BindingPoint, + ConstantBuffer* psCBuf, const Operand* psOperand, + bstring metal, AtomicVarList* psAtomicList) +{ + (void)psOperand; + + uint32_t i; + const char* StageName = "VS"; + uint32_t nextBufferRegister = 0; + uint32_t numDummyBuffers = 0; + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + PreDeclareStructTypeMETAL(metal, + psCBuf->asVars[i].sType.Name, + &psCBuf->asVars[i].sType, psAtomicList); + } + + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + StageName = "PS"; + break; + } + case COMPUTE_SHADER: + { + StageName = "CS"; + break; + } + default: + { + break; + } + } + + bformata(metal, "struct %s%s_Type {\n", psCBuf->Name, StageName); + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + uint32_t ui32RegNum = psCBuf->asVars[i].ui32StartOffset / 16; + if (ui32RegNum > nextBufferRegister) + { + bformata(metal, "\tfloat4 offsetDummy_%d[%d];\n", numDummyBuffers++, ui32RegNum - nextBufferRegister); + } + + DeclareConstBufferShaderVariableMETAL(metal, + psCBuf->asVars[i].sType.Name, + &psCBuf->asVars[i].sType, 0, i < psCBuf->ui32NumVars - 1, psAtomicList); + + uint32_t varSize = ComputeVariableTypeSize(&psCBuf->asVars[i].sType); + nextBufferRegister = ui32RegNum + varSize; + } + + bcatcstr(metal, "};\n"); + + bcatcstr(psContext->parameterDeclarations, "\tconstant "); + bformata(psContext->parameterDeclarations, "%s%s_Type ", psCBuf->Name, StageName); + bcatcstr(psContext->parameterDeclarations, "& "); + + bformata(psContext->parameterDeclarations, "%s%s_In", psCBuf->Name, StageName); + bformata(psContext->parameterDeclarations, " [[ buffer(%d) ]],\n", ui32BindingPoint); + + for (i = 0; i < psCBuf->ui32NumVars; ++i) + { + const struct ShaderVarType_TAG* psType = &psCBuf->asVars[i].sType; + const char* Name = psCBuf->asVars[i].sType.Name; + const char* addressSpace = "constant"; + + if (psType->Class == SVC_STRUCT) + { + bformata(psContext->earlyMain, "\t%s %s_Type%s const &%s", addressSpace, Name, psType->Elements > 1 ? "*" : "", Name); + } + else if (psType->Class == SVC_MATRIX_COLUMNS || psType->Class == SVC_MATRIX_ROWS) + { + switch (psType->Type) + { + case SVT_FLOAT: + { + bformata(psContext->earlyMain, "\t%s float%d%s const &%s", addressSpace, psType->Columns, "*", Name, psType->Rows); + break; + } + case SVT_FLOAT16: + { + bformata(psContext->earlyMain, "\t%s half%d%s const &%s", addressSpace, psType->Columns, "*", Name, psType->Rows); + break; + } + default: + { + ASSERT(0); + break; + } + } + } + else + if (psType->Class == SVC_VECTOR) + { + switch (psType->Type) + { + case SVT_FLOAT: + case SVT_DOUBLE: // double is not supported in metal + { + bformata(psContext->earlyMain, "\t%s float%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_FLOAT16: + { + bformata(psContext->earlyMain, "\t%s half%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_UINT: + { + bformata(psContext->earlyMain, "\t%s uint%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_INT: + { + bformata(psContext->earlyMain, "\t%s int%d%s const &%s", addressSpace, psType->Columns, psType->Elements > 1 ? "*" : "", Name); + break; + } + default: + { + ASSERT(0); + break; + } + } + } + else + if (psType->Class == SVC_SCALAR) + { + switch (psType->Type) + { + case SVT_FLOAT: + case SVT_DOUBLE: // double is not supported in metal + { + bformata(psContext->earlyMain, "\t%s float%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_FLOAT16: + { + bformata(psContext->earlyMain, "\t%s half%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_UINT: + { + bformata(psContext->earlyMain, "\t%s uint%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_INT: + { + bformata(psContext->earlyMain, "\t%s int%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); + break; + } + case SVT_BOOL: + { + //Use int instead of bool. + //Allows implicit conversions to integer + bformata(psContext->earlyMain, "\t%s int%s const &%s", addressSpace, psType->Elements > 1 ? "*" : "", Name); + break; + } + default: + { + ASSERT(0); + break; + } + } + } + + bformata(psContext->earlyMain, " = %s%s_In.%s;\n", psCBuf->Name, StageName, psCBuf->asVars[i].sType.Name); + } +} + +char* GetSamplerTypeMETAL(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eDimension, + const uint32_t ui32RegisterNumber, const uint32_t isShadow) +{ + ResourceBinding* psBinding = 0; + RESOURCE_RETURN_TYPE eType = RETURN_TYPE_UNORM; + int found; + found = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + if (found) + { + eType = (RESOURCE_RETURN_TYPE)psBinding->ui32ReturnType; + } + switch (eDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + switch (eType) + { + case RETURN_TYPE_SINT: + return ""; + case RETURN_TYPE_UINT: + return ""; + default: + return ""; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1D: + { + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture1d<int>"; + case RETURN_TYPE_UINT: + return "\ttexture1d<uint>"; + default: + return "\ttexture1d<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2D: + { + if (isShadow) + { + return "\tdepth2d<float>"; + } + + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture2d<int>"; + case RETURN_TYPE_UINT: + return "\ttexture2d<uint>"; + default: + return "\ttexture2d<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + if (isShadow) + { + return "\tdepth2d_ms<float>"; + } + + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture2d_ms<int>"; + case RETURN_TYPE_UINT: + return "\ttexture2d_ms<uint>"; + default: + return "\ttexture2d_ms<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + { + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture3d<int>"; + case RETURN_TYPE_UINT: + return "\ttexture3d<uint>"; + default: + return "\ttexture3d<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBE: + { + if (isShadow) + { + return "\tdepthcube<float>"; + } + + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexturecube<int>"; + case RETURN_TYPE_UINT: + return "\ttexturecube<uint>"; + default: + return "\ttexturecube<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture1d_array<int>"; + case RETURN_TYPE_UINT: + return "\ttexture1d_array<uint>"; + default: + return "\ttexture1d_array<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + if (isShadow) + { + return "\tdepth2d_array<float>"; + } + + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexture2d_array<int>"; + case RETURN_TYPE_UINT: + return "\ttexture2d_array<uint>"; + default: + return "\ttexture2d_array<float>"; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + //Metal does not support this type of resource + ASSERT(0); + switch (eType) + { + case RETURN_TYPE_SINT: + return ""; + case RETURN_TYPE_UINT: + return ""; + default: + return ""; + } + break; + } + + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + switch (eType) + { + case RETURN_TYPE_SINT: + return "\ttexturecube_array<int>"; + case RETURN_TYPE_UINT: + return "\ttexturecube_array<uint>"; + default: + return "\ttexturecube_array<float>"; + } + break; + } + } + + return "sampler2D"; +} + +static void TranslateResourceTexture(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, uint32_t samplerCanDoShadowCmp) +{ + bstring metal = *psContext->currentShaderString; + + const char* samplerTypeName = GetSamplerTypeMETAL(psContext, + psDecl->value.eResourceDimension, + psDecl->asOperands[0].ui32RegisterNumber, samplerCanDoShadowCmp && psDecl->ui32IsShadowTex); + + if (samplerCanDoShadowCmp && psDecl->ui32IsShadowTex) + { + //Create shadow and non-shadow sampler. + //HLSL does not have separate types for depth compare, just different functions. + bcatcstr(metal, samplerTypeName); + bcatcstr(metal, " "); + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 1); + } + else + { + bcatcstr(metal, samplerTypeName); + bcatcstr(metal, " "); + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, 0); + } +} + +void TranslateDeclarationMETAL(HLSLCrossCompilerContext* psContext, const Declaration* psDecl, AtomicVarList* psAtomicList) +{ + bstring metal = *psContext->currentShaderString; + ShaderData* psShader = psContext->psShader; + + switch (psDecl->eOpcode) + { + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_PS_SGV: + { + const SPECIAL_NAME eSpecialName = psDecl->asOperands[0].eSpecialName; + + if (psShader->eShaderType == PIXEL_SHADER) + { + switch (eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinInputMETAL(psContext, psDecl, "position", "float4"); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinInputMETAL(psContext, psDecl, "clip_distance", "float"); + break; + } + case NAME_INSTANCE_ID: + { + AddBuiltinInputMETAL(psContext, psDecl, "instance_id", "uint"); + break; + } + case NAME_IS_FRONT_FACE: + { + /* + Cast to int used because + if(gl_FrontFacing != 0) failed to compiled on Intel HD 4000. + Suggests no implicit conversion for bool<->int. + */ + + AddBuiltinInputMETAL(psContext, psDecl, "front_facing", "bool"); + break; + } + case NAME_SAMPLE_INDEX: + { + AddBuiltinInputMETAL(psContext, psDecl, "sample_id", "uint"); + break; + } + default: + { + DeclareInput(psContext, psDecl, + "user", OPERAND_MIN_PRECISION_DEFAULT, 4, INDEX_1D, psDecl->asOperands[0].pszSpecialName); + } + } + } + else if (psShader->eShaderType == VERTEX_SHADER) + { + switch (eSpecialName) + { + case NAME_VERTEX_ID: + { + AddBuiltinInputMETAL(psContext, psDecl, "vertex_id", "uint"); + break; + } + case NAME_INSTANCE_ID: + { + AddBuiltinInputMETAL(psContext, psDecl, "instance_id", "uint"); + break; + } + default: + { + DeclareInput(psContext, psDecl, + "attribute", OPERAND_MIN_PRECISION_DEFAULT, 4, INDEX_1D, psDecl->asOperands[0].pszSpecialName); + } + } + } + break; + } + + case OPCODE_DCL_OUTPUT_SIV: + { + switch (psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinOutputMETAL(psContext, psDecl, GLVARTYPE_FLOAT4, 0, "position"); + break; + } + case NAME_CLIP_DISTANCE: + { + AddBuiltinOutputMETAL(psContext, psDecl, GLVARTYPE_FLOAT, 0, "clip_distance"); + break; + } + case NAME_VERTEX_ID: + { + ASSERT(0); //VertexID is not an output + break; + } + case NAME_INSTANCE_ID: + { + ASSERT(0); //InstanceID is not an output + break; + } + case NAME_IS_FRONT_FACE: + { + ASSERT(0); //FrontFacing is not an output + break; + } + default: + { + bformata(metal, "float4 %s;\n", psDecl->asOperands[0].pszSpecialName); + + bcatcstr(metal, "#define "); + TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(metal, " %s\n", psDecl->asOperands[0].pszSpecialName); + break; + } + } + break; + } + case OPCODE_DCL_INPUT: + { + const Operand* psOperand = &psDecl->asOperands[0]; + //Force the number of components to be 4. + /*dcl_output o3.xy + dcl_output o3.z + + Would generate a vec2 and a vec3. We discard the second one making .z invalid! + + */ + int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); + const char* InputName; + + if ((psOperand->eType == OPERAND_TYPE_INPUT_DOMAIN_POINT) || + (psOperand->eType == OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID) || + (psOperand->eType == OPERAND_TYPE_INPUT_COVERAGE_MASK) || + (psOperand->eType == OPERAND_TYPE_INPUT_FORK_INSTANCE_ID)) + { + break; + } + if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID) + { + bformata(psContext->parameterDeclarations, "\tuint3 vThreadID [[ thread_position_in_grid ]],\n"); + break; + } + if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP) + { + bformata(psContext->parameterDeclarations, "\tuint3 vThreadIDInGroup [[ thread_position_in_threadgroup ]],\n"); + break; + } + if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_GROUP_ID) + { + bformata(psContext->parameterDeclarations, "\tuint3 vThreadGroupID [[ threadgroup_position_in_grid ]],\n"); + break; + } + if (psOperand->eType == OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED) + { + bformata(psContext->parameterDeclarations, "\tuint vThreadIDInGroupFlattened [[ thread_index_in_threadgroup ]],\n"); + break; + } + //Already declared as part of an array. + if (psShader->aIndexedInput[psDecl->asOperands[0].ui32RegisterNumber] == -1) + { + break; + } + + InputName = GetDeclaredInputNameMETAL(psContext, psShader->eShaderType, psOperand); + + DeclareInput(psContext, psDecl, + "attribute", (OPERAND_MIN_PRECISION)psOperand->eMinPrecision, iNumComponents, (OPERAND_INDEX_DIMENSION)psOperand->iIndexDims, InputName); + + break; + } + case OPCODE_DCL_INPUT_PS_SIV: + { + switch (psDecl->asOperands[0].eSpecialName) + { + case NAME_POSITION: + { + AddBuiltinInputMETAL(psContext, psDecl, "position", "float4"); + break; + } + } + break; + } + case OPCODE_DCL_INPUT_SIV: + { + break; + } + case OPCODE_DCL_INPUT_PS: + { + const Operand* psOperand = &psDecl->asOperands[0]; + int iNumComponents = 4;//GetMaxComponentFromComponentMask(psOperand); + const char* InputName = GetDeclaredInputNameMETAL(psContext, PIXEL_SHADER, psOperand); + + DeclareInput(psContext, psDecl, + "user", (OPERAND_MIN_PRECISION)psOperand->eMinPrecision, iNumComponents, INDEX_1D, InputName); + + break; + } + case OPCODE_DCL_TEMPS: + { + const uint32_t ui32NumTemps = psDecl->value.ui32NumTemps; + + if (ui32NumTemps > 0) + { + bformata(psContext->earlyMain, "\tfloat4 Temp[%d];\n", ui32NumTemps); + + bformata(psContext->earlyMain, "\tint4 Temp_int[%d];\n", ui32NumTemps); + bformata(psContext->earlyMain, "\tuint4 Temp_uint[%d];\n", ui32NumTemps); + bformata(psContext->earlyMain, "\thalf4 Temp_half[%d];\n", ui32NumTemps); + } + + break; + } + case OPCODE_SPECIAL_DCL_IMMCONST: + { + const Operand* psDest = &psDecl->asOperands[0]; + const Operand* psSrc = &psDecl->asOperands[1]; + + ASSERT(psSrc->eType == OPERAND_TYPE_IMMEDIATE32); + if (psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT) + { + bformata(metal, "const int4 IntImmConst%d = ", psDest->ui32RegisterNumber); + } + else + { + bformata(metal, "const float4 ImmConst%d = ", psDest->ui32RegisterNumber); + AddToDx9ImmConstIndexableArrayMETAL(psContext, psDest); + } + TranslateOperandMETAL(psContext, psSrc, psDest->eType == OPERAND_TYPE_SPECIAL_IMMCONSTINT ? TO_FLAG_INTEGER : TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(metal, ";\n"); + + break; + } + case OPCODE_DCL_CONSTANT_BUFFER: + { + const Operand* psOperand = &psDecl->asOperands[0]; + const uint32_t ui32BindingPoint = psOperand->aui32ArraySizes[0]; + + const char* StageName = "VS"; + + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + StageName = "PS"; + break; + } + case HULL_SHADER: + { + StageName = "HS"; + break; + } + case DOMAIN_SHADER: + { + StageName = "DS"; + break; + } + case GEOMETRY_SHADER: + { + StageName = "GS"; + break; + } + case COMPUTE_SHADER: + { + StageName = "CS"; + break; + } + default: + { + break; + } + } + + ConstantBuffer* psCBuf = NULL; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + if (psCBuf) + { + // Constant buffers declared as "dynamicIndexed" are declared as raw vec4 arrays, as there is no general way to retrieve the member corresponding to a dynamic index. + // Simple cases can probably be handled easily, but for example when arrays (possibly nested with structs) are contained in the constant buffer and the shader reads + // from a dynamic index we would need to "undo" the operations done in order to compute the variable offset, and such a feature is not available at the moment. + psCBuf->blob = psDecl->value.eCBAccessPattern == CONSTANT_BUFFER_ACCESS_PATTERN_DYNAMICINDEXED; + } + + // We don't have a original resource name, maybe generate one??? + if (!psCBuf) + { + bformata(metal, "struct ConstantBuffer%d {\n\tfloat4 data[%d];\n};\n", ui32BindingPoint, psOperand->aui32ArraySizes[1], ui32BindingPoint); + // For vertex shaders HLSLcc generates code that expectes the + // constant buffer to be a pointer. For other shaders it generates + // code that expects a reference instead... + if (psContext->psShader->eShaderType == VERTEX_SHADER) + { + bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d* cb%d [[ buffer(%d) ]],\n", ui32BindingPoint, ui32BindingPoint, ui32BindingPoint); + } + else + { + bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d& cb%d [[ buffer(%d) ]],\n", ui32BindingPoint, ui32BindingPoint, ui32BindingPoint); + } + break; + } + else if (psCBuf->blob) + { + // For vertex shaders HLSLcc generates code that expectes the + // constant buffer to be a pointer. For other shaders it generates + // code that expects a reference instead... + bformata(metal, "struct ConstantBuffer%d {\n\tfloat4 %s[%d];\n};\n", ui32BindingPoint, psCBuf->asVars->Name, psOperand->aui32ArraySizes[1], ui32BindingPoint); + if (psContext->psShader->eShaderType == VERTEX_SHADER) + { + bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d* %s%s_data [[ buffer(%d) ]],\n", ui32BindingPoint, psCBuf->Name, StageName, ui32BindingPoint); + } + else + { + bformata(psContext->parameterDeclarations, "\tconstant ConstantBuffer%d& %s%s_data [[ buffer(%d) ]],\n", ui32BindingPoint, psCBuf->Name, StageName, ui32BindingPoint); + } + break; + } + + DeclareStructConstantsMETAL(psContext, ui32BindingPoint, psCBuf, psOperand, metal, psAtomicList); + + break; + } + case OPCODE_DCL_SAMPLER: + { + if (psDecl->bIsComparisonSampler) + { + psContext->currentShaderString = &psContext->mainShader; + metal = *psContext->currentShaderString; + + bcatcstr(metal, "constexpr sampler "); + ResourceNameMETAL(metal, psContext, RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, 1); + bformata(metal, "(compare_func::less);\n", psDecl->asOperands[0].ui32RegisterNumber); + } + + /* CONFETTI NOTE (DAVID SROUR): + * The following declaration still needs to occur for comparison samplers. + * The Metal layer of the engine will still try to bind a sampler in the appropriate slot. + * This parameter of the shader's entrance function acts as a dummy comparison sampler for the engine. + * Note that 0 is always passed for the "bZCompare" argument of ResourceNameMETAL(...) as to give the dummy + * sampler a different name as the constexpr one. + */ + { + psContext->currentShaderString = &psContext->parameterDeclarations; + metal = *psContext->currentShaderString; + + bcatcstr(metal, "\tsampler "); + ResourceNameMETAL(metal, psContext, RGROUP_SAMPLER, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(metal, "[[ sampler(%d) ]],\n", psDecl->asOperands[0].ui32RegisterNumber); + } + break; + } + case OPCODE_DCL_RESOURCE: + { + // CONFETTI BEGIN: David Srour + // METAL PIXEL SHADER RT FETCH + if (psDecl->asOperands[0].ui32RegisterNumber >= GMEM_FLOAT_START_SLOT) + { + int regNum = GetGmemInputResourceSlotMETAL(psDecl->asOperands[0].ui32RegisterNumber); + int numElements = GetGmemInputResourceNumElementsMETAL(psDecl->asOperands[0].ui32RegisterNumber); + + switch (numElements) + { + case 1: + bformata(psContext->parameterDeclarations, "\tfloat"); + break; + case 2: + bformata(psContext->parameterDeclarations, "\tfloat2"); + break; + case 3: + bformata(psContext->parameterDeclarations, "\tfloat3"); + break; + case 4: + bformata(psContext->parameterDeclarations, "\tfloat4"); + break; + default: + bformata(psContext->parameterDeclarations, "\tfloat4"); + break; + } + + psContext->gmemOutputNumElements[regNum] = numElements; + + // Function input framebuffer + bformata(psContext->parameterDeclarations, " GMEM_Input%d [[ color(%d) ]],\n", regNum, regNum); + + break; + } + // CONFETTI END + + psContext->currentShaderString = &psContext->parameterDeclarations; + metal = *psContext->currentShaderString; + + switch (psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_BUFFER: + { + break; + } + case RESOURCE_DIMENSION_TEXTURE1D: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + TranslateResourceTexture(psContext, psDecl, 0); + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + TranslateResourceTexture(psContext, psDecl, 0); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + TranslateResourceTexture(psContext, psDecl, 1); + break; + } + } + + bformata(metal, "[[ texture(%d) ]],\n", psDecl->asOperands[0].ui32RegisterNumber); + psContext->currentShaderString = &psContext->mainShader; + metal = *psContext->currentShaderString; + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_TEXTURES); + psShader->aeResourceDims[psDecl->asOperands[0].ui32RegisterNumber] = psDecl->value.eResourceDimension; + break; + } + case OPCODE_DCL_OUTPUT: + { + AddUserOutputMETAL(psContext, psDecl); + break; + } + case OPCODE_DCL_GLOBAL_FLAGS: + { + uint32_t ui32Flags = psDecl->value.ui32GlobalFlags; + + if (ui32Flags & GLOBAL_FLAG_FORCE_EARLY_DEPTH_STENCIL) + { + psContext->needsFragmentTestHint = 1; + } + if (!(ui32Flags & GLOBAL_FLAG_REFACTORING_ALLOWED)) + { + //TODO add precise + //HLSL precise - http://msdn.microsoft.com/en-us/library/windows/desktop/hh447204(v=vs.85).aspx + } + if (ui32Flags & GLOBAL_FLAG_ENABLE_DOUBLE_PRECISION_FLOAT_OPS) + { + // TODO + // Is there something for this in METAL? + } + + break; + } + + case OPCODE_DCL_THREAD_GROUP: + { + /* CONFETTI NOTE: + The thread group information need to be passed to engine side. Add the information + into reflection data. + */ + psContext->psShader->sInfo.ui32Thread_x = psDecl->value.aui32WorkGroupSize[0]; + psContext->psShader->sInfo.ui32Thread_y = psDecl->value.aui32WorkGroupSize[1]; + psContext->psShader->sInfo.ui32Thread_z = psDecl->value.aui32WorkGroupSize[2]; + break; + } + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + { + break; + } + case OPCODE_DCL_TESS_DOMAIN: + { + break; + } + case OPCODE_DCL_TESS_PARTITIONING: + { + break; + } + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + { + break; + } + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + { + break; + } + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + { + break; + } + case OPCODE_DCL_INTERFACE: + { + break; + } + case OPCODE_DCL_FUNCTION_BODY: + { + //bformata(metal, "void Func%d();//%d\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].eType); + break; + } + case OPCODE_DCL_FUNCTION_TABLE: + { + break; + } + case OPCODE_CUSTOMDATA: + { + const uint32_t ui32NumVec4 = psDecl->ui32NumOperands; + const uint32_t ui32NumVec4Minus1 = (ui32NumVec4 - 1); + uint32_t ui32ConstIndex = 0; + float x, y, z, w; + + //If ShaderBitEncodingSupported then 1 integer buffer, use intBitsToFloat to get float values. - More instructions. + //else 2 buffers - one integer and one float. - More data + + if (ShaderBitEncodingSupported(psShader->eTargetLanguage) == 0) + { + bcatcstr(metal, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(metal, "#define immediateConstBufferF(idx) immediateConstBuffer[idx]\n"); + + bformata(metal, "static constant float4 immediateConstBuffer[%d] = {\n", ui32NumVec4, ui32NumVec4); + for (; ui32ConstIndex < ui32NumVec4Minus1; ui32ConstIndex++) + { + float loopLocalX, loopLocalY, loopLocalZ, loopLocalW; + loopLocalX = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + loopLocalY = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + loopLocalZ = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + loopLocalW = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + + //A single vec4 can mix integer and float types. + //Forced NAN and INF to zero inside the immediate constant buffer. This will allow the shader to compile. + if (fpcheck(loopLocalX)) + { + loopLocalX = 0; + } + if (fpcheck(loopLocalY)) + { + loopLocalY = 0; + } + if (fpcheck(loopLocalZ)) + { + loopLocalZ = 0; + } + if (fpcheck(loopLocalW)) + { + loopLocalW = 0; + } + + bformata(metal, "\tfloat4(%f, %f, %f, %f), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); + } + //No trailing comma on this one + x = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].a; + y = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].b; + z = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].c; + w = *(float*)&psDecl->asImmediateConstBuffer[ui32ConstIndex].d; + if (fpcheck(x)) + { + x = 0; + } + if (fpcheck(y)) + { + y = 0; + } + if (fpcheck(z)) + { + z = 0; + } + if (fpcheck(w)) + { + w = 0; + } + bformata(metal, "\tfloat4(%f, %f, %f, %f)\n", x, y, z, w); + bcatcstr(metal, "};\n"); + } + else + { + bcatcstr(metal, "#define immediateConstBufferI(idx) immediateConstBufferInt[idx]\n"); + bcatcstr(metal, "#define immediateConstBufferF(idx) as_type<float4>(immediateConstBufferInt[idx])\n"); + } + + { + uint32_t ui32ConstIndex2 = 0; + int x2, y2, z2, w2; + + bformata(metal, "static constant int4 immediateConstBufferInt[%d] = {\n", ui32NumVec4, ui32NumVec4); + for (; ui32ConstIndex2 < ui32NumVec4Minus1; ui32ConstIndex2++) + { + int loopLocalX, loopLocalY, loopLocalZ, loopLocalW; + loopLocalX = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; + loopLocalY = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; + loopLocalZ = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; + loopLocalW = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; + + bformata(metal, "\tint4(%d, %d, %d, %d), \n", loopLocalX, loopLocalY, loopLocalZ, loopLocalW); + } + //No trailing comma on this one + x2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].a; + y2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].b; + z2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].c; + w2 = *(int*)&psDecl->asImmediateConstBuffer[ui32ConstIndex2].d; + + bformata(metal, "\tint4(%d, %d, %d, %d)\n", x2, y2, z2, w2); + bcatcstr(metal, "};\n"); + } + + break; + } + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + { + break; + } + case OPCODE_DCL_INDEXABLE_TEMP: + { + const uint32_t ui32RegIndex = psDecl->sIdxTemp.ui32RegIndex; + const uint32_t ui32RegCount = psDecl->sIdxTemp.ui32RegCount; + const uint32_t ui32RegComponentSize = psDecl->sIdxTemp.ui32RegComponentSize; + bformata(psContext->earlyMain, "float%d TempArray%d[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + bformata(psContext->earlyMain, "int%d TempArray%d_int[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + if (HaveUVec(psShader->eTargetLanguage)) + { + bformata(psContext->earlyMain, "uint%d TempArray%d_uint[%d];\n", ui32RegComponentSize, ui32RegIndex, ui32RegCount); + } + break; + } + case OPCODE_DCL_INDEX_RANGE: + { + break; + } + case OPCODE_HS_DECLS: + { + break; + } + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + { + break; + } + case OPCODE_HS_FORK_PHASE: + { + break; + } + case OPCODE_HS_JOIN_PHASE: + { + break; + } + case OPCODE_DCL_HS_MAX_TESSFACTOR: + { + //For metal the max tessellation factor is fixed to the value of gl_MaxTessGenLevel. + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + { + psContext->currentShaderString = &psContext->parameterDeclarations; + metal = *psContext->currentShaderString; + + if (psDecl->value.eResourceDimension == RESOURCE_DIMENSION_BUFFER) + { + { + //give write access + bcatcstr(metal, "\tdevice "); + } + switch (psDecl->sUAV.Type) + { + case RETURN_TYPE_FLOAT: + bcatcstr(metal, "float "); + break; + case RETURN_TYPE_UNORM: + bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_UNORM "); + break; + case RETURN_TYPE_SNORM: + bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_SNORM "); + break; + case RETURN_TYPE_UINT: + bcatcstr(metal, "uint "); + break; + case RETURN_TYPE_SINT: + bcatcstr(metal, "int "); + break; + default: + ASSERT(0); + } + bstring StructName; + StructName = bfromcstr(""); + ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(metal, " * "); + TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(metal, " [[buffer(%d)]], \n", psDecl->asOperands[0].ui32RegisterNumber + UAV_BUFFER_START_SLOT); + int count = 0; + for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) + { + if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) + { + count++; + //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; + psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_CBUFFER; + } + } + //If count >2, the logic here is wrong and need to be modified. + ASSERT(count < 2); + } + else + { + switch (psDecl->value.eResourceDimension) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + bformata(metal, "\ttexture1d<"); + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + bformata(metal, "\ttexture2d<"); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMS: + { + //metal does not support this + ASSERT(0); + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + bformata(metal, "\ttexture3d<"); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + bformata(metal, "\ttexturecube<"); + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + bformata(metal, "\ttexture1d_array<"); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + bformata(metal, "\ttexture2d_array<"); + break; + } + case RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + { + //metal does not suuport this. + ASSERT(0); + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + bformata(metal, "\ttexturecube_array<"); + break; + } + } + switch (psDecl->sUAV.Type) + { + case RETURN_TYPE_FLOAT: + bcatcstr(metal, "float "); + break; + case RETURN_TYPE_UNORM: + bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_UNORM "); + break; + case RETURN_TYPE_SNORM: + bcatcstr(metal, "TODO: OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED->RETURN_TYPE_SNORM "); + break; + case RETURN_TYPE_UINT: + bcatcstr(metal, "uint "); + break; + case RETURN_TYPE_SINT: + bcatcstr(metal, "int "); + break; + default: + ASSERT(0); + } + if (psShader->aiOpcodeUsed[OPCODE_STORE_UAV_TYPED] == 0) + { + bcatcstr(metal, "> "); + } + else + { + //give write access + bcatcstr(metal, ", access::write> "); + } + bstring StructName; + StructName = bfromcstr(""); + ResourceNameMETAL(StructName, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(metal, " [[texture(%d)]], \n", psDecl->asOperands[0].ui32RegisterNumber + UAV_BUFFER_START_SLOT); + int count = 0; + for (uint32_t index = 0; index < psContext->psShader->sInfo.ui32NumResourceBindings; index++) + { + if (strcmp(psContext->psShader->sInfo.psResourceBindings[index].Name, (const char*)StructName->data) == 0) + { + count++; + //psContext->psShader->sInfo.psResourceBindings[index].ui32BindPoint += UAV_BUFFER_START_SLOT; + psContext->psShader->sInfo.psResourceBindings[index].eBindArea = UAVAREA_TEXTURE; + } + } + //If count >2, the logic here is wrong and need to be modified. + ASSERT(count < 2); + //TranslateOperand(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + } + psContext->currentShaderString = &psContext->mainShader; + metal = *psContext->currentShaderString; + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + { + const uint32_t ui32BindingPoint = psDecl->asOperands[0].aui32ArraySizes[0]; + ConstantBuffer* psCBuf = NULL; + + if (psDecl->sUAV.bCounter) + { + bformata(metal, "atomic_uint "); + ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(metal, "_counter; \n"); + } + + GetConstantBufferFromBindingPoint(RGROUP_UAV, ui32BindingPoint, &psContext->psShader->sInfo, &psCBuf); + + DeclareBufferVariableMETAL(psContext, ui32BindingPoint, psCBuf, &psDecl->asOperands[0], RTYPE_UAV_RWSTRUCTURED, metal, psAtomicList); + break; + } + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + { + if (psDecl->sUAV.bCounter) + { + bformata(metal, "atomic_uint "); + ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bformata(metal, "_counter; \n"); + } + + bformata(metal, "buffer Block%d {\n\tuint ", psDecl->asOperands[0].ui32RegisterNumber); + ResourceNameMETAL(metal, psContext, RGROUP_UAV, psDecl->asOperands[0].ui32RegisterNumber, 0); + bcatcstr(metal, "[];\n};\n"); + + break; + } + case OPCODE_DCL_RESOURCE_STRUCTURED: + { + ConstantBuffer* psCBuf = NULL; + + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psDecl->asOperands[0].ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + DeclareBufferVariableMETAL(psContext, psDecl->asOperands[0].ui32RegisterNumber, psCBuf, &psDecl->asOperands[0], + RTYPE_STRUCTURED, psContext->mainShader, psAtomicList); + break; + } + case OPCODE_DCL_RESOURCE_RAW: + { + bformata(metal, "buffer Block%d {\n\tuint RawRes%d[];\n};\n", psDecl->asOperands[0].ui32RegisterNumber, psDecl->asOperands[0].ui32RegisterNumber); + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + { + psContext->currentShaderString = &psContext->earlyMain; + metal = *psContext->currentShaderString; + + ShaderVarType* psVarType = &psShader->sGroupSharedVarType[psDecl->asOperands[0].ui32RegisterNumber]; + + ASSERT(psDecl->asOperands[0].ui32RegisterNumber < MAX_GROUPSHARED); + + bcatcstr(metal, "\tthreadgroup struct {\n"); + bformata(metal, "\t\tuint value[%d];\n", psDecl->sTGSM.ui32Stride / 4); + bcatcstr(metal, "\t} "); + TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(metal, "[%d];\n", + psDecl->sTGSM.ui32Count); + + memset(psVarType, 0, sizeof(ShaderVarType)); + strcpy(psVarType->Name, "$Element"); + + psVarType->Columns = psDecl->sTGSM.ui32Stride / 4; + psVarType->Elements = psDecl->sTGSM.ui32Count; + + psContext->currentShaderString = &psContext->mainShader; + metal = *psContext->currentShaderString; + break; + } + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + { +#ifdef _DEBUG + //AddIndentation(psContext); + //bcatcstr(metal, "//TODO: OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW\n"); +#endif + psContext->currentShaderString = &psContext->earlyMain; + metal = *psContext->currentShaderString; + bcatcstr(metal, "\tthreadgroup "); + bformata(metal, "atomic_uint "); + //psDecl->asOperands + TranslateOperandMETAL(psContext, &psDecl->asOperands[0], TO_FLAG_NONE); + bformata(metal, "[%d]; \n", psDecl->sTGSM.ui32Stride / 4); + + psContext->currentShaderString = &psContext->mainShader; + metal = *psContext->currentShaderString; + break; + } + case OPCODE_DCL_STREAM: + { + break; + } + case OPCODE_DCL_GS_INSTANCE_COUNT: + { + break; + } + default: + { + ASSERT(0); + break; + } + } +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c new file mode 100644 index 0000000000..547f293733 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALInstruction.c @@ -0,0 +1,4946 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toMETALInstruction.h" +#include "internal_includes/toMETALOperand.h" +#include "internal_includes/languages.h" +#include "bstrlib.h" +#include "stdio.h" +#include <stdlib.h> +#include "hlslcc.h" +#include <internal_includes/toGLSLOperand.h> +#include "internal_includes/debug.h" + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); +static int METALIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode); + +// Calculate the bits set in mask +static int METALWriteMaskToComponentCount(uint32_t writeMask) +{ + uint32_t count; + // In HLSL bytecode writemask 0 also means everything + if (writeMask == 0) + { + return 4; + } + + // Count bits set + // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 + count = (writeMask * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; + + return (int)count; +} + +static uint32_t METALBuildComponentMaskFromElementCount(int count) +{ + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + return (1 << count) - 1; +} + + +// This function prints out the destination name, possible destination writemask, assignment operator +// and any possible conversions needed based on the eSrcType+ui32SrcElementCount (type and size of data expected to be coming in) +// As an output, pNeedsParenthesis will be filled with the amount of closing parenthesis needed +// and pSrcCount will be filled with the number of components expected +// ui32CompMask can be used to only write to 1 or more components (used by MOVC) +static void METALAddOpAssignToDestWithMask(HLSLCrossCompilerContext* psContext, const Operand* psDest, + SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, const char* szAssignmentOp, int* pNeedsParenthesis, uint32_t ui32CompMask) +{ + uint32_t ui32DestElementCount = GetNumSwizzleElementsWithMaskMETAL(psDest, ui32CompMask); + bstring metal = *psContext->currentShaderString; + SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, psDest); + ASSERT(pNeedsParenthesis != NULL); + + *pNeedsParenthesis = 0; + + uint32_t flags = TO_FLAG_DESTINATION; + // Default is full floats. Handle half floats if the source is half precision + if (eSrcType == SVT_FLOAT16) + { + flags |= TO_FLAG_FLOAT16; + } + TranslateOperandWithMaskMETAL(psContext, psDest, flags, ui32CompMask); + + //GMEM data output types can only be full floats. + if(eDestDataType== SVT_FLOAT16 && psDest->eType== OPERAND_TYPE_OUTPUT && psContext->gmemOutputNumElements[0]>0 ) + { + eDestDataType = SVT_FLOAT; + } + + // Simple path: types match. + if (eDestDataType == eSrcType) + { + // Cover cases where the HLSL language expects the rest of the components to be default-filled + // eg. MOV r0, c0.x => Temp[0] = vec4(c0.x); + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(metal, " %s %s(", szAssignmentOp, GetConstructorForTypeMETAL(eDestDataType, ui32DestElementCount)); + *pNeedsParenthesis = 1; + } + else + { + bformata(metal, " %s ", szAssignmentOp); + } + return; + } + + switch (eDestDataType) + { + case SVT_INT: + { + if (1 == ui32DestElementCount) + { + bformata(metal, " %s as_type<int>(", szAssignmentOp); + } + else + { + bformata(metal, "%s as_type<int%d>(", szAssignmentOp, ui32DestElementCount); + } + break; + } + case SVT_UINT: + { + if (1 == ui32DestElementCount) + { + bformata(metal, " %s as_type<uint>(", szAssignmentOp); + } + else + { + bformata(metal, "%s as_type<uint%d>(", szAssignmentOp, ui32DestElementCount); + } + break; + } + case SVT_FLOAT: + { + const char* castType = eSrcType == SVT_FLOAT16 ? "static_cast" : "as_type"; + if (1 == ui32DestElementCount) + { + bformata(metal, " %s %s<float>(", szAssignmentOp, castType); + } + else + { + bformata(metal, "%s %s<float%d>(", szAssignmentOp, castType, ui32DestElementCount); + } + break; + } + case SVT_FLOAT16: + { + if (1 == ui32DestElementCount) + { + bformata(metal, " %s static_cast<half>(", szAssignmentOp); + } + else + { + bformata(metal, "%s static_cast<half%d>(", szAssignmentOp, ui32DestElementCount); + } + break; + } + default: + // TODO: Handle bools? + break; + } + + switch (eDestDataType) + { + case SVT_INT: + case SVT_UINT: + case SVT_FLOAT: + case SVT_FLOAT16: + { + // Cover cases where the HLSL language expects the rest of the components to be default-filled + if (ui32DestElementCount > ui32SrcElementCount) + { + bformata(metal, "%s(", GetConstructorForTypeMETAL(eSrcType, ui32DestElementCount)); + (*pNeedsParenthesis)++; + } + } + } + (*pNeedsParenthesis)++; + return; +} + +static void METALAddAssignToDest(HLSLCrossCompilerContext* psContext, const Operand* psDest, + SHADER_VARIABLE_TYPE eSrcType, uint32_t ui32SrcElementCount, int* pNeedsParenthesis) +{ + METALAddOpAssignToDestWithMask(psContext, psDest, eSrcType, ui32SrcElementCount, "=", pNeedsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); +} + +static void METALAddAssignPrologue(HLSLCrossCompilerContext* psContext, int numParenthesis) +{ + bstring glsl = *psContext->currentShaderString; + while (numParenthesis != 0) + { + bcatcstr(glsl, ")"); + numParenthesis--; + } + bcatcstr(glsl, ";\n"); +} +static uint32_t METALResourceReturnTypeToFlag(const RESOURCE_RETURN_TYPE eType) +{ + if (eType == RETURN_TYPE_SINT) + { + return TO_FLAG_INTEGER; + } + else if (eType == RETURN_TYPE_UINT) + { + return TO_FLAG_UNSIGNED_INTEGER; + } + else + { + return TO_FLAG_NONE; + } +} + + +typedef enum +{ + METAL_CMP_EQ, + METAL_CMP_LT, + METAL_CMP_GE, + METAL_CMP_NE, +} METALComparisonType; + +static void METALAddComparision(HLSLCrossCompilerContext* psContext, Instruction* psInst, METALComparisonType eType, + uint32_t typeFlag, Instruction* psNextInst) +{ + (void)psNextInst; + + // Multiple cases to consider here: + // For shader model <=3: all comparisons are floats + // otherwise: + // OPCODE_LT, _GT, _NE etc: inputs are floats, outputs UINT 0xffffffff or 0. typeflag: TO_FLAG_NONE + // OPCODE_ILT, _IGT etc: comparisons are signed ints, outputs UINT 0xffffffff or 0 typeflag TO_FLAG_INTEGER + // _ULT, UGT etc: inputs unsigned ints, outputs UINTs typeflag TO_FLAG_UNSIGNED_INTEGER + // + // Additional complexity: if dest swizzle element count is 1, we can use normal comparison operators, otherwise glsl intrinsics. + + uint32_t orig_type = typeFlag; + + bstring metal = *psContext->currentShaderString; + const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + const uint32_t s1ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[2]); + + uint32_t minElemCount = destElemCount < s0ElemCount ? destElemCount : s0ElemCount; + + int needsParenthesis = 0; + + ASSERT(s0ElemCount == s1ElemCount || s1ElemCount == 1 || s0ElemCount == 1); + if (s0ElemCount != s1ElemCount) + { + // Set the proper auto-expand flag is either argument is scalar + typeFlag |= (TO_AUTO_EXPAND_TO_VEC2 << (max(s0ElemCount, s1ElemCount) - 2)); + } + + const char* metalOpcode[] = { + "==", + "<", + ">=", + "!=", + }; + + //Scalar compare + + // Optimization shortcut for the IGE+BREAKC_NZ combo: + // First print out the if(cond)->break directly, and then + // to guarantee correctness with side-effects, re-run + // the actual comparison. In most cases, the second run will + // be removed by the shader compiler optimizer pass (dead code elimination) + // This also makes it easier for some GLSL optimizers to recognize the for loop. + + //if (psInst->eOpcode == OPCODE_IGE && + // psNextInst && + // psNextInst->eOpcode == OPCODE_BREAKC && + // (psInst->asOperands[0].ui32RegisterNumber == psNextInst->asOperands[0].ui32RegisterNumber)) + //{ + + // AddIndentation(psContext); + // bcatcstr(glsl, "// IGE+BREAKC opt\n"); + // AddIndentation(psContext); + + // if (psNextInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO) + // bcatcstr(glsl, "if (("); + // else + // bcatcstr(glsl, "if (!("); + // TranslateOperand(psContext, &psInst->asOperands[1], typeFlag); + // bformata(glsl, "%s ", glslOpcode[eType]); + // TranslateOperand(psContext, &psInst->asOperands[2], typeFlag); + // bcatcstr(glsl, ")) { break; }\n"); + + // // Mark the BREAKC instruction as already handled + // psNextInst->eOpcode = OPCODE_NOP; + + // // Continue as usual + //} + + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, destElemCount, &needsParenthesis); + + bcatcstr(metal, "select("); + + /* Confetti note: + ASM returns 0XFFFFFFFF or 0 + It's important to use int. + A sign intrinsic converts to the following: + lt r0.x, l(0.000000), v0.z + lt r0.y, v0.z, l(0.000000) + iadd r0.x, -r0.x, r0.y + itof o0.xyzw, r0.xxxx + */ + + if (destElemCount == 1) + { + bcatcstr(metal, "0, (int)0xFFFFFFFF, ("); + } + else + { + bformata(metal, "int%d(0), int%d(0xFFFFFFFF), (", destElemCount, destElemCount); + } + + TranslateOperandMETAL(psContext, &psInst->asOperands[1], typeFlag); + bcatcstr(metal, ")"); + if (destElemCount > 1) + { + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + } + else if (s0ElemCount > minElemCount) + { + AddSwizzleUsingElementCountMETAL(psContext, minElemCount); + } + bformata(metal, " %s (", metalOpcode[eType]); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], typeFlag); + bcatcstr(metal, ")"); + if (destElemCount > 1) + { + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + } + else if (s1ElemCount > minElemCount || orig_type != typeFlag) + { + AddSwizzleUsingElementCountMETAL(psContext, minElemCount); + } + bcatcstr(metal, ")"); + METALAddAssignPrologue(psContext, needsParenthesis); +} + + +static void METALAddMOVBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, Operand* pSrc) +{ + int numParenthesis = 0; + int srcSwizzleCount = GetNumSwizzleElementsMETAL(pSrc); + uint32_t writeMask = GetOperandWriteMaskMETAL(pDest); + + const SHADER_VARIABLE_TYPE eSrcType = GetOperandDataTypeExMETAL(psContext, pSrc, GetOperandDataTypeMETAL(psContext, pDest)); + uint32_t flags = SVTTypeToFlagMETAL(eSrcType); + + METALAddAssignToDest(psContext, pDest, eSrcType, srcSwizzleCount, &numParenthesis); + TranslateOperandWithMaskMETAL(psContext, pSrc, flags, writeMask); + + METALAddAssignPrologue(psContext, numParenthesis); +} + +static uint32_t METALElemCountToAutoExpandFlag(uint32_t elemCount) +{ + return TO_AUTO_EXPAND_TO_VEC2 << (elemCount - 2); +} + +static void METALAddMOVCBinaryOp(HLSLCrossCompilerContext* psContext, const Operand* pDest, const Operand* src0, Operand* src1, Operand* src2) +{ + bstring metal = *psContext->currentShaderString; + uint32_t destElemCount = GetNumSwizzleElementsMETAL(pDest); + uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(src0); + uint32_t s1ElemCount = GetNumSwizzleElementsMETAL(src1); + uint32_t s2ElemCount = GetNumSwizzleElementsMETAL(src2); + uint32_t destWriteMask = GetOperandWriteMaskMETAL(pDest); + uint32_t destElem; + + const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, pDest); + /* + for each component in dest[.mask] + if the corresponding component in src0 (POS-swizzle) + has any bit set + { + copy this component (POS-swizzle) from src1 into dest + } + else + { + copy this component (POS-swizzle) from src2 into dest + } + endfor + */ + + /* Single-component conditional variable (src0) */ + if (s0ElemCount == 1 || IsSwizzleReplicatedMETAL(src0)) + { + int numParenthesis = 0; + AddIndentation(psContext); + + bcatcstr(metal, "if ("); + TranslateOperandMETAL(psContext, src0, TO_AUTO_BITCAST_TO_INT); + if (s0ElemCount > 1) + { + bcatcstr(metal, ".x"); + } + + bcatcstr(metal, " != 0)\n"); + AddIndentation(psContext); + AddIndentation(psContext); + + METALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); + + if (s1ElemCount == 1 && destElemCount > 1) + { + TranslateOperandMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType) | METALElemCountToAutoExpandFlag(destElemCount)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType), destWriteMask); + } + + bcatcstr(metal, ";\n"); + AddIndentation(psContext); + bcatcstr(metal, "else\n"); + AddIndentation(psContext); + AddIndentation(psContext); + + METALAddAssignToDest(psContext, pDest, eDestType, destElemCount, &numParenthesis); + + if (s2ElemCount == 1 && destElemCount > 1) + { + TranslateOperandMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType) | METALElemCountToAutoExpandFlag(destElemCount)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType), destWriteMask); + } + + METALAddAssignPrologue(psContext, numParenthesis); + } + else + { + // TODO: We can actually do this in one op using mix(). + int srcElem = 0; + for (destElem = 0; destElem < 4; ++destElem) + { + int numParenthesis = 0; + if (pDest->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && pDest->ui32CompMask != 0 && !(pDest->ui32CompMask & (1 << destElem))) + { + continue; + } + + AddIndentation(psContext); + + bcatcstr(metal, "if ("); + TranslateOperandWithMaskMETAL(psContext, src0, TO_AUTO_BITCAST_TO_INT, 1 << destElem); + bcatcstr(metal, " != 0)\n"); + + AddIndentation(psContext); + AddIndentation(psContext); + + METALAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); + + TranslateOperandWithMaskMETAL(psContext, src1, SVTTypeToFlagMETAL(eDestType), 1 << destElem); + + bcatcstr(metal, ";\n"); + AddIndentation(psContext); + bcatcstr(metal, "else\n"); + AddIndentation(psContext); + AddIndentation(psContext); + + METALAddOpAssignToDestWithMask(psContext, pDest, eDestType, 1, "=", &numParenthesis, 1 << destElem); + TranslateOperandWithMaskMETAL(psContext, src2, SVTTypeToFlagMETAL(eDestType), 1 << destElem); + + METALAddAssignPrologue(psContext, numParenthesis); + + srcElem++; + } + } +} + +// Returns nonzero if operands are identical, only cares about temp registers currently. +static int METALAreTempOperandsIdentical(const Operand* psA, const Operand* psB) +{ + if (!psA || !psB) + { + return 0; + } + + if (psA->eType != OPERAND_TYPE_TEMP || psB->eType != OPERAND_TYPE_TEMP) + { + return 0; + } + + if (psA->eModifier != psB->eModifier) + { + return 0; + } + + if (psA->iNumComponents != psB->iNumComponents) + { + return 0; + } + + if (psA->ui32RegisterNumber != psB->ui32RegisterNumber) + { + return 0; + } + + if (psA->eSelMode != psB->eSelMode) + { + return 0; + } + + if (psA->eSelMode == OPERAND_4_COMPONENT_MASK_MODE && psA->ui32CompMask != psB->ui32CompMask) + { + return 0; + } + + if (psA->eSelMode != OPERAND_4_COMPONENT_MASK_MODE && psA->ui32Swizzle != psB->ui32Swizzle) + { + return 0; + } + + return 1; +} + +// Returns nonzero if the operation is commutative +static int METALIsOperationCommutative(OPCODE_TYPE eOpCode) +{ + switch (eOpCode) + { + case OPCODE_DADD: + case OPCODE_IADD: + case OPCODE_ADD: + case OPCODE_MUL: + case OPCODE_IMUL: + case OPCODE_OR: + case OPCODE_AND: + return 1; + default: + return 0; + } +} + +static void METALCallBinaryOp(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, SHADER_VARIABLE_TYPE eDataType) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t src1SwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[src1]); + uint32_t src0SwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[src0]); + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[dest]); + int needsParenthesis = 0; + + AddIndentation(psContext); + + if (src1SwizCount == src0SwizCount == dstSwizCount) + { + // Optimization for readability (and to make for loops in WebGL happy): detect cases where either src == dest and emit +=, -= etc. instead. + if (METALAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src0]) != 0) + { + METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); + TranslateOperandMETAL(psContext, &psInst->asOperands[src1], SVTTypeToFlagMETAL(eDataType)); + METALAddAssignPrologue(psContext, needsParenthesis); + return; + } + else if (METALAreTempOperandsIdentical(&psInst->asOperands[dest], &psInst->asOperands[src1]) != 0 && (METALIsOperationCommutative(psInst->eOpcode) != 0)) + { + METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, name, &needsParenthesis, OPERAND_4_COMPONENT_MASK_ALL); + TranslateOperandMETAL(psContext, &psInst->asOperands[src0], SVTTypeToFlagMETAL(eDataType)); + METALAddAssignPrologue(psContext, needsParenthesis); + return; + } + } + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], eDataType, dstSwizCount, &needsParenthesis); + + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], SVTTypeToFlagMETAL(eDataType), destMask); + bformata(glsl, " %s ", name); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], SVTTypeToFlagMETAL(eDataType), destMask); + METALAddAssignPrologue(psContext, needsParenthesis); +} + +static void METALCallTernaryOp(HLSLCrossCompilerContext* psContext, const char* op1, const char* op2, Instruction* psInst, + int dest, int src0, int src1, int src2, uint32_t dataType) +{ + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[dest]); + + const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); + uint32_t ui32Flags = dataType | SVTTypeToFlagMETAL(eDestType); + int numParenthesis = 0; + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], TypeFlagsToSVTTypeMETAL(dataType), dstSwizCount, &numParenthesis); + + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bformata(glsl, " %s ", op1); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + bformata(glsl, " %s ", op2); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src2], ui32Flags, destMask); + METALAddAssignPrologue(psContext, numParenthesis); +} + +static void METALCallHelper3(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, int src2, int paramsShouldFollowWriteMask) +{ + const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestType); + + bstring glsl = *psContext->currentShaderString; + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + int numParenthesis = 0; + + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src2], ui32Flags, destMask); + METALAddAssignPrologue(psContext, numParenthesis); +} + +static void METALCallHelper2(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + const SHADER_VARIABLE_TYPE eDestType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[dest]); + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestType); + + bstring glsl = *psContext->currentShaderString; + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + + int isDotProduct = (strncmp(name, "dot", 3) == 0) ? 1 : 0; + int numParenthesis = 0; + + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, isDotProduct ? 1 : dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + + METALAddAssignPrologue(psContext, numParenthesis); +} + +static void METALCallHelper2Int(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + METALAddAssignPrologue(psContext, numParenthesis); +} + +static void METALCallHelper2UInt(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int src1, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_UINT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_UINT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + bcatcstr(glsl, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src1], ui32Flags, destMask); + METALAddAssignPrologue(psContext, numParenthesis); +} + +static void METALCallHelper1(HLSLCrossCompilerContext* psContext, const char* name, Instruction* psInst, + int dest, int src0, int paramsShouldFollowWriteMask) +{ + uint32_t ui32Flags = TO_AUTO_BITCAST_TO_FLOAT; + bstring glsl = *psContext->currentShaderString; + uint32_t dstSwizCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[dest]); + uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMaskMETAL(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; + int numParenthesis = 0; + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_FLOAT, dstSwizCount, &numParenthesis); + + bformata(glsl, "%s(", name); + numParenthesis++; + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[src0], ui32Flags, destMask); + METALAddAssignPrologue(psContext, numParenthesis); +} + +////Result is an int. +//static void METALCallHelper1Int(HLSLCrossCompilerContext* psContext, +// const char* name, +// Instruction* psInst, +// const int dest, +// const int src0, +// int paramsShouldFollowWriteMask) +//{ +// uint32_t ui32Flags = TO_AUTO_BITCAST_TO_INT; +// bstring glsl = *psContext->currentShaderString; +// uint32_t src0SwizCount = GetNumSwizzleElements(&psInst->asOperands[src0]); +// uint32_t dstSwizCount = GetNumSwizzleElements(&psInst->asOperands[dest]); +// uint32_t destMask = paramsShouldFollowWriteMask ? GetOperandWriteMask(&psInst->asOperands[dest]) : OPERAND_4_COMPONENT_MASK_ALL; +// int numParenthesis = 0; +// +// AddIndentation(psContext); +// +// METALAddAssignToDest(psContext, &psInst->asOperands[dest], SVT_INT, dstSwizCount, &numParenthesis); +// +// bformata(glsl, "%s(", name); +// numParenthesis++; +// TranslateOperandWithMask(psContext, &psInst->asOperands[src0], ui32Flags, destMask); +// METALAddAssignPrologue(psContext, numParenthesis); +//} + +static void METALTranslateTexelFetch(HLSLCrossCompilerContext* psContext, + Instruction* psInst, + ResourceBinding* psBinding, + bstring metal) +{ + int numParenthesis = 0; + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTTypeMETAL(METALResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, &numParenthesis); + + switch (psBinding->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + { + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").x)"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").x, ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").y)"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + { + // METAL PIXEL SHADER RT FETCH + if (psInst->asOperands[2].ui32RegisterNumber >= GMEM_FLOAT_START_SLOT) + { + bformata(metal, "(GMEM_Input%d", GetGmemInputResourceSlotMETAL(psInst->asOperands[2].ui32RegisterNumber)); + + int gmemNumElements = GetGmemInputResourceNumElementsMETAL(psInst->asOperands[2].ui32RegisterNumber); + + int destNumElements = 0; + + if (psInst->asOperands[0].iNumComponents != 1) + { + //Component Mask + uint32_t mask = psInst->asOperands[0].ui32CompMask; + + if (mask == OPERAND_4_COMPONENT_MASK_ALL) + { + destNumElements = 4; + } + else if (mask != 0) + { + if (mask & OPERAND_4_COMPONENT_MASK_X) + { + destNumElements++; + } + if (mask & OPERAND_4_COMPONENT_MASK_Y) + { + destNumElements++; + } + if (mask & OPERAND_4_COMPONENT_MASK_Z) + { + destNumElements++; + } + if (mask & OPERAND_4_COMPONENT_MASK_W) + { + destNumElements++; + } + } + } + else + { + destNumElements = 4; + } + + TranslateGmemOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], OPERAND_4_COMPONENT_MASK_ALL, gmemNumElements); + bcatcstr(metal, ")"); + + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + } + else + { + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").xy, ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").w)"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + } + + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").xy, ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").z, ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").w)"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + { + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").xyz, ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").w)"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + { + ASSERT(psInst->eOpcode == OPCODE_LD_MS); + + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ".read("); + + bcatcstr(metal, "("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ").xy, "); + TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ")"); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[0]); + + break; + } + case REFLECT_RESOURCE_DIMENSION_BUFFER: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + case REFLECT_RESOURCE_DIMENSION_BUFFEREX: + default: + { + ASSERT(0); + break; + } + } + + METALAddAssignPrologue(psContext, numParenthesis); +} + +//static void METALTranslateTexelFetchOffset(HLSLCrossCompilerContext* psContext, +// Instruction* psInst, +// ResourceBinding* psBinding, +// bstring metal) +//{ +// int numParenthesis = 0; +// uint32_t destCount = GetNumSwizzleElements(&psInst->asOperands[0]); +// AddIndentation(psContext); +// METALAddAssignToDest(psContext, &psInst->asOperands[0], TypeFlagsToSVTType(METALResourceReturnTypeToFlag(psBinding->ui32ReturnType)), 4, &numParenthesis); +// +// bcatcstr(metal, "texelFetchOffset("); +// +// switch (psBinding->eDimension) +// { +// case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: +// { +// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); +// bcatcstr(metal, ", "); +// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); +// bformata(metal, ", 0, %d)", psInst->iUAddrOffset); +// break; +// } +// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: +// { +// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); +// bcatcstr(metal, ", "); +// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); +// bformata(metal, ", 0, int2(%d, %d))", +// psInst->iUAddrOffset, +// psInst->iVAddrOffset); +// break; +// } +// case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: +// { +// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); +// bcatcstr(metal, ", "); +// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC3, 7 /* .xyz */); +// bformata(metal, ", 0, int3(%d, %d, %d))", +// psInst->iUAddrOffset, +// psInst->iVAddrOffset, +// psInst->iWAddrOffset); +// break; +// } +// case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: +// { +// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); +// bcatcstr(metal, ", "); +// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); +// bformata(metal, ", 0, int2(%d, %d))", psInst->iUAddrOffset, psInst->iVAddrOffset); +// break; +// } +// case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: +// { +// TranslateOperand(psContext, &psInst->asOperands[2], TO_FLAG_NONE); +// bcatcstr(metal, ", "); +// TranslateOperandWithMask(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER | TO_AUTO_EXPAND_TO_VEC2, 3 /* .xy */); +// bformata(metal, ", 0, int(%d))", psInst->iUAddrOffset); +// break; +// } +// case REFLECT_RESOURCE_DIMENSION_BUFFER: +// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: +// case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: +// case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: +// case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: +// case REFLECT_RESOURCE_DIMENSION_BUFFEREX: +// default: +// { +// ASSERT(0); +// break; +// } +// } +// +// AddSwizzleUsingElementCount(psContext, destCount); +// METALAddAssignPrologue(psContext, numParenthesis); +//} + + +//Makes sure the texture coordinate swizzle is appropriate for the texture type. +//i.e. vecX for X-dimension texture. +//Currently supports floating point coord only, so not used for texelFetch. +static void METALTranslateTexCoord(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eResDim, + Operand* psTexCoordOperand) +{ + uint32_t flags = TO_AUTO_BITCAST_TO_FLOAT; + bstring glsl = *psContext->currentShaderString; + uint32_t opMask = OPERAND_4_COMPONENT_MASK_ALL; + int isArray = 0; + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + //Vec1 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X; + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + //Vec2 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; + flags |= TO_AUTO_EXPAND_TO_VEC2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + case RESOURCE_DIMENSION_TEXTURE3D: + { + //Vec3 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z; + flags |= TO_AUTO_EXPAND_TO_VEC3; + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + //Vec3 texcoord. Mask out the other components. + opMask = OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y; + flags |= TO_AUTO_EXPAND_TO_VEC2; + isArray = 1; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + flags |= TO_AUTO_EXPAND_TO_VEC4; + break; + } + default: + { + ASSERT(0); + break; + } + } + + //FIXME detect when integer coords are needed. + TranslateOperandWithMaskMETAL(psContext, psTexCoordOperand, flags, opMask); + if (isArray) + { + bformata(glsl, ","); + TranslateOperandWithMaskMETAL(psContext, psTexCoordOperand, 0, OPERAND_4_COMPONENT_MASK_Z); + } +} + +static int METALGetNumTextureDimensions(HLSLCrossCompilerContext* psContext, + const RESOURCE_DIMENSION eResDim) +{ + (void)psContext; + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + return 1; + } + case RESOURCE_DIMENSION_TEXTURE2D: + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBE: + { + return 2; + } + + case RESOURCE_DIMENSION_TEXTURE3D: + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + return 3; + } + default: + { + ASSERT(0); + break; + } + } + return 0; +} + +void GetResInfoDataMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, int index, int destElem) +{ + bstring metal = *psContext->currentShaderString; + int numParenthesis = 0; + const RESINFO_RETURN_TYPE eResInfoReturnType = psInst->eResInfoReturnType; + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + AddIndentation(psContext); + METALAddOpAssignToDestWithMask(psContext, &psInst->asOperands[0], eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? SVT_UINT : SVT_FLOAT, 1, "=", &numParenthesis, 1 << destElem); + + //[width, height, depth or array size, total-mip-count] + if (index < 3) + { + int dim = METALGetNumTextureDimensions(psContext, eResDim); + bcatcstr(metal, "("); + if (dim < (index + 1)) + { + bcatcstr(metal, eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT ? "0u" : "0.0"); + } + else + { + if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + { + bformata(metal, "uint%d(textureSize(", dim); + } + else if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_RCPFLOAT) + { + bformata(metal, "float%d(1.0) / float%d(textureSize(", dim, dim); + } + else + { + bformata(metal, "float%d(textureSize(", dim); + } + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ", "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(metal, "))"); + + switch (index) + { + case 0: + bcatcstr(metal, ".x"); + break; + case 1: + bcatcstr(metal, ".y"); + break; + case 2: + bcatcstr(metal, ".z"); + break; + } + } + + bcatcstr(metal, ")"); + } + else + { + if (eResInfoReturnType == RESINFO_INSTRUCTION_RETURN_UINT) + { + bcatcstr(metal, "uint("); + } + else + { + bcatcstr(metal, "float("); + } + bcatcstr(metal, "textureQueryLevels("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, "))"); + } + METALAddAssignPrologue(psContext, numParenthesis); +} + +#define TEXSMP_FLAG_NONE 0x0 +#define TEXSMP_FLAG_LOD 0x1 //LOD comes from operand +#define TEXSMP_FLAG_DEPTHCOMPARE 0x2 +#define TEXSMP_FLAG_FIRSTLOD 0x4 //LOD is 0 +#define TEXSMP_FLAG_BIAS 0x8 +#define TEXSMP_FLAGS_GRAD 0x10 + +// TODO FIXME: non-float samplers! +static void METALTranslateTextureSample(HLSLCrossCompilerContext* psContext, Instruction* psInst, + uint32_t ui32Flags) +{ + bstring metal = *psContext->currentShaderString; + int numParenthesis = 0; + + const char* funcName = "sample"; + const char* depthCmpCoordType = ""; + const char* gradSwizzle = ""; + + uint32_t ui32NumOffsets = 0; + + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + + ASSERT(psInst->asOperands[2].ui32RegisterNumber < MAX_TEXTURES); + switch (eResDim) + { + case RESOURCE_DIMENSION_TEXTURE1D: + { + gradSwizzle = ".x"; + ui32NumOffsets = 1; + break; + } + case RESOURCE_DIMENSION_TEXTURE2D: + { + depthCmpCoordType = "float2"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBE: + { + depthCmpCoordType = "float3"; + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + break; + } + case RESOURCE_DIMENSION_TEXTURE3D: + { + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + break; + } + case RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + gradSwizzle = ".x"; + ui32NumOffsets = 1; + break; + } + case RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + depthCmpCoordType = "float2"; + gradSwizzle = ".xy"; + ui32NumOffsets = 2; + break; + } + case RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + //bformata(metal, "TODO:Sample from texture cube array LOD\n"); + gradSwizzle = ".xyz"; + ui32NumOffsets = 3; + //ASSERT(0); + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE) + { + //For non-cubeMap Arrays the reference value comes from the + //texture coord vector in GLSL. For cubmap arrays there is a + //separate parameter. + //It is always separate paramter in HLSL. + SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); + + bcatcstr(metal, "(float4("); + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); + bformata(metal, ".%s_compare(", funcName); + bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 1)); + bformata(metal, ", %s(", depthCmpCoordType); + METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + bcatcstr(metal, "), "); + //.z = reference. + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(metal, ", level(0)"); + } + + if (psInst->bAddressOffset) + { + if (ui32NumOffsets == 2) + { + bformata(metal, ", int2(%d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset); + } + else + if (ui32NumOffsets == 3) + { + bformata(metal, ", int3(%d, %d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset, + psInst->iWAddrOffset); + } + } + bcatcstr(metal, ")))"); + + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + } + else + { + SHADER_VARIABLE_TYPE dataType = SVT_FLOAT; // TODO!! + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], dataType, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); + + bcatcstr(metal, "("); + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); + bformata(metal, ".%s(", funcName); + bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, 0)); + bformata(metal, ", "); + METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + if (ui32NumOffsets > 1) + { + if (ui32Flags & (TEXSMP_FLAG_LOD)) + { + bcatcstr(metal, ", level("); + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(metal, ")"); + } + else + if (ui32Flags & TEXSMP_FLAG_FIRSTLOD) + { + bcatcstr(metal, ", level(0)"); + } + else + if (ui32Flags & (TEXSMP_FLAG_BIAS)) + { + bcatcstr(metal, ", bias("); + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(metal, ")"); + } + else + if (ui32Flags & TEXSMP_FLAGS_GRAD) + { + if (eResDim == RESOURCE_DIMENSION_TEXTURECUBE) + { + bcatcstr(metal, ", gradientcube(float4("); + } + else + { + bformata(metal, ", gradient%dd(float4(", ui32NumOffsets); + } + + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_AUTO_BITCAST_TO_FLOAT); //dx + bcatcstr(metal, ")"); + bcatcstr(metal, gradSwizzle); + bcatcstr(metal, ", float4("); + TranslateOperandMETAL(psContext, &psInst->asOperands[5], TO_AUTO_BITCAST_TO_FLOAT); //dy + bcatcstr(metal, ")"); + bcatcstr(metal, gradSwizzle); + bcatcstr(metal, ")"); + } + } + + if (psInst->bAddressOffset) + { + if (ui32NumOffsets == 1) + { + bformata(metal, ", %d", + psInst->iUAddrOffset); + } + else + if (ui32NumOffsets == 2) + { + bformata(metal, ", int2(%d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset); + } + else + if (ui32NumOffsets == 3) + { + bformata(metal, ", int3(%d, %d, %d)", + psInst->iUAddrOffset, + psInst->iVAddrOffset, + psInst->iWAddrOffset); + } + } + + bcatcstr(metal, "))"); + } + + if (!(ui32Flags & TEXSMP_FLAG_DEPTHCOMPARE)) + { + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + } + METALAddAssignPrologue(psContext, numParenthesis); +} + +static ShaderVarType* METALLookupStructuredVar(HLSLCrossCompilerContext* psContext, + Operand* psResource, + Operand* psByteOffset, + uint32_t ui32Component) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; + int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; + int vec4Offset = 0; + int32_t index = -1; + int32_t rebase = -1; + int found; + + ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); + //TODO: multi-component stores and vector writes need testing. + + //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; + switch (psResource->eType) + { + case OPERAND_TYPE_RESOURCE: + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + //dcl_tgsm_structured defines the amount of memory and a stride. + ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); + return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; + } + default: + ASSERT(0); + break; + } + + switch (byteOffset % 16) + { + case 0: + aui32Swizzle[0] = 0; + break; + case 4: + aui32Swizzle[0] = 1; + break; + case 8: + aui32Swizzle[0] = 2; + break; + case 12: + aui32Swizzle[0] = 3; + break; + } + vec4Offset = byteOffset / 16; + + found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + ASSERT(found); + + return psVarType; +} + +static ShaderVarType* METALLookupStructuredVarAtomic(HLSLCrossCompilerContext* psContext, + Operand* psResource, + Operand* psByteOffset, + uint32_t ui32Component) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + uint32_t aui32Swizzle[4] = { OPERAND_4_COMPONENT_X }; + int byteOffset = ((int*)psByteOffset->afImmediates)[0] + 4 * ui32Component; + int vec4Offset = 0; + int32_t index = -1; + int32_t rebase = -1; + int found; + + ASSERT(psByteOffset->eType == OPERAND_TYPE_IMMEDIATE32); + //TODO: multi-component stores and vector writes need testing. + + //aui32Swizzle[0] = psInst->asOperands[0].aui32Swizzle[component]; + switch (psResource->eType) + { + case OPERAND_TYPE_RESOURCE: + GetConstantBufferFromBindingPoint(RGROUP_TEXTURE, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + GetConstantBufferFromBindingPoint(RGROUP_UAV, psResource->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + break; + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + //dcl_tgsm_structured defines the amount of memory and a stride. + ASSERT(psResource->ui32RegisterNumber < MAX_GROUPSHARED); + return &psContext->psShader->sGroupSharedVarType[psResource->ui32RegisterNumber]; + } + default: + ASSERT(0); + break; + } + + if (psCBuf->asVars->sType.Class == SVC_STRUCT) + { + //recalculate offset based on address.y; + int offset = *((int*)(&psByteOffset->afImmediates[1])); + if (offset > 0) + { + byteOffset = offset + 4 * ui32Component; + } + } + + switch (byteOffset % 16) + { + case 0: + aui32Swizzle[0] = 0; + break; + case 4: + aui32Swizzle[0] = 1; + break; + case 8: + aui32Swizzle[0] = 2; + break; + case 12: + aui32Swizzle[0] = 3; + break; + } + vec4Offset = byteOffset / 16; + + found = GetShaderVarFromOffset(vec4Offset, aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + ASSERT(found); + + return psVarType; +} + +static void METALTranslateShaderStorageStore(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring metal = *psContext->currentShaderString; + ShaderVarType* psVarType = NULL; + int component; + int srcComponent = 0; + + Operand* psDest = 0; + Operand* psDestAddr = 0; + Operand* psDestByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_STORE_STRUCTURED: + psDest = &psInst->asOperands[0]; + psDestAddr = &psInst->asOperands[1]; + psDestByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + + break; + case OPCODE_STORE_RAW: + psDest = &psInst->asOperands[0]; + psDestByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + for (component = 0; component < 4; component++) + { + const char* swizzleString[] = { ".x", ".y", ".z", ".w" }; + ASSERT(psInst->asOperands[0].eSelMode == OPERAND_4_COMPONENT_MASK_MODE); + if (psInst->asOperands[0].ui32CompMask & (1 << component)) + { + + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + psVarType = METALLookupStructuredVar(psContext, psDest, psDestByteOff, component); + } + + AddIndentation(psContext); + + if (!structured && (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(metal, "atomic_store_explicit( &"); + TranslateOperandMETAL(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + bformata(metal, "["); + if (structured) //Dest address and dest byte offset + { + if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "].value["); + TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "/4u ");//bytes to floats + } + else + { + TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + } + else + { + TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + //RAW: change component using index offset + if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(metal, " + %d", component); + } + bformata(metal, "],"); + + if (structured) + { + uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; + if (psVarType) + { + if (psVarType->Type == SVT_INT) + { + flags = TO_FLAG_INTEGER; + } + else if (psVarType->Type == SVT_FLOAT) + { + flags = TO_FLAG_NONE; + } + else if (psVarType->Type == SVT_FLOAT16) + { + flags = TO_FLAG_FLOAT16; + } + else + { + ASSERT(0); + } + } + //TGSM always uint + bformata(metal, " ("); + if (GetNumSwizzleElementsMETAL(psSrc) > 1) + { + TranslateOperandWithMaskMETAL(psContext, psSrc, flags, 1 << (srcComponent++)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); + } + } + else + { + //Dest type is currently always a uint array. + bformata(metal, " ("); + if (GetNumSwizzleElementsMETAL(psSrc) > 1) + { + TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); + } + } + + //Double takes an extra slot. + if (psVarType && psVarType->Type == SVT_DOUBLE) + { + if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + bcatcstr(metal, ")"); + } + component++; + } + + bformata(metal, "),"); + bformata(metal, "memory_order_relaxed"); + bformata(metal, ");\n"); + return; + } + + if (structured && psDest->eType == OPERAND_TYPE_RESOURCE) + { + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psDest->ui32RegisterNumber, 0); + } + else + { + TranslateOperandMETAL(psContext, psDest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + } + bformata(metal, "["); + if (structured) //Dest address and dest byte offset + { + if (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "].value["); + TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "/4u ");//bytes to floats + } + else + { + TranslateOperandMETAL(psContext, psDestAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + } + else + { + TranslateOperandMETAL(psContext, psDestByteOff, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + } + + //RAW: change component using index offset + if (!structured || (psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY)) + { + bformata(metal, " + %d", component); + } + + bformata(metal, "]"); + + if (structured && psDest->eType != OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + if (strcmp(psVarType->Name, "$Element") != 0) + { + bformata(metal, ".%s", psVarType->Name); + } + if (psVarType->Columns > 1 || psVarType->Rows > 1) + { + bformata(metal, "%s", swizzleString[((((int*)psDestByteOff->afImmediates)[0] + 4 * component - psVarType->Offset) % 16 / 4)]); + } + } + + if (structured) + { + uint32_t flags = TO_FLAG_UNSIGNED_INTEGER; + if (psVarType) + { + if (psVarType->Type == SVT_INT) + { + flags = TO_FLAG_INTEGER; + } + else if (psVarType->Type == SVT_FLOAT) + { + flags = TO_FLAG_NONE; + } + else if (psVarType->Type == SVT_FLOAT16) + { + flags = TO_FLAG_FLOAT16; + } + else + { + ASSERT(0); + } + } + //TGSM always uint + bformata(metal, " = ("); + if (GetNumSwizzleElementsMETAL(psSrc) > 1) + { + TranslateOperandWithMaskMETAL(psContext, psSrc, flags, 1 << (srcComponent++)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, psSrc, flags, OPERAND_4_COMPONENT_MASK_X); + } + } + else + { + //Dest type is currently always a uint array. + bformata(metal, " = ("); + if (GetNumSwizzleElementsMETAL(psSrc) > 1) + { + TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, 1 << (srcComponent++)); + } + else + { + TranslateOperandWithMaskMETAL(psContext, psSrc, TO_FLAG_UNSIGNED_INTEGER, OPERAND_4_COMPONENT_MASK_X); + } + } + + //Double takes an extra slot. + if (psVarType && psVarType->Type == SVT_DOUBLE) + { + if (structured && psDest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + bcatcstr(metal, ")"); + } + component++; + } + + bformata(metal, ");\n"); + } + } +} + +static void METALTranslateShaderStorageLoad(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring metal = *psContext->currentShaderString; + int component; + Operand* psDest = 0; + Operand* psSrcAddr = 0; + Operand* psSrcByteOff = 0; + Operand* psSrc = 0; + int structured = 0; + + switch (psInst->eOpcode) + { + case OPCODE_LD_STRUCTURED: + psDest = &psInst->asOperands[0]; + psSrcAddr = &psInst->asOperands[1]; + psSrcByteOff = &psInst->asOperands[2]; + psSrc = &psInst->asOperands[3]; + structured = 1; + break; + case OPCODE_LD_RAW: + psDest = &psInst->asOperands[0]; + psSrcByteOff = &psInst->asOperands[1]; + psSrc = &psInst->asOperands[2]; + break; + } + + if (psInst->eOpcode == OPCODE_LD_RAW) + { + int numParenthesis = 0; + int firstItemAdded = 0; + uint32_t destCount = GetNumSwizzleElementsMETAL(psDest); + uint32_t destMask = GetOperandWriteMaskMETAL(psDest); + AddIndentation(psContext); + METALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); + if (destCount > 1) + { + bformata(metal, "%s(", GetConstructorForTypeMETAL(SVT_UINT, destCount)); + numParenthesis++; + } + for (component = 0; component < 4; component++) + { + if (!(destMask & (1 << component))) + { + continue; + } + + if (firstItemAdded) + { + bcatcstr(metal, ", "); + } + else + { + firstItemAdded = 1; + } + + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + //ld from threadgroup shared memory + bformata(metal, "atomic_load_explicit( &"); + bformata(metal, "TGSM%d[((", psSrc->ui32RegisterNumber); + TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(metal, ") >> 2)"); + if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) + { + bformata(metal, " + %d", psSrc->aui32Swizzle[component]); + } + bcatcstr(metal, "]"); + bcatcstr(metal, " , "); + bcatcstr(metal, "memory_order::memory_order_relaxed"); + bformata(metal, ")"); + + /* + bformata(metal, "TGSM%d[((", psSrc->ui32RegisterNumber); + TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(metal, ") >> 2)"); + if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) + { + bformata(metal, " + %d", psSrc->aui32Swizzle[component]); + } + bcatcstr(metal, "]"); + */ + } + else + { + //ld from raw buffer + bformata(metal, "RawRes%d[((", psSrc->ui32RegisterNumber); + TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_INTEGER); + bcatcstr(metal, ") >> 2)"); + if (psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE && psSrc->aui32Swizzle[component] != 0) + { + bformata(metal, " + %d", psSrc->aui32Swizzle[component]); + } + bcatcstr(metal, "]"); + } + } + METALAddAssignPrologue(psContext, numParenthesis); + } + else + { + int numParenthesis = 0; + int firstItemAdded = 0; + uint32_t destCount = GetNumSwizzleElementsMETAL(psDest); + uint32_t destMask = GetOperandWriteMaskMETAL(psDest); + ASSERT(psInst->eOpcode == OPCODE_LD_STRUCTURED); + AddIndentation(psContext); + METALAddAssignToDest(psContext, psDest, SVT_UINT, destCount, &numParenthesis); + if (destCount > 1) + { + bformata(metal, "%s(", GetConstructorForTypeMETAL(SVT_UINT, destCount)); + numParenthesis++; + } + for (component = 0; component < 4; component++) + { + ShaderVarType* psVar = NULL; + int addedBitcast = 0; + if (!(destMask & (1 << component))) + { + continue; + } + + if (firstItemAdded) + { + bcatcstr(metal, ", "); + } + else + { + firstItemAdded = 1; + } + + if (psSrc->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + // input already in uints + TranslateOperandMETAL(psContext, psSrc, TO_FLAG_NAME_ONLY); + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(metal, "].value[("); + TranslateOperandMETAL(psContext, psSrcByteOff, TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, " >> 2u) + %d]", psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + } + else + { + ConstantBuffer* psCBuf = NULL; + psVar = METALLookupStructuredVar(psContext, psSrc, psSrcByteOff, psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component); + GetConstantBufferFromBindingPoint(RGROUP_UAV, psSrc->ui32RegisterNumber, &psContext->psShader->sInfo, &psCBuf); + + if (psVar->Type == SVT_FLOAT) + { + bcatcstr(metal, "as_type<uint>("); + bcatcstr(metal, "("); + addedBitcast = 1; + } + else if (psVar->Type == SVT_DOUBLE) + { + bcatcstr(metal, "as_type<uint>("); + bcatcstr(metal, "("); + addedBitcast = 1; + } + if (psSrc->eType == OPERAND_TYPE_UNORDERED_ACCESS_VIEW) + { + bformata(metal, "%s[", psCBuf->Name); + TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(metal, "]"); + if (strcmp(psVar->Name, "$Element") != 0) + { + bcatcstr(metal, "."); + bcatcstr(metal, psVar->Name); + } + + int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; + int bytes = byteOffset - psVar->Offset; + if (psVar->Class != SVC_SCALAR) + { + static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; + int offset = (bytes % 16) / 4; + if (offset == 0) + { + bcatcstr(metal, ".x"); + } + if (offset == 1) + { + bcatcstr(metal, ".y"); + } + if (offset == 2) + { + bcatcstr(metal, ".z"); + } + if (offset == 3) + { + bcatcstr(metal, ".w"); + } + } + } + else + { + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psSrc->ui32RegisterNumber, 0); + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psSrcAddr, TO_FLAG_INTEGER); + bcatcstr(metal, "]"); + if (strcmp(psVar->Name, "$Element") != 0) + { + bcatcstr(metal, "."); + bcatcstr(metal, psVar->Name); + int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; + int bytes = byteOffset - psVar->Offset; + if (psVar->Class == SVC_MATRIX_ROWS) + { + int offset = bytes / 16; + bcatcstr(metal, "["); + bformata(metal, "%i", offset); + bcatcstr(metal, "]"); + } + if (psVar->Class != SVC_SCALAR) + { + static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; + + int offset = (bytes % 16) / 4; + if (offset == 0) + { + bcatcstr(metal, ".x"); + } + if (offset == 1) + { + bcatcstr(metal, ".y"); + } + if (offset == 2) + { + bcatcstr(metal, ".z"); + } + if (offset == 3) + { + bcatcstr(metal, ".w"); + } + } + } + else if (psVar->Columns > 1) + { + int swizcomponent = psSrc->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE ? psSrc->aui32Swizzle[component] : component; + int byteOffset = ((int*)psSrcByteOff->afImmediates)[0] + 4 * swizcomponent; + int bytes = byteOffset - psVar->Offset; + + static const char* const m_swizzlers[] = { "x", "y", "z", "w" }; + + int offset = (bytes % 16) / 4; + if (offset == 0) + { + bcatcstr(metal, ".x"); + } + if (offset == 1) + { + bcatcstr(metal, ".y"); + } + if (offset == 2) + { + bcatcstr(metal, ".z"); + } + if (offset == 3) + { + bcatcstr(metal, ".w"); + } + } + } + + if (addedBitcast) + { + bcatcstr(metal, "))"); + } + + if (psVar->Columns > 1) + { + int multiplier = 1; + + if (psVar->Type == SVT_DOUBLE) + { + multiplier++; // doubles take up 2 slots + } + //component += psVar->Columns * multiplier; + } + } + } + METALAddAssignPrologue(psContext, numParenthesis); + + return; + } +} + +void TranslateAtomicMemOpMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst) +{ + bstring metal = *psContext->currentShaderString; + int numParenthesis = 0; + ShaderVarType* psVarType = NULL; + uint32_t ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER; + const char* func = ""; + Operand* dest = 0; + Operand* previousValue = 0; + Operand* destAddr = 0; + Operand* src = 0; + Operand* compare = 0; + + switch (psInst->eOpcode) + { + case OPCODE_IMM_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_IADD\n"); +#endif + func = "atomic_fetch_add_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_IADD\n"); +#endif + func = "atomic_fetch_add_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_AND\n"); +#endif + func = "atomic_fetch_and_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_AND\n"); +#endif + func = "atomic_fetch_and_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_OR\n"); +#endif + func = "atomic_fetch_or_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_OR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_OR\n"); +#endif + func = "atomic_fetch_or_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_XOR\n"); +#endif + func = "atomic_fetch_xor_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_XOR\n"); +#endif + func = "atomic_fetch_xor_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + + case OPCODE_IMM_ATOMIC_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_EXCH\n"); +#endif + func = "atomic_exchange_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_CMP_EXC\n"); +#endif + func = "atomic_compare_exchange_weak_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + compare = &psInst->asOperands[3]; + src = &psInst->asOperands[4]; + break; + } + case OPCODE_ATOMIC_CMP_STORE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_CMP_STORE\n"); +#endif + func = "atomic_compare_exchange_weak_explicit"; + previousValue = 0; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + compare = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_IMM_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_UMIN\n"); +#endif + func = "atomic_fetch_min_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_UMIN\n"); +#endif + func = "atomic_fetch_min_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_IMIN\n"); +#endif + func = "atomic_fetch_min_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_IMIN\n"); +#endif + func = "atomic_fetch_min_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_UMAX\n"); +#endif + func = "atomic_fetch_max_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_UMAX\n"); +#endif + func = "atomic_fetch_max_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + case OPCODE_IMM_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMM_ATOMIC_IMAX\n"); +#endif + func = "atomic_fetch_max_explicit"; + previousValue = &psInst->asOperands[0]; + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + src = &psInst->asOperands[3]; + break; + } + case OPCODE_ATOMIC_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ATOMIC_IMAX\n"); +#endif + func = "atomic_fetch_max_explicit"; + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + src = &psInst->asOperands[2]; + break; + } + } + + AddIndentation(psContext); + + if (previousValue) + { + //all atomic operation returns uint or int + METALAddAssignToDest(psContext, previousValue, SVT_UINT, 1, &numParenthesis); + } + + bcatcstr(metal, func); + bformata(metal, "( &"); + TranslateOperandMETAL(psContext, dest, TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY); + + if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + //threadgroup shared mem + bformata(metal, "["); + TranslateOperandMETAL(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "]"); + } + else + { + ResourceBinding* psRes; +#if defined(_DEBUG) + int foundResource = +#endif + GetResourceFromBindingPoint(RGROUP_UAV, + dest->ui32RegisterNumber, + &psContext->psShader->sInfo, + &psRes); + + ASSERT(foundResource); + + if (psRes->eBindArea == UAVAREA_CBUFFER) + { + //rwbuffer + if (psRes->eType == RTYPE_UAV_RWTYPED) + { + bformata(metal, "["); + TranslateOperandMETAL(psContext, destAddr, TO_FLAG_INTEGER | TO_FLAG_UNSIGNED_INTEGER); + bformata(metal, "]"); + } + //rwstructured buffer + else if (psRes->eType == RTYPE_UAV_RWSTRUCTURED) + { + if (destAddr->eType == OPERAND_TYPE_IMMEDIATE32) + { + psVarType = METALLookupStructuredVarAtomic(psContext, dest, destAddr, 0); + } + if (psVarType->Type == SVT_UINT) + { + ui32DataTypeFlag = TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT; + } + else + { + ui32DataTypeFlag = TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT; + } + bformata(metal, "["); + bformata(metal, "%i", *((int*)(&destAddr->afImmediates[0]))); + bformata(metal, "]"); + if (strcmp(psVarType->Name, "$Element") != 0) + { + bformata(metal, ".%s", psVarType->Name); + } + } + } + else if (psRes->eBindArea == UAVAREA_TEXTURE) + { + //Atomic operation on texture uav not supported + ASSERT(0); + } + else + { + //UAV is not exist in either [[buffer]] or [[texture]] + ASSERT(0); + } + } + //ResourceNameMETAL(metal, psContext, RGROUP_UAV, dest->ui32RegisterNumber, 0); + + bcatcstr(metal, ", "); + + if (compare) + { + bcatcstr(metal, "& "); + TranslateOperandMETAL(psContext, compare, ui32DataTypeFlag); + bcatcstr(metal, ", "); + } + + TranslateOperandMETAL(psContext, src, ui32DataTypeFlag); + bcatcstr(metal, ", "); + if (compare) + { + bcatcstr(metal, "memory_order_relaxed "); + bcatcstr(metal, ","); + } + bcatcstr(metal, "memory_order_relaxed "); + bcatcstr(metal, ")"); + if (previousValue) + { + METALAddAssignPrologue(psContext, numParenthesis); + } + else + { + bcatcstr(metal, ";\n"); + } +} + +static void METALTranslateConditional(HLSLCrossCompilerContext* psContext, + Instruction* psInst, + bstring glsl) +{ + const char* statement = ""; + if (psInst->eOpcode == OPCODE_BREAKC) + { + statement = "break"; + } + else if (psInst->eOpcode == OPCODE_CONTINUEC) + { + statement = "continue"; + } + else if (psInst->eOpcode == OPCODE_RETC) + { + statement = "return"; + } + + if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(glsl, "if(("); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF) + { + bformata(glsl, ")==0u){%s;}\n", statement); + } + else + { + bcatcstr(glsl, ")==0u){\n"); + } + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(glsl, "if(("); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER); + + if (psInst->eOpcode != OPCODE_IF) + { + bformata(glsl, ")!=0u){%s;}\n", statement); + } + else + { + bcatcstr(glsl, ")!=0u){\n"); + } + } +} + +// Returns the "more important" type of a and b, currently int < uint < float +static SHADER_VARIABLE_TYPE METALSelectHigherType(SHADER_VARIABLE_TYPE a, SHADER_VARIABLE_TYPE b) +{ + if (a == SVT_FLOAT || b == SVT_FLOAT) + { + return SVT_FLOAT; + } + + if (a == SVT_FLOAT16 || b == SVT_FLOAT16) + { + return SVT_FLOAT16; + } + // Apart from floats, the enum values are fairly well-ordered, use that directly. + return a > b ? a : b; +} + +// Helper function to set the vector type of 1 or more components in a vector +// If the existing values (that we're writing to) are all SVT_VOID, just upgrade the value and we're done +// Otherwise, set all the components in the vector that currently are set to that same value OR are now being written to +// to the "highest" type value (ordering int->uint->float) +static void METALSetVectorType(SHADER_VARIABLE_TYPE* aeTempVecType, uint32_t regBaseIndex, uint32_t componentMask, SHADER_VARIABLE_TYPE eType) +{ + int existingTypesFound = 0; + int i = 0; + for (i = 0; i < 4; i++) + { + if (componentMask & (1 << i)) + { + if (aeTempVecType[regBaseIndex + i] != SVT_VOID) + { + existingTypesFound = 1; + break; + } + } + } + + if (existingTypesFound != 0) + { + // Expand the mask to include all components that are used, also upgrade type + for (i = 0; i < 4; i++) + { + if (aeTempVecType[regBaseIndex + i] != SVT_VOID) + { + componentMask |= (1 << i); + eType = METALSelectHigherType(eType, aeTempVecType[regBaseIndex + i]); + } + } + } + + // Now componentMask contains the components we actually need to update and eType may have been changed to something else. + // Write the results + for (i = 0; i < 4; i++) + { + if (componentMask & (1 << i)) + { + aeTempVecType[regBaseIndex + i] = eType; + } + } +} + +static void METALMarkOperandAs(Operand* psOperand, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) +{ + if (psOperand->eType == OPERAND_TYPE_INDEXABLE_TEMP || psOperand->eType == OPERAND_TYPE_TEMP) + { + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + METALSetVectorType(aeTempVecType, ui32RegIndex, 1 << psOperand->aui32Swizzle[0], eType); + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + // 0xf == all components, swizzle order doesn't matter. + METALSetVectorType(aeTempVecType, ui32RegIndex, 0xf, eType); + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + METALSetVectorType(aeTempVecType, ui32RegIndex, ui32CompMask, eType); + } + } +} + +static void METALMarkAllOperandsAs(Instruction* psInst, SHADER_VARIABLE_TYPE eType, SHADER_VARIABLE_TYPE* aeTempVecType) +{ + uint32_t i = 0; + for (i = 0; i < psInst->ui32NumOperands; i++) + { + METALMarkOperandAs(&psInst->asOperands[i], eType, aeTempVecType); + } +} + +static void METALWriteOperandTypes(Operand* psOperand, const SHADER_VARIABLE_TYPE* aeTempVecType) +{ + const uint32_t ui32RegIndex = psOperand->ui32RegisterNumber * 4; + + if (psOperand->eType != OPERAND_TYPE_TEMP) + { + return; + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + psOperand->aeDataType[0] = aeTempVecType[ui32RegIndex]; + psOperand->aeDataType[1] = aeTempVecType[ui32RegIndex + 1]; + psOperand->aeDataType[2] = aeTempVecType[ui32RegIndex + 2]; + psOperand->aeDataType[3] = aeTempVecType[ui32RegIndex + 3]; + } + else + { + psOperand->aeDataType[psOperand->aui32Swizzle[0]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[0]]; + psOperand->aeDataType[psOperand->aui32Swizzle[1]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[1]]; + psOperand->aeDataType[psOperand->aui32Swizzle[2]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[2]]; + psOperand->aeDataType[psOperand->aui32Swizzle[3]] = aeTempVecType[ui32RegIndex + psOperand->aui32Swizzle[3]]; + } + } + else if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + int c = 0; + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + + for (; c < 4; ++c) + { + if (ui32CompMask & (1 << c)) + { + psOperand->aeDataType[c] = aeTempVecType[ui32RegIndex + c]; + } + } + } +} + +// Mark scalars from CBs. TODO: Do we need to do the same for vec2/3's as well? There may be swizzles involved which make it vec4 or something else again. +static void METALSetCBOperandComponents(HLSLCrossCompilerContext* psContext, Operand* psOperand) +{ + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + int rebase = 0; + + if (psOperand->eType != OPERAND_TYPE_CONSTANT_BUFFER) + { + return; + } + + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + + if (psVarType->Class == SVC_SCALAR) + { + psOperand->iNumComponents = 1; + } +} + + +void SetDataTypesMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, const int32_t i32InstCount) +{ + int32_t i; + Instruction* psFirstInst = psInst; + + SHADER_VARIABLE_TYPE aeTempVecType[MAX_TEMP_VEC4 * 4]; + + // Start with void, then move up the chain void->int->uint->float + for (i = 0; i < MAX_TEMP_VEC4 * 4; ++i) + { + aeTempVecType[i] = SVT_VOID; + } + + { + // First pass, do analysis: deduce the data type based on opcodes, fill out aeTempVecType table + // Only ever to int->float promotion (or int->uint), never the other way around + for (i = 0; i < i32InstCount; ++i, psInst++) + { + if (psInst->ui32NumOperands == 0) + { + continue; + } + + switch (psInst->eOpcode) + { + // All float-only ops + case OPCODE_ADD: + case OPCODE_DERIV_RTX: + case OPCODE_DERIV_RTY: + case OPCODE_DIV: + case OPCODE_DP2: + case OPCODE_DP3: + case OPCODE_DP4: + case OPCODE_EQ: + case OPCODE_EXP: + case OPCODE_FRC: + case OPCODE_LOG: + case OPCODE_MAD: + case OPCODE_MIN: + case OPCODE_MAX: + case OPCODE_MUL: + case OPCODE_NE: + case OPCODE_ROUND_NE: + case OPCODE_ROUND_NI: + case OPCODE_ROUND_PI: + case OPCODE_ROUND_Z: + case OPCODE_RSQ: + case OPCODE_SAMPLE: + case OPCODE_SAMPLE_C: + case OPCODE_SAMPLE_C_LZ: + case OPCODE_SAMPLE_L: + case OPCODE_SAMPLE_D: + case OPCODE_SAMPLE_B: + case OPCODE_SQRT: + case OPCODE_SINCOS: + case OPCODE_LOD: + case OPCODE_GATHER4: + + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_GATHER4_C: + case OPCODE_GATHER4_PO: + case OPCODE_GATHER4_PO_C: + case OPCODE_RCP: + + METALMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); + break; + + // Int-only ops, no need to do anything + case OPCODE_AND: + case OPCODE_BREAKC: + case OPCODE_CALLC: + case OPCODE_CONTINUEC: + case OPCODE_IADD: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_IF: + case OPCODE_NOT: + case OPCODE_OR: + case OPCODE_RETC: + case OPCODE_XOR: + case OPCODE_BUFINFO: + case OPCODE_COUNTBITS: + case OPCODE_FIRSTBIT_HI: + case OPCODE_FIRSTBIT_LO: + case OPCODE_FIRSTBIT_SHI: + case OPCODE_UBFE: + case OPCODE_IBFE: + case OPCODE_BFI: + case OPCODE_BFREV: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_IMAX: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_MOV: + case OPCODE_MOVC: + case OPCODE_SWAPC: + METALMarkAllOperandsAs(psInst, SVT_INT, aeTempVecType); + break; + // uint ops + case OPCODE_UDIV: + case OPCODE_ULT: + case OPCODE_UGE: + case OPCODE_UMUL: + case OPCODE_UMAD: + case OPCODE_UMAX: + case OPCODE_UMIN: + case OPCODE_USHR: + case OPCODE_UADDC: + case OPCODE_USUBB: + METALMarkAllOperandsAs(psInst, SVT_UINT, aeTempVecType); + break; + + // Need special handling + case OPCODE_FTOI: + case OPCODE_FTOU: + METALMarkOperandAs(&psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOI ? SVT_INT : SVT_UINT, aeTempVecType); + METALMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_GE: + case OPCODE_LT: + METALMarkOperandAs(&psInst->asOperands[0], SVT_UINT, aeTempVecType); + METALMarkOperandAs(&psInst->asOperands[1], SVT_FLOAT, aeTempVecType); + METALMarkOperandAs(&psInst->asOperands[2], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_ITOF: + case OPCODE_UTOF: + METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + METALMarkOperandAs(&psInst->asOperands[1], psInst->eOpcode == OPCODE_ITOF ? SVT_INT : SVT_UINT, aeTempVecType); + break; + + case OPCODE_LD: + case OPCODE_LD_MS: + // TODO: Would need to know the sampler return type + METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + + case OPCODE_RESINFO: + { + if (psInst->eResInfoReturnType != RESINFO_INSTRUCTION_RETURN_UINT) + { + METALMarkAllOperandsAs(psInst, SVT_FLOAT, aeTempVecType); + } + break; + } + + case OPCODE_SAMPLE_INFO: + // TODO decode the _uint flag + METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + case OPCODE_SAMPLE_POS: + METALMarkOperandAs(&psInst->asOperands[0], SVT_FLOAT, aeTempVecType); + break; + + + case OPCODE_LD_UAV_TYPED: + case OPCODE_STORE_UAV_TYPED: + case OPCODE_LD_RAW: + case OPCODE_STORE_RAW: + case OPCODE_LD_STRUCTURED: + case OPCODE_STORE_STRUCTURED: + { + METALMarkOperandAs(&psInst->asOperands[0], SVT_INT, aeTempVecType); + break; + } + case OPCODE_F32TOF16: + case OPCODE_F16TOF32: + // TODO + break; + + + + // No-operands, should never get here anyway + /* case OPCODE_BREAK: + case OPCODE_CALL: + case OPCODE_CASE: + case OPCODE_CONTINUE: + case OPCODE_CUT: + case OPCODE_DEFAULT: + case OPCODE_DISCARD: + case OPCODE_ELSE: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_ENDIF: + case OPCODE_ENDLOOP: + case OPCODE_ENDSWITCH: + + case OPCODE_LABEL: + case OPCODE_LOOP: + case OPCODE_CUSTOMDATA: + case OPCODE_NOP: + case OPCODE_RET: + case OPCODE_SWITCH: + case OPCODE_DCL_RESOURCE: // DCL* opcodes have + case OPCODE_DCL_CONSTANT_BUFFER: // custom operand formats. + case OPCODE_DCL_SAMPLER: + case OPCODE_DCL_INDEX_RANGE: + case OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: + case OPCODE_DCL_GS_INPUT_PRIMITIVE: + case OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: + case OPCODE_DCL_INPUT: + case OPCODE_DCL_INPUT_SGV: + case OPCODE_DCL_INPUT_SIV: + case OPCODE_DCL_INPUT_PS: + case OPCODE_DCL_INPUT_PS_SGV: + case OPCODE_DCL_INPUT_PS_SIV: + case OPCODE_DCL_OUTPUT: + case OPCODE_DCL_OUTPUT_SGV: + case OPCODE_DCL_OUTPUT_SIV: + case OPCODE_DCL_TEMPS: + case OPCODE_DCL_INDEXABLE_TEMP: + case OPCODE_DCL_GLOBAL_FLAGS: + + + case OPCODE_HS_DECLS: // token marks beginning of HS sub-shader + case OPCODE_HS_CONTROL_POINT_PHASE: // token marks beginning of HS sub-shader + case OPCODE_HS_FORK_PHASE: // token marks beginning of HS sub-shader + case OPCODE_HS_JOIN_PHASE: // token marks beginning of HS sub-shader + + case OPCODE_EMIT_STREAM: + case OPCODE_CUT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + case OPCODE_INTERFACE_CALL: + + + case OPCODE_DCL_STREAM: + case OPCODE_DCL_FUNCTION_BODY: + case OPCODE_DCL_FUNCTION_TABLE: + case OPCODE_DCL_INTERFACE: + + case OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: + case OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: + case OPCODE_DCL_TESS_DOMAIN: + case OPCODE_DCL_TESS_PARTITIONING: + case OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: + case OPCODE_DCL_HS_MAX_TESSFACTOR: + case OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: + case OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: + + case OPCODE_DCL_THREAD_GROUP: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: + case OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: + case OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: + case OPCODE_DCL_RESOURCE_RAW: + case OPCODE_DCL_RESOURCE_STRUCTURED: + case OPCODE_SYNC: + + // TODO + case OPCODE_DADD: + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_DTOF: + case OPCODE_FTOD: + + case OPCODE_EVAL_SNAPPED: + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_CENTROID: + + case OPCODE_DCL_GS_INSTANCE_COUNT: + + case OPCODE_ABORT: + case OPCODE_DEBUG_BREAK:*/ + + default: + break; + } + } + } + + // Fill the rest of aeTempVecType, just in case. + for (i = 0; i < MAX_TEMP_VEC4 * 4; i++) + { + if (aeTempVecType[i] == SVT_VOID) + { + aeTempVecType[i] = SVT_INT; + } + } + + // Now the aeTempVecType table has been filled with (mostly) valid data, write it back to all operands + psInst = psFirstInst; + for (i = 0; i < i32InstCount; ++i, psInst++) + { + int k = 0; + + if (psInst->ui32NumOperands == 0) + { + continue; + } + + //Preserve the current type on dest array index + if (psInst->asOperands[0].eType == OPERAND_TYPE_INDEXABLE_TEMP) + { + Operand* psSubOperand = psInst->asOperands[0].psSubOperand[1]; + if (psSubOperand != 0) + { + METALWriteOperandTypes(psSubOperand, aeTempVecType); + } + } + if (psInst->asOperands[0].eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + METALSetCBOperandComponents(psContext, &psInst->asOperands[0]); + } + + //Preserve the current type on sources. + for (k = psInst->ui32NumOperands - 1; k >= (int)psInst->ui32FirstSrc; --k) + { + int32_t subOperand; + Operand* psOperand = &psInst->asOperands[k]; + + METALWriteOperandTypes(psOperand, aeTempVecType); + if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + METALSetCBOperandComponents(psContext, psOperand); + } + + for (subOperand = 0; subOperand < MAX_SUB_OPERANDS; subOperand++) + { + if (psOperand->psSubOperand[subOperand] != 0) + { + Operand* psSubOperand = psOperand->psSubOperand[subOperand]; + METALWriteOperandTypes(psSubOperand, aeTempVecType); + if (psSubOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + METALSetCBOperandComponents(psContext, psSubOperand); + } + } + } + + //Set immediates + if (METALIsIntegerImmediateOpcode(psInst->eOpcode)) + { + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32) + { + psOperand->iIntegerImmediate = 1; + } + } + } + + //Process the destination last in order to handle instructions + //where the destination register is also used as a source. + for (k = 0; k < (int)psInst->ui32FirstSrc; ++k) + { + Operand* psOperand = &psInst->asOperands[k]; + METALWriteOperandTypes(psOperand, aeTempVecType); + } + } +} + +void DetectAtomicInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst, AtomicVarList* psAtomicList) +{ + (void)psNextInst; + + Operand* dest = 0; + Operand* destAddr = 0; + + switch (psInst->eOpcode) + { + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_ATOMIC_AND: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_IMAX: + dest = &psInst->asOperands[0]; + destAddr = &psInst->asOperands[1]; + break; + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + case OPCODE_IMM_ATOMIC_AND: + dest = &psInst->asOperands[1]; + destAddr = &psInst->asOperands[2]; + break; + default: + return; + } + + if (dest->eType == OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY) + { + } + else + { + ResourceBinding* psRes; +#if defined(_DEBUG) + int foundResource = +#endif + GetResourceFromBindingPoint(RGROUP_UAV, + dest->ui32RegisterNumber, + &psContext->psShader->sInfo, + &psRes); + + ASSERT(foundResource); + + { + //rwbuffer + if (psRes->eType == RTYPE_UAV_RWTYPED) + { + } + //rwstructured buffer + else if (psRes->eType == RTYPE_UAV_RWSTRUCTURED) + { + if (destAddr->eType == OPERAND_TYPE_IMMEDIATE32) + { + psAtomicList->AtomicVars[psAtomicList->Filled] = METALLookupStructuredVarAtomic(psContext, dest, destAddr, 0); + psAtomicList->Filled++; + } + } + } + } +} + +void TranslateInstructionMETAL(HLSLCrossCompilerContext* psContext, Instruction* psInst, Instruction* psNextInst) +{ + bstring metal = *psContext->currentShaderString; + int numParenthesis = 0; + +#ifdef _DEBUG + AddIndentation(psContext); + bformata(metal, "//Instruction %d\n", psInst->id); +#if 0 + if (psInst->id == 73) + { + ASSERT(1); //Set breakpoint here to debug an instruction from its ID. + } +#endif +#endif + + switch (psInst->eOpcode) + { + case OPCODE_FTOI: + case OPCODE_FTOU: + { + uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_FTOU) + { + bcatcstr(metal, "//FTOU\n"); + } + else + { + bcatcstr(metal, "//FTOI\n"); + } +#endif + + AddIndentation(psContext); + + METALAddAssignToDest(psContext, &psInst->asOperands[0], psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount, &numParenthesis); + bcatcstr(metal, GetConstructorForTypeMETAL(psInst->eOpcode == OPCODE_FTOU ? SVT_UINT : SVT_INT, srcCount == dstCount ? dstCount : 4)); + bcatcstr(metal, "("); // 1 + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(metal, ")"); // 1 + // Add destination writemask if the component counts do not match + if (srcCount != dstCount) + { + AddSwizzleUsingElementCountMETAL(psContext, dstCount); + } + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + + case OPCODE_MOV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MOV\n"); +#endif + AddIndentation(psContext); + METALAddMOVBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1]); + break; + } + case OPCODE_ITOF://signed to float + case OPCODE_UTOF://unsigned to float + { + uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + uint32_t destMask = GetOperandWriteMaskMETAL(&psInst->asOperands[0]); + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_ITOF) + { + bcatcstr(metal, "//ITOF\n"); + } + else + { + bcatcstr(metal, "//UTOF\n"); + } +#endif + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, srcCount, &numParenthesis); + bcatcstr(metal, GetConstructorForTypeMETAL(SVT_FLOAT, dstCount)); + bcatcstr(metal, "("); // 1 + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], psInst->eOpcode == OPCODE_UTOF ? TO_AUTO_BITCAST_TO_UINT : TO_AUTO_BITCAST_TO_INT, destMask); + bcatcstr(metal, ")"); // 1 + // Add destination writemask if the component counts do not match + if (srcCount != dstCount) + { + AddSwizzleUsingElementCountMETAL(psContext, dstCount); + } + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_MAD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MAD\n"); +#endif + METALCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, TO_FLAG_NONE); + break; + } + case OPCODE_IMAD: + { + uint32_t ui32Flags = TO_FLAG_INTEGER; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMAD\n"); +#endif + + if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + ui32Flags = TO_FLAG_UNSIGNED_INTEGER; + } + + METALCallTernaryOp(psContext, "*", "+", psInst, 0, 1, 2, 3, ui32Flags); + break; + } + case OPCODE_DADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DADD\n"); +#endif + METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_DOUBLE); + break; + } + case OPCODE_IADD: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IADD\n"); +#endif + //Is this a signed or unsigned add? + if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ADD\n"); +#endif + METALCallBinaryOp(psContext, "+", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_OR: + { + /*Todo: vector version */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//OR\n"); +#endif + METALCallBinaryOp(psContext, "|", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_AND: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//AND\n"); +#endif + METALCallBinaryOp(psContext, "&", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_GE: + { + /* + dest = vec4(greaterThanEqual(vec4(srcA), vec4(srcB)); + Caveat: The result is a boolean but HLSL asm returns 0xFFFFFFFF/0x0 instead. + */ +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//GE\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_MUL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MUL\n"); +#endif + METALCallBinaryOp(psContext, "*", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_IMUL: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMUL\n"); +#endif + if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[1]) == SVT_UINT) + { + eType = SVT_UINT; + } + + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_NULL); + + METALCallBinaryOp(psContext, "*", psInst, 1, 2, 3, eType); + break; + } + case OPCODE_UDIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//UDIV\n"); +#endif + //destQuotient, destRemainder, src0, src1 + METALCallBinaryOp(psContext, "/", psInst, 0, 2, 3, SVT_UINT); + METALCallBinaryOp(psContext, "%", psInst, 1, 2, 3, SVT_UINT); + break; + } + case OPCODE_DIV: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DIV\n"); +#endif + METALCallBinaryOp(psContext, "/", psInst, 0, 1, 2, SVT_FLOAT); + break; + } + case OPCODE_SINCOS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SINCOS\n"); +#endif + // Need careful ordering if src == dest[0], as then the cos() will be reading from wrong value + if (psInst->asOperands[0].eType == psInst->asOperands[2].eType && + psInst->asOperands[0].ui32RegisterNumber == psInst->asOperands[2].ui32RegisterNumber) + { + // sin() result overwrites source, do cos() first. + // The case where both write the src shouldn't really happen anyway. + if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) + { + METALCallHelper1(psContext, "cos", psInst, 1, 2, 1); + } + + if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) + { + METALCallHelper1(psContext, "sin", psInst, 0, 2, 1); + } + } + else + { + if (psInst->asOperands[0].eType != OPERAND_TYPE_NULL) + { + METALCallHelper1(psContext, "sin", psInst, 0, 2, 1); + } + + if (psInst->asOperands[1].eType != OPERAND_TYPE_NULL) + { + METALCallHelper1(psContext, "cos", psInst, 1, 2, 1); + } + } + break; + } + + case OPCODE_DP2: + { + SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); + int numParenthesis2 = 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DP2\n"); +#endif + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); + bcatcstr(metal, "dot("); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 3 /* .xy */); + bcatcstr(metal, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 3 /* .xy */); + bcatcstr(metal, ")"); + METALAddAssignPrologue(psContext, numParenthesis2); + break; + } + case OPCODE_DP3: + { + SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); + int numParenthesis2 = 0; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DP3\n"); +#endif + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 1, &numParenthesis2); + bcatcstr(metal, "dot("); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 7 /* .xyz */); + bcatcstr(metal, ", "); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], TO_AUTO_BITCAST_TO_FLOAT | SVTTypeToFlagMETAL(eDestDataType), 7 /* .xyz */); + bcatcstr(metal, ")"); + METALAddAssignPrologue(psContext, numParenthesis2); + break; + } + case OPCODE_DP4: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DP4\n"); +#endif + METALCallHelper2(psContext, "dot", psInst, 0, 1, 2, 0); + break; + } + case OPCODE_INE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//INE\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_NE, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//NE\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_NE, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_IGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IGE\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_INTEGER, psNextInst); + break; + } + case OPCODE_ILT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ILT\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_LT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LT\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_IEQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IEQ\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_EQ, TO_FLAG_INTEGER, NULL); + break; + } + case OPCODE_ULT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ULT\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_LT, TO_FLAG_UNSIGNED_INTEGER, NULL); + break; + } + case OPCODE_UGE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//UGE\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_GE, TO_FLAG_UNSIGNED_INTEGER, NULL); + break; + } + case OPCODE_MOVC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MOVC\n"); +#endif + METALAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3]); + break; + } + case OPCODE_SWAPC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SWAPC\n"); +#endif + // TODO needs temps!! + METALAddMOVCBinaryOp(psContext, &psInst->asOperands[0], &psInst->asOperands[2], &psInst->asOperands[4], &psInst->asOperands[3]); + METALAddMOVCBinaryOp(psContext, &psInst->asOperands[1], &psInst->asOperands[2], &psInst->asOperands[3], &psInst->asOperands[4]); + break; + } + + case OPCODE_LOG: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LOG\n"); +#endif + METALCallHelper1(psContext, "log2", psInst, 0, 1, 1); + break; + } + case OPCODE_RSQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//RSQ\n"); +#endif + METALCallHelper1(psContext, "rsqrt", psInst, 0, 1, 1); + break; + } + case OPCODE_EXP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//EXP\n"); +#endif + METALCallHelper1(psContext, "exp2", psInst, 0, 1, 1); + break; + } + case OPCODE_SQRT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SQRT\n"); +#endif + METALCallHelper1(psContext, "sqrt", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_PI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ROUND_PI\n"); +#endif + METALCallHelper1(psContext, "ceil", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_NI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ROUND_NI\n"); +#endif + METALCallHelper1(psContext, "floor", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_Z: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ROUND_Z\n"); +#endif + METALCallHelper1(psContext, "trunc", psInst, 0, 1, 1); + break; + } + case OPCODE_ROUND_NE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ROUND_NE\n"); +#endif + METALCallHelper1(psContext, "rint", psInst, 0, 1, 1); + break; + } + case OPCODE_FRC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//FRC\n"); +#endif + METALCallHelper1(psContext, "fract", psInst, 0, 1, 1); + break; + } + case OPCODE_IMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMAX\n"); +#endif + METALCallHelper2Int(psContext, "max", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_MAX: + case OPCODE_UMAX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MAX\n"); +#endif + METALCallHelper2(psContext, "max", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_IMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IMIN\n"); +#endif + METALCallHelper2Int(psContext, "min", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_MIN: + case OPCODE_UMIN: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//MIN\n"); +#endif + METALCallHelper2(psContext, "min", psInst, 0, 1, 2, 1); + break; + } + case OPCODE_GATHER4: + case OPCODE_GATHER4_C: + { + //dest, coords, tex, sampler + const RESOURCE_DIMENSION eResDim = psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber]; + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_GATHER4_C) + { + bcatcstr(metal, "//GATHER4_C\n"); + } + else + { + bcatcstr(metal, "//GATHER4\n"); + } +#endif + //gather4 r7.xyzw, r3.xyxx, t3.xyzw, s0.x + AddIndentation(psContext); // TODO FIXME integer samplers + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(metal, "("); + + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, 0); + + bcatcstr(metal, ".gather("); + bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[2].ui32RegisterNumber, psInst->asOperands[3].ui32RegisterNumber, psInst->eOpcode == OPCODE_GATHER4_PO_C)); + bcatcstr(metal, ", "); + METALTranslateTexCoord(psContext, eResDim, &psInst->asOperands[1]); + + if (psInst->eOpcode == OPCODE_GATHER4_C) + { + bcatcstr(metal, ", "); + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_FLAG_NONE); + } + bcatcstr(metal, ")"); + + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[2]); + bcatcstr(metal, ")"); + + AddSwizzleUsingElementCountMETAL(psContext, GetNumSwizzleElementsMETAL(&psInst->asOperands[0])); + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_GATHER4_PO: + case OPCODE_GATHER4_PO_C: + { + //dest, coords, offset, tex, sampler, srcReferenceValue + +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_GATHER4_PO_C) + { + bcatcstr(metal, "//GATHER4_PO_C\n"); + } + else + { + bcatcstr(metal, "//GATHER4_PO\n"); + } +#endif + + AddIndentation(psContext); // TODO FIXME integer samplers + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, GetNumSwizzleElementsMETAL(&psInst->asOperands[2]), &numParenthesis); + bcatcstr(metal, "("); + + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psInst->asOperands[3].ui32RegisterNumber, 0); + + bcatcstr(metal, ".gather("); + bconcat(metal, TextureSamplerNameMETAL(&psContext->psShader->sInfo, psInst->asOperands[3].ui32RegisterNumber, psInst->asOperands[4].ui32RegisterNumber, psInst->eOpcode == OPCODE_GATHER4_PO_C)); + + bcatcstr(metal, ", "); + //Texture coord cannot be vec4 + //Determining if it is a vec3 for vec2 yet to be done. + psInst->asOperands[1].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[1].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + + if (psInst->eOpcode == OPCODE_GATHER4_PO_C) + { + bcatcstr(metal, ", "); + TranslateOperandMETAL(psContext, &psInst->asOperands[5], TO_FLAG_NONE); + } + + bcatcstr(metal, ", as_type<int2>("); + //ivec2 offset + psInst->asOperands[2].aui32Swizzle[2] = 0xFFFFFFFF; + psInst->asOperands[2].aui32Swizzle[3] = 0xFFFFFFFF; + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, "))"); + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleMETAL(psContext, &psInst->asOperands[3]); + bcatcstr(metal, ")"); + + AddSwizzleUsingElementCountMETAL(psContext, GetNumSwizzleElementsMETAL(&psInst->asOperands[0])); + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_SAMPLE: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE\n"); +#endif + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_NONE); + break; + } + case OPCODE_SAMPLE_L: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE_L\n"); +#endif + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_LOD); + break; + } + case OPCODE_SAMPLE_C: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE_C\n"); +#endif + + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE); + break; + } + case OPCODE_SAMPLE_C_LZ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE_C_LZ\n"); +#endif + + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_DEPTHCOMPARE | TEXSMP_FLAG_FIRSTLOD); + break; + } + case OPCODE_SAMPLE_D: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE_D\n"); +#endif + + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAGS_GRAD); + break; + } + case OPCODE_SAMPLE_B: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SAMPLE_B\n"); +#endif + + METALTranslateTextureSample(psContext, psInst, TEXSMP_FLAG_BIAS); + break; + } + case OPCODE_RET: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//RET\n"); +#endif + if (psContext->havePostShaderCode[psContext->currentPhase]) + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//--- Post shader code ---\n"); +#endif + bconcat(metal, psContext->postShaderCode[psContext->currentPhase]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//--- End post shader code ---\n"); +#endif + } + AddIndentation(psContext); + if (blength(psContext->declaredOutputs) > 0) + { + //has output + bcatcstr(metal, "return output;\n"); + } + else + { + //no output declared + bcatcstr(metal, "return;\n"); + } + break; + } + case OPCODE_INTERFACE_CALL: + { + const char* name; + ShaderVar* psVar; + uint32_t varFound; + + uint32_t funcPointer; + uint32_t funcTableIndex; + uint32_t funcTable; + uint32_t funcBodyIndex; + uint32_t funcBody; + uint32_t ui32NumBodiesPerTable; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//INTERFACE_CALL\n"); +#endif + + ASSERT(psInst->asOperands[0].eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32); + + funcPointer = psInst->asOperands[0].aui32ArraySizes[0]; + funcTableIndex = psInst->asOperands[0].aui32ArraySizes[1]; + funcBodyIndex = psInst->ui32FuncIndexWithinInterface; + + ui32NumBodiesPerTable = psContext->psShader->funcPointer[funcPointer].ui32NumBodiesPerTable; + + funcTable = psContext->psShader->funcPointer[funcPointer].aui32FuncTables[funcTableIndex]; + + funcBody = psContext->psShader->funcTable[funcTable].aui32FuncBodies[funcBodyIndex]; + + varFound = GetInterfaceVarFromOffset(funcPointer, &psContext->psShader->sInfo, &psVar); + + ASSERT(varFound); + + name = &psVar->Name[0]; + + AddIndentation(psContext); + bcatcstr(metal, name); + TranslateOperandIndexMADMETAL(psContext, &psInst->asOperands[0], 1, ui32NumBodiesPerTable, funcBodyIndex); + //bformata(glsl, "[%d]", funcBodyIndex); + bcatcstr(metal, "();\n"); + break; + } + case OPCODE_LABEL: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LABEL\n"); +#endif + --psContext->indent; + AddIndentation(psContext); + bcatcstr(metal, "}\n"); //Closing brace ends the previous function. + AddIndentation(psContext); + + bcatcstr(metal, "subroutine(SubroutineType)\n"); + bcatcstr(metal, "void "); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, "(){\n"); + ++psContext->indent; + break; + } + case OPCODE_COUNTBITS: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//COUNTBITS\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(metal, " = popcount("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(metal, ");\n"); + break; + } + case OPCODE_FIRSTBIT_HI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//FIRSTBIT_HI\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(metal, " = (32 - clz("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, "));\n"); + break; + } + case OPCODE_FIRSTBIT_LO: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//FIRSTBIT_LO\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_UNSIGNED_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(metal, " = (1 + ctz("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ")));\n"); + break; + } + case OPCODE_FIRSTBIT_SHI: //signed high + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//FIRSTBIT_SHI\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER | TO_FLAG_DESTINATION); + bcatcstr(metal, " = (32 - clz("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(metal, " > 0 ? "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(metal, " : 0xFFFFFFFF ^ "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER); + bcatcstr(metal, ")));\n"); + break; + } + case OPCODE_BFI: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//BFI\n"); +#endif + // This instruction is not available in Metal shading language. + // Need to expend it out (http://http.developer.nvidia.com/Cg/bitfieldInsert.html) + + int numComponents = psInst->asOperands[0].iNumComponents; + + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, " = 0;\n"); + + AddIndentation(psContext); + bcatcstr(metal, "{\n"); + + AddIndentation(psContext); + bformata(metal, " %s mask = ~(%s(0xffffffff) << ", GetConstructorForTypeMETAL(SVT_UINT, numComponents), GetConstructorForTypeMETAL(SVT_UINT, numComponents)); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ") << "); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ";\n"); + + AddIndentation(psContext); + bcatcstr(metal, " mask = ~mask;\n"); + + AddIndentation(psContext); + bcatcstr(metal, " "); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bformata(metal, " = ( as_type<%s>( (", GetConstructorForTypeMETAL(psInst->asOperands[0].aeDataType[0], numComponents)); + TranslateOperandMETAL(psContext, &psInst->asOperands[4], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, " & mask) | ("); + TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, " << "); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ")) )"); + TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[0], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + bcatcstr(metal, ";\n"); + + AddIndentation(psContext); + bcatcstr(metal, "}\n"); + + + + break; + } + case OPCODE_BFREV: + case OPCODE_CUT: + case OPCODE_EMIT: + case OPCODE_EMITTHENCUT: + case OPCODE_CUT_STREAM: + case OPCODE_EMIT_STREAM: + case OPCODE_EMITTHENCUT_STREAM: + { + // not implemented in metal + ASSERT(0); + break; + } + case OPCODE_REP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//REP\n"); +#endif + //Need to handle nesting. + //Max of 4 for rep - 'Flow Control Limitations' http://msdn.microsoft.com/en-us/library/windows/desktop/bb219848(v=vs.85).aspx + + AddIndentation(psContext); + bcatcstr(metal, "RepCounter = as_type<int4>("); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(metal, ").x;\n"); + + AddIndentation(psContext); + bcatcstr(metal, "while(RepCounter!=0){\n"); + ++psContext->indent; + break; + } + case OPCODE_ENDREP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ENDREP\n"); +#endif + AddIndentation(psContext); + bcatcstr(metal, "RepCounter--;\n"); + + --psContext->indent; + + AddIndentation(psContext); + bcatcstr(metal, "}\n"); + break; + } + case OPCODE_LOOP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LOOP\n"); +#endif + AddIndentation(psContext); + + if (psInst->ui32NumOperands == 2) + { + //DX9 version + ASSERT(psInst->asOperands[0].eType == OPERAND_TYPE_SPECIAL_LOOPCOUNTER); + bcatcstr(metal, "for("); + bcatcstr(metal, "LoopCounter = "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, ".y, ZeroBasedCounter = 0;"); + bcatcstr(metal, "ZeroBasedCounter < "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, ".x;"); + + bcatcstr(metal, "LoopCounter += "); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, ".z, ZeroBasedCounter++){\n"); + ++psContext->indent; + } + else + { + bcatcstr(metal, "while(true){\n"); + ++psContext->indent; + } + break; + } + case OPCODE_ENDLOOP: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ENDLOOP\n"); +#endif + AddIndentation(psContext); + bcatcstr(metal, "}\n"); + break; + } + case OPCODE_BREAK: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//BREAK\n"); +#endif + AddIndentation(psContext); + bcatcstr(metal, "break;\n"); + break; + } + case OPCODE_BREAKC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//BREAKC\n"); +#endif + AddIndentation(psContext); + + METALTranslateConditional(psContext, psInst, metal); + break; + } + case OPCODE_CONTINUEC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//CONTINUEC\n"); +#endif + AddIndentation(psContext); + + METALTranslateConditional(psContext, psInst, metal); + break; + } + case OPCODE_IF: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//IF\n"); +#endif + AddIndentation(psContext); + + METALTranslateConditional(psContext, psInst, metal); + ++psContext->indent; + break; + } + case OPCODE_RETC: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//RETC\n"); +#endif + AddIndentation(psContext); + + METALTranslateConditional(psContext, psInst, metal); + break; + } + case OPCODE_ELSE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ELSE\n"); +#endif + AddIndentation(psContext); + bcatcstr(metal, "} else {\n"); + psContext->indent++; + break; + } + case OPCODE_ENDSWITCH: + case OPCODE_ENDIF: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(metal, "//ENDIF\n"); + AddIndentation(psContext); + bcatcstr(metal, "}\n"); + break; + } + case OPCODE_CONTINUE: + { + AddIndentation(psContext); + bcatcstr(metal, "continue;\n"); + break; + } + case OPCODE_DEFAULT: + { + --psContext->indent; + AddIndentation(psContext); + bcatcstr(metal, "default:\n"); + ++psContext->indent; + break; + } + case OPCODE_NOP: + { + break; + } + case OPCODE_SYNC: + { + const uint32_t ui32SyncFlags = psInst->ui32SyncFlags; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SYNC\n"); +#endif + // warning. Although Metal documentation claims the flag can be combined + // this is not true in terms of binary operations. One can't simply OR flags + // but rather have to use pre-defined literals. + char* aszBarrierType[] = { + "mem_flags::mem_none", + "mem_flags::mem_threadgroup", + "mem_flags::mem_device", + "mem_flags::mem_device_and_threadgroup" + }; + typedef enum + { + BT_None, + BT_MemThreadGroup, + BT_MemDevice, + BT_MemDeviceAndMemThreadGroup + } BT; + BT barrierType = BT_None; + + if (ui32SyncFlags & SYNC_THREADS_IN_GROUP) + { + AddIndentation(psContext); + bcatcstr(metal, "threadgroup_barrier("); + } + else + { + AddIndentation(psContext); + // simdgroup_barrier is faster than threadgroup_barrier. It is supported on iOS 10+ on all hardware. + bcatcstr(metal, "threadgroup_barrier("); + } + + if (ui32SyncFlags & SYNC_THREAD_GROUP_SHARED_MEMORY) + { + barrierType = (BT)(barrierType | BT_MemThreadGroup); + } + if (ui32SyncFlags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP | SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GLOBAL)) + { + barrierType = (BT)(barrierType | BT_MemDevice); + } + + bcatcstr(metal, aszBarrierType[barrierType]); + bcatcstr(metal, ");\n"); + + break; + } + case OPCODE_SWITCH: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//SWITCH\n"); +#endif + AddIndentation(psContext); + bcatcstr(metal, "switch(int("); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(metal, ")){\n"); + + psContext->indent += 2; + break; + } + case OPCODE_CASE: + { + --psContext->indent; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//case\n"); +#endif + AddIndentation(psContext); + + bcatcstr(metal, "case "); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(metal, ":\n"); + + ++psContext->indent; + break; + } + case OPCODE_EQ: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//EQ\n"); +#endif + METALAddComparision(psContext, psInst, METAL_CMP_EQ, TO_FLAG_NONE, NULL); + break; + } + case OPCODE_USHR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//USHR\n"); +#endif + METALCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_ISHL: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ISHL\n"); +#endif + + if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + + METALCallBinaryOp(psContext, "<<", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_ISHR: + { + SHADER_VARIABLE_TYPE eType = SVT_INT; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//ISHR\n"); +#endif + + if (GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]) == SVT_UINT) + { + eType = SVT_UINT; + } + + METALCallBinaryOp(psContext, ">>", psInst, 0, 1, 2, eType); + break; + } + case OPCODE_LD: + case OPCODE_LD_MS: + { + ResourceBinding* psBinding = 0; +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_LD) + { + bcatcstr(metal, "//LD\n"); + } + else + { + bcatcstr(metal, "//LD_MS\n"); + } +#endif + + GetResourceFromBindingPoint(RGROUP_TEXTURE, psInst->asOperands[2].ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + + //if (psInst->bAddressOffset) + //{ + // METALTranslateTexelFetchOffset(psContext, psInst, psBinding, metal); + //} + //else + //{ + METALTranslateTexelFetch(psContext, psInst, psBinding, metal); + //} + break; + } + case OPCODE_DISCARD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DISCARD\n"); +#endif + AddIndentation(psContext); + + if (psInst->eBooleanTestType == INSTRUCTION_TEST_ZERO) + { + bcatcstr(metal, "if(all("); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(metal, "==0)){discard_fragment();}\n"); + } + else + { + ASSERT(psInst->eBooleanTestType == INSTRUCTION_TEST_NONZERO); + bcatcstr(metal, "if(any("); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_INTEGER); + bcatcstr(metal, "!=0)){discard_fragment();}\n"); + } + break; + } + case OPCODE_LOD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LOD\n"); +#endif + //LOD computes the following vector (ClampedLOD, NonClampedLOD, 0, 0) + + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, 4, &numParenthesis); + + //If the core language does not have query-lod feature, + //then the extension is used. The name of the function + //changed between extension and core. + if (HaveQueryLod(psContext->psShader->eTargetLanguage)) + { + bcatcstr(metal, "textureQueryLod("); + } + else + { + bcatcstr(metal, "textureQueryLOD("); + } + + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ","); + METALTranslateTexCoord(psContext, + psContext->psShader->aeResourceDims[psInst->asOperands[2].ui32RegisterNumber], + &psInst->asOperands[1]); + bcatcstr(metal, ")"); + + //The swizzle on srcResource allows the returned values to be swizzled arbitrarily before they are written to the destination. + + // iWriteMaskEnabled is forced off during DecodeOperand because swizzle on sampler uniforms + // does not make sense. But need to re-enable to correctly swizzle this particular instruction. + psInst->asOperands[2].iWriteMaskEnabled = 1; + TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[2], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_EVAL_CENTROID: + case OPCODE_EVAL_SAMPLE_INDEX: + case OPCODE_EVAL_SNAPPED: + { + // ERROR: evaluation functions are not implemented in metal + ASSERT(0); + break; + } + case OPCODE_LD_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LD_STRUCTURED\n"); +#endif + METALTranslateShaderStorageLoad(psContext, psInst); + break; + } + case OPCODE_LD_UAV_TYPED: + { + // not implemented in metal + ASSERT(0); + break; + } + case OPCODE_STORE_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//STORE_RAW\n"); +#endif + METALTranslateShaderStorageStore(psContext, psInst); + break; + } + case OPCODE_STORE_STRUCTURED: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//STORE_STRUCTURED\n"); +#endif + METALTranslateShaderStorageStore(psContext, psInst); + break; + } + + case OPCODE_STORE_UAV_TYPED: + { + ResourceBinding* psRes; + int foundResource; + +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//STORE_UAV_TYPED\n"); +#endif + AddIndentation(psContext); + + foundResource = GetResourceFromBindingPoint(RGROUP_UAV, + psInst->asOperands[0].ui32RegisterNumber, + &psContext->psShader->sInfo, + &psRes); + + ASSERT(foundResource); + + if (psRes->eBindArea == UAVAREA_CBUFFER) + { + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(metal, "["); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(metal, "]="); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], METALResourceReturnTypeToFlag(psRes->ui32ReturnType), OPERAND_4_COMPONENT_MASK_X); + bcatcstr(metal, ";\n"); + } + else if (psRes->eBindArea == UAVAREA_TEXTURE) + { + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".write("); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[2], METALResourceReturnTypeToFlag(psRes->ui32ReturnType), OPERAND_4_COMPONENT_MASK_ALL); + switch (psRes->eDimension) + { + case REFLECT_RESOURCE_DIMENSION_TEXTURE1D: + { + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ") "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2D: + { + bcatcstr(metal, ",as_type<uint2>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".xy) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE1DARRAY: + { + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".x) "); + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".y) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DARRAY: + { + bcatcstr(metal, ",as_type<uint2>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".xy) "); + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".z) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE3D: + { + bcatcstr(metal, ", as_type<uint3>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".xyz) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBE: + { + bcatcstr(metal, ",as_type<uint2>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".xy) "); + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".z) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURECUBEARRAY: + { + bcatcstr(metal, ",as_type<uint2>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".xy) "); + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".z) "); + bcatcstr(metal, ",as_type<uint>("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NAME_ONLY); + bcatcstr(metal, ".w) "); + break; + } + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMS: + case REFLECT_RESOURCE_DIMENSION_TEXTURE2DMSARRAY: + //not supported in mnetal + ASSERT(0); + break; + } + ; + bcatcstr(metal, ");\n"); + } + else + { + //UAV is not exist in either [[buffer]] or [[texture]] + ASSERT(0); + } + break; + } + case OPCODE_LD_RAW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LD_RAW\n"); +#endif + + METALTranslateShaderStorageLoad(psContext, psInst); + break; + } + + case OPCODE_ATOMIC_CMP_STORE: + case OPCODE_IMM_ATOMIC_AND: + case OPCODE_ATOMIC_AND: + case OPCODE_IMM_ATOMIC_IADD: + case OPCODE_ATOMIC_IADD: + case OPCODE_ATOMIC_OR: + case OPCODE_ATOMIC_XOR: + case OPCODE_ATOMIC_IMIN: + case OPCODE_ATOMIC_UMIN: + case OPCODE_ATOMIC_UMAX: + case OPCODE_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMAX: + case OPCODE_IMM_ATOMIC_IMIN: + case OPCODE_IMM_ATOMIC_UMAX: + case OPCODE_IMM_ATOMIC_UMIN: + case OPCODE_IMM_ATOMIC_OR: + case OPCODE_IMM_ATOMIC_XOR: + case OPCODE_IMM_ATOMIC_EXCH: + case OPCODE_IMM_ATOMIC_CMP_EXCH: + { + TranslateAtomicMemOpMETAL(psContext, psInst); + break; + } + case OPCODE_UBFE: + case OPCODE_IBFE: + { +#ifdef _DEBUG + AddIndentation(psContext); + if (psInst->eOpcode == OPCODE_UBFE) + { + bcatcstr(metal, "//OPCODE_UBFE\n"); + } + else + { + bcatcstr(metal, "//OPCODE_IBFE\n"); + } +#endif + // These instructions are not available in Metal shading language. + // Need to expend it out (http://http.developer.nvidia.com/Cg/bitfieldExtract.html) + // NOTE: we assume bitoffset is always > 0 as to avoid dynamic branching. + // NOTE: We have taken out the -1 as this was breaking the GPU particles bitfields. + + int numComponents = psInst->asOperands[0].iNumComponents; + + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, " = 0;\n"); + + AddIndentation(psContext); + bcatcstr(metal, "{\n"); + + AddIndentation(psContext); + bformata(metal, " %s mask = ~(%s(0xffffffff) << ", GetConstructorForTypeMETAL(SVT_UINT, numComponents), GetConstructorForTypeMETAL(SVT_UINT, numComponents)); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ");\n"); + + AddIndentation(psContext); + bcatcstr(metal, " "); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bformata(metal, " = ( as_type<%s>((", GetConstructorForTypeMETAL(psInst->asOperands[0].aeDataType[0], numComponents)); + TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, " >> ( "); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_UNSIGNED_INTEGER); + bcatcstr(metal, ")) & mask) )"); + TranslateOperandSwizzleWithMaskMETAL(psContext, &psInst->asOperands[0], GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + bcatcstr(metal, ";\n"); + + AddIndentation(psContext); + bcatcstr(metal, "}\n"); + + break; + } + case OPCODE_RCP: + { + const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//RCP\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, " = (float4(1.0) / float4("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, "))"); + AddSwizzleUsingElementCountMETAL(psContext, destElemCount); + bcatcstr(metal, ";\n"); + break; + } + case OPCODE_F32TOF16: + { + const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//F32TOF16\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = { ".x", ".y", ".z", ".w" }; + + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + if (destElemCount > 1) + { + bcatcstr(metal, swizzle[destElem]); + } + + bcatcstr(metal, " = "); + + SHADER_VARIABLE_TYPE eDestDataType = GetOperandDataTypeMETAL(psContext, &psInst->asOperands[0]); + if (SVT_FLOAT == eDestDataType) + { + bcatcstr(metal, "as_type<float>"); + } + bcatcstr(metal, "( (uint( as_type<unsigned short>( (half)"); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + if (s0ElemCount > 1) + { + bcatcstr(metal, swizzle[destElem]); + } + bcatcstr(metal, " ) ) ) );\n"); + } + break; + } + case OPCODE_F16TOF32: + { + const uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + const uint32_t s0ElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//F16TOF32\n"); +#endif + for (destElem = 0; destElem < destElemCount; ++destElem) + { + const char* swizzle[] = { ".x", ".y", ".z", ".w" }; + + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION | TO_FLAG_UNSIGNED_INTEGER); + if (destElemCount > 1) + { + bcatcstr(metal, swizzle[destElem]); + } + + bcatcstr(metal, " = as_type<half> ((unsigned short)"); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_UNSIGNED_INTEGER); + if (s0ElemCount > 1) + { + bcatcstr(metal, swizzle[destElem]); + } + bcatcstr(metal, ");\n"); + } + break; + } + case OPCODE_INEG: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//INEG\n"); +#endif + uint32_t dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + uint32_t srcCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[1]); + + //dest = 0 - src0 + bcatcstr(metal, "-("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE | TO_FLAG_INTEGER); + if (srcCount > dstCount) + { + AddSwizzleUsingElementCountMETAL(psContext, dstCount); + } + bcatcstr(metal, ")"); + bcatcstr(metal, ";\n"); + break; + } + case OPCODE_DERIV_RTX_COARSE: + case OPCODE_DERIV_RTX_FINE: + case OPCODE_DERIV_RTX: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DERIV_RTX\n"); +#endif + METALCallHelper1(psContext, "dfdx", psInst, 0, 1, 1); + break; + } + case OPCODE_DERIV_RTY_COARSE: + case OPCODE_DERIV_RTY_FINE: + case OPCODE_DERIV_RTY: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DERIV_RTY\n"); +#endif + METALCallHelper1(psContext, "dfdy", psInst, 0, 1, 1); + break; + } + case OPCODE_LRP: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//LRP\n"); +#endif + METALCallHelper3(psContext, "mix", psInst, 0, 2, 3, 1, 1); + break; + } + case OPCODE_DP2ADD: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//DP2ADD\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, " = dot(float2("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, "), float2("); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ")) + "); + TranslateOperandMETAL(psContext, &psInst->asOperands[3], TO_FLAG_NONE); + bcatcstr(metal, ";\n"); + break; + } + case OPCODE_POW: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//POW\n"); +#endif + AddIndentation(psContext); + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_FLAG_DESTINATION); + bcatcstr(metal, " = pow(abs("); + TranslateOperandMETAL(psContext, &psInst->asOperands[1], TO_FLAG_NONE); + bcatcstr(metal, "), "); + TranslateOperandMETAL(psContext, &psInst->asOperands[2], TO_FLAG_NONE); + bcatcstr(metal, ");\n"); + break; + } + + case OPCODE_IMM_ATOMIC_ALLOC: + case OPCODE_IMM_ATOMIC_CONSUME: + { + // not implemented in metal + ASSERT(0); + break; + } + + case OPCODE_NOT: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//INOT\n"); +#endif + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_INT, GetNumSwizzleElementsMETAL(&psInst->asOperands[1]), &numParenthesis); + + bcatcstr(metal, "~"); + TranslateOperandWithMaskMETAL(psContext, &psInst->asOperands[1], TO_FLAG_INTEGER, GetOperandWriteMaskMETAL(&psInst->asOperands[0])); + METALAddAssignPrologue(psContext, numParenthesis); + break; + } + case OPCODE_XOR: + { +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//XOR\n"); +#endif + + METALCallBinaryOp(psContext, "^", psInst, 0, 1, 2, SVT_UINT); + break; + } + case OPCODE_RESINFO: + { + uint32_t destElemCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + uint32_t destElem; +#ifdef _DEBUG + AddIndentation(psContext); + bcatcstr(metal, "//RESINFO\n"); +#endif + + for (destElem = 0; destElem < destElemCount; ++destElem) + { + + GetResInfoDataMETAL(psContext, psInst, psInst->asOperands[2].aui32Swizzle[destElem], destElem); + } + + break; + } + + + case OPCODE_DMAX: + case OPCODE_DMIN: + case OPCODE_DMUL: + case OPCODE_DEQ: + case OPCODE_DGE: + case OPCODE_DLT: + case OPCODE_DNE: + case OPCODE_DMOV: + case OPCODE_DMOVC: + case OPCODE_DTOF: + case OPCODE_FTOD: + case OPCODE_DDIV: + case OPCODE_DFMA: + case OPCODE_DRCP: + case OPCODE_MSAD: + case OPCODE_DTOI: + case OPCODE_DTOU: + case OPCODE_ITOD: + case OPCODE_UTOD: + default: + { + ASSERT(0); + break; + } + } + + if (psInst->bSaturate) //Saturate is only for floating point data (float opcodes or MOV) + { + int dstCount = GetNumSwizzleElementsMETAL(&psInst->asOperands[0]); + AddIndentation(psContext); + METALAddAssignToDest(psContext, &psInst->asOperands[0], SVT_FLOAT, dstCount, &numParenthesis); + bcatcstr(metal, "clamp("); + + TranslateOperandMETAL(psContext, &psInst->asOperands[0], TO_AUTO_BITCAST_TO_FLOAT); + bcatcstr(metal, ", 0.0, 1.0)"); + METALAddAssignPrologue(psContext, numParenthesis); + } +} + +static int METALIsIntegerImmediateOpcode(OPCODE_TYPE eOpcode) +{ + switch (eOpcode) + { + case OPCODE_IADD: + case OPCODE_IF: + case OPCODE_IEQ: + case OPCODE_IGE: + case OPCODE_ILT: + case OPCODE_IMAD: + case OPCODE_IMAX: + case OPCODE_IMIN: + case OPCODE_IMUL: + case OPCODE_INE: + case OPCODE_INEG: + case OPCODE_ISHL: + case OPCODE_ISHR: + case OPCODE_ITOF: + case OPCODE_USHR: + case OPCODE_AND: + case OPCODE_OR: + case OPCODE_XOR: + case OPCODE_BREAKC: + case OPCODE_CONTINUEC: + case OPCODE_RETC: + case OPCODE_DISCARD: + //MOV is typeless. + //Treat immediates as int, bitcast to float if necessary + case OPCODE_MOV: + case OPCODE_MOVC: + { + return 1; + } + default: + { + return 0; + } + } +} + +int InstructionUsesRegisterMETAL(const Instruction* psInst, const Operand* psOperand) +{ + uint32_t operand; + for (operand = 0; operand < psInst->ui32NumOperands; ++operand) + { + if (psInst->asOperands[operand].eType == psOperand->eType) + { + if (psInst->asOperands[operand].ui32RegisterNumber == psOperand->ui32RegisterNumber) + { + if (CompareOperandSwizzlesMETAL(&psInst->asOperands[operand], psOperand)) + { + return 1; + } + } + } + } + return 0; +} + +void MarkIntegerImmediatesMETAL(HLSLCrossCompilerContext* psContext) +{ + const uint32_t count = psContext->psShader->asPhase[MAIN_PHASE].pui32InstCount[0]; + Instruction* psInst = psContext->psShader->asPhase[MAIN_PHASE].ppsInst[0]; + uint32_t i; + + for (i = 0; i < count; ) + { + if (psInst[i].eOpcode == OPCODE_MOV && psInst[i].asOperands[1].eType == OPERAND_TYPE_IMMEDIATE32 && + psInst[i].asOperands[0].eType == OPERAND_TYPE_TEMP) + { + uint32_t k; + + for (k = i + 1; k < count; ++k) + { + if (psInst[k].eOpcode == OPCODE_ILT) + { + k = k; + } + if (InstructionUsesRegisterMETAL(&psInst[k], &psInst[i].asOperands[0])) + { + if (METALIsIntegerImmediateOpcode(psInst[k].eOpcode)) + { + psInst[i].asOperands[1].iIntegerImmediate = 1; + } + + goto next_iteration; + } + } + } +next_iteration: + ++i; + } +} diff --git a/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c new file mode 100644 index 0000000000..f1ab027108 --- /dev/null +++ b/Code/Tools/HLSLCrossCompilerMETAL/src/toMETALOperand.c @@ -0,0 +1,2377 @@ +// Modifications copyright Amazon.com, Inc. or its affiliates +// Modifications copyright Crytek GmbH + +#include "internal_includes/toMETALOperand.h" +#include "internal_includes/toMETALDeclaration.h" +#include "bstrlib.h" +#include "hlslcc.h" +#include "internal_includes/debug.h" + +#include <float.h> +#include <stdlib.h> + +#ifdef _MSC_VER +#define isnan(x) _isnan(x) +#define isinf(x) (!_finite(x)) +#endif + +#define fpcheck(x) (isnan(x) || isinf(x)) +#define MAX_STR_LENGTH 128 + +extern void AddIndentation(HLSLCrossCompilerContext* psContext); + +uint32_t SVTTypeToFlagMETAL(const SHADER_VARIABLE_TYPE eType) +{ + if (eType == SVT_UINT) + { + return TO_FLAG_UNSIGNED_INTEGER; + } + else if (eType == SVT_INT) + { + return TO_FLAG_INTEGER; + } + else if (eType == SVT_BOOL) + { + return TO_FLAG_INTEGER; // TODO bools? + } + else if (eType == SVT_FLOAT16) + { + return TO_FLAG_FLOAT16; + } + else + { + return TO_FLAG_NONE; + } +} + +SHADER_VARIABLE_TYPE TypeFlagsToSVTTypeMETAL(const uint32_t typeflags) +{ + if (typeflags & (TO_FLAG_INTEGER | TO_AUTO_BITCAST_TO_INT)) + { + return SVT_INT; + } + if (typeflags & (TO_FLAG_UNSIGNED_INTEGER | TO_AUTO_BITCAST_TO_UINT)) + { + return SVT_UINT; + } + if (typeflags & (TO_FLAG_FLOAT16 | TO_AUTO_BITCAST_TO_FLOAT16)) + { + return SVT_FLOAT16; + } + return SVT_FLOAT; +} + +uint32_t GetOperandWriteMaskMETAL(const Operand* psOperand) +{ + if (psOperand->eSelMode != OPERAND_4_COMPONENT_MASK_MODE || psOperand->ui32CompMask == 0) + { + return OPERAND_4_COMPONENT_MASK_ALL; + } + + return psOperand->ui32CompMask; +} + + +const char* GetConstructorForTypeMETAL(const SHADER_VARIABLE_TYPE eType, + const int components) +{ + static const char* const uintTypes[] = { " ", "uint", "uint2", "uint3", "uint4" }; + static const char* const intTypes[] = { " ", "int", "int2", "int3", "int4" }; + static const char* const floatTypes[] = { " ", "float", "float2", "float3", "float4" }; + static const char* const float16Types[] = { " ", "half", "half2", "half3", "half4" }; + + if (components < 1 || components > 4) + { + return "ERROR TOO MANY COMPONENTS IN VECTOR"; + } + + switch (eType) + { + case SVT_UINT: + return uintTypes[components]; + case SVT_INT: + return intTypes[components]; + case SVT_FLOAT: + return floatTypes[components]; + case SVT_FLOAT16: + return float16Types[components]; + default: + return "ERROR UNSUPPORTED TYPE"; + } +} + + +const char* GetConstructorForTypeFlagMETAL(const uint32_t ui32Flag, + const int components) +{ + if (ui32Flag & TO_FLAG_UNSIGNED_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_UINT) + { + return GetConstructorForTypeMETAL(SVT_UINT, components); + } + else if (ui32Flag & TO_FLAG_INTEGER || ui32Flag & TO_AUTO_BITCAST_TO_INT) + { + return GetConstructorForTypeMETAL(SVT_INT, components); + } + else + { + return GetConstructorForTypeMETAL(SVT_FLOAT, components); + } +} + +int GetMaxComponentFromComponentMaskMETAL(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 4; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 3; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 1; + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + return 4; + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return 1; + } + } + + return 4; +} + +//Single component repeated +//e..g .wwww +uint32_t IsSwizzleReplicatedMETAL(const Operand* psOperand) +{ + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == WWWW_SWIZZLE || + psOperand->ui32Swizzle == ZZZZ_SWIZZLE || + psOperand->ui32Swizzle == YYYY_SWIZZLE || + psOperand->ui32Swizzle == XXXX_SWIZZLE) + { + return 1; + } + } + } + return 0; +} + +static uint32_t METALGetNumberBitsSet(uint32_t a) +{ + // Calculate number of bits in a + // Taken from https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64 + // Works only up to 14 bits (we're only using up to 4) + return (a * 0x200040008001ULL & 0x111111111111111ULL) % 0xf; +} + +//e.g. +//.z = 1 +//.x = 1 +//.yw = 2 +uint32_t GetNumSwizzleElementsMETAL(const Operand* psOperand) +{ + return GetNumSwizzleElementsWithMaskMETAL(psOperand, OPERAND_4_COMPONENT_MASK_ALL); +} + +// Get the number of elements returned by operand, taking additional component mask into account +uint32_t GetNumSwizzleElementsWithMaskMETAL(const Operand* psOperand, uint32_t ui32CompMask) +{ + uint32_t count = 0; + + switch (psOperand->eType) + { + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + return 1; // TODO: does mask make any sense here? + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + // Adjust component count and break to more processing + ((Operand*)psOperand)->iNumComponents = 3; + break; + case OPERAND_TYPE_IMMEDIATE32: + case OPERAND_TYPE_IMMEDIATE64: + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + case OPERAND_TYPE_OUTPUT_DEPTH: + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return METALGetNumberBitsSet(compMask); + } + default: + { + break; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents != 1) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t compMask = psOperand->ui32CompMask; + if (compMask == 0) + { + compMask = OPERAND_4_COMPONENT_MASK_ALL; + } + compMask &= ui32CompMask; + + if (compMask == OPERAND_4_COMPONENT_MASK_ALL) + { + return 4; + } + + if (compMask & OPERAND_4_COMPONENT_MASK_X) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_Y) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_Z) + { + count++; + } + if (compMask & OPERAND_4_COMPONENT_MASK_W) + { + count++; + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if ((ui32CompMask & (1 << i)) == 0) + { + continue; + } + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + count++; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + count++; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + count++; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + count++; + } + } + + //Component Select 1 + } + + if (!count) + { + // Translate numComponents into bitmask + // 1 -> 1, 2 -> 3, 3 -> 7 and 4 -> 15 + uint32_t compMask = (1 << psOperand->iNumComponents) - 1; + + compMask &= ui32CompMask; + // Calculate bits left in compMask + return METALGetNumberBitsSet(compMask); + } + + return count; +} + +void AddSwizzleUsingElementCountMETAL(HLSLCrossCompilerContext* psContext, uint32_t count) +{ + bstring metal = *psContext->currentShaderString; + if (count == 4) + { + return; + } + if (count) + { + bcatcstr(metal, "."); + bcatcstr(metal, "x"); + count--; + } + if (count) + { + bcatcstr(metal, "y"); + count--; + } + if (count) + { + bcatcstr(metal, "z"); + count--; + } + if (count) + { + bcatcstr(metal, "w"); + count--; + } +} + +static uint32_t METALConvertOperandSwizzleToComponentMask(const Operand* psOperand) +{ + uint32_t mask = 0; + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + mask = psOperand->ui32CompMask; + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + mask |= OPERAND_4_COMPONENT_MASK_X; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + mask |= OPERAND_4_COMPONENT_MASK_Y; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + mask |= OPERAND_4_COMPONENT_MASK_Z; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + mask |= OPERAND_4_COMPONENT_MASK_W; + } + } + + //Component Select 1 + } + + return mask; +} + +//Non-zero means the components overlap +int CompareOperandSwizzlesMETAL(const Operand* psOperandA, const Operand* psOperandB) +{ + uint32_t maskA = METALConvertOperandSwizzleToComponentMask(psOperandA); + uint32_t maskB = METALConvertOperandSwizzleToComponentMask(psOperandB); + + return maskA & maskB; +} + + +void TranslateOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, OPERAND_4_COMPONENT_MASK_ALL); +} + +void TranslateOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask) +{ + bstring metal = *psContext->currentShaderString; + + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return; + } + } + + if (psOperand->eType == OPERAND_TYPE_CONSTANT_BUFFER) + { + /*ConstantBuffer* psCBuf = NULL; + ShaderVar* psVar = NULL; + int32_t index = -1; + GetConstantBufferFromBindingPoint(psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + //Access the Nth vec4 (N=psOperand->aui32ArraySizes[1]) + //then apply the sizzle. + + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVar, &index); + + bformata(metal, ".%s", psVar->Name); + if(index != -1) + { + bformata(metal, "[%d]", index); + }*/ + + //return; + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents != 1) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t mask; + if (psOperand->ui32CompMask != 0) + { + mask = psOperand->ui32CompMask & ui32ComponentMask; + } + else + { + mask = ui32ComponentMask; + } + + if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) + { + bcatcstr(metal, "."); + if (mask & OPERAND_4_COMPONENT_MASK_X) + { + bcatcstr(metal, "x"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Y) + { + bcatcstr(metal, "y"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Z) + { + bcatcstr(metal, "z"); + } + if (mask & OPERAND_4_COMPONENT_MASK_W) + { + bcatcstr(metal, "w"); + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || + !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && + psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && + psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && + psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W + ) + ) + { + uint32_t i; + + bcatcstr(metal, "."); + + for (i = 0; i < 4; ++i) + { + if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) + { + continue; + } + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(metal, "y"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(metal, "z"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + bcatcstr(metal, "w"); + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case + { + bcatcstr(metal, "."); + + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + bcatcstr(metal, "y"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + bcatcstr(metal, "z"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + bcatcstr(metal, "w"); + } + } + + //Component Select 1 + } +} + +void TranslateGmemOperandSwizzleWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32ComponentMask, uint32_t gmemNumElements) +{ + // Similar as TranslateOperandSwizzleWithMaskMETAL but need to considerate max # of elements + + bstring metal = *psContext->currentShaderString; + + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents != 1) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t mask; + if (psOperand->ui32CompMask != 0) + { + mask = psOperand->ui32CompMask & ui32ComponentMask; + } + else + { + mask = ui32ComponentMask; + } + + if (mask != 0 && mask != OPERAND_4_COMPONENT_MASK_ALL) + { + bcatcstr(metal, "."); + if (mask & OPERAND_4_COMPONENT_MASK_X) + { + bcatcstr(metal, "x"); + } + if (mask & OPERAND_4_COMPONENT_MASK_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + if (mask & OPERAND_4_COMPONENT_MASK_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + if (mask & OPERAND_4_COMPONENT_MASK_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (ui32ComponentMask != OPERAND_4_COMPONENT_MASK_ALL || + !(psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X && + psOperand->aui32Swizzle[1] == OPERAND_4_COMPONENT_Y && + psOperand->aui32Swizzle[2] == OPERAND_4_COMPONENT_Z && + psOperand->aui32Swizzle[3] == OPERAND_4_COMPONENT_W + ) + ) + { + uint32_t i; + + bcatcstr(metal, "."); + + for (i = 0; i < 4; ++i) + { + if (!(ui32ComponentMask & (OPERAND_4_COMPONENT_MASK_X << i))) + { + continue; + } + + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + else if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) // ui32ComponentMask is ignored in this case + { + bcatcstr(metal, "."); + + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + bcatcstr(metal, "x"); + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + if (gmemNumElements < 2) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "y"); + } + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + if (gmemNumElements < 3) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "z"); + } + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + if (gmemNumElements < 4) + { + bcatcstr(metal, "x"); + } + else + { + bcatcstr(metal, "w"); + } + } + } + + //Component Select 1 + } +} + +int GetFirstOperandSwizzleMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + if (psOperand->eType == OPERAND_TYPE_INPUT) + { + if (psContext->psShader->abScalarInput[psOperand->ui32RegisterNumber]) + { + return -1; + } + } + + if (psOperand->iWriteMaskEnabled && + psOperand->iNumComponents == 4) + { + //Component Mask + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + if (psOperand->ui32CompMask != 0 && psOperand->ui32CompMask != (OPERAND_4_COMPONENT_MASK_X | OPERAND_4_COMPONENT_MASK_Y | OPERAND_4_COMPONENT_MASK_Z | OPERAND_4_COMPONENT_MASK_W)) + { + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_X) + { + return 0; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Y) + { + return 1; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_Z) + { + return 2; + } + if (psOperand->ui32CompMask & OPERAND_4_COMPONENT_MASK_W) + { + return 3; + } + } + } + else + //Component Swizzle + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle != (NO_SWIZZLE)) + { + uint32_t i; + + for (i = 0; i < 4; ++i) + { + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else + if (psOperand->aui32Swizzle[i] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + } + } + else + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_X) + { + return 0; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Y) + { + return 1; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_Z) + { + return 2; + } + else + if (psOperand->aui32Swizzle[0] == OPERAND_4_COMPONENT_W) + { + return 3; + } + } + + //Component Select 1 + } + + return -1; +} + +void TranslateOperandIndexMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index) +{ + int i = index; + + bstring metal = *psContext->currentShaderString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0) + { + bformata(metal, "[%d]", psOperand->aui32ArraySizes[i]); + } + else + { + bformata(metal, "%d", psOperand->aui32ArraySizes[i]); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bcatcstr(metal, "]"); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(metal, "["); //Indexes must be integral. + TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_INTEGER); + bformata(metal, " + %d]", psOperand->aui32ArraySizes[i]); + break; + } + default: + { + break; + } + } +} + +void TranslateOperandIndexMADMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, int index, uint32_t multiply, uint32_t add) +{ + int i = index; + + bstring metal = *psContext->currentShaderString; + + ASSERT(index < psOperand->iIndexDims); + + switch (psOperand->eIndexRep[i]) + { + case OPERAND_INDEX_IMMEDIATE32: + { + if (i > 0) + { + bformata(metal, "[%d*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + } + else + { + bformata(metal, "%d*%d+%d", psOperand->aui32ArraySizes[i], multiply, add); + } + break; + } + case OPERAND_INDEX_RELATIVE: + { + bcatcstr(metal, "[int("); //Indexes must be integral. + TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); + bformata(metal, ")*%d+%d]", multiply, add); + break; + } + case OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE: + { + bcatcstr(metal, "[(int("); //Indexes must be integral. + TranslateOperandMETAL(psContext, psOperand->psSubOperand[i], TO_FLAG_NONE); + bformata(metal, ") + %d)*%d+%d]", psOperand->aui32ArraySizes[i], multiply, add); + break; + } + default: + { + break; + } + } +} + +// Returns nonzero if a direct constructor can convert src->dest +static int METALCanDoDirectCast( SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) +{ + // uint<->int<->bool conversions possible + if ((src == SVT_INT || src == SVT_UINT || src == SVT_BOOL) && (dest == SVT_INT || dest == SVT_UINT || dest == SVT_BOOL)) + { + return 1; + } + + // float<->double possible + if ((src == SVT_FLOAT || src == SVT_DOUBLE) && (dest == SVT_FLOAT || dest == SVT_DOUBLE)) + { + return 1; + } + + return 0; +} + +// Returns true if one of the src or dest is half float while the other is not +static int IsHalfFloatCastNeeded(SHADER_VARIABLE_TYPE src, SHADER_VARIABLE_TYPE dest) +{ + // uint<->int<->bool conversions possible + if ((src == SVT_FLOAT16) && (dest != SVT_FLOAT16)) + { + return 1; + } + + // float<->double possible + if ((src != SVT_FLOAT16) && (dest == SVT_FLOAT16)) + { + return 1; + } + + return 0; +} + +static const char* GetOpDestType(SHADER_VARIABLE_TYPE to) +{ + switch (to) + { + case SVT_FLOAT: + return "float"; + break; + case SVT_FLOAT16: + return "half"; + break; + case SVT_INT: + return "int"; + break; + case SVT_UINT: + return "uint"; + break; + default: + ASSERT(0); + return ""; + } +} + +static const char* GetOpCastType(SHADER_VARIABLE_TYPE from, SHADER_VARIABLE_TYPE to) +{ + if (to == SVT_FLOAT && (from == SVT_INT || from == SVT_UINT)) + { + return "as_type"; + } + else if (to == SVT_INT && (from == SVT_FLOAT || from == SVT_UINT)) + { + return "as_type"; + } + else if (to == SVT_UINT && (from == SVT_FLOAT || from == SVT_INT)) + { + return "as_type"; + } + + ASSERT(0); + return "ERROR missing components in GetBitcastOp()"; +} + +// Helper function to print out a single 32-bit immediate value in desired format +static void METALprintImmediate32(HLSLCrossCompilerContext* psContext, uint32_t value, SHADER_VARIABLE_TYPE eType) +{ + bstring metal = *psContext->currentShaderString; + int needsParenthesis = 0; + + if (eType == SVT_FLOAT || eType == SVT_FLOAT16) + { + // Print floats as bit patterns. + switch (eType) + { + case SVT_FLOAT: + bcatcstr(metal, "as_type<float>("); + break; + case SVT_FLOAT16: + bcatcstr(metal, "static_cast<half>("); + break; + } + + eType = SVT_INT; + needsParenthesis = 1; + } + + + + switch (eType) + { + default: + case SVT_INT: + // Need special handling for anything >= uint 0x3fffffff + if (value > 0x3ffffffe) + { + bformata(metal, "int(0x%Xu)", value); + } + else + { + bformata(metal, "0x%X", value); + } + break; + case SVT_UINT: + bformata(metal, "%uu", value); + break; + case SVT_FLOAT: + bformata(metal, "%f", *((float*)(&value))); + break; + } + if (needsParenthesis) + { + bcatcstr(metal, ")"); + } +} + +static void METALMETALTranslateVariableNameWithMask(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle, uint32_t ui32CompMask) +{ + int numParenthesis = 0; + int hasCtor = 0; + bstring metal = *psContext->currentShaderString; + SHADER_VARIABLE_TYPE requestedType = TypeFlagsToSVTTypeMETAL(ui32TOFlag); + SHADER_VARIABLE_TYPE eType = GetOperandDataTypeExMETAL(psContext, psOperand, requestedType); + int numComponents = GetNumSwizzleElementsWithMaskMETAL(psOperand, ui32CompMask); + int requestedComponents = 0; + + if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC2) + { + requestedComponents = 2; + } + else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC3) + { + requestedComponents = 3; + } + else if (ui32TOFlag & TO_AUTO_EXPAND_TO_VEC4) + { + requestedComponents = 4; + } + + requestedComponents = max(requestedComponents, numComponents); + + *pui32IgnoreSwizzle = 0; + + + if (!(ui32TOFlag & (TO_FLAG_DESTINATION | TO_FLAG_NAME_ONLY | TO_FLAG_DECLARATION_NAME))) + { + if (psOperand->eType == OPERAND_TYPE_IMMEDIATE32 || psOperand->eType == OPERAND_TYPE_IMMEDIATE64) + { + // Mark the operand type to match whatever we're asking for in the flags. + ((Operand*)psOperand)->aeDataType[0] = requestedType; + ((Operand*)psOperand)->aeDataType[1] = requestedType; + ((Operand*)psOperand)->aeDataType[2] = requestedType; + ((Operand*)psOperand)->aeDataType[3] = requestedType; + } + + if (eType != requestedType) + { + if (METALCanDoDirectCast(eType, requestedType)) + { + bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, requestedComponents)); + hasCtor = 1; + } + else if (IsHalfFloatCastNeeded(eType, requestedType)) + { + // half float static cast needed + if (requestedComponents > 1) + { + bformata(metal, "static_cast<%s%i>(", GetOpDestType(requestedType), requestedComponents); + } + else + { + bformata(metal, "static_cast<%s>(", GetOpDestType(requestedType)); + } + } + else + { + // Direct cast not possible, need to do bitcast. + if (requestedComponents > 1) + { + bformata(metal, "%s<%s%i>(", GetOpCastType(eType, requestedType), GetOpDestType(requestedType), requestedComponents); + } + else + { + bformata(metal, "%s<%s>(", GetOpCastType(eType, requestedType), GetOpDestType(requestedType)); + } + } + numParenthesis++; + } + + // Add ctor if needed (upscaling) + if (numComponents < requestedComponents && (hasCtor == 0)) + { + ASSERT(numComponents == 1); + bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, requestedComponents)); + numParenthesis++; + hasCtor = 1; + } + } + + + switch (psOperand->eType) + { + case OPERAND_TYPE_IMMEDIATE32: + { + if (psOperand->iNumComponents == 1) + { + METALprintImmediate32(psContext, *((unsigned int*)(&psOperand->afImmediates[0])), requestedType); + } + else + { + int i; + int firstItemAdded = 0; + if (hasCtor == 0) + { + bformata(metal, "%s(", GetConstructorForTypeMETAL(requestedType, numComponents)); + numParenthesis++; + hasCtor = 1; + } + for (i = 0; i < 4; i++) + { + uint32_t uval; + if (!(ui32CompMask & (1 << i))) + { + continue; + } + + if (firstItemAdded) + { + bcatcstr(metal, ", "); + } + uval = *((uint32_t*)(&psOperand->afImmediates[i])); + METALprintImmediate32(psContext, uval, requestedType); + firstItemAdded = 1; + } + bcatcstr(metal, ")"); + *pui32IgnoreSwizzle = 1; + numParenthesis--; + } + break; + } + case OPERAND_TYPE_IMMEDIATE64: + { + if (psOperand->iNumComponents == 1) + { + bformata(metal, "%f", + psOperand->adImmediates[0]); + } + else + { + bformata(metal, "float4(%f, %f, %f, %f)", + psOperand->adImmediates[0], + psOperand->adImmediates[1], + psOperand->adImmediates[2], + psOperand->adImmediates[3]); + if (psOperand->iNumComponents != 4) + { + AddSwizzleUsingElementCountMETAL(psContext, psOperand->iNumComponents); + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + switch (psOperand->iIndexDims) + { + case INDEX_2D: + { + if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. + { + bcatcstr(metal, "stageIn"); + TranslateOperandIndexMETAL(psContext, psOperand, 0); //Vertex index + bcatcstr(metal, ".position"); + } + else + { + const char* name = "Input"; + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + name = GetDeclaredInputNameMETAL(psContext, psContext->psShader->eShaderType, psOperand); + } + + bformata(metal, "%s%d", name, psOperand->aui32ArraySizes[1]); + TranslateOperandIndexMETAL(psContext, psOperand, 0); //Vertex index + } + break; + } + default: + { + if (psOperand->eIndexRep[0] == OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE) + { + bformata(metal, "Input%d[", psOperand->ui32RegisterNumber); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(metal, "]"); + } + else + { + if (psContext->psShader->aIndexedInput[psOperand->ui32RegisterNumber] != 0) + { + const uint32_t parentIndex = psContext->psShader->aIndexedInputParents[psOperand->ui32RegisterNumber]; + bformata(metal, "Input%d[%d]", parentIndex, + psOperand->ui32RegisterNumber - parentIndex); + } + else + { + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + const char* name = GetDeclaredInputNameMETAL(psContext, psContext->psShader->eShaderType, psOperand); + bcatcstr(metal, name); + } + else + { + bformata(metal, "Input%d", psOperand->ui32RegisterNumber); + } + } + } + break; + } + } + break; + } + case OPERAND_TYPE_OUTPUT: + { + bformata(metal, "Output%d", psOperand->ui32RegisterNumber); + if (psOperand->psSubOperand[0]) + { + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_AUTO_BITCAST_TO_INT); + bcatcstr(metal, "]"); + } + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH: + { + bcatcstr(metal, "DepthAny"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL: + { + bcatcstr(metal, "DepthGreater"); + break; + } + case OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL: + { + bcatcstr(metal, "DepthLess"); + break; + } + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eType2 = GetOperandDataTypeMETAL(psContext, psOperand); + bcatcstr(metal, "Temp"); + + if (eType2 == SVT_INT) + { + bcatcstr(metal, "_int"); + } + else if (eType2 == SVT_UINT) + { + bcatcstr(metal, "_uint"); + } + else if (eType2 == SVT_DOUBLE) + { + bcatcstr(metal, "_double"); + } + else if (eType2 == SVT_FLOAT16) + { + bcatcstr(metal, "_half"); + } + else if (eType2 == SVT_VOID && + (ui32TOFlag & TO_FLAG_DESTINATION)) + { + ASSERT(0 && "Should never get here!"); + /* if(ui32TOFlag & TO_FLAG_INTEGER) + { + bcatcstr(metal, "_int"); + } + else + if(ui32TOFlag & TO_FLAG_UNSIGNED_INTEGER) + { + bcatcstr(metal, "_uint"); + }*/ + } + + bformata(metal, "[%d]", psOperand->ui32RegisterNumber); + + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONSTINT: + { + bformata(metal, "IntImmConst%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_SPECIAL_IMMCONST: + { + if (psOperand->psSubOperand[0] != NULL) + { + if (psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber] != 0) + { + bformata(metal, "ImmConstArray[%d + ", psContext->psShader->aui32Dx9ImmConstArrayRemap[psOperand->ui32RegisterNumber]); + } + else + { + bcatcstr(metal, "ImmConstArray["); + } + TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER, OPERAND_4_COMPONENT_MASK_X); + bcatcstr(metal, "]"); + } + else + { + bformata(metal, "ImmConst%d", psOperand->ui32RegisterNumber); + } + break; + } + case OPERAND_TYPE_SPECIAL_OUTBASECOLOUR: + { + bcatcstr(metal, "BaseColour"); + break; + } + case OPERAND_TYPE_SPECIAL_OUTOFFSETCOLOUR: + { + bcatcstr(metal, "OffsetColour"); + break; + } + case OPERAND_TYPE_SPECIAL_POSITION: + { + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "stageIn."); + } + bcatcstr(metal, "position"); + break; + } + case VERTEX_SHADER: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "output."); + } + bcatcstr(metal, "position"); + break; + } + default: + { + break; + } + } + break; + } + case OPERAND_TYPE_SPECIAL_FOG: + { + bcatcstr(metal, "Fog"); + break; + } + case OPERAND_TYPE_SPECIAL_POINTSIZE: + { + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "stageIn."); + } + bcatcstr(metal, "pointSize"); + break; + } + case VERTEX_SHADER: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "output."); + } + bcatcstr(metal, "pointSize"); + break; + } + default: + { + break; + } + } + break; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + { + bcatcstr(metal, "Address"); + break; + } + case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: + { + bcatcstr(metal, "LoopCounter"); + pui32IgnoreSwizzle[0] = 1; + break; + } + case OPERAND_TYPE_SPECIAL_TEXCOORD: + { + bformata(metal, "TexCoord%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + const char* StageName = "VS"; + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + + switch (psContext->psShader->eShaderType) + { + case PIXEL_SHADER: + { + StageName = "PS"; + break; + } + ////////////////////// FOLLOWING SHOULDN'T HIT IN METAL AS IT'S NOT SUPPORTED ////////////////////////////////////////// + case HULL_SHADER: + { + StageName = "HS"; + break; + } + case DOMAIN_SHADER: + { + StageName = "DS"; + break; + } + case GEOMETRY_SHADER: + { + StageName = "GS"; + break; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + case COMPUTE_SHADER: + { + StageName = "CS"; + break; + } + default: + { + break; + } + } + + if (ui32TOFlag & TO_FLAG_DECLARATION_NAME) + { + pui32IgnoreSwizzle[0] = 1; + } + + // FIXME: With ES 3.0 the buffer name is often not prepended to variable names + if (((psContext->flags & HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) != HLSLCC_FLAG_UNIFORM_BUFFER_OBJECT) && + ((psContext->flags & HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT) != HLSLCC_FLAG_DISABLE_GLOBALS_STRUCT)) + { + if (psCBuf) + { + //$Globals. + if (psCBuf->Name[0] == '$') + { + bformata(metal, "Globals%s", StageName); + } + else + { + bformata(metal, "%s%s", psCBuf->Name, StageName); + } + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "."); + } + } + else + { + //bformata(metal, "cb%d", psOperand->aui32ArraySizes[0]); + } + } + + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + //Work out the variable name. Don't apply swizzle to that variable yet. + int32_t rebase = 0; + + if (psCBuf && !psCBuf->blob) + { + GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + + bformata(metal, "%s", psVarType->FullName); + } + else if (psCBuf) + { + bformata(metal, "%s%s_data", psCBuf->Name, StageName); + if (psContext->psShader->eShaderType == PIXEL_SHADER) + { + bformata(metal, ".%s", psCBuf->asVars->Name); + } + else if (psContext->psShader->eShaderType == VERTEX_SHADER) + { + bformata(metal, "->%s", psCBuf->asVars->Name); + } + else + { + ASSERT(0); + } + index = psOperand->aui32ArraySizes[1]; + } + else // We don't have a semantic for this variable, so try the raw dump appoach. + { + bformata(metal, "cb%d.data", psOperand->aui32ArraySizes[0]); // + index = psOperand->aui32ArraySizes[1]; + } + + //Dx9 only? + if (psOperand->psSubOperand[0] != NULL) + { + // Array of matrices is treated as array of vec4s in HLSL, + // but that would mess up uniform types in metal. Do gymnastics. + uint32_t opFlags = TO_FLAG_INTEGER; + + if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays + bcatcstr(metal, "[("); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], opFlags); + bformata(metal, ") / 4]"); + if (psContext->psShader->eTargetLanguage <= LANG_120) + { + bcatcstr(metal, "[int(mod(float("); + TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); + bformata(metal, "), 4.0))]"); + } + else + { + bcatcstr(metal, "[(("); + TranslateOperandWithMaskMETAL(psContext, psOperand->psSubOperand[0], opFlags, OPERAND_4_COMPONENT_MASK_X); + bformata(metal, ") %% 4)]"); + } + } + else + { + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], opFlags); + bformata(metal, "]"); + } + } + else + if (index != -1 && psOperand->psSubOperand[1] != NULL) + { + // Array of matrices is treated as array of vec4s in HLSL, + // but that would mess up uniform types in metal. Do gymnastics. + SHADER_VARIABLE_TYPE eType2 = GetOperandDataTypeMETAL(psContext, psOperand->psSubOperand[1]); + uint32_t opFlags = TO_FLAG_INTEGER; + if (eType2 != SVT_INT && eType2 != SVT_UINT) + { + opFlags = TO_AUTO_BITCAST_TO_INT; + } + + if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays + bcatcstr(metal, "[("); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); + bformata(metal, " + %d) / 4]", index); + if (psContext->psShader->eTargetLanguage <= LANG_120) + { + bcatcstr(metal, "[int(mod(float("); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); + bformata(metal, " + %d), 4.0))]", index); + } + else + { + bcatcstr(metal, "[(("); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); + bformata(metal, " + %d) %% 4)]", index); + } + } + else + { + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], opFlags); + bformata(metal, " + %d]", index); + } + } + else if (index != -1) + { + if (psVarType && (psVarType->Class == SVC_MATRIX_COLUMNS || psVarType->Class == SVC_MATRIX_ROWS) && (psVarType->Elements > 1)) + { + // Special handling for matrix arrays, open them up into vec4's + size_t matidx = index / 4; + size_t rowidx = index - (matidx * 4); + bformata(metal, "[%d][%d]", matidx, rowidx); + } + else + { + bformata(metal, "[%d]", index); + } + } + else if (psOperand->psSubOperand[1] != NULL) + { + bcatcstr(metal, "["); + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + bcatcstr(metal, "]"); + } + + if (psVarType && psVarType->Class == SVC_VECTOR) + { + switch (rebase) + { + case 4: + { + if (psVarType->Columns == 2) + { + //.x(metal) is .y(HLSL). .y(metal) is .z(HLSL) + bcatcstr(metal, ".xxyx"); + } + else if (psVarType->Columns == 3) + { + //.x(metal) is .y(HLSL). .y(metal) is .z(HLSL) .z(metal) is .w(HLSL) + bcatcstr(metal, ".xxyz"); + } + break; + } + case 8: + { + if (psVarType->Columns == 2) + { + //.x(metal) is .z(HLSL). .y(metal) is .w(HLSL) + bcatcstr(metal, ".xxxy"); + } + break; + } + case 0: + default: + { + //No rebase, but extend to vec4. + if (psVarType->Columns == 2) + { + bcatcstr(metal, ".xyxx"); + } + else if (psVarType->Columns == 3) + { + bcatcstr(metal, ".xyzx"); + } + break; + } + } + } + + if (psVarType && psVarType->Class == SVC_SCALAR) + { + *pui32IgnoreSwizzle = 1; + } + } + break; + } + case OPERAND_TYPE_RESOURCE: + { + ResourceNameMETAL(metal, psContext, RGROUP_TEXTURE, psOperand->ui32RegisterNumber, 0); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_SAMPLER: + { + bformata(metal, "Sampler%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_FUNCTION_BODY: + { + const uint32_t ui32FuncBody = psOperand->ui32RegisterNumber; + const uint32_t ui32FuncTable = psContext->psShader->aui32FuncBodyToFuncTable[ui32FuncBody]; + //const uint32_t ui32FuncPointer = psContext->psShader->aui32FuncTableToFuncPointer[ui32FuncTable]; + const uint32_t ui32ClassType = psContext->psShader->sInfo.aui32TableIDToTypeID[ui32FuncTable]; + const char* ClassTypeName = &psContext->psShader->sInfo.psClassTypes[ui32ClassType].Name[0]; + const uint32_t ui32UniqueClassFuncIndex = psContext->psShader->ui32NextClassFuncName[ui32ClassType]++; + + bformata(metal, "%s_Func%d", ClassTypeName, ui32UniqueClassFuncIndex); + break; + } + case OPERAND_TYPE_INPUT_FORK_INSTANCE_ID: + { + bcatcstr(metal, "forkInstanceID"); + *pui32IgnoreSwizzle = 1; + return; + } + case OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: + { + bcatcstr(metal, "immediateConstBufferF"); + + if (psOperand->psSubOperand[0]) + { + bcatcstr(metal, "("); //Indexes must be integral. + TranslateOperandMETAL(psContext, psOperand->psSubOperand[0], TO_FLAG_INTEGER); + bcatcstr(metal, ")"); + } + break; + } + case OPERAND_TYPE_INPUT_DOMAIN_POINT: + { + bcatcstr(metal, "gl_TessCoord"); + break; + } + case OPERAND_TYPE_INPUT_CONTROL_POINT: + { + if (psOperand->aui32ArraySizes[1] == 0) //Input index zero - position. + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "stageIn."); + } + bformata(metal, "position", psOperand->aui32ArraySizes[0]); + } + else + { + bformata(metal, "Input%d[%d]", psOperand->aui32ArraySizes[1], psOperand->aui32ArraySizes[0]); + } + break; + } + case OPERAND_TYPE_NULL: + { + // Null register, used to discard results of operations + bcatcstr(metal, "//null"); + break; + } + case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: + { + break; + } + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "output."); + } + bcatcstr(metal, "sampleMask"); + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_COVERAGE_MASK: + { + if ((ui32TOFlag & TO_FLAG_DECLARATION_NAME) != TO_FLAG_DECLARATION_NAME) + { + bcatcstr(metal, "stageIn."); + } + bcatcstr(metal, "sampleMask"); + //Skip swizzle on scalar types. + *pui32IgnoreSwizzle = 1; + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID: //SV_DispatchThreadID + { + bcatcstr(metal, "vThreadID"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: //SV_GroupThreadID + { + bcatcstr(metal, "vThreadGroupID"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: //SV_GroupID + { + bcatcstr(metal, "vThreadIDInGroup"); + break; + } + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: //SV_GroupIndex + { + bcatcstr(metal, "vThreadIDInGroupFlattened"); + *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. + break; + } + case OPERAND_TYPE_UNORDERED_ACCESS_VIEW: + { + ResourceNameMETAL(metal, psContext, RGROUP_UAV, psOperand->ui32RegisterNumber, 0); + if (ui32TOFlag | TO_FLAG_NAME_ONLY) + { + *pui32IgnoreSwizzle = 1; + } + break; + } + case OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY: + { + bformata(metal, "TGSM%d", psOperand->ui32RegisterNumber); + *pui32IgnoreSwizzle = 1; // No swizzle meaningful for scalar. + break; + } + case OPERAND_TYPE_INPUT_PRIMITIVEID: + { + break; + } + case OPERAND_TYPE_INDEXABLE_TEMP: + { + bformata(metal, "TempArray%d", psOperand->aui32ArraySizes[0]); + bcatcstr(metal, "["); + if (psOperand->aui32ArraySizes[1] != 0 || !psOperand->psSubOperand[1]) + { + bformata(metal, "%d", psOperand->aui32ArraySizes[1]); + } + + if (psOperand->psSubOperand[1]) + { + if (psOperand->aui32ArraySizes[1] != 0) + { + bcatcstr(metal, "+"); + } + TranslateOperandMETAL(psContext, psOperand->psSubOperand[1], TO_FLAG_INTEGER); + } + bcatcstr(metal, "]"); + break; + } + case OPERAND_TYPE_STREAM: + { + bformata(metal, "%d", psOperand->ui32RegisterNumber); + break; + } + case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: + { + // No GS in METAL + break; + } + case OPERAND_TYPE_THIS_POINTER: + { + /* + The "this" register is a register that provides up to 4 pieces of information: + X: Which CB holds the instance data + Y: Base element offset of the instance data within the instance CB + Z: Base sampler index + W: Base Texture index + + Can be different for each function call + */ + break; + } + case OPERAND_TYPE_INPUT_PATCH_CONSTANT: + { + bformata(metal, "myPatchConst%d", psOperand->ui32RegisterNumber); + break; + } + default: + { + ASSERT(0); + break; + } + } + + if (hasCtor && (*pui32IgnoreSwizzle == 0)) + { + TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, ui32CompMask); + *pui32IgnoreSwizzle = 1; + } + + if (*pui32IgnoreSwizzle == 0) + { + TranslateOperandSwizzleWithMaskMETAL(psContext, psOperand, ui32CompMask); + } + + while (numParenthesis != 0) + { + bcatcstr(metal, ")"); + numParenthesis--; + } +} + +static void METALTranslateVariableName(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t* pui32IgnoreSwizzle) +{ + METALMETALTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, pui32IgnoreSwizzle, OPERAND_4_COMPONENT_MASK_ALL); +} + + +SHADER_VARIABLE_TYPE GetOperandDataTypeMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand) +{ + return GetOperandDataTypeExMETAL(psContext, psOperand, SVT_INT); +} + +SHADER_VARIABLE_TYPE GetOperandDataTypeExMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, SHADER_VARIABLE_TYPE ePreferredTypeForImmediates) +{ + + // The min precision qualifier overrides all of the stuff below + if (psOperand->eMinPrecision == OPERAND_MIN_PRECISION_FLOAT_16) + { + return SVT_FLOAT16; + } + + switch (psOperand->eType) + { + case OPERAND_TYPE_TEMP: + { + SHADER_VARIABLE_TYPE eCurrentType = SVT_VOID; + int i = 0; + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SELECT_1_MODE) + { + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + if (psOperand->eSelMode == OPERAND_4_COMPONENT_SWIZZLE_MODE) + { + if (psOperand->ui32Swizzle == (NO_SWIZZLE)) + { + return psOperand->aeDataType[0]; + } + + return psOperand->aeDataType[psOperand->aui32Swizzle[0]]; + } + + if (psOperand->eSelMode == OPERAND_4_COMPONENT_MASK_MODE) + { + uint32_t ui32CompMask = psOperand->ui32CompMask; + if (!psOperand->ui32CompMask) + { + ui32CompMask = OPERAND_4_COMPONENT_MASK_ALL; + } + for (; i < 4; ++i) + { + if (ui32CompMask & (1 << i)) + { + eCurrentType = psOperand->aeDataType[i]; + break; + } + } + + #ifdef _DEBUG + //Check if all elements have the same basic type. + for (; i < 4; ++i) + { + if (psOperand->ui32CompMask & (1 << i)) + { + if (eCurrentType != psOperand->aeDataType[i]) + { + ASSERT(0); + } + } + } + #endif + return eCurrentType; + } + + ASSERT(0); + + break; + } + case OPERAND_TYPE_OUTPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psOut; + + if (GetOutputSignatureFromRegister(psContext->currentPhase, + ui32Register, + psOperand->ui32CompMask, + 0, + &psContext->psShader->sInfo, + &psOut)) + { + if (psOut->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psOut->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_INPUT: + { + const uint32_t ui32Register = psOperand->aui32ArraySizes[psOperand->iIndexDims - 1]; + InOutSignature* psIn; + + //UINT in DX, INT in GL. + if (psOperand->eSpecialName == NAME_PRIMITIVE_ID) + { + return SVT_INT; + } + if (psOperand->eSpecialName == NAME_IS_FRONT_FACE) + { + return SVT_BOOL; + } + + if (GetInputSignatureFromRegister(ui32Register, &psContext->psShader->sInfo, &psIn)) + { + if (psIn->eComponentType == INOUT_COMPONENT_UINT32) + { + return SVT_UINT; + } + else if (psIn->eComponentType == INOUT_COMPONENT_SINT32) + { + return SVT_INT; + } + } + break; + } + case OPERAND_TYPE_CONSTANT_BUFFER: + { + ConstantBuffer* psCBuf = NULL; + ShaderVarType* psVarType = NULL; + int32_t index = -1; + int32_t rebase = -1; + int foundVar; + GetConstantBufferFromBindingPoint(RGROUP_CBUFFER, psOperand->aui32ArraySizes[0], &psContext->psShader->sInfo, &psCBuf); + if (psCBuf && !psCBuf->blob) + { + foundVar = GetShaderVarFromOffset(psOperand->aui32ArraySizes[1], psOperand->aui32Swizzle, psCBuf, &psVarType, &index, &rebase); + if (foundVar && index == -1 && psOperand->psSubOperand[1] == NULL) + { + return psVarType->Type; + } + } + else + { + // Todo: this isn't correct yet. + return SVT_FLOAT; + } + break; + } + case OPERAND_TYPE_IMMEDIATE32: + { + return ePreferredTypeForImmediates; + } + + case OPERAND_TYPE_INPUT_THREAD_ID: + case OPERAND_TYPE_INPUT_THREAD_GROUP_ID: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: + case OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: + { + return SVT_UINT; + } + case OPERAND_TYPE_SPECIAL_ADDRESS: + case OPERAND_TYPE_SPECIAL_LOOPCOUNTER: + { + return SVT_INT; + } + case OPERAND_TYPE_INPUT_GS_INSTANCE_ID: + { + return SVT_UINT; + } + case OPERAND_TYPE_OUTPUT_COVERAGE_MASK: + { + return SVT_INT; + } + case OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: + { + return SVT_INT; + } + default: + { + return SVT_FLOAT; + } + } + + return SVT_FLOAT; +} + +void TranslateOperandMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag) +{ + TranslateOperandWithMaskMETAL(psContext, psOperand, ui32TOFlag, OPERAND_4_COMPONENT_MASK_ALL); +} + +void TranslateOperandWithMaskMETAL(HLSLCrossCompilerContext* psContext, const Operand* psOperand, uint32_t ui32TOFlag, uint32_t ui32ComponentMask) +{ + bstring metal = *psContext->currentShaderString; + uint32_t ui32IgnoreSwizzle = 0; + + if (ui32TOFlag & TO_FLAG_NAME_ONLY) + { + METALTranslateVariableName(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle); + return; + } + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + bcatcstr(metal, "(-"); + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(metal, "abs("); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(metal, "-abs("); + break; + } + } + + METALMETALTranslateVariableNameWithMask(psContext, psOperand, ui32TOFlag, &ui32IgnoreSwizzle, ui32ComponentMask); + + switch (psOperand->eModifier) + { + case OPERAND_MODIFIER_NONE: + { + break; + } + case OPERAND_MODIFIER_NEG: + { + bcatcstr(metal, ")"); + break; + } + case OPERAND_MODIFIER_ABS: + { + bcatcstr(metal, ")"); + break; + } + case OPERAND_MODIFIER_ABSNEG: + { + bcatcstr(metal, ")"); + break; + } + } +} + +void ResourceNameMETAL(bstring targetStr, HLSLCrossCompilerContext* psContext, ResourceGroup group, const uint32_t ui32RegisterNumber, const int bZCompare) +{ + bstring metal = (targetStr == NULL) ? *psContext->currentShaderString : targetStr; + ResourceBinding* psBinding = 0; + int found; + + found = GetResourceFromBindingPoint(group, ui32RegisterNumber, &psContext->psShader->sInfo, &psBinding); + + if (found) + { + int i = 0; + char name[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32ArrayOffset = ui32RegisterNumber - psBinding->ui32BindPoint; + + while (psBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) + { + name[i] = psBinding->Name[i]; + + //array syntax [X] becomes _0_ + //Otherwise declarations could end up as: + //uniform sampler2D SomeTextures[0]; + //uniform sampler2D SomeTextures[1]; + if (name[i] == '[' || name[i] == ']') + { + name[i] = '_'; + } + + ++i; + } + + name[i] = '\0'; + + if (ui32ArrayOffset) + { + bformata(metal, "%s%d", name, ui32ArrayOffset); + } + else + { + bformata(metal, "%s", name); + } + + if (RGROUP_SAMPLER == group) + { + if (bZCompare) + { + bcatcstr(metal, "_cmp"); + } + else + { + bcatcstr(metal, "_s"); + } + } + } + else + { + bformata(metal, "UnknownResource%d", ui32RegisterNumber); + } +} + +bstring TextureSamplerNameMETAL(ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) +{ + bstring result; + ResourceBinding* psTextureBinding = 0; + ResourceBinding* psSamplerBinding = 0; + int foundTexture, foundSampler; + uint32_t i = 0; + char samplerName[MAX_REFLECT_STRING_LENGTH]; + uint32_t ui32ArrayOffset; + + foundTexture = GetResourceFromBindingPoint(RGROUP_TEXTURE, ui32TextureRegisterNumber, psShaderInfo, &psTextureBinding); + foundSampler = GetResourceFromBindingPoint(RGROUP_SAMPLER, ui32SamplerRegisterNumber, psShaderInfo, &psSamplerBinding); + + if (!foundTexture || !foundSampler) + { + result = bformat("UnknownResource%d_%d", ui32TextureRegisterNumber, ui32SamplerRegisterNumber); + return result; + } + + ui32ArrayOffset = ui32SamplerRegisterNumber - psSamplerBinding->ui32BindPoint; + + while (psSamplerBinding->Name[i] != '\0' && i < (MAX_REFLECT_STRING_LENGTH - 1)) + { + samplerName[i] = psSamplerBinding->Name[i]; + + //array syntax [X] becomes _0_ + //Otherwise declarations could end up as: + //uniform sampler2D SomeTextures[0]; + //uniform sampler2D SomeTextures[1]; + if (samplerName[i] == '[' || samplerName[i] == ']') + { + samplerName[i] = '_'; + } + + ++i; + } + samplerName[i] = '\0'; + + result = bfromcstr(""); + + + + if (ui32ArrayOffset) + { + bformata(result, "%s%d", samplerName, ui32ArrayOffset); + } + else + { + bformata(result, "%s", samplerName); + } + + if (bZCompare) + { + bcatcstr(result, "_cmp"); + } + else + { + bcatcstr(result, "_s"); + } + + return result; +} + +void ConcatTextureSamplerNameMETAL(bstring str, ShaderInfo* psShaderInfo, const uint32_t ui32TextureRegisterNumber, const uint32_t ui32SamplerRegisterNumber, const int bZCompare) +{ + bstring texturesamplername = TextureSamplerNameMETAL(psShaderInfo, ui32TextureRegisterNumber, ui32SamplerRegisterNumber, bZCompare); + bconcat(str, texturesamplername); + bdestroy(texturesamplername); +} + +uint32_t GetGmemInputResourceSlotMETAL(uint32_t const slotIn) +{ + if (slotIn >= GMEM_FLOAT4_START_SLOT) + { + return slotIn - GMEM_FLOAT4_START_SLOT; + } + if (slotIn >= GMEM_FLOAT3_START_SLOT) + { + return slotIn - GMEM_FLOAT3_START_SLOT; + } + if (slotIn >= GMEM_FLOAT2_START_SLOT) + { + return slotIn - GMEM_FLOAT2_START_SLOT; + } + if (slotIn >= GMEM_FLOAT_START_SLOT) + { + return slotIn - GMEM_FLOAT_START_SLOT; + } + return slotIn; +} + +uint32_t GetGmemInputResourceNumElementsMETAL(uint32_t const slotIn) +{ + if (slotIn >= GMEM_FLOAT4_START_SLOT) + { + return 4; + } + if (slotIn >= GMEM_FLOAT3_START_SLOT) + { + return 3; + } + if (slotIn >= GMEM_FLOAT2_START_SLOT) + { + return 2; + } + if (slotIn >= GMEM_FLOAT_START_SLOT) + { + return 1; + } + return 0; +} From 961f2ef1133ec27d68cbf2d6ee0c839cdecf1760 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 20 Apr 2021 12:04:57 -0700 Subject: [PATCH 25/96] Replace string/hash based execution out look up for indices, 10-50% speed up in lookup code. Fix bugs calling dependent functions. --- .../ScriptCanvasBuilderWorkerUtility.cpp | 2 + .../FunctionNodePaletteTreeItemTypes.cpp | 4 +- .../AutoGen/ScriptCanvasNodeable_Source.jinja | 2 +- .../ScriptCanvas_Nodeable_Macros.jinja | 34 +- .../Include/ScriptCanvas/Core/EBusHandler.cpp | 14 +- .../Code/Include/ScriptCanvas/Core/Node.cpp | 44 + .../Code/Include/ScriptCanvas/Core/Node.h | 4 + .../Include/ScriptCanvas/Core/Nodeable.cpp | 83 +- .../Code/Include/ScriptCanvas/Core/Nodeable.h | 114 +- .../ScriptCanvas/Core/NodeableNode.cpp | 13 - .../Include/ScriptCanvas/Core/NodeableNode.h | 2 - .../ScriptCanvas/Core/SlotExecutionMap.cpp | 16 - .../ScriptCanvas/Core/SlotExecutionMap.h | 2 - .../ScriptCanvas/Core/SubgraphInterface.cpp | 21 +- .../ScriptCanvas/Core/SubgraphInterface.h | 4 +- .../Interpreted/ExecutionInterpretedAPI.cpp | 73 +- .../ExecutionInterpretedEBusAPI.cpp | 35 +- .../Execution/RuntimeComponent.cpp | 2 +- .../Grammar/AbstractCodeModel.cpp | 37 +- .../ScriptCanvas/Grammar/AbstractCodeModel.h | 1 + .../ScriptCanvas/Grammar/ParsingUtilities.cpp | 7 + .../ScriptCanvas/Grammar/ParsingUtilities.h | 2 + .../Include/ScriptCanvas/Grammar/Primitives.h | 2 +- .../Grammar/PrimitivesDeclarations.h | 2 +- .../Grammar/PrimitivesExecution.cpp | 10 + .../Grammar/PrimitivesExecution.h | 6 + .../Internal/Nodeables/BaseTimer.cpp | 2 +- .../Libraries/Core/EBusEventHandler.cpp | 5 + .../Libraries/Core/EBusEventHandler.h | 1 + .../Libraries/Core/ReceiveScriptEvent.cpp | 5 + .../Libraries/Core/ReceiveScriptEvent.h | 1 + .../Operators/Math/OperatorLerpNodeable.h | 9 +- .../Include/ScriptCanvas/SystemComponent.h | 2 +- .../ScriptCanvas/Translation/GraphToLua.cpp | 67 +- .../Code/Source/SystemComponent.cpp | 4 +- ..._SC_UnitTest_ExecutionCycle10.scriptcanvas | 3216 +++++++++ ...tTest_ExecutionOutPerformance.scriptcanvas | 5753 +++++++++++++++++ ...C_UnitTest_HelloWorldFunction.scriptcanvas | 628 ++ ...est_HelloWorldFunctionNotPure.scriptcanvas | 733 +++ ...tentCallOfNotPureUserFunction.scriptcanvas | 750 +++ ..._LatentCallOfPureUserFunction.scriptcanvas | 750 +++ .../Framework/ScriptCanvasTestFixture.h | 12 +- .../Code/Source/ScriptCanvasTestBus.cpp | 81 + .../Code/Source/ScriptCanvasTestBus.h | 21 + .../ScriptCanvasTestingSystemComponent.cpp | 6 +- .../Tests/ScriptCanvas_RuntimeInterpreted.cpp | 15 + 46 files changed, 12331 insertions(+), 266 deletions(-) create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionCycle10.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionOutPerformance.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunction.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunctionNotPure.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas create mode 100644 Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas diff --git a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp index 0a0c3f3712..ab59ddd840 100644 --- a/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp +++ b/Gems/ScriptCanvas/Code/Builder/ScriptCanvasBuilderWorkerUtility.cpp @@ -394,11 +394,13 @@ namespace ScriptCanvasBuilder int GetBuilderVersion() { + // #functions2 remove-execution-out-hash include version from all library nodes, split fingerprint generation to relax Is Out of Data restriction when graphs only need a recompile return static_cast<int>(BuilderVersion::Current) + static_cast<int>(ScriptCanvas::GrammarVersion::Current) + static_cast<int>(ScriptCanvas::RuntimeVersion::Current) ; } + AZ::Outcome < AZ::Data::Asset<ScriptCanvasEditor::ScriptCanvasAsset>, AZStd::string> LoadEditorAsset(AZStd::string_view filePath) { AZStd::shared_ptr<AZ::Data::AssetDataStream> assetDataStream = AZStd::make_shared<AZ::Data::AssetDataStream>(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.cpp index 6d36236906..e1d02c2792 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/FunctionNodePaletteTreeItemTypes.cpp @@ -41,11 +41,11 @@ namespace ScriptCanvasEditor if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext)) { serializeContext->Class<CreateFunctionMimeEvent, CreateNodeMimeEvent>() - ->Version(4) + ->Version(5) ->Field("AssetId", &CreateFunctionMimeEvent::m_assetId) + ->Field("sourceId", &CreateFunctionMimeEvent::m_sourceId) ; } - } CreateFunctionMimeEvent::CreateFunctionMimeEvent(const AZ::Data::AssetId& assetId, const AZ::Data::AssetType& assetType, const ScriptCanvas::Grammar::FunctionSourceId& sourceId) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja index 7b873e1362..27498a2aec 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvasNodeable_Source.jinja @@ -158,7 +158,7 @@ return {{returnNames[0]}}; {% endfor %} {# ExecutionOuts #} // ExecutionOuts begin -{{ nodemacro.ExecutionOutDefinitions(Class, attribute_QualifiedName )}} +{{ nodemacro.ExecutionOutDefinitions(Class, attribute_QualifiedName)}} // ExecutionOuts end {# Reflect #} void {{attribute_QualifiedName}}::Reflect(AZ::ReflectContext* context) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvas_Nodeable_Macros.jinja b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvas_Nodeable_Macros.jinja index f66765004c..6cd0edd68c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvas_Nodeable_Macros.jinja +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/AutoGen/ScriptCanvas_Nodeable_Macros.jinja @@ -307,41 +307,49 @@ AZStd::tuple<{{returns|join(", ")}}> {% for executionOut in Class.findall('Output') %} {{ ExecutionOutDeclaration(Class, executionOut) }} {%- endfor %} +size_t GetRequiredOutCount() const override; {% endmacro %} -{% macro ExecutionBranchDefinition(Class, qualifiedName, executionOut) %} +{% macro ExecutionBranchDefinition(Class, qualifiedName, executionOut, outIndexBranch) %} {% set outName = CleanName(executionOut.attrib['Name']) %} {% set returns = executionOut.findall('Parameter') %} {% set params = executionOut.findall('Return') %} -void {{qualifiedName}}::Call{{CleanName(outName)}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) { +void {{qualifiedName}}::Call{{outName}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) { {% if returns|length() == 0 %} - ExecutionOut(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"){% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %} + ExecutionOut({{ outIndexBranch }}{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %} {% else %} - OutResult(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"), result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %} -{% endif -%}); + ExecutionOutResult({{ outIndexBranch }}, result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %} +{% endif -%}); // {{ executionOut.attrib['Name'] }} } {% endmacro %} -{% macro ExecutionOutDefinition(Class, qualifiedName, executionOut) %} +{% macro ExecutionOutDefinition(Class, qualifiedName, executionOut, outIndexLatent) %} {% set outName = CleanName(executionOut.attrib['Name']) %} {% set returns = executionOut.findall('Return') %} {% set params = executionOut.findall('Parameter') %} void {{qualifiedName}}::Call{{CleanName(outName)}}({{ExecutionOutReturnDefinition(returns)}}{{ExecutionOutParameterDefinition(returns, params)}}) { {% if returns|length() == 0 %} - ExecutionOut(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"){% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %} + ExecutionOut({{ outIndexLatent }}{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %} {% else %} - OutResult(AZ_CRC_CE("{{ executionOut.attrib['Name'] }}"), result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}} {% endfor %} -{% endif -%} ); + ExecutionOutResult({{ outIndexLatent }}, result{% for parameter in params %}, {{CleanName(parameter.attrib['Name'])}}{% endfor %} +{% endif -%}); // {{ executionOut.attrib['Name'] }} } {% endmacro %} {% macro ExecutionOutDefinitions(Class, qualifiedName) %} +{% set branches = [] %} {% for method in Class.findall('Input') %} {%- for branch in method.findall('Branch') %} - {{ ExecutionBranchDefinition(Class, qualifiedName, branch) }} +{% if branches.append(branch) %}{% endif %} {%- endfor %} -{% endfor %} -{%- for executionOut in Class.findall('Output') -%} - {{ ExecutionOutDefinition(Class, qualifiedName, executionOut) }} +{% endfor %} +{%- for branch in branches -%} + {{ ExecutionBranchDefinition(Class, qualifiedName, branch, loop.index0) }} +{%- endfor %} +{%- for executionOut in Class.findall('Output') -%} + {{ ExecutionOutDefinition(Class, qualifiedName, executionOut, loop.index0 + branches|length) }} {%- endfor %} + +size_t {{qualifiedName}}::GetRequiredOutCount() const { return {{Class.findall('Output')|length + branches|length}}; } + {% endmacro %} \ No newline at end of file diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/EBusHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/EBusHandler.cpp index 84e67c1215..804bb59e56 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/EBusHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/EBusHandler.cpp @@ -88,17 +88,7 @@ namespace ScriptCanvas void EBusHandler::InitializeEBusHandling(AZStd::string_view busName, AZ::BehaviorContext* behaviorContext) { CreateHandler(busName, behaviorContext); - - const AZ::BehaviorEBusHandler::EventArray& events = m_handler->GetEvents(); - AZStd::vector<AZ::Crc32> eventKeys; - eventKeys.reserve(events.size()); - - for (int eventIndex(0); eventIndex < events.size(); ++eventIndex) - { - eventKeys.push_back(eventIndex); - } - - InitializeExecutionOuts(eventKeys); + InitializeExecutionOuts(m_handler->GetEvents().size()); } bool EBusHandler::IsConnected() const @@ -137,7 +127,7 @@ namespace ScriptCanvas void EBusHandler::OnEvent(const char* /*eventName*/, const int eventIndex, AZ::BehaviorValueParameter* result, const int numParameters, AZ::BehaviorValueParameter* parameters) { - CallOut(AZ::Crc32(eventIndex), result, parameters, numParameters); + CallOut(eventIndex, result, parameters, numParameters); } void EBusHandler::Reflect(AZ::ReflectContext* reflectContext) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp index 23def4cb55..4a936c8824 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.cpp @@ -3155,6 +3155,11 @@ namespace ScriptCanvas return {}; } + AZStd::optional<size_t> Node::GetEventIndex([[maybe_unused]] AZStd::string eventName) const + { + return AZStd::nullopt; + } + AZStd::vector<SlotId> Node::GetEventSlotIds() const { return {}; @@ -3404,6 +3409,45 @@ namespace ScriptCanvas return GetSlotByName("True"); } + size_t Node::GetOutIndex(const Slot& slot) const + { + size_t index = 0; + auto slotId = slot.GetId(); + + if (auto map = GetSlotExecutionMap()) + { + auto& ins = map->GetIns(); + for (auto& in : ins) + { + for (auto& out : in.outs) + { + // only count branches + if (in.outs.size() > 1) + { + if (out.slotId == slotId) + { + return index; + } + + ++index; + } + } + } + + for (auto& latent : map->GetLatents()) + { + if (latent.slotId == slotId) + { + return index; + } + + ++index; + } + } + + return std::numeric_limits<size_t>::max(); + } + AZ::Outcome<AZStd::string> Node::GetInternalOutKey(const Slot& slot) const { if (auto map = GetSlotExecutionMap()) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h index d51667764f..d3d36ae71b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Node.h @@ -700,6 +700,8 @@ namespace ScriptCanvas // override if necessary, usually only when the node's execution topology dramatically alters at edit-time in a way that is not generally parseable ConstSlotsOutcome GetSlotsInExecutionThreadByType(const Slot& executionSlot, CombinedSlotType targetSlotType, const Slot* executionChildSlot = nullptr) const; + size_t GetOutIndex(const Slot& slot) const; + // override if necessary, only used by NodeableNodes which can hide branched outs and rename them later virtual AZ::Outcome<AZStd::string> GetInternalOutKey(const Slot& slot) const; @@ -751,6 +753,8 @@ namespace ScriptCanvas virtual AZStd::string GetEBusName() const; + virtual AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const; + virtual AZStd::vector<SlotId> GetEventSlotIds() const; virtual AZStd::vector<SlotId> GetNonEventSlotIds() const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.cpp index ff8779319a..b642ef3889 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.cpp @@ -19,7 +19,7 @@ namespace NodeableOutCpp { - void NoOp(AZ::BehaviorValueParameter* /*result*/, AZ::BehaviorValueParameter* /*arguments*/, int /*numArguments*/) {} + void NoOp([[maybe_unused]] AZ::BehaviorValueParameter*, [[maybe_unused]] AZ::BehaviorValueParameter*, [[maybe_unused]] int) {} } namespace ScriptCanvas @@ -36,14 +36,14 @@ namespace ScriptCanvas {} #if !defined(RELEASE) - void Nodeable::CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const + void Nodeable::CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const { - GetExecutionOutChecked(key)(resultBVP, argsBVPs, numArguments); + GetExecutionOutChecked(index)(resultBVP, argsBVPs, numArguments); } #else - void Nodeable::CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const + void Nodeable::CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const { - GetExecutionOut(key)(resultBVP, argsBVPs, numArguments); + GetExecutionOut(index)(resultBVP, argsBVPs, numArguments); } #endif // !defined(RELEASE) @@ -62,11 +62,6 @@ namespace ScriptCanvas return m_executionState->GetEntityId(); } - AZ::EntityId Nodeable::GetScriptCanvasId() const - { - return m_executionState->GetScriptCanvasId(); - } - void Nodeable::Reflect(AZ::ReflectContext* reflectContext) { if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(reflectContext)) @@ -77,9 +72,9 @@ namespace ScriptCanvas { editContext->Class<Nodeable>("Nodeable", "Nodeable") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false) + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ; } } @@ -92,71 +87,69 @@ namespace ScriptCanvas ->Constructor<ExecutionStateWeakPtr>() ->Method("Deactivate", &Nodeable::Deactivate) ->Method("InitializeExecutionState", &Nodeable::InitializeExecutionState) + ->Method("InitializeExecutionOuts", &Nodeable::InitializeExecutionOuts) + ->Method("InitializeExecutionOutByRequiredCount", &Nodeable::InitializeExecutionOutByRequiredCount) ->Method("IsActive", &Nodeable::IsActive) ; } } - const FunctorOut& Nodeable::GetExecutionOut(AZ::Crc32 key) const + const FunctorOut& Nodeable::GetExecutionOut(size_t index) const { - auto iter = m_outs.find(key); - AZ_Assert(iter != m_outs.end(), "no out registered for key: %d", key); - AZ_Assert(iter->second, "null execution methods are not allowed, key: %d", key); - return iter->second; + AZ_Assert(index < m_outs.size(), "index out of range in Nodeable::m_outs"); + auto& iter = m_outs[index]; + AZ_Assert(iter, "null execution methods are not allowed, index: %zu", index); + return iter; } - const FunctorOut& Nodeable::GetExecutionOutChecked(AZ::Crc32 key) const + const FunctorOut& Nodeable::GetExecutionOutChecked(size_t index) const { - auto iter = m_outs.find(key); - - if (iter == m_outs.end()) - { - return m_noOpFunctor; - } - else if (!iter->second) + + if (index >= m_outs.size() && m_outs[index]) { return m_noOpFunctor; } - return iter->second; + return m_outs[index]; } - void Nodeable::InitializeExecutionState(ExecutionState* executionState) + AZ::EntityId Nodeable::GetScriptCanvasId() const { - AZ_Assert(executionState != nullptr, "execution state for nodeable must not be nullptr"); - AZ_Assert(m_executionState == nullptr, "execution state already initialized"); - m_executionState = executionState->WeakFromThis(); + return m_executionState->GetScriptCanvasId(); } - void Nodeable::InitializeExecutionOuts(const AZ::Crc32* begin, const AZ::Crc32* end) + void Nodeable::InitializeExecutionOuts(size_t count) { - m_outs.reserve(end - begin); + m_outs.resize(count, m_noOpFunctor); + } - for (; begin != end; ++begin) - { - SetExecutionOut(*begin, AZStd::move(FunctorOut(&NodeableOutCpp::NoOp))); - } + void Nodeable::InitializeExecutionOutByRequiredCount() + { + InitializeExecutionOuts(GetRequiredOutCount()); } - void Nodeable::InitializeExecutionOuts(const AZStd::vector<AZ::Crc32>& keys) + void Nodeable::InitializeExecutionState(ExecutionState* executionState) { - InitializeExecutionOuts(keys.begin(), keys.end()); + AZ_Assert(executionState != nullptr, "execution state for nodeable must not be nullptr"); + AZ_Assert(m_executionState == nullptr, "execution state already initialized"); + m_executionState = executionState->WeakFromThis(); + OnInitializeExecutionState(); } - void Nodeable::SetExecutionOut(AZ::Crc32 key, FunctorOut&& out) + void Nodeable::SetExecutionOut(size_t index, FunctorOut&& out) { - AZ_Assert(out, "null executions methods are not allowed, key: %d", key); - m_outs[key] = AZStd::move(out); + AZ_Assert(out, "null executions methods are not allowed, index: %zu", index); + m_outs[index] = AZStd::move(out); } - void Nodeable::SetExecutionOutChecked(AZ::Crc32 key, FunctorOut&& out) + void Nodeable::SetExecutionOutChecked(size_t index, FunctorOut&& out) { if (!out) { - AZ_Error("ScriptCanvas", false, "null executions methods are not allowed, key: %d", key); + AZ_Error("ScriptCanvas", false, "null executions methods are not allowed, index: %zu", index); return; } - SetExecutionOut(key, AZStd::move(out)); + SetExecutionOut(index, AZStd::move(out)); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.h index 3695f3e9fa..963893ee3f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Nodeable.h @@ -29,6 +29,23 @@ namespace ScriptCanvas class SubgraphInterface; } + /* + Note: Many parts of AzAutoGen, compilation, and runtime depend on the order of declaration and addition of slots. + The display order can be manipulated in the editor, but it will always just be a change of view. + + Whenever in doubt, this is the order, in pseudo code + + for in : Ins do + somethingOrdered(in) + for branch : in.Branches do + somethingOrdered(branch) + end + end + for out : Outs do + somethingOrdered(out) + end + */ + // derive from this to make an object that when wrapped with a NodeableNode can be instantly turned into a node that is easily embedded in graphs, // and easily compiled in class Nodeable @@ -40,21 +57,23 @@ namespace ScriptCanvas // reflect nodeable class API static void Reflect(AZ::ReflectContext* reflectContext); + // the run-time constructor for non-EBus handlers Nodeable(); + // this constructor is used by EBus handlers only Nodeable(ExecutionStateWeakPtr executionState); virtual ~Nodeable() = default; - void CallOut(const AZ::Crc32 key, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const; + void CallOut(size_t index, AZ::BehaviorValueParameter* resultBVP, AZ::BehaviorValueParameter* argsBVPs, int numArguments) const; AZ::Data::AssetId GetAssetId() const; AZ::EntityId GetEntityId() const; - const Execution::FunctorOut& GetExecutionOut(AZ::Crc32 key) const; + const Execution::FunctorOut& GetExecutionOut(size_t index) const; - const Execution::FunctorOut& GetExecutionOutChecked(AZ::Crc32 key) const; + const Execution::FunctorOut& GetExecutionOutChecked(size_t index) const; virtual NodePropertyInterface* GetPropertyInterface(AZ::Crc32 /*propertyId*/) { return nullptr; } @@ -66,98 +85,97 @@ namespace ScriptCanvas // any would only be good if graphs could opt into it, and execution slots could annotate changing activity level virtual bool IsActive() const { return false; } - void InitializeExecutionOuts(const AZ::Crc32* begin, const AZ::Crc32* end); - - void InitializeExecutionOuts(const AZStd::vector<AZ::Crc32>& keys); + void InitializeExecutionOuts(size_t count); - void SetExecutionOut(AZ::Crc32 key, Execution::FunctorOut&& out); + void SetExecutionOut(size_t index, Execution::FunctorOut&& out); - void SetExecutionOutChecked(AZ::Crc32 key, Execution::FunctorOut&& out); + void SetExecutionOutChecked(size_t index, Execution::FunctorOut&& out); protected: + void InitializeExecutionOutByRequiredCount(); + void InitializeExecutionState(ExecutionState* executionState); + virtual void OnInitializeExecutionState() {} + virtual void OnDeactivate() {} + virtual size_t GetRequiredOutCount() const { return 0; } + + // Required to decay array type to pointer type + template<typename T> + using decay_array = AZStd::conditional_t<AZStd::is_array_v<AZStd::remove_reference_t<T>>, std::remove_extent_t<AZStd::remove_reference_t<T>>*, T&&>; + // all of these hooks are known at compile time, so no branching - // we will need with and without result calls for each time for method + // we will need with and without result calls for each type of method // methods with result but no result requested, etc + template<typename... t_Args> + void ExecutionOut(size_t index, t_Args&&... args) const + { + // it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) + AZStd::tuple<decay_array<t_Args>...> lvalueWrapper(AZStd::forward<t_Args>(args)...); + using BVPReserveArray = AZStd::array<AZ::BehaviorValueParameter, sizeof...(args)>; + auto MakeBVPArrayFunction = [](auto&&... element) + { + return BVPReserveArray{ {AZ::BehaviorValueParameter{&element}...} }; + }; + + BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper); + CallOut(index, nullptr, argsBVPs.data(), sizeof...(t_Args)); + } + + void ExecutionOut(size_t index) const + { + // it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) + CallOut(index, nullptr, nullptr, 0); + } template<typename t_Return> - void OutResult(const AZ::Crc32 key, t_Return& result) const + void ExecutionOutResult(size_t index, t_Return& result) const { - // this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) + // It is up to the FunctorOut referenced by the index to decide what to do with these params (whether to modify or handle strings differently) AZ::BehaviorValueParameter resultBVP(&result); - - CallOut(key, &resultBVP, nullptr, 0); + CallOut(index, &resultBVP, nullptr, 0); #if !defined(RELEASE) if (!resultBVP.GetAsUnsafe<t_Return>()) { - AZ_Error("ScriptCanvas", false, "%s:CallOut(%u) failed to provide a useable result", TYPEINFO_Name(), (AZ::u32)key); + AZ_Error("ScriptCanvas", false, "%s:CallOut(%zu) failed to provide a useable result", TYPEINFO_Name(), index); return; } #endif result = *resultBVP.GetAsUnsafe<t_Return>(); } - // Required to decay array type to pointer type - template<typename T> - using decay_array = AZStd::conditional_t<AZStd::is_array_v<AZStd::remove_reference_t<T>>, std::remove_extent_t<AZStd::remove_reference_t<T>>*, T&&>; - template<typename t_Return, typename... t_Args> - void OutResult(const AZ::Crc32 key, t_Return& result, t_Args&&... args) const + void ExecutionOutResult(size_t index, t_Return& result, t_Args&&... args) const { - // this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) + // it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) AZStd::tuple<decay_array<t_Args>...> lvalueWrapper(AZStd::forward<t_Args>(args)...); using BVPReserveArray = AZStd::array<AZ::BehaviorValueParameter, sizeof...(args)>; auto MakeBVPArrayFunction = [](auto&&... element) { return BVPReserveArray{ {AZ::BehaviorValueParameter{&element}...} }; }; + BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper); AZ::BehaviorValueParameter resultBVP(&result); - - CallOut(key, &resultBVP, argsBVPs.data(), sizeof...(t_Args)); + CallOut(index, &resultBVP, argsBVPs.data(), sizeof...(t_Args)); #if !defined(RELEASE) if (!resultBVP.GetAsUnsafe<t_Return>()) { - AZ_Error("ScriptCanvas", false, "%s:CallOut(%u) failed to provide a useable result", TYPEINFO_Name(), (AZ::u32)key); + AZ_Error("ScriptCanvas", false, "%s:CallOut(%zu) failed to provide a useable result", TYPEINFO_Name(), index); return; } #endif result = *resultBVP.GetAsUnsafe<t_Return>(); } - template<typename... t_Args> - void ExecutionOut(const AZ::Crc32 key, t_Args&&... args) const - { - // this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) - AZStd::tuple<decay_array<t_Args>...> lvalueWrapper(AZStd::forward<t_Args>(args)...); - using BVPReserveArray = AZStd::array<AZ::BehaviorValueParameter, sizeof...(args)>; - auto MakeBVPArrayFunction = [](auto&&... element) - { - return BVPReserveArray{ {AZ::BehaviorValueParameter{&element}...} }; - }; - BVPReserveArray argsBVPs = AZStd::apply(MakeBVPArrayFunction, lvalueWrapper); - - CallOut(key, nullptr, argsBVPs.data(), sizeof...(t_Args)); - } - - void ExecutionOut(const AZ::Crc32 key) const - { - // this is correct, it is up to the FunctorOut referenced by key to decide what to do with these params (whether to modify or handle strings differently) - CallOut(key, nullptr, nullptr, 0); - } - private: - // keep this here, and don't even think about putting it back in the FunctorOuts by any method*, lambda capture or other. - // programmers will need this for internal node state debugging and who knows what other reasons - // * Lua execution is an exception ExecutionStateWeakPtr m_executionState = nullptr; Execution::FunctorOut m_noOpFunctor; - AZStd::unordered_map<AZ::Crc32, Execution::FunctorOut> m_outs; + AZStd::vector<Execution::FunctorOut> m_outs; }; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.cpp index 8fc582954a..c406a5c100 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.cpp @@ -91,19 +91,6 @@ namespace ScriptCanvas AZ_Error("ScriptCanvas", m_nodeable, "null Nodeable in NodeableNode::ConfigureSlots"); } - AZ::Outcome<AZStd::pair<size_t, size_t>> NodeableNode::FindMethodAndInputIndexOfSlot(const SlotId& slotID) const - { - if (auto thisSlot = GetSlot(slotID)) - { - if (thisSlot->GetType() == CombinedSlotType::DataIn) - { - return m_slotExecutionMap.FindInAndInputIndexOfSlot(slotID); - } - } - - return AZ::Failure(); - } - AZ::Outcome<const AZ::BehaviorClass*, AZStd::string> NodeableNode::GetBehaviorContextClass() const { AZ::BehaviorContext* behaviorContext = NodeableNodeCpp::GetBehaviorContext(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.h index 60ad7d3273..0193641d97 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/NodeableNode.h @@ -73,8 +73,6 @@ namespace ScriptCanvas void ConfigureSlots() override; - AZ::Outcome<AZStd::pair<size_t, size_t>> FindMethodAndInputIndexOfSlot(const SlotId& slotID) const; - AZ::Outcome<const AZ::BehaviorClass*, AZStd::string> GetBehaviorContextClass() const; ConstSlotsOutcome GetBehaviorContextOutName(const Slot& inSlot) const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.cpp index 34af917c96..05c5e0e5d7 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.cpp @@ -152,22 +152,6 @@ namespace ScriptCanvas return nullptr; } - AZ::Outcome<AZStd::pair<size_t, size_t>> Map::FindInAndInputIndexOfSlot(const SlotId& slotID) const - { - for (const auto& in : m_ins) - { - auto inputIter = find_if(in.inputs, [&slotID](const Input& input) { return input.slotId == slotID; }); - if (inputIter != in.inputs.end()) - { - const size_t inIndex = &in - m_ins.begin(); - const size_t inputIndex = inputIter - in.inputs.begin(); - return AZ::Success(AZStd::make_pair(inIndex, inputIndex)); - } - } - - return AZ::Failure(); - } - const In* Map::FindInFromInputSlot(const SlotId& slotID) const { auto iter = find_if diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.h index 25c237b138..9daf1d8eb9 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotExecutionMap.h @@ -124,8 +124,6 @@ namespace ScriptCanvas Map(Outs&& latents); - AZ::Outcome<AZStd::pair<size_t, size_t>> FindInAndInputIndexOfSlot(const SlotId& slotID) const; - const In* FindInFromInputSlot(const SlotId& slotID) const; SlotId FindInputSlotIdBySource(VariableId inputSourceId, Grammar::FunctionSourceId inSourceId) const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp index 61ea74d011..e73c049780 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp @@ -209,13 +209,18 @@ namespace ScriptCanvas m_latents.push_back(out); } - void SubgraphInterface::AddOutKey(const AZStd::string& name) + bool SubgraphInterface::AddOutKey(const AZStd::string& name) { const AZ::Crc32 key(name); if (AZStd::find(m_outKeys.begin(), m_outKeys.end(), key) == m_outKeys.end()) { m_outKeys.push_back(key); + return true; + } + else + { + return false; } } @@ -708,7 +713,7 @@ namespace ScriptCanvas } // Populates the list of out keys - void SubgraphInterface::Parse() + AZ::Outcome<void, AZStd::string> SubgraphInterface::Parse() { m_outKeys.clear(); @@ -716,14 +721,22 @@ namespace ScriptCanvas { for (const auto& out : in.outs) { - AddOutKey(out.displayName); + if (!AddOutKey(out.displayName)) + { + return AZ::Failure(AZStd::string::format("Out %s was already in the list: %s", out.displayName.c_str())); + } } } for (const auto& latent : m_latents) { - AddOutKey(latent.displayName); + if (!AddOutKey(latent.displayName)) + { + return AZ::Failure(AZStd::string::format("Out %s was already in the list: %s", latent.displayName.c_str())); + } } + + return AZ::Success(); } void SubgraphInterface::Reflect(AZ::ReflectContext* refectContext) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h index 3eea850666..069f3c84a2 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.h @@ -232,7 +232,7 @@ namespace ScriptCanvas bool operator==(const SubgraphInterface& rhs) const; // Populates the list of out keys - void Parse(); + AZ::Outcome<void, AZStd::string> Parse(); bool RequiresConstructionParameters() const; @@ -266,7 +266,7 @@ namespace ScriptCanvas AZStd::vector<AZ::Crc32> m_outKeys; NamespacePath m_namespacePath; - void AddOutKey(const AZStd::string& name); + bool AddOutKey(const AZStd::string& name); const Out* FindImmediateOut(const AZStd::string& in, const AZStd::string& out) const; const In* FindIn(const AZStd::string& inSlotId) const; const Out* FindLatentOut(const AZStd::string& latent) const; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp index 722328ff17..518174d0f8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.cpp @@ -508,11 +508,10 @@ namespace ScriptCanvas const int argsCount = lua_gettop(lua); AZ_Assert(argsCount >= 2, "CallExecutionOut: Error in compiled Lua file, not enough arguments"); AZ_Assert(lua_isuserdata(lua, 1), "CallExecutionOut: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); + AZ_Assert(lua_isnumber(lua, 2), "CallExecutionOut: Error in compiled lua file, 2nd argument to SetExecutionOut is not a number"); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1); - const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, 2); - AZ_Assert(keyStr, "CallExecutionOut: Failed to read key string"); - nodeable->CallOut(AZ::Crc32(keyStr), nullptr, nullptr, argsCount - 2); + size_t index = aznumeric_caster(lua_tointeger(lua, -2)); + nodeable->CallOut(index, nullptr, nullptr, argsCount - 2); // Lua: results... return lua_gettop(lua); } @@ -559,23 +558,14 @@ namespace ScriptCanvas int InitializeNodeableOutKeys(lua_State* lua) { using namespace ExecutionInterpretedAPICpp; - // Lua: usernodeable, outKeys... + // Lua: usernodeable, keyCount const int argsCount = lua_gettop(lua); - AZ_Assert(argsCount >= 2, "InitializeNodeableOutKeys: Error in compiled Lua file, not enough arguments"); - AZ_Assert((argsCount - 1) < k_MaxNodeableOuts, "InitializeNodeableOutKeys: Error in compiled Lua file, too many outs for nodeable out)"); + AZ_Assert(argsCount == 2, "InitializeNodeableOutKeys: Error in compiled Lua file, not enough arguments"); AZ_Assert(lua_isuserdata(lua, 1), "InitializeNodeableOutKeys: Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, 1); - const int keyCount = argsCount - 1; - - AZStd::array<AZ::Crc32, k_MaxNodeableOuts> keys; - - for (int argumentIndex = 2, sentinel = argsCount + 1; argumentIndex != sentinel; ++argumentIndex) - { - AZ_Assert(lua_isnumber(lua, argumentIndex), "InitializeNodeableOutKeys: Error in compiled lua file, argument at Lua index #%d was not an integer", argumentIndex); - keys[argumentIndex - 2] = static_cast<AZ::u32>(lua_tointeger(lua, argumentIndex)); - } - - nodeable->InitializeExecutionOuts(keys.begin(), keys.begin() + keyCount); + AZ_Assert(lua_isnumber(lua, 2), "InitializeNodeableOutKeys: Error in compiled lua file, 2nd argument was not an integer"); + const size_t keyCount = aznumeric_caster(lua_tointeger(lua, 2)); + nodeable->InitializeExecutionOuts(keyCount); return 0; } @@ -595,19 +585,18 @@ namespace ScriptCanvas // \see https://jira.agscollab.com/browse/LY-99750 AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); + AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a number"); AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3); AZ_Assert(nodeable, "Failed to read nodeable"); - const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2); - AZ_Assert(keyStr, "Failed to read key string"); - // Lua: nodeable, string, lambda + size_t index = aznumeric_caster(lua_tointeger(lua, -2)); + // Lua: nodeable, index, lambda lua_pushvalue(lua, -1); - // Lua: nodeable, string, lambda, lambda + // Lua: nodeable, index, lambda, lambda - nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpreted(lua)); - // Lua: nodeable, string, lambda + nodeable->SetExecutionOut(index, OutInterpreted(lua)); + // Lua: nodeable, index, lambda // \todo clear these immediately after they are not needed with an explicit call written by the translator return 0; @@ -618,20 +607,19 @@ namespace ScriptCanvas // \note Return values could become necessary. // \see https://jira.agscollab.com/browse/LY-99750 - AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); - AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); + AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOutResult is not userdata (Nodeable)"); + AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOutResult is not a number"); + AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOutResult is not a function (lambda need to get around atypically routed arguments)"); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely AZ_Assert(nodeable, "Failed to read nodeable"); - const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2); - AZ_Assert(keyStr, "Failed to read key string"); - // Lua: nodeable, string, lambda + size_t index = aznumeric_caster(lua_tointeger(lua, -2)); + // Lua: nodeable, index, lambda lua_pushvalue(lua, -1); - // Lua: nodeable, string, lambda, lambda + // Lua: nodeable, index, lambda, lambda - nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpretedResult(lua)); - // Lua: nodeable, string, lambda + nodeable->SetExecutionOut(index, OutInterpretedResult(lua)); + // Lua: nodeable, index, lambda // \todo clear these immediately after they are not needed with an explicit call written by the translator return 0; @@ -639,20 +627,19 @@ namespace ScriptCanvas int SetExecutionOutUserSubgraph(lua_State* lua) { - AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); - AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); + AZ_Assert(lua_isuserdata(lua, -3), "Error in compiled lua file, 1st argument to SetExecutionOutUserSubgraph is not userdata (Nodeable)"); + AZ_Assert(lua_isnumber(lua, -2), "Error in compiled lua file, 2nd argument to SetExecutionOutUserSubgraph is not a number"); + AZ_Assert(lua_isfunction(lua, -1), "Error in compiled lua file, 3rd argument to SetExecutionOutUserSubgraph is not a function (lambda need to get around atypically routed arguments)"); Nodeable* nodeable = AZ::ScriptValue<Nodeable*>::StackRead(lua, -3); AZ_Assert(nodeable, "Failed to read nodeable"); - const char* keyStr = AZ::ScriptValue<const char*>::StackRead(lua, -2); - AZ_Assert(keyStr, "Failed to read key string"); - // Lua: nodeable, string, lambda + size_t index = aznumeric_caster(lua_tointeger(lua, -2)); + // Lua: nodeable, index, lambda lua_pushvalue(lua, -1); - // Lua: nodeable, string, lambda, lambda + // Lua: nodeable, index, lambda, lambda - nodeable->SetExecutionOut(AZ::Crc32(keyStr), OutInterpretedUserSubgraph(lua)); - // Lua: nodeable, string, lambda + nodeable->SetExecutionOut(index, OutInterpretedUserSubgraph(lua)); + // Lua: nodeable, index, lambda // \todo clear these immediately after they are not needed with an explicit call written by the translator return 0; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp index 6612039c65..72b787213b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/Interpreted/ExecutionInterpretedEBusAPI.cpp @@ -83,7 +83,7 @@ namespace ScriptCanvas int EBusHandlerCreateAndConnectTo(lua_State* lua) { - // Lua: executionState, (event name) string, (address aztypeid) string, (address) ? + // Lua: executionState, (ebus name) string, (address aztypeid) string, (address) ? auto executionState = AZ::ScriptValue<ExecutionStateInterpreted*>::StackRead(lua, 1); auto ebusName = AZ::ScriptValue<const char*>::StackRead(lua, 2); EBusHandler* ebusHandler = aznew EBusHandler(executionState->WeakFromThis(), ebusName, AZ::ScriptContext::FromNativeContext(lua)->GetBoundContext()); @@ -96,7 +96,7 @@ namespace ScriptCanvas ebusHandler->ConnectTo(address); AZ::Internal::LuaClassToStack(lua, ebusHandler, azrtti_typeid<EBusHandler>(), AZ::ObjectToLua::ByReference, AZ::AcquisitionOnPush::ScriptAcquire); - // Lua: executionState, (event name) string, (address aztypeid) string, (address) ?, handler + // Lua: executionState, (ebus name) string, (address aztypeid) string, (address) ?, handler return 1; } @@ -114,27 +114,23 @@ namespace ScriptCanvas const int k_eventNameIndex = -2; const int k_lambdaIndex = -1; - AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); - AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); + AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to EBusHandlerHandleEvent is not userdata (EBusHandler)"); + AZ_Assert(lua_isnumber(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to EBusHandlerHandleEvent is not a number"); + AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to EBusHandlerHandleEvent is not a function"); - auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely + auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); AZ_Assert(nodeable, "Failed to read EBusHandler"); - const char* keyStr = lua_tostring(lua, k_eventNameIndex); - AZ_Assert(keyStr, "Failed to read key string"); - const int eventIndex = nodeable->GetEventIndex(keyStr); - AZ_Assert(eventIndex != -1, "Event index was not found for %s-%s", nodeable->GetEBusName().data(), keyStr); + const int eventIndex = lua_tointeger(lua, k_eventNameIndex); + AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data()); // install the generic hook for the event nodeable->HandleEvent(eventIndex); // Lua: nodeable, string, lambda - lua_pushvalue(lua, k_lambdaIndex); // Lua: nodeable, string, lambda, lambda // route the event handling to the lambda on the top of the stack nodeable->SetExecutionOut(AZ::Crc32(eventIndex), OutInterpreted(lua)); // Lua: nodeable, string, lambda - return 0; } @@ -145,16 +141,14 @@ namespace ScriptCanvas const int k_eventNameIndex = -2; const int k_lambdaIndex = -1; - AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to SetExecutionOut is not userdata (Nodeable)"); - AZ_Assert(lua_isstring(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to SetExecutionOut is not a string (Crc key)"); - AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to SetExecutionOut is not a function (lambda need to get around atypically routed arguments)"); + AZ_Assert(lua_isuserdata(lua, k_nodeableIndex), "Error in compiled lua file, 1st argument to EBusHandlerHandleEventResult is not userdata (EBusHandler)"); + AZ_Assert(lua_isnumber(lua, k_eventNameIndex), "Error in compiled lua file, 2nd argument to EBusHandlerHandleEventResult is not a number"); + AZ_Assert(lua_isfunction(lua, k_lambdaIndex), "Error in compiled lua file, 3rd argument to EBusHandlerHandleEventResult is not a function"); - auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); // this won't be a BCO, because BCOs won't be necessary in the interpreted mode...most likely + auto nodeable = AZ::ScriptValue<EBusHandler*>::StackRead(lua, k_nodeableIndex); AZ_Assert(nodeable, "Failed to read EBusHandler"); - const char* keyStr = lua_tostring(lua, k_eventNameIndex); - AZ_Assert(keyStr, "Failed to read key string"); - const int eventIndex = nodeable->GetEventIndex(keyStr); - AZ_Assert(eventIndex != -1, "Event index was not found for %s-%s", nodeable->GetEBusName().data(), keyStr); + const int eventIndex = lua_tointeger(lua, k_eventNameIndex); + AZ_Assert(eventIndex != -1, "Event index was not found for %s", nodeable->GetEBusName().data()); // install the generic hook for the event nodeable->HandleEvent(eventIndex); // Lua: nodeable, string, lambda @@ -165,7 +159,6 @@ namespace ScriptCanvas // route the event handling to the lambda on the top of the stack nodeable->SetExecutionOut(AZ::Crc32(eventIndex), OutInterpretedResult(lua)); // Lua: nodeable, string, lambda - return 0; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp index dbcaad635b..ba1d34fea0 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Execution/RuntimeComponent.cpp @@ -70,7 +70,7 @@ namespace ScriptCanvas void RuntimeComponent::Execute() { - AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::InitializeExecution (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str()); + AZ_PROFILE_SCOPE_DYNAMIC(AZ::Debug::ProfileCategory::ScriptCanvas, "RuntimeComponent::Execute (%s)", m_runtimeAsset.GetId().ToString<AZStd::string>().c_str()); AZ_Assert(m_executionState, "RuntimeComponent::Execute called without an execution state"); SC_EXECUTION_TRACE_GRAPH_ACTIVATED(CreateActivationInfo()); SCRIPT_CANVAS_PERFORMANCE_SCOPE_EXECUTION(m_executionState->GetScriptCanvasId(), m_runtimeAsset.GetId()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 8f7fa2263e..958e37f82c 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -434,7 +434,7 @@ namespace ScriptCanvas if (!root->HasExplicitUserOutCalls()) { - // there is a single out call, default or not + // there is a single out, default or not Out out; if (outCalls.empty()) @@ -468,9 +468,7 @@ namespace ScriptCanvas } else { - // for now, all outs must return all the same output, - // if the UI changes, we'll need to track the output of each individual output - if (outCalls.empty()) + if (outCalls.size() < 2) { AddError(root->GetNodeId(), root, ScriptCanvas::ParseErrors::NotEnoughBranchesForReturn); return; @@ -503,6 +501,9 @@ namespace ScriptCanvas , returnValueVariable->m_sourceVariableId }); } + AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount); + ++m_outIndexCount; + in.outs.push_back(AZStd::move(out)); } } @@ -543,6 +544,8 @@ namespace ScriptCanvas , returnValueVariable->m_sourceVariableId }); } + AZStd::const_pointer_cast<ExecutionTree>(outCall)->SetOutCallIndex(m_outIndexCount); + ++m_outIndexCount; m_subgraphInterface.AddLatent(AZStd::move(out)); } @@ -908,6 +911,7 @@ namespace ScriptCanvas ebusHandling->m_startingAdress = startingAddress; } + ebusHandling->m_node = &node; m_ebusHandlingByNode.emplace(&node, ebusHandling); return true; } @@ -3252,6 +3256,15 @@ namespace ScriptCanvas AZ_Assert(childOutSlot, "null slot in child out slot list"); ExecutionTreePtr internalOut = OpenScope(child, node, childOutSlot); internalOut->SetNodeable(execution->GetNodeable()); + + const size_t outIndex = node->GetOutIndex(*childOutSlot); + if (outIndex == std::numeric_limits<size_t>::max()) + { + AddError(execution, aznew Internal::ParseError(node->GetEntityId(), AZStd::string::format("Missing internal out key for slot %s", childOutSlot->GetName().c_str()))); + return; + } + + internalOut->SetOutCallIndex(outIndex); internalOut->MarkInternalOut(); internalOut->SetSymbol(Symbol::FunctionDefinition); auto outNameOutcome = node->GetInternalOutKey(*childOutSlot); @@ -3893,6 +3906,14 @@ namespace ScriptCanvas auto latentOutKeyOutcome = node.GetLatentOutKey(*slot); if (latentOutKeyOutcome.IsSuccess()) { + const size_t outIndex = node.GetOutIndex(*slot); + if (outIndex == std::numeric_limits<size_t>::max()) + { + AddError(outRoot, aznew Internal::ParseError(node.GetEntityId(), AZStd::string::format("Missing internal out key for slot %s", slot->GetName().c_str()))); + return; + } + + outRoot->SetOutCallIndex(outIndex); outRoot->SetName(latentOutKeyOutcome.GetValue().data()); AZStd::const_pointer_cast<NodeableParse>(nodeableParseIter->second)->m_latents.emplace_back(outRoot->GetName(), outRoot); } @@ -4622,7 +4643,13 @@ namespace ScriptCanvas m_userInsThatRequireTopology.clear(); ParseUserOuts(); - m_subgraphInterface.Parse(); + + auto parseOutcome = m_subgraphInterface.Parse(); + + if (!parseOutcome.IsSuccess()) + { + AddError(nullptr, aznew Internal::ParseError(AZ::EntityId(), AZStd::string::format("Subgraph interface failed to parse: %s", parseOutcome.GetError().c_str()).c_str())); + } } void AbstractCodeModel::ParseUserIn(ExecutionTreePtr root, const Nodes::Core::FunctionDefinitionNode* nodeling) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h index 6eef1b6934..f1ad7b986b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.h @@ -507,6 +507,7 @@ namespace ScriptCanvas static UserInParseTopologyResult ParseUserInTolopology(size_t nodelingsOutCount, size_t leavesWithoutNodelingsCount); + size_t m_outIndexCount = 0; ExecutionTreePtr m_start; AZStd::vector<const Nodes::Core::Start*> m_startNodes; ScopePtr m_graphScope; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp index ab467127c1..a5a98b5444 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.cpp @@ -1057,6 +1057,13 @@ namespace ScriptCanvas && azrtti_istypeof<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node); } + bool IsUserFunctionCallPure(const ExecutionTreeConstPtr& execution) + { + return (execution->GetSymbol() == Symbol::FunctionCall) + && azrtti_istypeof<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node) + && azrtti_cast<const ScriptCanvas::Nodes::Core::FunctionCallNode*>(execution->GetId().m_node)->IsPure(); + } + bool IsUserFunctionDefinition(const ExecutionTreeConstPtr& execution) { auto nodeling = azrtti_cast<const ScriptCanvas::Nodes::Core::FunctionDefinitionNode*>(execution->GetId().m_node); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.h index 7bdfa39c7c..1e2d102d2d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/ParsingUtilities.h @@ -163,6 +163,8 @@ namespace ScriptCanvas bool IsUserFunctionCall(const ExecutionTreeConstPtr& execution); + bool IsUserFunctionCallPure(const ExecutionTreeConstPtr& execution); + bool IsUserFunctionDefinition(const ExecutionTreeConstPtr& execution); const ScriptCanvas::Nodes::Core::FunctionDefinitionNode* IsUserOutNode(const Node* node); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h index 68856325d0..c2605dce45 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.h @@ -90,11 +90,11 @@ namespace ScriptCanvas AZ_CLASS_ALLOCATOR(EBusHandling, AZ::SystemAllocator, 0); bool m_isAddressed = false; + const Node* m_node = nullptr; VariableConstPtr m_startingAdress; AZStd::string m_ebusName; AZStd::string m_handlerName; AZStd::vector<AZStd::pair<AZStd::string, ExecutionTreeConstPtr>> m_events; - void Clear(); }; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h index 72449ebc6d..bcfcccbaca 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesDeclarations.h @@ -110,7 +110,7 @@ namespace ScriptCanvas constexpr const char* k_InitializeStaticsName = "InitializeStatics"; constexpr const char* k_InitializeNodeableOutKeys = "InitializeNodeableOutKeys"; - + constexpr const char* k_InitializeExecutionOutByRequiredCountName = "InitializeExecutionOutByRequiredCount"; constexpr const char* k_InterpretedConfigurationPerformance = "SCRIPT_CANVAS_GLOBAL_PERFORMANCE"; constexpr const char* k_InterpretedConfigurationRelease = "SCRIPT_CANVAS_GLOBAL_RELEASE"; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp index e1e46d231e..c6e7925a31 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp @@ -260,6 +260,11 @@ namespace ScriptCanvas return m_nodeable; } + AZStd::optional<size_t> ExecutionTree::GetOutCallIndex() const + { + return m_outCallIndex != std::numeric_limits<size_t>::max() ? AZStd::optional<size_t>(m_outCallIndex) : AZStd::nullopt; + } + ExecutionTreeConstPtr ExecutionTree::GetParent() const { return m_parent; @@ -559,6 +564,11 @@ namespace ScriptCanvas m_lexicalScope = lexicalScope; } + void ExecutionTree::SetOutCallIndex(size_t index) + { + m_outCallIndex = index; + } + void ExecutionTree::SetParent(ExecutionTreePtr parent) { m_parent = parent; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.h index 518b1ba7f1..f1cebde204 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.h @@ -170,6 +170,8 @@ namespace ScriptCanvas VariableConstPtr GetNodeable() const; + AZStd::optional<size_t> GetOutCallIndex() const; + ExecutionTreeConstPtr GetParent() const; ExecutionTreeConstPtr GetRoot() const; @@ -252,6 +254,8 @@ namespace ScriptCanvas void SetNodeable(VariableConstPtr nodeable); + void SetOutCallIndex(size_t index); + void SetParent(ExecutionTreePtr parent); void SetScope(ScopePtr scope); @@ -286,6 +290,8 @@ namespace ScriptCanvas bool m_hasExplicitUserOutCalls = false; + size_t m_outCallIndex = std::numeric_limits<size_t>::max(); + // The node and the activation slot. The execution in, or the event or latent out slot. ExecutionId m_in; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodeables/BaseTimer.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodeables/BaseTimer.cpp index 881d087a3d..a23575693e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodeables/BaseTimer.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Internal/Nodeables/BaseTimer.cpp @@ -66,7 +66,7 @@ namespace ScriptCanvas break; } - while (m_timerCounter > m_timerDuration) + while (m_timerCounter >= m_timerDuration) { if (!m_isActive) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp index cd57cb6608..0fc40bceee 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.cpp @@ -393,6 +393,11 @@ namespace ScriptCanvas return false; } + AZStd::optional<size_t> EBusEventHandler::GetEventIndex(AZStd::string eventName) const + { + return m_handler->GetFunctionIndex(eventName.c_str()); + } + const EBusEventEntry* EBusEventHandler::FindEvent(const AZStd::string& name) const { AZ::Crc32 key = AZ::Crc32(name.c_str()); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h index 890b50a9e4..be624d608d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/EBusEventHandler.h @@ -115,6 +115,7 @@ namespace ScriptCanvas AZ::Outcome<AZStd::string, void> GetFunctionCallName(const Slot* /*slot*/) const override; bool IsEBusAddressed() const override; + AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const; const EBusEventEntry* FindEvent(const AZStd::string& name) const; AZStd::string GetEBusName() const override; bool IsAutoConnected() const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp index 962ee3e515..a7dc586a94 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.cpp @@ -548,6 +548,11 @@ namespace ScriptCanvas return EBusEventHandlerProperty::GetDisconnectSlot(this); } + AZStd::optional<size_t> ReceiveScriptEvent::GetEventIndex(AZStd::string eventName) const + { + return m_handler->GetFunctionIndex(eventName.c_str());; + } + AZStd::vector<SlotId> ReceiveScriptEvent::GetEventSlotIds() const { AZStd::vector<SlotId> eventSlotIds; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h index 3f2425cd4a..dcf1bca50e 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/ReceiveScriptEvent.h @@ -57,6 +57,7 @@ namespace ScriptCanvas AZ::Outcome<AZStd::string> GetInternalOutKey(const Slot& slot) const override; const Slot* GetEBusConnectSlot() const override; const Slot* GetEBusDisconnectSlot() const override; + AZStd::optional<size_t> GetEventIndex(AZStd::string eventName) const override; AZStd::vector<SlotId> GetEventSlotIds() const override; AZStd::vector<SlotId> GetNonEventSlotIds() const override; diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Math/OperatorLerpNodeable.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Math/OperatorLerpNodeable.h index 157f086fca..4b4bd59dc9 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Math/OperatorLerpNodeable.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Operators/Math/OperatorLerpNodeable.h @@ -136,16 +136,21 @@ namespace ScriptCanvas } protected: + size_t GetRequiredOutCount() const override + { + return 2; + } + void Lerp(float t) { const t_Operand step = m_start + (m_difference * t); // make a release note that the lerp complete and tick slot are two different execution threads - ExecutionOut(AZ_CRC_CE("Tick"), step, t); + ExecutionOut(0, step, t); if (AZ::IsClose(t, 1.0f, AZ::Constants::FloatEpsilon)) { StopLerp(); - ExecutionOut(AZ_CRC_CE("Lerp Complete")); + ExecutionOut(1); } } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h index b15ec596f9..3d5acfbee1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h @@ -100,7 +100,7 @@ namespace ScriptCanvas using LockType = AZStd::lock_guard<MutexType>; AZStd::unordered_map<const void*, BehaviorContextObject*> m_ownedObjectsByAddress; MutexType m_ownedObjectsByAddressMutex; - int m_infiniteLoopDetectionMaxIterations = 3000; + int m_infiniteLoopDetectionMaxIterations = 1000000; int m_maxHandlerStackDepth = 50; static void SafeRegisterPerformanceTracker(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp index bd583cb43d..8f28a7f94b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp @@ -689,8 +689,16 @@ namespace ScriptCanvas void GraphToLua::TranslateExecutionTreeUserOutCall(Grammar::ExecutionTreeConstPtr execution) { - // \todo revisit with per-entity run time storage that keeps execution out calls - m_dotLua.WriteIndented("%s(self, \"%s\"", Grammar::k_NodeableCallInterpretedOut, execution->GetName().data()); + auto outCallIndexOptional = execution->GetOutCallIndex(); + if (!outCallIndexOptional) + { + AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), "Execution did not return required out call index")); + return; + } + + const size_t outIndex = *outCallIndexOptional; + + m_dotLua.WriteIndented("%s(self, %zu", Grammar::k_NodeableCallInterpretedOut, outIndex); if (execution->GetInputCount() > 0) { @@ -698,7 +706,7 @@ namespace ScriptCanvas WriteFunctionCallInput(execution); } - m_dotLua.WriteLine(")"); + m_dotLua.WriteLine(") -- %s", execution->GetName().data()); } void GraphToLua::TranslateFunction(Grammar::ExecutionTreeConstPtr execution, IsNamed lex) @@ -861,14 +869,23 @@ namespace ScriptCanvas const bool hasResults = eventThread->HasReturnValues(); + AZStd::optional<size_t> eventIndex = ebusHandling->m_node->GetEventIndex(eventName); + if (!eventIndex) + { + AddError(nullptr, aznew Internal::ParseError(ebusHandling->m_node->GetEntityId(), AZStd::string::format("EBus handler did not return a valid index for event %s", eventName.c_str()))); + return; + } + m_dotLua.WriteNewLine(); - m_dotLua.WriteLineIndented("%s(%s%s, '%s'," + m_dotLua.WriteLineIndented("%s(%s%s, %zu, -- %s" , hasResults ? Grammar::k_EBusHandlerHandleEventResultName : Grammar::k_EBusHandlerHandleEventName , leftValue.data() , ebusHandling->m_handlerName.data() + , *eventIndex , eventThread->GetName().data()); m_dotLua.Indent(); + TranslateFunction(eventThread, IsNamed::No); m_dotLua.WriteLine(")"); @@ -983,14 +1000,7 @@ namespace ScriptCanvas const auto& outKeys = m_model.GetInterface().GetOutKeys(); if (!outKeys.empty()) { - m_dotLua.WriteIndented("%s(self", Grammar::k_InitializeNodeableOutKeys); - - for (auto& key : outKeys) - { - m_dotLua.Write(", %u", AZ::u32(key)); - } - - m_dotLua.WriteLine(")"); + m_dotLua.WriteLineIndented("%s(self, %zu)", Grammar::k_InitializeNodeableOutKeys, outKeys.size()); } } else @@ -1009,15 +1019,26 @@ namespace ScriptCanvas void GraphToLua::TranslateNodeableOut(Grammar::ExecutionTreeConstPtr execution) { + auto outCallIndexOptional = execution->GetOutCallIndex(); + if (!outCallIndexOptional) + { + AddError(nullptr, aznew Internal::ParseError(execution->GetNodeId(), "Execution did not return required out call index")); + return; + } + + const size_t outIndex = *outCallIndexOptional; + + // #functions2 remove-execution-out-hash const auto setExecutionOutName = Grammar::IsUserFunctionDefinition(execution) ? Grammar::k_NodeableSetExecutionOutUserSubgraphName : execution->HasReturnValues() ? Grammar::k_NodeableSetExecutionOutResultName : Grammar::k_NodeableSetExecutionOutName; - m_dotLua.WriteLineIndented("%s(self.%s, '%s'," + m_dotLua.WriteLineIndented("%s(self.%s, %zu, -- %s" , setExecutionOutName - , execution->GetNodeable()->m_name.data() + , execution->GetNodeable()->m_name.data() + , outIndex , execution->GetName().data()); m_dotLua.Indent(); @@ -1050,7 +1071,6 @@ namespace ScriptCanvas return; } - m_dotLua.WriteIndented("function %s.%s(self, ", m_tableName.c_str(), Grammar::k_InitializeStaticsName); WriteStaticInitializerInput(IsLeadingCommaRequired::No); m_dotLua.WriteLine(")"); @@ -1078,7 +1098,7 @@ namespace ScriptCanvas continue; } - if (variable->m_datum.GetType().GetAZType() == azrtti_typeid<Nodeable>()) + if (m_model.IsUserNodeable(variable)) { auto nodeableName = variable->m_name; if (nodeableName.starts_with(Grammar::k_memberNamePrefix)) @@ -1104,7 +1124,7 @@ namespace ScriptCanvas // indexInfo->second.requiresCtorParamsForDependencies // self.nonLeafDependency = NonLeafDependency.new(executionState, UnpackDependencyArgs(executionState, dependentAssets, 7)) // -- has more dependencies, index, known from compile time, pushes the correct asset further down construction - m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %s))" + m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %zu))" , leftValue.data() , variable->m_name.data() , nodeableName.data() @@ -1112,7 +1132,7 @@ namespace ScriptCanvas , Grammar::k_UnpackDependencyConstructionArgsFunctionName , Grammar::k_executionStateVariableName , Grammar::k_DependentAssetsArgName - , AZStd::to_string(indexInfo->first).data()); + , indexInfo->first); } else // vs. @@ -1120,7 +1140,7 @@ namespace ScriptCanvas // !indexInfo->second.hasMoreDependencies // self.leafDependency = LeafDependency.new(executionState, UnpackDependencyArgsLeaf(executionState, dependentAssets, 10)) // -- has NO more dependencies, index, known from compile time - m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %s))" + m_dotLua.WriteLineIndented("%s%s = %s.new(%s, %s(%s, %s, %zu))" , leftValue.data() , variable->m_name.data() , nodeableName.data() @@ -1128,7 +1148,7 @@ namespace ScriptCanvas , Grammar::k_UnpackDependencyConstructionArgsLeafFunctionName , Grammar::k_executionStateVariableName , Grammar::k_DependentAssetsArgName - , AZStd::to_string(indexInfo->first).data()); + , indexInfo->first); } } else @@ -1158,6 +1178,7 @@ namespace ScriptCanvas case Grammar::VariableConstructionRequirement::InputNodeable: m_dotLua.WriteLineIndented("%s:InitializeExecutionState(%s)", variable->m_name.data(), Grammar::k_executionStateVariableName); + m_dotLua.WriteLineIndented("%s:%s()", variable->m_name.c_str(), Grammar::k_InitializeExecutionOutByRequiredCountName); m_dotLua.WriteLineIndented("%s%s = %s", leftValue.data(), variable->m_name.data(), variable->m_name.data()); break; @@ -1227,9 +1248,7 @@ namespace ScriptCanvas void GraphToLua::WriteConstructionDependencyArgs() { - auto& dependencyArgs = m_model.GetOrderedDependencies().orderedAssetIds; - - if (!dependencyArgs.empty()) + if (m_model.GetInterface().RequiresConstructionParametersForDependencies()) { m_dotLua.Write(", %s", Grammar::k_DependentAssetsArgName); } @@ -1740,7 +1759,7 @@ namespace ScriptCanvas size_t GraphToLua::WriteFunctionCallInputThisPointer(Grammar::ExecutionTreeConstPtr execution) { - if (IsUserFunctionCall(execution) && execution->GetRoot()->IsPure()) + if (IsUserFunctionCallPure(execution)) { m_dotLua.Write("%s", Grammar::k_executionStateVariableName); diff --git a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp index 315d786712..bbcbde5c6c 100644 --- a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp @@ -37,10 +37,10 @@ namespace ScriptCanvasSystemComponentCpp { #if !defined(_RELEASE) && !defined(PERFORMANCE_BUILD) - const int k_infiniteLoopDetectionMaxIterations = 3000; + const int k_infiniteLoopDetectionMaxIterations = 1000000; const int k_maxHandlerStackDepth = 25; #else - const int k_infiniteLoopDetectionMaxIterations = 10000; + const int k_infiniteLoopDetectionMaxIterations = 10000000; const int k_maxHandlerStackDepth = 100; #endif diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionCycle10.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionCycle10.scriptcanvas new file mode 100644 index 0000000000..81af42910c --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionCycle10.scriptcanvas @@ -0,0 +1,3216 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24034832917361" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="LY_SC_UnitTest_ExecutionCycle10" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6571535133870744578" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24039127884657" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="231457506464632010" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{39108B6D-FD0C-4699-9ABA-2DD5948AC134}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{686D6185-BBD8-40D2-8742-11A084917794}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{D49B6BBD-54A4-4F98-A6CB-2D8954842DD9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24043422851953" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="300012501469391999" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6D1636C0-842F-489E-9FC9-E2288430AE18}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B080372D-CF11-4306-8FA0-74A30AAB34D4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{EC97EF9A-9A1F-4D5F-A628-FB81A80B9E19}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Cycle)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Cycle" field="element" type="{974258F5-EE1B-4AEE-B956-C7B303801847}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="4962443026073947036" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1811D879-4DAA-4360-AA43-98F4A217D3B7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5DF41C1C-D0BE-4AB1-80AF-780B473F54F0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Output 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9312B1FD-6623-4F35-B7EA-A1A0AB052E21}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3CEB28EE-83E9-4611-BC3E-220AD2EBB363}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7B128BF2-1294-44C5-AD7B-52342F27BA64}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BA15F2E5-D81B-4D31-A41C-EB2220FBADAF}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1D97F156-780A-4B55-92A3-078BB91B96A0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{774E7DA4-735F-474C-A460-ED102A2933FB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9DE7971F-0FA6-4C7F-898F-51D5F11078CC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{38023ED5-2ABC-422D-8D5A-79F2200C7CBC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B9A3FBC4-43A9-4F74-B528-8663E2391371}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out 9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1020632324" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24052012786545" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="13472499544374311683" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{FBB98497-D520-40A6-B6EA-C192483423B2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2576CB5F-613C-455A-88A2-1C7AE304B299}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{C5F2BDD5-DB4E-46BB-AC18-C12D63053CB5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24056307753841" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="17138225739278384487" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D75C993F-6E77-442D-B294-C8115CA68ADE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{94D7E689-4A71-45E8-B9CE-F41DF1DF75A5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="New Input" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{F23F2E68-E248-4B64-867F-AFEAE1C5F410}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24060602721137" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="13599030359755569927" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D692CDA0-4DAE-45FA-B4E0-82A441003C5B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7B44D940-9148-4B45-80D7-7291122741B9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{7488E694-CF0F-466D-A35C-D9029E6E1CAC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24064897688433" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7395027362843708591" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{03E23FB0-EBD5-4ECA-A2BC-4842E2456F6E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{93F72CDE-B2BC-422D-9EF8-577346D46597}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{560B0EE1-2AF2-4853-ABC8-8E5F6AE9EF69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24069192655729" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="17707596372115241930" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F27E0AE8-9FB6-4F66-9493-027612795894}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{C6537112-56F2-401A-BF37-42EBD81EB551}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{36EC80A4-2D4C-489F-9AE1-EA92603AA3AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24073487623025" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6591042316409852095" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{77552F75-B57E-42A0-BC7D-6695E0BD33D9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{97ABE1CC-9AB0-48E0-BD6D-5A73941AF9B9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{B53A7403-3F29-4A72-B4FE-856357AF0CA1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24077782590321" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15487157420376638056" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E1388F05-3EC4-4109-B288-CA9107656D44}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{534C6E04-4BA5-41C6-8CEF-B215D46EBACB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{5197B195-9847-4696-8171-C11EA8783E2A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24082077557617" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="4651505437919141318" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F5A5D7C7-7F0C-41D7-A0D4-944A65007B68}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D89796B5-7A19-465B-BC0D-D78621AD5032}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{2B4D20B6-6AC0-4710-945E-E127622D22DB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24086372524913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(OperatorAdd)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="OperatorAdd" field="element" type="{C1B42FEC-0545-4511-9FAC-11E0387FEDF0}"> + <Class name="OperatorArithmetic" field="BaseClass1" version="1" type="{FE0589B0-F835-4CD5-BBD3-86510CBB985B}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="286972003137058640" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5C79314E-431B-45FB-AF1F-DC4BC037CBB4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A5E2EEB6-56D7-4492-A696-C14B9C6F4DAA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6D07D071-5078-4937-9D25-4198BCA06AA5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="An operand to use in performing the specified Operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{4EA64DC2-6CE4-4971-BF81-73FC9E38C501}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{77614E16-4395-4CB0-A10E-5357B3F09451}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="An operand to use in performing the specified Operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{45973CC1-E836-453A-9155-1C43453AE4E6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Result" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="The result of the specified operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{4EA64DC2-6CE4-4971-BF81-73FC9E38C501}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="1.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24090667492209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1619858450106398240" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{621E0C48-B944-46CB-A0DE-CE8FBA21A6AD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{09337D6B-E5EF-4001-81A8-41284B8287F8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Cycle : Out 8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{3B6A8103-75CA-474E-80D1-8F6D55AE4536}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24094962459505" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 0), destEndpoint=(Cycle : Out 0: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="3949217833837904520" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5DF41C1C-D0BE-4AB1-80AF-780B473F54F0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24082077557617" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F5A5D7C7-7F0C-41D7-A0D4-944A65007B68}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24099257426801" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 1), destEndpoint=(Cycle : Out 1: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1821559268027891028" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9312B1FD-6623-4F35-B7EA-A1A0AB052E21}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24073487623025" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{77552F75-B57E-42A0-BC7D-6695E0BD33D9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24103552394097" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 2), destEndpoint=(Cycle : Out 2: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="11555589687672866993" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3CEB28EE-83E9-4611-BC3E-220AD2EBB363}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24039127884657" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{39108B6D-FD0C-4699-9ABA-2DD5948AC134}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24107847361393" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 3), destEndpoint=(Cycle : Out 3: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16439354976112058676" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7B128BF2-1294-44C5-AD7B-52342F27BA64}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24043422851953" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6D1636C0-842F-489E-9FC9-E2288430AE18}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24112142328689" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 4), destEndpoint=(Cycle : Out 4: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="10870245039772806165" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BA15F2E5-D81B-4D31-A41C-EB2220FBADAF}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24052012786545" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{FBB98497-D520-40A6-B6EA-C192483423B2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24116437295985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 5), destEndpoint=(Cycle : Out 5: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="14582087168292455360" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1D97F156-780A-4B55-92A3-078BB91B96A0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24060602721137" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D692CDA0-4DAE-45FA-B4E0-82A441003C5B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24120732263281" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 6), destEndpoint=(Cycle : Out 6: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="8762272658681556522" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{774E7DA4-735F-474C-A460-ED102A2933FB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24064897688433" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{03E23FB0-EBD5-4ECA-A2BC-4842E2456F6E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24125027230577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 7), destEndpoint=(Cycle : Out 7: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15082870043040884105" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9DE7971F-0FA6-4C7F-898F-51D5F11078CC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24077782590321" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E1388F05-3EC4-4109-B288-CA9107656D44}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24129322197873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 8), destEndpoint=(Cycle : Out 8: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1577668504035211787" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{38023ED5-2ABC-422D-8D5A-79F2200C7CBC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24090667492209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{621E0C48-B944-46CB-A0DE-CE8FBA21A6AD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24133617165169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Cycle: Out 9), destEndpoint=(Cycle : Out 9: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="11401813353737964711" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B9A3FBC4-43A9-4F74-B528-8663E2391371}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24069192655729" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F27E0AE8-9FB6-4F66-9493-027612795894}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24137912132465" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(New Input: ), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15811979562692611686" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24056307753841" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{94D7E689-4A71-45E8-B9CE-F41DF1DF75A5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24086372524913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5C79314E-431B-45FB-AF1F-DC4BC037CBB4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24142207099761" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Add (+): Out), destEndpoint=(Cycle: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15140392189412230076" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24086372524913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A5E2EEB6-56D7-4492-A696-C14B9C6F4DAA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1811D879-4DAA-4360-AA43-98F4A217D3B7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FD03954FC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24077782590321" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1200.0000000 740.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{2F080428-9539-496E-9BBE-35E0AF6DE6C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24047717819249" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="580.0000000 240.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="LogicNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{D7141549-3918-4190-99CF-86D6AE865C14}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24034832917361" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="0.6640885" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="281.5889893" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="99.3843460" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24064897688433" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1320.0000000 620.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{96E90B40-85E5-4C5C-8D18-EECD1C17BB84}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24090667492209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1060.0000000 860.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{F2F2BFC9-9324-4D5C-A5B7-39055FAF8769}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24060602721137" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1320.0000000 500.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{0BEA3925-18BA-47CF-8701-0AC972E52C87}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24069192655729" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="760.0000000 880.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{3498A512-65E5-4EF8-9CEE-CCBF785F9D9A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24039127884657" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1320.0000000 160.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{DE30BA79-D528-4D68-8CD9-C3CFDE6CC8CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24056307753841" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-40.0000000 40.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{5D0F81CD-D6BF-4D5C-AAC0-6D711B68A6C0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24086372524913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{8F515C6F-1A0F-406F-B602-063F76FEC3AD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MathNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-40.0000000 240.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24052012786545" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1340.0000000 400.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{F48934F3-E0D3-470C-BC58-72684CAC342E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24082077557617" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="740.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{56A1924A-8148-45A4-8E84-43B069331533}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24043422851953" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1340.0000000 280.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{42683FEF-14C3-409C-BDE6-E4125DDCC270}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="24073487623025" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1040.0000000 120.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{358E7881-FAD1-48C1-8531-083C41FC0452}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7011818094993955847" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="11" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="1244476766431948410" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="17170567245090241616" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15689091942531117650" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"> + <Class name="AZStd::pair" field="element" type="{E64D2110-EB38-5AE1-9B1D-3C06A10C7D6A}"> + <Class name="VariableId" field="value1" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{4EA64DC2-6CE4-4971-BF81-73FC9E38C501}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="GraphVariable" field="value2" version="4" type="{5BDC128B-8355-479C-8FA8-4BFFAB6915A8}"> + <Class name="Datum" field="Datum" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="count" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Crc32" field="InputControlVisibility" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2755429085" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="AZStd::string" field="ExposureCategory" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="SortPriority" value="-1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="ReplicaNetworkProperties" field="ReplicaNetProps" version="1" type="{4F055551-DD75-4877-93CE-E80C844FC155}"> + <Class name="bool" field="m_isSynchronized" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="VariableId" field="VariableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{4EA64DC2-6CE4-4971-BF81-73FC9E38C501}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="VariableName" value="count" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="unsigned char" field="Scope" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="unsigned char" field="InitialValueSource" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionOutPerformance.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionOutPerformance.scriptcanvas new file mode 100644 index 0000000000..9ec8c01d35 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_ExecutionOutPerformance.scriptcanvas @@ -0,0 +1,5753 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34286919852913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="LY_SC_UnitTest_ExecutionOutPerformance" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="14798455556932944677" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34291214820209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC Node(SetVariable)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="SetVariableNode" field="element" version="1" type="{5EFD2942-AFF9-4137-939C-023AEAA72EB0}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7309622534718952288" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6B05913B-6D9D-41BA-B350-B2ED7FA5BDC8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="When signaled sends the variable referenced by this node to a Data Output slot" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A3C477A5-714B-45EF-B482-6BD95AFB82DD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled after the referenced variable has been pushed to the Data Output slot" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E8053413-636A-4E29-BDAB-C85BB1E54755}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Boolean" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{685B866F-FE2A-40E3-B827-F632CAD77901}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Boolean" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Boolean" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="VariableId" field="m_variableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{E0FC20D3-23FD-42DF-ADA5-B0EBAC4D5309}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_variableDataInSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E8053413-636A-4E29-BDAB-C85BB1E54755}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_variableDataOutSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{685B866F-FE2A-40E3-B827-F632CAD77901}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_propertyAccounts" type="{3BEC267E-B4D3-588E-B183-954A20D83BDD}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34295509787505" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare8)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="14919024213595562113" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{630B3F95-22C6-46E8-8417-7F154EE2E294}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{75E009FF-35A3-4D61-A076-EE412BD399CB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34299804754801" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Start" field="element" version="2" type="{F200B22A-5903-483A-BF63-5241BC03632B}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="18438668922672769349" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2156CEDC-A88C-4E32-9BAA-8B21C93A432C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when the entity that owns this graph is fully activated." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34304099722097" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare1)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12011826511803795247" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{C7B398BB-37BD-4D6E-B584-DC29E0198807}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{CD1D00C1-42C6-4D1C-AB7F-D985EE114158}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34308394689393" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Mark Complete)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="8801483587718085462" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7210046F-CDF8-4313-847D-0B91CA38EB46}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="EntityID: 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{EA8C75AD-E94E-4271-870B-BFFC557C1A00}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="additional notes for the test report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9AD7C840-2D7A-454E-84FB-98B688FF7D2E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{46938C11-A85C-4663-B6A0-44950A6BCBF0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="EntityId" field="m_data" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4276206253" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="AZStd::string" field="m_data" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="Mark Complete" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34312689656689" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare0)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7237459212439082899" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{42CC4859-6565-402C-8AFA-729BEEBDF249}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4522D3E3-B785-4C38-9A59-9AB60A18D508}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(OperatorAdd)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="OperatorAdd" field="element" type="{C1B42FEC-0545-4511-9FAC-11E0387FEDF0}"> + <Class name="OperatorArithmetic" field="BaseClass1" version="1" type="{FE0589B0-F835-4CD5-BBD3-86510CBB985B}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="4061757306078902625" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{37EF5A16-FAFD-467A-A685-E6701BF80DF0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A7C3FCC0-DFE0-4920-8A1A-18B0A82FE743}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="An operand to use in performing the specified Operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{36654436-671D-4F4A-9287-AA639201DE8B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E3843799-5626-4196-B47F-1A2EC7DA01BE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="An operand to use in performing the specified Operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5CDBB06B-CC31-4BE3-9265-031422444518}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="MathOperatorContract" field="element" version="1" type="{17B1AEA6-B36B-4EE5-83E9-4563CAC79889}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="AZStd::string" field="OperatorType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::unordered_set" field="NativeTypes" type="{2A8293DA-3587-5E58-8D7A-FA303290D99F}"> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="9" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="11" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="15" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="14" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="10" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="8" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Type" field="element" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="12" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Result" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="The result of the specified operation" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1114760223" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{36654436-671D-4F4A-9287-AA639201DE8B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="1.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34321279591281" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare2)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7510401417958133790" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7B71BA2D-1213-421A-BBF7-21667894FE40}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D71780FE-FBC5-43FA-B4BD-048CD9E6F829}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34325574558577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(EqualTo)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="EqualTo" field="element" type="{02A3A3E6-9D80-432B-8AF5-F3AF24CF6959}"> + <Class name="EqualityExpression" field="BaseClass1" type="{78D20EB6-BA07-4071-B646-7C2D68A0A4A6}"> + <Class name="BooleanExpression" field="BaseClass1" type="{36C69825-CFF8-4F70-8F3B-1A9227E8BEEA}"> + <Class name="BinaryOperator" field="BaseClass1" type="{5BD0E8C7-9B0A-42F5-9EB0-199E6EC8FA99}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="2095343925933247030" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2EB5EAFE-45C3-4AB1-AAD8-4C66B93940E7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Result" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4ADEE9CC-DEA4-4630-9EAE-3CB4FCC279DC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signal to perform the evaluation when desired." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8C1FB727-B330-4176-A0A6-3B0B731D5204}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="True" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled if the result of the operation is true." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1D61F299-D8F0-4B76-A53F-D8614E2C2BCC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="False" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled if the result of the operation is false." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5984247B-1B28-4B3C-9D3E-38EE7874307A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Value A" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3545012108" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{36654436-671D-4F4A-9287-AA639201DE8B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{ABA36E1A-FE2E-4B32-AE8D-D966DF02DFAE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Value B" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3545012108" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{C2417605-B90A-47DF-A5D6-FC79C5D4B5C5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Value A" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Value B" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="EBusEventHandler" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="EBusEventHandler" field="element" version="5" type="{33E12915-EFCA-4AA7-A188-D694DAD58980}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5377446763920135448" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{FFEEA3ED-5317-4A63-9EA0-62885FC5B349}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Connect" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Connect this event handler to the specified entity." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{64413DEE-1BE7-4210-80FE-3768F372C283}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Disconnect" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Disconnect this event handler." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{04538BE3-6660-4E62-BD52-5F99FC61CD64}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="OnConnected" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when a connection has taken place." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A9CFC76E-8F0C-4164-ADBE-96E7DB09BF35}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="OnDisconnected" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when this event handler is disconnected." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6E8C95CC-BA63-4699-B467-749265E1419F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="OnFailure" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when it is not possible to connect this handler." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5476A290-120E-4624-B979-2C07177C01A8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6880DECD-1220-4BC1-8414-B0C5C31E73A6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7E4791CB-B140-447C-97BE-BC5BDD14AFA4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A6F9BF49-F845-4C1A-B358-BB2971F6DACE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4CB231A0-7F71-49D4-AA76-F93D22A188B6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3E18E493-3964-44D2-8D44-3381C44E118A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{46377097-E4D4-47BB-8577-F34A34BD5B21}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{131D3154-632A-47D3-BC1F-85E5285FC2AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D369EB94-DD8E-4F65-A516-A0FDBDBB9545}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F2FCBB0D-9450-46D2-B79B-16CECE2AAE73}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="ExecutionSlot:ForceStringCompare9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::map" field="m_eventMap" type="{E3F40B9E-9589-5736-8135-A35819EB700E}"> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="155513494" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="155513494" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A6F9BF49-F845-4C1A-B358-BB2971F6DACE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="237581967" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="237581967" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{131D3154-632A-47D3-BC1F-85E5285FC2AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2033059353" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2033059353" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{46377097-E4D4-47BB-8577-F34A34BD5B21}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2118369792" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2118369792" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7E4791CB-B140-447C-97BE-BC5BDD14AFA4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2421007148" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2421007148" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5476A290-120E-4624-B979-2C07177C01A8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2535483189" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2535483189" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4CB231A0-7F71-49D4-AA76-F93D22A188B6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2660641566" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2660641566" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D369EB94-DD8E-4F65-A516-A0FDBDBB9545}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3760674723" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3760674723" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3E18E493-3964-44D2-8D44-3381C44E118A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3880424378" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3880424378" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6880DECD-1220-4BC1-8414-B0C5C31E73A6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{220A15CE-9196-5EEA-A8CF-72AF80F1F6A9}"> + <Class name="Crc32" field="value1" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3918601096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="EBusEventEntry" field="value2" version="1" type="{92A20C1B-A54A-4583-97DB-A894377ACE21}"> + <Class name="AZStd::string" field="m_eventName" value="ForceStringCompare9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_eventId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3918601096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotId" field="m_eventSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F2FCBB0D-9450-46D2-B79B-16CECE2AAE73}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="SlotId" field="m_resultSlotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="m_parameterSlotIds" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"/> + <Class name="int" field="m_numExpectedArguments" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="m_resultEvaluated" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="m_ebusName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Crc32" field="m_busId" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="678608116" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="bool" field="m_autoConnectToGraphOwner" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="FunctionCallNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionCallNode" field="element" version="6" type="{ECFDD30E-A16D-4435-97B7-B2A4DF3C543A}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="62140919384716312" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0D4F915-A8E0-4020-B848-400BA7CE9EED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="New Input" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{33C19124-3E10-4C70-88DD-339D1B018DFB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3B50C804-20EB-4D21-B608-23E3A305D001}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E6A883A8-16FD-4032-AD07-6A8823AA5F69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E7AF4354-E597-4BF1-9541-021A5D392AFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3A82D8B4-B77D-4A94-A4F5-1B330C28EDA7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5DD61551-9A73-47B6-9F66-D62A8F7440A2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3309BD23-83FF-4777-9B72-B49230933EFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1EBDD2B5-E9D1-47AF-A57A-AAF069F2B65D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E1114E94-FFE6-4A18-B897-BD7403FAFEF8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{CD6D8267-7A38-4BB0-9E08-C61DE4E705E4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Cycle : Out 9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3670724126" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZ::Uuid" field="m_sourceId" value="{F09EC8A3-FB7F-0000-8C46-2ECA30FC71AD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="Asset" field="m_asset" value="id={11009E3D-639A-5C9F-96BC-0AE99251D844}:dfe6dc72,type={E22967AC-7673-4778-9125-AF49D82CAF9F},hint={scriptcanvas/unittests/ly_sc_unittest_executioncycle10.scriptcanvas_fn_compiled},loadBehavior=2" version="2" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/> + <Class name="Map" field="m_slotExecutionMap" version="1" type="{BAA81EAF-E35A-4F19-B73A-699B91DB113C}"> + <Class name="AZStd::vector" field="ins" type="{733E7AAD-19AD-5FAE-A634-B3B6EB0D3ED3}"> + <Class name="In" field="element" version="1" type="{4AAAEB0B-6367-46E5-B05D-E76EF884E16F}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0D4F915-A8E0-4020-B848-400BA7CE9EED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="_inputs" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + <Class name="AZStd::vector" field="_outs" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{33C19124-3E10-4C70-88DD-339D1B018DFB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{2B4D20B6-6AC0-4710-945E-E127622D22DB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3B50C804-20EB-4D21-B608-23E3A305D001}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{B53A7403-3F29-4A72-B4FE-856357AF0CA1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E6A883A8-16FD-4032-AD07-6A8823AA5F69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{D49B6BBD-54A4-4F98-A6CB-2D8954842DD9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E7AF4354-E597-4BF1-9541-021A5D392AFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{EC97EF9A-9A1F-4D5F-A628-FB81A80B9E19}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3A82D8B4-B77D-4A94-A4F5-1B330C28EDA7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{C5F2BDD5-DB4E-46BB-AC18-C12D63053CB5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5DD61551-9A73-47B6-9F66-D62A8F7440A2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{7488E694-CF0F-466D-A35C-D9029E6E1CAC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3309BD23-83FF-4777-9B72-B49230933EFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{560B0EE1-2AF2-4853-ABC8-8E5F6AE9EF69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1EBDD2B5-E9D1-47AF-A57A-AAF069F2B65D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{5197B195-9847-4696-8171-C11EA8783E2A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E1114E94-FFE6-4A18-B897-BD7403FAFEF8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{3B6A8103-75CA-474E-80D1-8F6D55AE4536}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{CD6D8267-7A38-4BB0-9E08-C61DE4E705E4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Cycle : Out 9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{36EC80A4-2D4C-489F-9AE1-EA92603AA3AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="_parsedName" value="NewInput_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{F23F2E68-E248-4B64-867F-AFEAE1C5F410}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{5970B601-529F-5E37-99F2-942F34360771}"/> + </Class> + <Class name="SubgraphInterface" field="m_slotExecutionMapSourceInterface" version="7" type="{52B27A11-8294-4A6F-BFCF-6C1582649DB2}"> + <Class name="bool" field="areAllChildrenPure" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="hasOnGraphStart" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isActiveDefaultObject" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::vector" field="ins" type="{16DA1AFC-705E-559D-8CF0-2E939187BB4B}"> + <Class name="In" field="element" version="1" type="{DFDA32F7-41D2-45BB-8ADF-876679053836}"> + <Class name="AZStd::string" field="displayName" value="New Input" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="NewInput_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="inputs" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZStd::vector" field="outs" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{2B4D20B6-6AC0-4710-945E-E127622D22DB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{B53A7403-3F29-4A72-B4FE-856357AF0CA1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut2" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{D49B6BBD-54A4-4F98-A6CB-2D8954842DD9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{EC97EF9A-9A1F-4D5F-A628-FB81A80B9E19}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{C5F2BDD5-DB4E-46BB-AC18-C12D63053CB5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{7488E694-CF0F-466D-A35C-D9029E6E1CAC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{560B0EE1-2AF2-4853-ABC8-8E5F6AE9EF69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{5197B195-9847-4696-8171-C11EA8783E2A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut8" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{3B6A8103-75CA-474E-80D1-8F6D55AE4536}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Cycle : Out 9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="CycleOut9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{36EC80A4-2D4C-489F-9AE1-EA92603AA3AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="bool" field="isPure" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZ::Uuid" field="sourceID" value="{F23F2E68-E248-4B64-867F-AFEAE1C5F410}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"/> + <Class name="AZStd::vector" field="outKeys" type="{287CEE87-6FF3-52FC-9D32-38255E2C7FE9}"> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1146643095" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="861884929" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2857763771" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3713086253" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1127589518" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="875730456" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2906376098" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3661428532" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1250159269" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1032116787" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="namespacePath" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"> + <Class name="AZStd::string" field="element" value="scriptcanvas" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="unittests" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="ly_sc_unittest_executioncycle10_VM" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="unsigned int" field="executionCharacteristics" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="requiresConstructionParameters" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="requiresConstructionParametersForDependencies" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34338459460465" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare6)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7229110679494214936" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{DA4AE0CC-EEBB-4F57-AD89-A32CD7BB00A0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{433A333D-87F5-48FE-B7D4-02DFFDB1E743}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare6" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34342754427761" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare3)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12707656951406144988" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{52F30833-B756-43EA-B893-762996BAD754}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{C5418C94-3B19-4FF0-81E2-A31905FBEA1F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare3" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34347049395057" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare4)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="2733418282104887234" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{32D46258-870D-4E6A-8717-38EB82562346}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{58F8AD2A-8C72-4E67-AF1C-22BA14CF4BF5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare4" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34351344362353" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(While)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="While" field="element" type="{C5BDF392-9669-4928-A0F5-F55B8A5B3BAC}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16262960001195467277" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A0F294EF-0648-4A6B-B572-01045DE05FE2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Condition" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="While this condition is true, Loop will signal, otherwise, Out will." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{E0FC20D3-23FD-42DF-ADA5-B0EBAC4D5309}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F7B40A90-A55A-4C8E-B1CA-0136CCE60DE5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{048D670E-9F1E-4A5E-98EF-EA47C6C06F26}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signalled if the condition is false, or if the loop calls the break node" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{FC0611F6-AA87-48A4-8011-13B399D592B5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Loop" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signalled if the condition is true, and every time the last node of 'Loop' finishes" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="bool" field="m_data" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Condition" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34355639329649" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare9)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16764550162392525836" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D8C4F92C-B02C-49BE-B7AC-4920D7994B73}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{CAD7621D-FB03-4718-A235-CF957C12472A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare9" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34359934296945" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare7)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15256176343563112317" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5A72A911-6F8F-4FBA-9BFF-16AE9EEE3BF1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{DBF9AE50-A94F-4306-8EC0-DCC7E1DEB077}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare7" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34364229264241" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(ForceStringCompare5)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6356770533381444073" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BD81D837-B9DC-44C0-8408-5B2B03668338}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{95EF4B8F-654E-4294-8783-AD123C7052B0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="ForceStringCompare5" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="PerformanceStressEBus" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34368524231537" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(On Graph Start: Out), destEndpoint=(While: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="13350740475277789897" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34299804754801" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2156CEDC-A88C-4E32-9BAA-8B21C93A432C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34351344362353" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F7B40A90-A55A-4C8E-B1CA-0136CCE60DE5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34372819198833" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Add (+): Out), destEndpoint=(Equal To (==): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="13437218436462898844" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{37EF5A16-FAFD-467A-A685-E6701BF80DF0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34325574558577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4ADEE9CC-DEA4-4630-9EAE-3CB4FCC279DC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34377114166129" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Equal To (==): True), destEndpoint=(Set Variable: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5105874669677142148" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34325574558577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8C1FB727-B330-4176-A0A6-3B0B731D5204}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34291214820209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6B05913B-6D9D-41BA-B350-B2ED7FA5BDC8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34381409133425" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(While: Out), destEndpoint=(Mark Complete: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7294768134060640692" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34351344362353" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{048D670E-9F1E-4A5E-98EF-EA47C6C06F26}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34308394689393" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{9AD7C840-2D7A-454E-84FB-98B688FF7D2E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34385704100721" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare3), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="908119725739496297" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A6F9BF49-F845-4C1A-B358-BB2971F6DACE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34389999068017" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare7), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="10158649226418371822" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{131D3154-632A-47D3-BC1F-85E5285FC2AE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34394294035313" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare6), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="477165002842784159" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{46377097-E4D4-47BB-8577-F34A34BD5B21}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34398589002609" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare2), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5227385701130505004" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7E4791CB-B140-447C-97BE-BC5BDD14AFA4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34402883969905" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare0), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16999799460204066187" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5476A290-120E-4624-B979-2C07177C01A8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34407178937201" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare4), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5540021479805551085" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{4CB231A0-7F71-49D4-AA76-F93D22A188B6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34411473904497" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare8), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="18243034122605890757" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D369EB94-DD8E-4F65-A516-A0FDBDBB9545}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34415768871793" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare5), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="11262933789558327723" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3E18E493-3964-44D2-8D44-3381C44E118A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34420063839089" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare1), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="4693971132318181726" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6880DECD-1220-4BC1-8414-B0C5C31E73A6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34424358806385" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(PerformanceStressEBus Handler: ExecutionSlot:ForceStringCompare9), destEndpoint=(Add (+): In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12265280187133221365" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F2FCBB0D-9450-46D2-B79B-16CECE2AAE73}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3FEED16A-E8E4-4404-8252-BFB828717CE0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34428653773681" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(While: Loop), destEndpoint=(Function Call Node: New Input)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="2759172179355450754" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34351344362353" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{FC0611F6-AA87-48A4-8011-13B399D592B5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0D4F915-A8E0-4020-B848-400BA7CE9EED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34432948740977" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 0), destEndpoint=(ForceStringCompare0: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="10755161076559491356" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{33C19124-3E10-4C70-88DD-339D1B018DFB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34312689656689" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{42CC4859-6565-402C-8AFA-729BEEBDF249}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34437243708273" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 1), destEndpoint=(ForceStringCompare1: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="7239062801293922356" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3B50C804-20EB-4D21-B608-23E3A305D001}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34304099722097" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{C7B398BB-37BD-4D6E-B584-DC29E0198807}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34441538675569" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 2), destEndpoint=(ForceStringCompare2: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="932703222647348506" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E6A883A8-16FD-4032-AD07-6A8823AA5F69}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34321279591281" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7B71BA2D-1213-421A-BBF7-21667894FE40}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34445833642865" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 3), destEndpoint=(ForceStringCompare3: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="3107975971700931932" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E7AF4354-E597-4BF1-9541-021A5D392AFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34342754427761" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{52F30833-B756-43EA-B893-762996BAD754}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34450128610161" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 4), destEndpoint=(ForceStringCompare4: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="18345521779661708124" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3A82D8B4-B77D-4A94-A4F5-1B330C28EDA7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34347049395057" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{32D46258-870D-4E6A-8717-38EB82562346}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34454423577457" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 5), destEndpoint=(ForceStringCompare5: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16700397200035393421" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5DD61551-9A73-47B6-9F66-D62A8F7440A2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34364229264241" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BD81D837-B9DC-44C0-8408-5B2B03668338}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34458718544753" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 6), destEndpoint=(ForceStringCompare6: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="9495194248285446603" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3309BD23-83FF-4777-9B72-B49230933EFE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34338459460465" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{DA4AE0CC-EEBB-4F57-AD89-A32CD7BB00A0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34463013512049" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 7), destEndpoint=(ForceStringCompare7: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="4343848055614846617" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{1EBDD2B5-E9D1-47AF-A57A-AAF069F2B65D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34359934296945" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{5A72A911-6F8F-4FBA-9BFF-16AE9EEE3BF1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34467308479345" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 8), destEndpoint=(ForceStringCompare8: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="8710192160495269590" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E1114E94-FFE6-4A18-B897-BD7403FAFEF8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34295509787505" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{630B3F95-22C6-46E8-8417-7F154EE2E294}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34471603446641" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Cycle : Out 9), destEndpoint=(ForceStringCompare9: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1051839336573017066" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{CD6D8267-7A38-4BB0-9E08-C61DE4E705E4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34355639329649" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D8C4F92C-B02C-49BE-B7AC-4920D7994B73}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-7D22-2F3E60F855FC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34342754427761" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{083F4500-27AA-440E-8BF3-153C54560D63}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 -80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34312689656689" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{36A2A3BC-506C-47B0-91D8-832DF10F2C5A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 -440.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34334164493169" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{CF11AEBE-1F69-4E49-AF60-4C86F8004218}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="460.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34304099722097" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{7691F68A-A22D-4EA5-9861-5420EC5373F5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 -320.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34364229264241" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{DC494E1E-9945-4039-AF2D-56F932E47224}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 160.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34338459460465" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{366628F4-C521-4663-9A26-05C280DED85C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 280.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34308394689393" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{8282C736-99AD-46D3-8E97-9EA40065B71A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="460.0000000 -160.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34329869525873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{9E81C95F-89C0-4476-8E82-63CCC4E52E04}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="EBusHandlerNodeDescriptorSaveData" field="value2" version="2" type="{9E81C95F-89C0-4476-8E82-63CCC4E52E04}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="bool" field="DisplayConnections" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::vector" field="EventIds" type="{287CEE87-6FF3-52FC-9D32-38255E2C7FE9}"> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2421007148" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3880424378" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2118369792" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="155513494" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2535483189" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3760674723" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2033059353" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="237581967" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2660641566" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3918601096" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="460.0000000 500.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{16096FB4-5CA7-4BD8-BCF9-EB077FA8A1B4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34299804754801" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-60.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{330D4156-D8BD-4360-9235-97B85642402F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34359934296945" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{77ADFABC-DFCB-4713-94EA-65A5162BE629}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 400.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34295509787505" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{5D5D2AFC-A90D-41A6-85D3-F2A1CE8107FF}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 520.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34325574558577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{EBCFB37A-8CDE-4DDC-9F9F-06B292040D3C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MathNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="1600.0000000 860.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34355639329649" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{C98A34B9-367E-48D2-A344-C9A05A60109A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 640.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34286919852913" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="1.0440125" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="389.8420715" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="129.3087921" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34316984623985" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{1E31679C-92D4-422A-8A3F-B867B4A1E540}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MathNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="960.0000000 840.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34347049395057" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{D0981542-1CDD-4DB8-ABBA-3B1C73DC28CA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 40.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34291214820209" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{ED9E8EBA-C31C-4055-AE9E-6142B4CCA235}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="SetVariableNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".setVariable" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="2080.0000000 840.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34321279591281" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{C4B3FDC5-553D-471C-9486-F24656E1BC42}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="920.0000000 -200.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="34351344362353" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="100.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="LogicNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{6239A4D3-0D2F-44F7-8335-468FDD07488E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516250201531530" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117487324689374" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516248669651698" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516250163207356" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516250316216471" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516212078506904" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117487509911543" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117487089405954" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117486815238396" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516211896532867" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516248435436590" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117485093389172" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117484910167917" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117489890992528" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7721683751185626951" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="3117476785392655547" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117486940689419" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="4199610336680704683" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516249359345721" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117487896388729" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="6840657073857873079" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="2902967532902889342" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="5842117489928120422" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="10002527926881348873" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516249211876368" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="13774516248856973085" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="1244476766431948410" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12152097629303315968" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"> + <Class name="AZStd::pair" field="element" type="{E64D2110-EB38-5AE1-9B1D-3C06A10C7D6A}"> + <Class name="VariableId" field="value1" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{36654436-671D-4F4A-9287-AA639201DE8B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="GraphVariable" field="value2" version="4" type="{5BDC128B-8355-479C-8FA8-4BFFAB6915A8}"> + <Class name="Datum" field="Datum" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="0.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="count" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Crc32" field="InputControlVisibility" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2755429085" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="AZStd::string" field="ExposureCategory" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="SortPriority" value="-1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="ReplicaNetworkProperties" field="ReplicaNetProps" version="1" type="{4F055551-DD75-4877-93CE-E80C844FC155}"> + <Class name="bool" field="m_isSynchronized" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="VariableId" field="VariableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{36654436-671D-4F4A-9287-AA639201DE8B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="VariableName" value="count" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="unsigned char" field="Scope" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="unsigned char" field="InitialValueSource" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{E64D2110-EB38-5AE1-9B1D-3C06A10C7D6A}"> + <Class name="VariableId" field="value1" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{E0FC20D3-23FD-42DF-ADA5-B0EBAC4D5309}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="GraphVariable" field="value2" version="4" type="{5BDC128B-8355-479C-8FA8-4BFFAB6915A8}"> + <Class name="Datum" field="Datum" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="bool" field="m_data" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="counting" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Crc32" field="InputControlVisibility" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2755429085" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="AZStd::string" field="ExposureCategory" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="SortPriority" value="-1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="ReplicaNetworkProperties" field="ReplicaNetProps" version="1" type="{4F055551-DD75-4877-93CE-E80C844FC155}"> + <Class name="bool" field="m_isSynchronized" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="VariableId" field="VariableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{E0FC20D3-23FD-42DF-ADA5-B0EBAC4D5309}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="VariableName" value="counting" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="unsigned char" field="Scope" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="unsigned char" field="InitialValueSource" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{E64D2110-EB38-5AE1-9B1D-3C06A10C7D6A}"> + <Class name="VariableId" field="value1" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{C2417605-B90A-47DF-A5D6-FC79C5D4B5C5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="GraphVariable" field="value2" version="4" type="{5BDC128B-8355-479C-8FA8-4BFFAB6915A8}"> + <Class name="Datum" field="Datum" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="10000.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Number" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Crc32" field="InputControlVisibility" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2755429085" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="AZStd::string" field="ExposureCategory" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="SortPriority" value="-1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="ReplicaNetworkProperties" field="ReplicaNetProps" version="1" type="{4F055551-DD75-4877-93CE-E80C844FC155}"> + <Class name="bool" field="m_isSynchronized" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="VariableId" field="VariableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{C2417605-B90A-47DF-A5D6-FC79C5D4B5C5}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="VariableName" value="limit" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="unsigned char" field="Scope" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="unsigned char" field="InitialValueSource" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunction.scriptcanvas new file mode 100644 index 0000000000..36be46edc9 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunction.scriptcanvas @@ -0,0 +1,628 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7502347485766" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="HelloWorld" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="9052377962154227383" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7506642453062" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Print)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Print" field="element" type="{E1940FB4-83FE-4594-9AFF-375FF7603338}"> + <Class name="StringFormatted" field="BaseClass1" version="1" type="{0B1577E0-339D-4573-93D1-6C311AD12A13}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12477281170783134906" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6BD6DD55-A040-4323-A6A1-671A45593FED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Input signal" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8599B85F-2657-4E02-B2F0-2CC3DF2F9CC3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_format" value="Hello, world!" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="m_numericPrecision" value="4" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::map" field="m_arrayBindingMap" type="{B3879B66-F836-5380-B4C8-4D519373E77E}"/> + <Class name="AZStd::vector" field="m_unresolvedString" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"> + <Class name="AZStd::string" field="element" value="Hello, world!" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::map" field="m_formatSlotMap" type="{8E9FB38C-2A95-5DC6-B051-90FF0BA8567F}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7510937420358" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6253414662616905213" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{18D19F1C-2F6E-4C90-A2BE-466C4CE87963}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A153F445-5192-46F2-BB1F-7708711C88C3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7515232387654" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="11396419963012713497" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{645D4BAA-1541-4DD6-A80A-C50980E98916}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AFF912AE-890A-4C0D-B1E2-BDDC2B008FA1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7519527354950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Print : In: ), destEndpoint=(Print: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5288914408229439479" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7510937420358" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A153F445-5192-46F2-BB1F-7708711C88C3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7506642453062" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6BD6DD55-A040-4323-A6A1-671A45593FED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7523822322246" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Print: Out), destEndpoint=(Print : Out: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="14264987585494436513" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7506642453062" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8599B85F-2657-4E02-B2F0-2CC3DF2F9CC3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7515232387654" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{645D4BAA-1541-4DD6-A80A-C50980E98916}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FE0D9D9E8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7502347485766" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="1.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7506642453062" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="480.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="StringNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{96F5E83F-7D91-4DB0-9D24-83AB3B904691}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7510937420358" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-40.0000000 80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{2587A848-1232-4166-9D1E-0CE74FEF46A1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7515232387654" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="780.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{921DBB72-7E8E-4B5F-ACC9-4FCA3DC32824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="10684225535275896474" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7011818094993955847" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="3854067922352095961" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"/> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunctionNotPure.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunctionNotPure.scriptcanvas new file mode 100644 index 0000000000..2e6439c95b --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_HelloWorldFunctionNotPure.scriptcanvas @@ -0,0 +1,733 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10199586947654" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="HelloWorld" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="9052377962154227383" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10203881914950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Print)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Print" field="element" type="{E1940FB4-83FE-4594-9AFF-375FF7603338}"> + <Class name="StringFormatted" field="BaseClass1" version="1" type="{0B1577E0-339D-4573-93D1-6C311AD12A13}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="12477281170783134906" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6BD6DD55-A040-4323-A6A1-671A45593FED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Input signal" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AE2400F7-9090-467E-BC98-7DCE3C4576BE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="3" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Value" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Value which replaces instances of {Value} in the resulting string." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1015031923" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{52EFC6D7-937B-4D05-BC78-A5B995D415CD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8599B85F-2657-4E02-B2F0-2CC3DF2F9CC3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="AZStd::string" field="m_data" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Value" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_format" value="Hello, world!{Value}" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="m_numericPrecision" value="4" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::map" field="m_arrayBindingMap" type="{B3879B66-F836-5380-B4C8-4D519373E77E}"> + <Class name="AZStd::pair" field="element" type="{F7CB29A1-551D-5BAD-9B38-B2279A75B957}"> + <Class name="AZ::u64" field="value1" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="SlotId" field="value2" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AE2400F7-9090-467E-BC98-7DCE3C4576BE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::vector" field="m_unresolvedString" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"> + <Class name="AZStd::string" field="element" value="Hello, world!" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::map" field="m_formatSlotMap" type="{8E9FB38C-2A95-5DC6-B051-90FF0BA8567F}"> + <Class name="AZStd::pair" field="element" type="{A17FF4ED-B460-5612-99F4-90D2832CF8F5}"> + <Class name="AZStd::string" field="value1" value="Value" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="SlotId" field="value2" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AE2400F7-9090-467E-BC98-7DCE3C4576BE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10208176882246" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6253414662616905213" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{18D19F1C-2F6E-4C90-A2BE-466C4CE87963}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A153F445-5192-46F2-BB1F-7708711C88C3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10212471849542" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(FunctionDefinitionNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionDefinitionNode" field="element" version="1" type="{4EE28D9F-67FB-4E61-B777-5DC5B059710F}"> + <Class name="Nodeling" field="BaseClass1" version="1" type="{4413EEA0-8D81-4D61-A1E1-3C1A437F3643}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="11396419963012713497" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{645D4BAA-1541-4DD6-A80A-C50980E98916}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisallowReentrantExecutionContract" field="element" type="{8B476D16-D11C-4274-BE61-FA9B34BF54A3}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AFF912AE-890A-4C0D-B1E2-BDDC2B008FA1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="DisplayGroupConnectedSlotLimitContract" field="element" type="{71E55CC5-6212-48C2-973E-1AC9E20A4481}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + <Class name="unsigned int" field="limit" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZStd::string" field="displayGroup" value="NodelingSlotDisplayGroup" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="errorMessage" value="Execution nodes can only be connected to either the Input or Output, and not both at the same time." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value=" " type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3992535411" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::string" field="m_displayName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="m_identifier" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="m_isExecutionEntry" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10216766816838" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Print : In: ), destEndpoint=(Print: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="5288914408229439479" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10208176882246" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{A153F445-5192-46F2-BB1F-7708711C88C3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10203881914950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{6BD6DD55-A040-4323-A6A1-671A45593FED}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10221061784134" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Print: Out), destEndpoint=(Print : Out: )" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="14264987585494436513" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10203881914950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8599B85F-2657-4E02-B2F0-2CC3DF2F9CC3}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10212471849542" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{645D4BAA-1541-4DD6-A80A-C50980E98916}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FE0D9D9E8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10199586947654" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="1.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="-232.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="2.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10203881914950" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="400.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="StringNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{96F5E83F-7D91-4DB0-9D24-83AB3B904691}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10208176882246" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-40.0000000 80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{2587A848-1232-4166-9D1E-0CE74FEF46A1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="10212471849542" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="740.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".nodeling" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="NodelingTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{921DBB72-7E8E-4B5F-ACC9-4FCA3DC32824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="10684225535275896474" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7011818094993955847" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="3854067922352095961" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"> + <Class name="AZStd::pair" field="element" type="{E64D2110-EB38-5AE1-9B1D-3C06A10C7D6A}"> + <Class name="VariableId" field="value1" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{52EFC6D7-937B-4D05-BC78-A5B995D415CD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="GraphVariable" field="value2" version="4" type="{5BDC128B-8355-479C-8FA8-4BFFAB6915A8}"> + <Class name="Datum" field="Datum" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="AZStd::string" field="m_data" value="blerp" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="String" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Crc32" field="InputControlVisibility" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2755429085" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="AZStd::string" field="ExposureCategory" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="int" field="SortPriority" value="-1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="ReplicaNetworkProperties" field="ReplicaNetProps" version="1" type="{4F055551-DD75-4877-93CE-E80C844FC155}"> + <Class name="bool" field="m_isSynchronized" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="VariableId" field="VariableId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{52EFC6D7-937B-4D05-BC78-A5B995D415CD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="VariableName" value="Variable 1" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="unsigned char" field="Scope" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="unsigned char" field="InitialValueSource" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas new file mode 100644 index 0000000000..eb208d7fd2 --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas @@ -0,0 +1,750 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13541071503942" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="DelayCallPure" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6571535133870744578" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Start" field="element" version="2" type="{F200B22A-5903-483A-BF63-5241BC03632B}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15193913073954065552" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when the entity that owns this graph is fully activated." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(TimeDelayNodeableNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="TimeDelayNodeableNode" field="element" type="{D3629902-02E9-AE59-0424-F366D342B433}"> + <Class name="NodeableNode" field="BaseClass1" type="{80351020-5778-491A-B6CA-C78364C19499}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1053952827100754458" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{357C23C8-2A4C-49F1-BE4B-939734B6F05B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Delay" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="The amount of time to delay before the Done is signalled." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AEBF8386-4C3B-4A58-904B-30907580EADA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="On Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Done" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled after waiting for the specified amount of times." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="271442091" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="3.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Delay" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::unique_ptr" field="nodeable" type="{8115FDE2-2859-5710-B2C6-72C11F9CFFF0}"> + <Class name="TimeDelayNodeable" field="element" type="{0B46D60A-EFCD-D8FD-8510-390C8E939FF6}"> + <Class name="BaseTimer" field="BaseClass1" type="{64814C82-DAE5-9B04-B375-5E47D51ECD26}"> + <Class name="Nodeable" field="BaseClass1" type="{C8195695-423A-4960-A090-55B2E94E0B25}"/> + <Class name="int" field="m_timeUnits" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="m_tickOrder" value="1000" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="Map" field="slotExecutionMap" version="1" type="{BAA81EAF-E35A-4F19-B73A-699B91DB113C}"> + <Class name="AZStd::vector" field="ins" type="{733E7AAD-19AD-5FAE-A634-B3B6EB0D3ED3}"> + <Class name="In" field="element" version="1" type="{4AAAEB0B-6367-46E5-B05D-E76EF884E16F}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="_inputs" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"> + <Class name="Input" field="element" type="{4E52A04D-C9FC-477F-8065-35F96A972CD6}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{357C23C8-2A4C-49F1-BE4B-939734B6F05B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="VariableId" field="_interfaceSourceId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::vector" field="_outs" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AEBF8386-4C3B-4A58-904B-30907580EADA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="On Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{00000000-0000-0080-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="_parsedName" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{B0889881-5902-0000-9625-123BF87F0000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Done" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{F06B71D1-FF7F-0000-2000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="FunctionCallNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionCallNode" field="element" version="6" type="{ECFDD30E-A16D-4435-97B7-B2A4DF3C543A}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="8173632389711398098" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8BF89FFE-4D6F-4A53-9CFB-1E9D32E20AD0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1609338446" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F12F8492-EDE6-4F0B-8A31-EC7944F1C779}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1609338446" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZ::Uuid" field="m_sourceId" value="{F09ED5CE-FF7F-0000-8C46-2ECA30FC71AD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="Asset" field="m_asset" value="id={601A64F0-3CFD-5B7D-A0B4-FA7E4485AA72}:dfe6dc72,type={E22967AC-7673-4778-9125-AF49D82CAF9F},hint={scriptcanvas/unittests/ly_sc_unittest_helloworldfunctionnotpure.scriptcanvas_fn_compiled},loadBehavior=2" version="2" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/> + <Class name="Map" field="m_slotExecutionMap" version="1" type="{BAA81EAF-E35A-4F19-B73A-699B91DB113C}"> + <Class name="AZStd::vector" field="ins" type="{733E7AAD-19AD-5FAE-A634-B3B6EB0D3ED3}"> + <Class name="In" field="element" version="1" type="{4AAAEB0B-6367-46E5-B05D-E76EF884E16F}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8BF89FFE-4D6F-4A53-9CFB-1E9D32E20AD0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="_inputs" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + <Class name="AZStd::vector" field="_outs" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F12F8492-EDE6-4F0B-8A31-EC7944F1C779}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="_parsedName" value="In_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{5970B601-529F-5E37-99F2-942F34360771}"/> + </Class> + <Class name="SubgraphInterface" field="m_slotExecutionMapSourceInterface" version="7" type="{52B27A11-8294-4A6F-BFCF-6C1582649DB2}"> + <Class name="bool" field="areAllChildrenPure" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="hasOnGraphStart" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isActiveDefaultObject" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::vector" field="ins" type="{16DA1AFC-705E-559D-8CF0-2E939187BB4B}"> + <Class name="In" field="element" version="1" type="{DFDA32F7-41D2-45BB-8ADF-876679053836}"> + <Class name="AZStd::string" field="displayName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="In_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="inputs" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZStd::vector" field="outs" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="bool" field="isPure" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZ::Uuid" field="sourceID" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"/> + <Class name="AZStd::vector" field="outKeys" type="{287CEE87-6FF3-52FC-9D32-38255E2C7FE9}"> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3119148441" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="namespacePath" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"> + <Class name="AZStd::string" field="element" value="ScriptCanvas" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="UnitTests" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="LY_SC_UnitTest_HelloWorldFunctionNotPure_VM" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="unsigned int" field="executionCharacteristics" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="requiresConstructionParameters" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="requiresConstructionParametersForDependencies" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13558251373126" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(On Graph Start: Out), destEndpoint=(TimeDelay: Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1596432431347764630" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13562546340422" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(TimeDelay: Done), destEndpoint=(Function Call Node: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="3568626474031118159" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8BF89FFE-4D6F-4A53-9CFB-1E9D32E20AD0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FB0BCBAE8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{7BED9343-8F8D-4C4C-BF13-CF0E81082975}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="360.0000000 220.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="-180.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="20.0000000 20.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="13541071503942" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="0.9191536" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="-311.1558228" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="-34.8146400" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="4199610336680704683" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="6462358712820489356" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7721683751185626951" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15689091942531117650" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"/> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas new file mode 100644 index 0000000000..1140c64bbd --- /dev/null +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas @@ -0,0 +1,750 @@ +<ObjectStream version="3"> + <Class name="ScriptCanvasData" version="4" type="{1072E894-0C67-4091-8B64-F7DB324AD13C}"> + <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9091485385286" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="DelayCallPure" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> + <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="6571535133870744578" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="GraphData" field="m_graphData" version="4" type="{ADCB5EB5-8D3F-42ED-8F65-EAB58A82C381}"> + <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Start" field="element" version="2" type="{F200B22A-5903-483A-BF63-5241BC03632B}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15193913073954065552" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled when the entity that owns this graph is fully activated." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(TimeDelayNodeableNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="TimeDelayNodeableNode" field="element" type="{D3629902-02E9-AE59-0424-F366D342B433}"> + <Class name="NodeableNode" field="BaseClass1" type="{80351020-5778-491A-B6CA-C78364C19499}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1053952827100754458" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{357C23C8-2A4C-49F1-BE4B-939734B6F05B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Delay" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="The amount of time to delay before the Done is signalled." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AEBF8386-4C3B-4A58-904B-30907580EADA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="On Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="2675529103" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Done" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="Signaled after waiting for the specified amount of times." type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="271442091" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="double" field="m_data" value="3.0000000" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Delay" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::unique_ptr" field="nodeable" type="{8115FDE2-2859-5710-B2C6-72C11F9CFFF0}"> + <Class name="TimeDelayNodeable" field="element" type="{0B46D60A-EFCD-D8FD-8510-390C8E939FF6}"> + <Class name="BaseTimer" field="BaseClass1" type="{64814C82-DAE5-9B04-B375-5E47D51ECD26}"> + <Class name="Nodeable" field="BaseClass1" type="{C8195695-423A-4960-A090-55B2E94E0B25}"/> + <Class name="int" field="m_timeUnits" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="m_tickOrder" value="1000" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="Map" field="slotExecutionMap" version="1" type="{BAA81EAF-E35A-4F19-B73A-699B91DB113C}"> + <Class name="AZStd::vector" field="ins" type="{733E7AAD-19AD-5FAE-A634-B3B6EB0D3ED3}"> + <Class name="In" field="element" version="1" type="{4AAAEB0B-6367-46E5-B05D-E76EF884E16F}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="_inputs" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"> + <Class name="Input" field="element" type="{4E52A04D-C9FC-477F-8065-35F96A972CD6}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{357C23C8-2A4C-49F1-BE4B-939734B6F05B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="VariableId" field="_interfaceSourceId" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::vector" field="_outs" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{AEBF8386-4C3B-4A58-904B-30907580EADA}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="On Start" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{00000000-0000-0080-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="_parsedName" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{B0889881-5902-0000-9625-123BF87F0000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Done" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{F06B71D1-FF7F-0000-2000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="FunctionCallNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="FunctionCallNode" field="element" version="6" type="{ECFDD30E-A16D-4435-97B7-B2A4DF3C543A}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="16811267658047538831" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B9BCC3F2-0B3B-448A-9535-1BEC67F90BEE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1609338446" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3D5A170D-0E7D-43C1-957D-FAA97B9E0907}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="1609338446" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"/> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZ::Uuid" field="m_sourceId" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="Asset" field="m_asset" value="id={D1D3EB5E-1541-53D9-90F0-0F39BCEBB30C}:dfe6dc72,type={E22967AC-7673-4778-9125-AF49D82CAF9F},hint={scriptcanvas/unittests/ly_sc_unittest_helloworldfunction.scriptcanvas_fn_compiled},loadBehavior=2" version="2" type="{77A19D40-8731-4D3C-9041-1B43047366A4}"/> + <Class name="Map" field="m_slotExecutionMap" version="1" type="{BAA81EAF-E35A-4F19-B73A-699B91DB113C}"> + <Class name="AZStd::vector" field="ins" type="{733E7AAD-19AD-5FAE-A634-B3B6EB0D3ED3}"> + <Class name="In" field="element" version="1" type="{4AAAEB0B-6367-46E5-B05D-E76EF884E16F}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B9BCC3F2-0B3B-448A-9535-1BEC67F90BEE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::vector" field="_inputs" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + <Class name="AZStd::vector" field="_outs" type="{5970B601-529F-5E37-99F2-942F34360771}"> + <Class name="Out" field="element" version="1" type="{DD3D2547-868C-40DF-A37C-F60BE06FFFBA}"> + <Class name="SlotId" field="_slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3D5A170D-0E7D-43C1-957D-FAA97B9E0907}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="AZStd::string" field="_name" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="_outputs" type="{275A1212-6B40-5045-BA6D-39FF976D6634}"/> + <Class name="Return" field="_returnValues" version="1" type="{8CD09346-BF99-4B34-91EA-C553549F7639}"> + <Class name="AZStd::vector" field="_values" type="{ED971363-ECC9-5B7D-A9E7-C70BEF283BC0}"/> + </Class> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="_parsedName" value="In_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZ::Uuid" field="_interfaceSourceId" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{5970B601-529F-5E37-99F2-942F34360771}"/> + </Class> + <Class name="SubgraphInterface" field="m_slotExecutionMapSourceInterface" version="7" type="{52B27A11-8294-4A6F-BFCF-6C1582649DB2}"> + <Class name="bool" field="areAllChildrenPure" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="hasOnGraphStart" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isActiveDefaultObject" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::vector" field="ins" type="{16DA1AFC-705E-559D-8CF0-2E939187BB4B}"> + <Class name="In" field="element" version="1" type="{DFDA32F7-41D2-45BB-8ADF-876679053836}"> + <Class name="AZStd::string" field="displayName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="In_scvm" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="inputs" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZStd::vector" field="outs" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"> + <Class name="Out" field="element" version="1" type="{6175D897-C06D-48B5-8775-388B232D429D}"> + <Class name="AZStd::string" field="displayName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="parsedName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="outputs" type="{5457916A-40A0-5DF0-9742-1DEECFEE5C48}"/> + <Class name="AZStd::vector" field="returnValues" type="{A7E036E1-781C-5FF3-B5E2-5F7CCA518624}"/> + <Class name="AZ::Uuid" field="sourceID" value="{1EDB5858-BF68-4C06-81BE-C4C6C18500C2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="bool" field="isPure" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZ::Uuid" field="sourceID" value="{C54DF87A-22B0-4B5F-A3A5-32C7461C7824}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="latents" type="{CA41DC3D-DBB4-5EA5-A9AA-91EC2056766E}"/> + <Class name="AZStd::vector" field="outKeys" type="{287CEE87-6FF3-52FC-9D32-38255E2C7FE9}"> + <Class name="Crc32" field="element" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="3119148441" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="namespacePath" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"> + <Class name="AZStd::string" field="element" value="ScriptCanvas" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="UnitTests" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="element" value="LY_SC_UnitTest_HelloWorldFunction_VM" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="unsigned int" field="executionCharacteristics" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="requiresConstructionParameters" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="requiresConstructionParametersForDependencies" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9108665254470" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(On Graph Start: Out), destEndpoint=(TimeDelay: Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1596432431347764630" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9112960221766" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(TimeDelay: Done), destEndpoint=(Function Call Node: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="2452595094640216734" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{B9BCC3F2-0B3B-448A-9535-1BEC67F90BEE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> + <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> + </Class> + <Class name="unsigned char" field="executionMode" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/> + <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FB0BCBAE8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="unsigned int" field="m_variableCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="bool" field="m_saveFormatConverted" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="120.0000000 80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="320.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9091485385286" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="0.9191536" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="-311.1558228" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="-34.8146400" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{A9407C52-FC80-4F58-B489-D37FF5871277}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="640.0000000 200.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::unordered_map" field="CRCCacheMap" type="{2376BDB0-D7B6-586B-A603-42BE703EB2C9}"/> + <Class name="GraphStatisticsHelper" field="StatisticsHelper" version="1" type="{7D5B7A65-F749-493E-BA5C-6B8724791F03}"> + <Class name="AZStd::unordered_map" field="InstanceCounter" type="{9EC84E0A-F296-5212-8B69-4DE48E695D61}"> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="4199610336680704683" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="6462358712820489356" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="7721683751185626951" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + </Class> + </Class> + <Class name="int" field="GraphCanvasSaveVersion" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="EditorGraphVariableManagerComponent" field="element" type="{86B7CC96-9830-4BD1-85C3-0C0BD0BFBEE7}"> + <Class name="GraphVariableManagerComponent" field="BaseClass1" version="3" type="{825DC28D-667D-43D0-AF11-73681351DD2F}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15689091942531117650" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="VariableData" field="m_variableData" version="3" type="{4F80659A-CD11-424E-BF04-AF02ABAC06B0}"> + <Class name="AZStd::unordered_map" field="m_nameVariableMap" type="{6C3A5734-6C27-5033-B033-D5CAD11DE55A}"/> + </Class> + <Class name="AZStd::unordered_map" field="CopiedVariableRemapping" type="{723F81A5-0980-50C7-8B1F-BE646339362B}"/> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + </Class> +</ObjectStream> + diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h index cb3c9cdccb..ab00593dbc 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h @@ -108,9 +108,15 @@ namespace ScriptCanvasTests auto m_serializeContext = s_application->GetSerializeContext(); auto m_behaviorContext = s_application->GetBehaviorContext(); - - ScriptCanvasTesting::Reflect(m_serializeContext); - ScriptCanvasTesting::Reflect(m_behaviorContext); + ScriptCanvasTesting::GlobalBusTraits::Reflect(m_serializeContext); + ScriptCanvasTesting::GlobalBusTraits::Reflect(m_behaviorContext); + ScriptCanvasTesting::LocalBusTraits::Reflect(m_serializeContext); + ScriptCanvasTesting::LocalBusTraits::Reflect(m_behaviorContext); + ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(m_serializeContext); + ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(m_behaviorContext); + ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(m_serializeContext); + ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(m_behaviorContext); + ScriptCanvasTesting::TestTupleMethods::Reflect(m_behaviorContext); ::Nodes::InputMethodSharedDataSlotExampleNode::Reflect(m_serializeContext); ::Nodes::InputMethodSharedDataSlotExampleNode::Reflect(m_behaviorContext); diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp index 34df10fdea..dc43bb862d 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp @@ -130,6 +130,87 @@ namespace ScriptCanvasTesting } } + class PerformanceStressEBusHandler + : public PerformanceStressEBus::Handler + , public AZ::BehaviorEBusHandler + { + public: + AZ_EBUS_BEHAVIOR_BINDER( + PerformanceStressEBusHandler, "{EAE36675-F06B-4755-B3A5-CEC9495DC92E}", AZ::SystemAllocator + , ForceStringCompare0 + , ForceStringCompare1 + , ForceStringCompare2 + , ForceStringCompare3 + , ForceStringCompare4 + , ForceStringCompare5 + , ForceStringCompare6 + , ForceStringCompare7 + , ForceStringCompare8 + , ForceStringCompare9 + ); + + void ForceStringCompare0() override + { + Call(FN_ForceStringCompare0); + } + void ForceStringCompare1() override + { + Call(FN_ForceStringCompare1); + } + void ForceStringCompare2() override + { + Call(FN_ForceStringCompare2); + } + void ForceStringCompare3() override + { + Call(FN_ForceStringCompare3); + } + void ForceStringCompare4() override + { + Call(FN_ForceStringCompare4); + } + void ForceStringCompare5() override + { + Call(FN_ForceStringCompare5); + } + void ForceStringCompare6() override + { + Call(FN_ForceStringCompare6); + } + void ForceStringCompare7() override + { + Call(FN_ForceStringCompare7); + } + void ForceStringCompare8() override + { + Call(FN_ForceStringCompare8); + } + void ForceStringCompare9() override + { + Call(FN_ForceStringCompare9); + } + }; + + void PerformanceStressBusTraits::Reflect(AZ::ReflectContext* context) + { + if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) + { + behaviorContext->EBus<PerformanceStressEBus>("PerformanceStressEBus") + ->Handler<PerformanceStressEBusHandler>() + ->Event("ForceStringCompare0", &PerformanceStressEBus::Events::ForceStringCompare0) + ->Event("ForceStringCompare1", &PerformanceStressEBus::Events::ForceStringCompare1) + ->Event("ForceStringCompare2", &PerformanceStressEBus::Events::ForceStringCompare2) + ->Event("ForceStringCompare3", &PerformanceStressEBus::Events::ForceStringCompare3) + ->Event("ForceStringCompare4", &PerformanceStressEBus::Events::ForceStringCompare4) + ->Event("ForceStringCompare5", &PerformanceStressEBus::Events::ForceStringCompare5) + ->Event("ForceStringCompare6", &PerformanceStressEBus::Events::ForceStringCompare6) + ->Event("ForceStringCompare7", &PerformanceStressEBus::Events::ForceStringCompare7) + ->Event("ForceStringCompare8", &PerformanceStressEBus::Events::ForceStringCompare8) + ->Event("ForceStringCompare9", &PerformanceStressEBus::Events::ForceStringCompare9) + ; + } + } + class LocalEBusHandler : public LocalEBus::Handler , public AZ::BehaviorEBusHandler diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.h b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.h index c31627f9fb..5aa8c3c3ec 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.h +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.h @@ -46,6 +46,27 @@ namespace ScriptCanvasTesting }; using GlobalEBus = AZ::EBus<GlobalBusTraits>; + class PerformanceStressBusTraits : public AZ::EBusTraits + { + public: + AZ_TYPE_INFO(PerformanceStressBusTraits, "{68AF0B81-70F4-4822-8127-AAC442D924C7}"); + + static void Reflect(AZ::ReflectContext* context); + + virtual void ForceStringCompare0() = 0; + virtual void ForceStringCompare1() = 0; + virtual void ForceStringCompare2() = 0; + virtual void ForceStringCompare3() = 0; + virtual void ForceStringCompare4() = 0; + virtual void ForceStringCompare5() = 0; + virtual void ForceStringCompare6() = 0; + virtual void ForceStringCompare7() = 0; + virtual void ForceStringCompare8() = 0; + virtual void ForceStringCompare9() = 0; + }; + using PerformanceStressEBus = AZ::EBus<PerformanceStressBusTraits>; + + class LocalBusTraits : public AZ::EBusTraits { public: diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp index e6bd4f53cf..281ca211a3 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp @@ -43,7 +43,11 @@ namespace ScriptCanvasTesting NodeableTestingLibrary::Reflect(context); ScriptCanvasTestingNodes::BehaviorContextObjectTest::Reflect(context); - ScriptCanvasTesting::Reflect(context); + ScriptCanvasTesting::GlobalBusTraits::Reflect(context); + ScriptCanvasTesting::LocalBusTraits::Reflect(context); + ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(context); + ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(context); + ScriptCanvasTesting::TestTupleMethods::Reflect(context); } void ScriptCanvasTestingSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) diff --git a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp index 9e6f7aa051..53f124476f 100644 --- a/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp +++ b/Gems/ScriptCanvasTesting/Code/Tests/ScriptCanvas_RuntimeInterpreted.cpp @@ -283,6 +283,16 @@ TEST_F(ScriptCanvasTestFixture, NodeableDurationFunction) ExpectParse("LY_SC_UnitTest_NodeableDurationFunction"); } +TEST_F(ScriptCanvasTestFixture, LatentCallOfPureUserFunction) +{ + RunUnitTestGraph("LY_SC_UnitTest_LatentCallOfPureUserFunction", ExecutionMode::Interpreted, DurationSpec::Ticks(3)); +} + +TEST_F(ScriptCanvasTestFixture, LatentCallOfNotPureUserFunction) +{ + RunUnitTestGraph("LY_SC_UnitTest_LatentCallOfNotPureUserFunction", ExecutionMode::Interpreted, DurationSpec::Ticks(3)); +} + TEST_F(ScriptCanvasTestFixture, NodeableDurationSubgraph) { RunUnitTestGraph("LY_SC_UnitTest_NodeableDurationSubgraph", ExecutionMode::Interpreted, DurationSpec::Ticks(3)); @@ -887,6 +897,11 @@ TEST_F(ScriptCanvasTestFixture, InterpretedNodeableInputMethodSharedDataSlot) RunUnitTestGraph("LY_SC_UnitTest_NodeableInputMethodSharedDataSlot", ExecutionMode::Interpreted); } +TEST_F(ScriptCanvasTestFixture, InterpretedExecutionOutPerformance) +{ + RunUnitTestGraph("LY_SC_UnitTest_ExecutionOutPerformance", ExecutionMode::Interpreted); +} + #if defined(FUNCTION_LEGACY_SUPPORT_ENABLED) TEST_F(ScriptCanvasTestFixture, InterpretedSubgraph_UserNodeable) From ba411893a3b24b0be4595a0c7aafeae50e63a545 Mon Sep 17 00:00:00 2001 From: Aristo7 <5432499+Aristo7@users.noreply.github.com> Date: Tue, 20 Apr 2021 15:51:57 -0400 Subject: [PATCH 26/96] openimageio to rev2 --- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 58050652c0..c5cce2194b 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -52,7 +52,7 @@ ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-windows TARGETS goo ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-windows TARGETS GoogleBenchmark PACKAGE_HASH 0c94ca69ae8e7e4aab8e90032b5c82c5964410429f3dd9dbb1f9bf4fe032b1d4) ly_associate_package(PACKAGE_NAME d3dx12-headers-rev1-windows TARGETS d3dx12 PACKAGE_HASH 088c637159fba4a3e4c0cf08fb4921906fd4cca498939bd239db7c54b5b2f804) ly_associate_package(PACKAGE_NAME pyside2-qt-5.15.1-rev2-windows TARGETS pyside2 PACKAGE_HASH c90f3efcc7c10e79b22a33467855ad861f9dbd2e909df27a5cba9db9fa3edd0f) -ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev1-windows TARGETS OpenImageIO PACKAGE_HASH b9f6d6df180ad240b9f17a68c1862c7d8f38234de0e692e83116254b0ee467e5) +ly_associate_package(PACKAGE_NAME openimageio-2.1.16.0-rev2-windows TARGETS OpenImageIO PACKAGE_HASH 85a2a6cf35cbc4c967c56ca8074babf0955c5b490c90c6e6fd23c78db99fc282) ly_associate_package(PACKAGE_NAME qt-5.15.2-windows TARGETS Qt PACKAGE_HASH edaf954c647c99727bfd313dab2959803d2df0873914bb96368c3d8286eed6d9) ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-windows TARGETS libsamplerate PACKAGE_HASH dcf3c11a96f212a52e2c9241abde5c364ee90b0f32fe6eeb6dcdca01d491829f) ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) \ No newline at end of file From 64e625a79fde20f6854c52122badcd9a9d92f558 Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Tue, 20 Apr 2021 12:52:56 -0700 Subject: [PATCH 27/96] Added support for cavity maps by changing the "Ambient Occlusion" material property group go just "Occlusion", which now contains properties for both "Diffuse AO" and "Specular Cavity". Added new input attachment to the fullscreen reflection pass to receive the "ambient" gbuffer. Added diffuse and specular occlusion to the Skin material type; it was missing before. ATOM-14040 Add Support for Cavity Maps Testing: AtomSampleViewer automation, with updates that will be submitted in that repo. Manual testing in Material Editor. Built all AtomTest assets and opened a few test levels, with updates that will be submitted in that repo. Made local copies of the occlusion test materials and changed replaced the material types with EnhancedPBR and Skin, and got identical results (with clear coat disabled since it works different in EnhancedPBR and is absent in Skin). --- .../ReflectionProbeVisualization.materialtype | 32 -- .../Materials/Types/EnhancedPBR.materialtype | 132 ++++---- .../Types/EnhancedPBR_ForwardPass.azsl | 8 +- .../Types/MaterialInputs/OcclusionInput.azsli | 14 +- .../Common/Assets/Materials/Types/Skin.azsl | 8 +- .../Assets/Materials/Types/Skin.materialtype | 96 ++++-- .../Types/StandardMultilayerPBR.materialtype | 288 ++++++++++++++---- .../StandardMultilayerPBR_ForwardPass.azsl | 15 +- .../Materials/Types/StandardPBR.materialtype | 93 ++++-- .../Materials/Types/StandardPBR_AoState.lua | 48 --- .../StandardPBR_DiffuseOcclusionState.lua | 52 ++++ .../Types/StandardPBR_ForwardPass.azsl | 8 +- .../StandardPBR_SpecularOcclusionState.lua | 52 ++++ .../Common/Assets/Passes/OpaqueParent.pass | 7 + .../Passes/ReflectionGlobalFullscreen.pass | 6 + .../Common/Assets/Passes/Reflections.pass | 12 + .../Atom/Features/PBR/ForwardPassOutput.azsli | 16 +- .../Atom/Features/PBR/LightingModel.azsli | 16 +- .../ReflectionGlobalFullscreen.azsl | 9 +- .../atom_feature_common_asset_files.cmake | 1 - .../TestData/Materials/ParallaxRock.material | 4 +- .../001_ManyFeatures.material | 29 +- .../010_AmbientOcclusion.material | 18 +- .../010_BothOcclusion.material | 15 + .../010_OcclusionBase.material | 25 ++ .../010_SpecularOcclusion.material | 13 + .../100_UvTiling_AmbientOcclusion.material | 4 +- .../Types/AutoBrick_ForwardPass.azsl | 5 +- .../Types/MinimalPBR_ForwardPass.azsl | 2 +- .../Materials/Bricks038_8K/bricks038.material | 4 +- .../PaintedPlaster015.material | 6 +- .../Assets/Materials/baseboards.material | 3 - .../Assets/Materials/crown.material | 3 - .../Assets/Objects/Lucy/lucy_brass.material | 4 +- .../Assets/Objects/Lucy/lucy_stone.material | 4 +- .../Scripts/Python/DCC_Materials/pbr.material | 5 +- .../Scripts/Python/dcc_materials/pbr.material | 5 +- .../standardPBR.template.material | 11 +- .../standardPBR.template.material | 11 +- .../standardpbr.template.material | 11 +- .../StandardPBR_AllProperties.material | 11 +- 41 files changed, 767 insertions(+), 339 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_AoState.lua create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua create mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material create mode 100644 Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material diff --git a/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype index e401b42644..214fc02660 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/ReflectionProbe/ReflectionProbeVisualization.materialtype @@ -401,38 +401,6 @@ "step": 0.1 } ], - "ambientOcclusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", - "type": "Bool", - "defaultValue": false - }, - { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", - "type": "Float", - "defaultValue": 1.0, - "min": 0.0, - "max": 2.0, - "connection": { - "type": "ShaderInput", - "id": "m_ambientOcclusionFactor" - } - }, - { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_ambientOcclusionMap" - } - } - ], "emissive": [ { "id": "enable", diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index e95c82e435..b3e4695880 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -49,9 +49,9 @@ "description": "Properties for configuring UV transforms." }, { - "id": "ambientOcclusion", - "displayName": "Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "occlusion", + "displayName": "Occlusion", + "description": "Properties for baked textures that represent geometric occlusion of light." }, { "id": "emissive", @@ -780,47 +780,96 @@ "step": 0.1 } ], - "ambientOcclusion": [ + "occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_diffuseOcclusionMap" + } + }, + { + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_diffuseOcclusionMapUvIndex" + } + }, + { + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionFactor" + "id": "m_diffuseOcclusionFactor" } }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMap" + "id": "m_specularOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", "type": "Enum", - "enumValues": [ "UV0", "UV1" ], - "defaultValue": "UV0", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMapUvIndex" + "id": "m_specularOcclusionFactor" } } ], @@ -1641,17 +1690,15 @@ } }, { - // See the comment above for details. - "type": "UseTexture", + "type": "Lua", "args": { - "textureProperty": "ambientOcclusion.textureMap", - "dependentProperties": ["ambientOcclusion.textureMapUv"], - "useTextureProperty": "ambientOcclusion.enable", - "shaderTags": [ - "ForwardPass", - "ForwardPass_EDS" - ], - "shaderOption": "o_ambientOcclusion_useTexture" + "file": "StandardPBR_DiffuseOcclusionState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua" } }, { @@ -1712,31 +1759,6 @@ "shaderOption": "o_transmission_useTexture" } }, - { - // Controls visibility for properties in the editor. - // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue. - // @param affectedProperties - the properties that are affected by actions. - "type": "UpdatePropertyVisibility", - "args": { - "actions": [ - { - "triggerProperty": "ambientOcclusion.enable", - "triggerValue": true, - "visibility": "Enabled" - }, - { - "triggerProperty": "ambientOcclusion.enable", - "triggerValue": false, - "visibility": "Disabled" - } - ], - "affectedProperties": [ - "ambientOcclusion.factor", - "ambientOcclusion.textureMap", - "ambientOcclusion.textureMapUv" - ] - } - }, { // Controls visibility for properties in the editor. // @param actions - a list of actions that are executed in order. visibility will be set when triggerProperty hits the triggerValue. diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index ff8b4b7778..1f7a1a73f7 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -212,9 +212,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float3 emissive = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); // ------- Occlusion ------- - - float2 occlusionUv = IN.m_uv[MaterialSrg::m_ambientOcclusionMapUvIndex]; - float occlusion = GetOcclusionInput(MaterialSrg::m_ambientOcclusionMap, MaterialSrg::m_sampler, occlusionUv, MaterialSrg::m_ambientOcclusionFactor, o_ambientOcclusion_useTexture); + + float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); // ------- Subsurface ------- @@ -250,7 +250,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normal, IN.m_tangent, IN.m_bitangent, anisotropy, - emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); + emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); // ------- Opacity ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/OcclusionInput.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/OcclusionInput.azsli index 6149934ba5..103745cf56 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/OcclusionInput.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/MaterialInputs/OcclusionInput.azsli @@ -12,19 +12,23 @@ #pragma once -// This file provides utilities for common handling of inputs for ambient occlusion maps for PBR materials. +// This file provides utilities for common handling of inputs for baked occlusion maps for PBR materials. // These macros can be used to declare common shader inputs for this feature. // Use the COMMON_SRG_INPUTS_* macro in your material SRG definition, and use the COMMON_OPTIONS_* macro at the global scope in your shader. Then you can pass these variables to the Get*Input() function below. // You can optionally provide a prefix for the set of inputs which corresponds to a prefix string supplied by the .materialtype file. This is common for multi-layered material types. #define COMMON_SRG_INPUTS_OCCLUSION(prefix) \ -float prefix##m_ambientOcclusionFactor; \ -Texture2D prefix##m_ambientOcclusionMap; \ -uint prefix##m_ambientOcclusionMapUvIndex; +float prefix##m_diffuseOcclusionFactor; \ +Texture2D prefix##m_diffuseOcclusionMap; \ +uint prefix##m_diffuseOcclusionMapUvIndex; \ +float prefix##m_specularOcclusionFactor; \ +Texture2D prefix##m_specularOcclusionMap; \ +uint prefix##m_specularOcclusionMapUvIndex; #define COMMON_OPTIONS_OCCLUSION(prefix) \ -option bool prefix##o_ambientOcclusion_useTexture; +option bool prefix##o_diffuseOcclusion_useTexture; \ +option bool prefix##o_specularOcclusion_useTexture; float GetOcclusionInput(Texture2D map, sampler mapSampler, float2 uv, float factor, bool useTexture) { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index aa8ae3a010..adc9257414 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -271,6 +271,11 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) float roughness = GetRoughnessInput(MaterialSrg::m_roughnessMap, MaterialSrg::m_sampler, roughnessUv, MaterialSrg::m_roughnessFactor, MaterialSrg::m_roughnessLowerBound, MaterialSrg::m_roughnessUpperBound, o_roughness_useTexture); + // ------- Occlusion ------- + + float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); + // ------- Specular ------- float2 specularUv = IN.m_uv[MaterialSrg::m_specularF0MapUvIndex]; @@ -299,7 +304,6 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) float metallic = 0; float3 emissive = float3(0,0,0); - float occlusion = 1; float2 anisotropy = float2(0,0); float clearCoatFactor = 0.0; float clearCoatRoughness = 0.0; @@ -308,7 +312,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normalWS, tangents[0], bitangents[0], anisotropy, - emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); + emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); // ------- Preparing output ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 5912bc1484..62b1f863dd 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -24,9 +24,9 @@ "description": "Properties related to configuring surface normal." }, { - "id": "ambientOcclusion", - "displayName": "Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "occlusion", + "displayName": "Occlusion", + "description": "Properties for baked textures that represent geometric occlusion of light." }, { "id": "subsurfaceScattering", @@ -383,48 +383,96 @@ } } ], - - "ambientOcclusion": [ + "occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMap" + "id": "m_diffuseOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", "type": "Enum", "enumIsUv": true, - "defaultValue": "Unwrapped", + "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMapUvIndex" + "id": "m_diffuseOcclusionMapUvIndex" } }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionFactor" + "id": "m_specularOcclusionFactor" } } ], @@ -1023,7 +1071,13 @@ { "type": "Lua", "args": { - "file": "StandardPBR_AoState.lua" + "file": "StandardPBR_DiffuseOcclusionState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index 3b40d80b67..c7f0884d9f 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -73,9 +73,9 @@ "description": "Properties for configuring gloss clear coat" }, { - "id": "layer1_ambientOcclusion", - "displayName": "Layer 1: Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "layer1_occlusion", + "displayName": "Layer 1: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { "id": "layer1_emissive", @@ -126,9 +126,9 @@ "description": "Properties for configuring gloss clear coat" }, { - "id": "layer2_ambientOcclusion", - "displayName": "Layer 2: Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "layer2_occlusion", + "displayName": "Layer 2: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { "id": "layer2_emissive", @@ -179,9 +179,9 @@ "description": "Properties for configuring gloss clear coat" }, { - "id": "layer3_ambientOcclusion", - "displayName": "Layer 3: Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "layer3_occlusion", + "displayName": "Layer 3: Occlusion", + "description": "Properties for baked textures for diffuse and specular occlusion of ambient lighting." }, { "id": "layer3_emissive", @@ -1169,47 +1169,96 @@ } } ], - "layer1_ambientOcclusion": [ + "layer1_occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_ambientOcclusionMap" + "id": "m_layer1_m_diffuseOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", "type": "Enum", "enumIsUv": true, "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer1_m_ambientOcclusionMapUvIndex" + "id": "m_layer1_m_diffuseOcclusionMapUvIndex" } }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer1_m_ambientOcclusionFactor" + "id": "m_layer1_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer1_m_specularOcclusionFactor" } } ], @@ -1820,47 +1869,96 @@ } } ], - "layer2_ambientOcclusion": [ + "layer2_occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_ambientOcclusionMap" + "id": "m_layer2_m_diffuseOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", "type": "Enum", "enumIsUv": true, "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer2_m_ambientOcclusionMapUvIndex" + "id": "m_layer2_m_diffuseOcclusionMapUvIndex" } }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer2_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_layer2_m_ambientOcclusionFactor" + "id": "m_layer2_m_specularOcclusionFactor" } } ], @@ -2471,47 +2569,96 @@ } } ], - "layer3_ambientOcclusion": [ + "layer3_occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_ambientOcclusionMap" + "id": "m_layer3_m_diffuseOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", "type": "Enum", "enumIsUv": true, "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_ambientOcclusionMapUvIndex" + "id": "m_layer3_m_diffuseOcclusionMapUvIndex" } }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_layer3_m_ambientOcclusionFactor" + "id": "m_layer3_m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_layer3_m_specularOcclusionFactor" } } ], @@ -2896,7 +3043,16 @@ { "type": "Lua", "args": { - "file": "StandardPBR_AoState.lua", + "file": "StandardPBR_DiffuseOcclusionState.lua", + "propertyNamePrefix": "layer1_", + "srgNamePrefix": "m_layer1_", + "optionsNamePrefix": "o_layer1_" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua", "propertyNamePrefix": "layer1_", "srgNamePrefix": "m_layer1_", "optionsNamePrefix": "o_layer1_" @@ -3024,7 +3180,16 @@ { "type": "Lua", "args": { - "file": "StandardPBR_AoState.lua", + "file": "StandardPBR_DiffuseOcclusionState.lua", + "propertyNamePrefix": "layer2_", + "srgNamePrefix": "m_layer2_", + "optionsNamePrefix": "o_layer2_" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua", "propertyNamePrefix": "layer2_", "srgNamePrefix": "m_layer2_", "optionsNamePrefix": "o_layer2_" @@ -3152,7 +3317,16 @@ { "type": "Lua", "args": { - "file": "StandardPBR_AoState.lua", + "file": "StandardPBR_DiffuseOcclusionState.lua", + "propertyNamePrefix": "layer3_", + "srgNamePrefix": "m_layer3_", + "optionsNamePrefix": "o_layer3_" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua", "propertyNamePrefix": "layer3_", "srgNamePrefix": "m_layer3_", "optionsNamePrefix": "o_layer3_" diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 04407adf7d..5e8ad11d54 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -267,10 +267,15 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Occlusion ------- - float layer1_occlusion = GetOcclusionInput(MaterialSrg::m_layer1_m_ambientOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_ambientOcclusionMapUvIndex], MaterialSrg::m_layer1_m_ambientOcclusionFactor, o_layer1_o_ambientOcclusion_useTexture); - float layer2_occlusion = GetOcclusionInput(MaterialSrg::m_layer2_m_ambientOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_ambientOcclusionMapUvIndex], MaterialSrg::m_layer2_m_ambientOcclusionFactor, o_layer2_o_ambientOcclusion_useTexture); - float layer3_occlusion = GetOcclusionInput(MaterialSrg::m_layer3_m_ambientOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_ambientOcclusionMapUvIndex], MaterialSrg::m_layer3_m_ambientOcclusionFactor, o_layer3_o_ambientOcclusion_useTexture); - float occlusion = BlendLayers(layer1_occlusion, layer2_occlusion, layer3_occlusion, blendMaskValues); + float layer1_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer1_m_diffuseOcclusionFactor, o_layer1_o_diffuseOcclusion_useTexture); + float layer2_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer2_m_diffuseOcclusionFactor, o_layer2_o_diffuseOcclusion_useTexture); + float layer3_diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_diffuseOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_diffuseOcclusionMapUvIndex], MaterialSrg::m_layer3_m_diffuseOcclusionFactor, o_layer3_o_diffuseOcclusion_useTexture); + float diffuseAmbientOcclusion = BlendLayers(layer1_diffuseAmbientOcclusion, layer2_diffuseAmbientOcclusion, layer3_diffuseAmbientOcclusion, blendMaskValues); + + float layer1_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer1_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer1[MaterialSrg::m_layer1_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer1_m_specularOcclusionFactor, o_layer1_o_specularOcclusion_useTexture); + float layer2_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer2_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer2[MaterialSrg::m_layer2_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer2_m_specularOcclusionFactor, o_layer2_o_specularOcclusion_useTexture); + float layer3_specularOcclusion = GetOcclusionInput(MaterialSrg::m_layer3_m_specularOcclusionMap, MaterialSrg::m_sampler, uvLayer3[MaterialSrg::m_layer3_m_specularOcclusionMapUvIndex], MaterialSrg::m_layer3_m_specularOcclusionFactor, o_layer3_o_specularOcclusion_useTexture); + float specularOcclusion = BlendLayers(layer1_specularOcclusion, layer2_specularOcclusion, layer3_specularOcclusion, blendMaskValues); // ------- Subsurface ------- @@ -348,7 +353,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normalWS, tangents[0], bitangents[0], anisotropy, - emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); + emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); // ------- Opacity ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index 9750d09538..f8c7edb2ed 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -44,9 +44,9 @@ "description": "Properties for configuring UV transforms." }, { - "id": "ambientOcclusion", - "displayName": "Ambient Occlusion", - "description": "Properties for baked AO texture." + "id": "occlusion", + "displayName": "Occlusion", + "description": "Properties for baked textures that represent geometric occlusion of light." }, { "id": "emissive", @@ -724,47 +724,96 @@ "step": 0.1 } ], - "ambientOcclusion": [ + "occlusion": [ { "id": "enable", "displayName": "Enable", - "description": "Whether to enable the ambient occlusion feature.", + "description": "Whether to enable the occlusion features.", "type": "Bool", "defaultValue": false }, { - "id": "textureMap", - "displayName": "Texture Map", - "description": "Texture map for defining ambient occlusion area.", + "id": "diffuseTextureMap", + "displayName": "Diffuse AO", + "description": "Texture map for defining occlusion area for diffuse ambient lighting.", "type": "Image", "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMap" + "id": "m_diffuseOcclusionMap" } }, { - "id": "textureMapUv", - "displayName": "UV", - "description": "Ambient occlusion texture map UV set", + "id": "diffuseUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Diffuse AO texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "diffuseTextureMapUv", + "displayName": " UV", + "description": "Diffuse AO texture map UV set.", "type": "Enum", "enumIsUv": true, "defaultValue": "Tiled", "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionMapUvIndex" + "id": "m_diffuseOcclusionMapUvIndex" } }, { - "id": "factor", - "displayName": "Factor", - "description": "Strength factor for scaling the values", + "id": "diffuseFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Diffuse AO", "type": "Float", "defaultValue": 1.0, "min": 0.0, - "max": 2.0, + "softMax": 2.0, "connection": { "type": "ShaderInput", - "id": "m_ambientOcclusionFactor" + "id": "m_diffuseOcclusionFactor" + } + }, + { + "id": "specularTextureMap", + "displayName": "Specular Cavity", + "description": "Texture map for defining occlusion area for specular lighting.", + "type": "Image", + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionMap" + } + }, + { + "id": "specularUseTexture", + "displayName": " Use Texture", + "description": "Whether to use the Specular Cavity texture map.", + "type": "Bool", + "defaultValue": true + }, + { + "id": "specularTextureMapUv", + "displayName": " UV", + "description": "Specular Cavity texture map UV set.", + "type": "Enum", + "enumIsUv": true, + "defaultValue": "Tiled", + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionMapUvIndex" + } + }, + { + "id": "specularFactor", + "displayName": " Factor", + "description": "Strength factor for scaling the values of Specular Cavity", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0, + "connection": { + "type": "ShaderInput", + "id": "m_specularOcclusionFactor" } } ], @@ -1272,7 +1321,13 @@ { "type": "Lua", "args": { - "file": "StandardPBR_AoState.lua" + "file": "StandardPBR_DiffuseOcclusionState.lua" + } + }, + { + "type": "Lua", + "args": { + "file": "StandardPBR_SpecularOcclusionState.lua" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_AoState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_AoState.lua deleted file mode 100644 index a27817d925..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_AoState.lua +++ /dev/null @@ -1,48 +0,0 @@ --------------------------------------------------------------------------------------- --- --- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or --- its licensors. --- --- For complete copyright and license terms please see the LICENSE at the root of this --- distribution (the "License"). All use of this software is governed by the License, --- or, if provided, by the license below or the license accompanying this file. Do not --- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- --- ----------------------------------------------------------------------------------------------------- - -function GetMaterialPropertyDependencies() - return {"ambientOcclusion.enable", "ambientOcclusion.textureMap"} -end - -function GetShaderOptionDependencies() - return {"o_ambientOcclusion_useTexture"} -end - -function Process(context) - local enableAo = context:GetMaterialPropertyValue_bool("ambientOcclusion.enable") - local textureMap = context:GetMaterialPropertyValue_image("ambientOcclusion.textureMap") - - context:SetShaderOptionValue_bool("o_ambientOcclusion_useTexture", enableAo and textureMap ~= nil) -end - -function ProcessEditor(context) - local enableAo = context:GetMaterialPropertyValue_bool("ambientOcclusion.enable") - - if(not enableAo) then - context:SetMaterialPropertyVisibility("ambientOcclusion.factor", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("ambientOcclusion.textureMap", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("ambientOcclusion.textureMapUv", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("ambientOcclusion.textureMap", MaterialPropertyVisibility_Enabled) - local textureMap = context:GetMaterialPropertyValue_image("ambientOcclusion.textureMap") - if(textureMap == nil) then - context:SetMaterialPropertyVisibility("ambientOcclusion.factor", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("ambientOcclusion.textureMapUv", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("ambientOcclusion.factor", MaterialPropertyVisibility_Enabled) - context:SetMaterialPropertyVisibility("ambientOcclusion.textureMapUv", MaterialPropertyVisibility_Enabled) - end - end -end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua new file mode 100644 index 0000000000..aed13fa83f --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua @@ -0,0 +1,52 @@ +-------------------------------------------------------------------------------------- +-- +-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +-- its licensors. +-- +-- For complete copyright and license terms please see the LICENSE at the root of this +-- distribution (the "License"). All use of this software is governed by the License, +-- or, if provided, by the license below or the license accompanying this file. Do not +-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- +-- +---------------------------------------------------------------------------------------------------- + +function GetMaterialPropertyDependencies() + return {"occlusion.enable", "occlusion.diffuseTextureMap", "occlusion.diffuseUseTexture"} +end + +function GetShaderOptionDependencies() + return {"o_diffuseOcclusion_useTexture"} +end + +function Process(context) + local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") + local textureMap = context:GetMaterialPropertyValue_image("occlusion.diffuseTextureMap") + local enableDiffuse = context:GetMaterialPropertyValue_bool("occlusion.diffuseUseTexture") + + context:SetShaderOptionValue_bool("o_diffuseOcclusion_useTexture", enableOcclusionMaps and textureMap ~= nil and enableDiffuse) +end + +function ProcessEditor(context) + local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") + + if(not enableOcclusionMaps) then + context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMap", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Hidden) + else + context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMap", MaterialPropertyVisibility_Enabled) + local textureMap = context:GetMaterialPropertyValue_image("occlusion.diffuseTextureMap") + if(textureMap == nil) then + context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Hidden) + else + context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Enabled) + context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Enabled) + context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Enabled) + end + end +end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 22e3da4572..0c2882365a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -171,9 +171,9 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float3 emissive = GetEmissiveInput(MaterialSrg::m_emissiveMap, MaterialSrg::m_sampler, emissiveUv, MaterialSrg::m_emissiveIntensity, MaterialSrg::m_emissiveColor.rgb, o_emissiveEnabled, o_emissive_useTexture); // ------- Occlusion ------- - - float2 occlusionUv = IN.m_uv[MaterialSrg::m_ambientOcclusionMapUvIndex]; - float occlusion = GetOcclusionInput(MaterialSrg::m_ambientOcclusionMap, MaterialSrg::m_sampler, occlusionUv, MaterialSrg::m_ambientOcclusionFactor, o_ambientOcclusion_useTexture); + + float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); // ------- Subsurface ------- @@ -208,7 +208,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normalWS, tangents[0], bitangents[0], anisotropy, - emissive, occlusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); + emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, MaterialSrg::m_transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, o_opacity_mode); // ------- Opacity ------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua new file mode 100644 index 0000000000..d67f658c7b --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua @@ -0,0 +1,52 @@ +-------------------------------------------------------------------------------------- +-- +-- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +-- its licensors. +-- +-- For complete copyright and license terms please see the LICENSE at the root of this +-- distribution (the "License"). All use of this software is governed by the License, +-- or, if provided, by the license below or the license accompanying this file. Do not +-- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- +-- +---------------------------------------------------------------------------------------------------- + +function GetMaterialPropertyDependencies() + return {"occlusion.enable", "occlusion.specularTextureMap", "occlusion.specularUseTexture"} +end + +function GetShaderOptionDependencies() + return {"o_specularOcclusion_useTexture"} +end + +function Process(context) + local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") + local textureMap = context:GetMaterialPropertyValue_image("occlusion.specularTextureMap") + local enableDiffuse = context:GetMaterialPropertyValue_bool("occlusion.specularUseTexture") + + context:SetShaderOptionValue_bool("o_specularOcclusion_useTexture", enableOcclusionMaps and textureMap ~= nil and enableDiffuse) +end + +function ProcessEditor(context) + local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") + + if(not enableOcclusionMaps) then + context:SetMaterialPropertyVisibility("occlusion.specularTextureMap", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Hidden) + else + context:SetMaterialPropertyVisibility("occlusion.specularTextureMap", MaterialPropertyVisibility_Enabled) + local textureMap = context:GetMaterialPropertyValue_image("occlusion.specularTextureMap") + if(textureMap == nil) then + context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Hidden) + context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Hidden) + else + context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Enabled) + context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Enabled) + context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Enabled) + end + end +end diff --git a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass index 9877d736a8..87e93e16b3 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass @@ -180,6 +180,13 @@ "Attachment": "SpecularF0Output" } }, + { + "LocalSlot": "AlbedoInput", + "AttachmentRef": { + "Pass": "ForwardMSAAPass", + "Attachment": "AlbedoOutput" + } + }, { "LocalSlot": "ClearCoatNormalInput", "AttachmentRef": { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionGlobalFullscreen.pass b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionGlobalFullscreen.pass index d77ba74cf9..1b763f86c2 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/ReflectionGlobalFullscreen.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/ReflectionGlobalFullscreen.pass @@ -27,6 +27,12 @@ "SlotType": "Input", "ScopeAttachmentUsage": "Shader" }, + { + // This is needed for the alpha channel which has specularOcclusion factor + "Name": "AlbedoInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, { "Name": "ClearCoatNormalInput", "SlotType": "Input", diff --git a/Gems/Atom/Feature/Common/Assets/Passes/Reflections.pass b/Gems/Atom/Feature/Common/Assets/Passes/Reflections.pass index 083c6bd16f..97881d3d71 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/Reflections.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/Reflections.pass @@ -17,6 +17,11 @@ "SlotType": "Input", "ScopeAttachmentUsage": "Shader" }, + { + "Name": "AlbedoInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, { "Name": "ClearCoatNormalInput", "SlotType": "Input", @@ -127,6 +132,13 @@ "Attachment": "SpecularF0Input" } }, + { + "LocalSlot": "AlbedoInput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "AlbedoInput" + } + }, { "LocalSlot": "ClearCoatNormalInput", "AttachmentRef": { diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassOutput.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassOutput.azsli index 4185b08571..f0a43d6b1d 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassOutput.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/ForwardPassOutput.azsli @@ -12,19 +12,19 @@ struct ForwardPassOutput { - // m_diffuseColor.a should be encoded with subsurface scattering's strength factor and quality factor if enabled - float4 m_diffuseColor : SV_Target0; - float4 m_specularColor : SV_Target1; - float4 m_albedo : SV_Target2; - float4 m_specularF0 : SV_Target3; - float4 m_normal : SV_Target4; - float4 m_clearCoatNormal : SV_Target5; + float4 m_diffuseColor : SV_Target0; //!< RGB = Diffuse Lighting, A = Blend Alpha (for blended surfaces) OR A = special encoding of surfaceScatteringFactor, m_subsurfaceScatteringQuality, o_enableSubsurfaceScattering + float4 m_specularColor : SV_Target1; //!< RGB = Specular Lighting, A = Unused + float4 m_albedo : SV_Target2; //!< RGB = Surface albedo pre-multiplied by other factors that will be multiplied later by diffuse GI, A = specularOcclusion + float4 m_specularF0 : SV_Target3; //!< RGB = Specular F0, A = roughness + float4 m_normal : SV_Target4; //!< RGB10 = EncodeNormalSignedOctahedron(worldNormal), A2 = multiScatterCompensationEnabled + float4 m_clearCoatNormal : SV_Target5; //!< RG = EncodeNormalSphereMap(clearCoatNormal), B = clearCoatFactor, A = clearCoatRoughness float3 m_scatterDistance : SV_Target6; }; struct ForwardPassOutputWithDepth { - // m_diffuseColor.a should be encoded with subsurface scattering's strength factor and quality factor if enabled + // See above for descriptions of special encodings + float4 m_diffuseColor : SV_Target0; float4 m_specularColor : SV_Target1; float4 m_albedo : SV_Target2; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli index 71e283291f..d1d1fbb8b1 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli @@ -100,6 +100,7 @@ PbrLightingOutput PbrLighting( in VSOutput IN, float2 anisotropy, // angle and factor float3 emissive, float diffuseAmbientOcclusion, + float specularOcclusion, float4 transmissionTintThickness, float4 transmissionParams, float clearCoatFactor, @@ -237,11 +238,6 @@ PbrLightingOutput PbrLighting( in VSOutput IN, } } - // Emissive contribution - // Emissive light is apply to specular now, as diffuse will be used for subsurface scattering later down the pipeline - // We may change this if specular is also used for other processing - specularLighting += emissive; - if (o_enableDirectionalLights) { ApplyDirectionalLights(dirToCamera, surface, IN.m_shadowCoords, diffuseLighting, specularLighting, translucentBackLighting); @@ -253,6 +249,13 @@ PbrLightingOutput PbrLighting( in VSOutput IN, diffuseLighting += translucentBackLighting * transmissionTintThickness.xyz; } + specularLighting *= specularOcclusion; + + // Emissive contribution + // Emissive light is apply to specular now, as diffuse will be used for subsurface scattering later down the pipeline + // We may change this if specular is also used for other processing + specularLighting += emissive; + PbrLightingOutput lightingOutput; lightingOutput.m_diffuseColor = float4(diffuseLighting, alpha); @@ -261,6 +264,7 @@ PbrLightingOutput PbrLighting( in VSOutput IN, // albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc) lightingOutput.m_specularF0 = float4(specularF0, roughness); lightingOutput.m_albedo.rgb = surface.albedo * diffuseResponse * diffuseAmbientOcclusion; + lightingOutput.m_albedo.a = specularOcclusion; lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(normal); lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f; @@ -299,7 +303,7 @@ PbrLightingOutput MakeDebugOutput(VSOutput IN, float3 debugColor, float3 normalW PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normal, IN.m_tangent, IN.m_bitangent, anisotropy, - emissive, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); + emissive, occlusion, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); return lightingOutput; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.azsl index 136e205d49..98f2672ee8 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionGlobalFullscreen.azsl @@ -43,8 +43,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass { Texture2DMS<float> m_depth; - Texture2DMS<float4> m_normal; // RGB10 = Normal (Encoded), A2 = Flags + Texture2DMS<float4> m_normal; // RGB10 = EncodeNormalSignedOctahedron(worldNormal), A2 = multiScatterCompensationEnabled Texture2DMS<float4> m_specularF0; // RGB8 = SpecularF0, A8 = Roughness + Texture2DMS<float4> m_albedo; // RGB = Not used here, A = specularOcclusion Texture2DMS<float4> m_clearCoatNormal; // R16G16 = Normal (Packed), B16A16 = (factor, perceptual roughness) Texture2DMS<float> m_blendWeight; Texture2D<float2> m_brdfMap; @@ -80,6 +81,9 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) float4 encodedNormal = PassSrg::m_normal.Load(IN.m_position.xy, sampleIndex); float3 normal = DecodeNormalSignedOctahedron(encodedNormal.rgb); bool multiScatterCompensationEnabled = (encodedNormal.a > 0.0f); + + float4 albedo = PassSrg::m_albedo.Load(IN.m_position.xy, sampleIndex); + float specularOcclusion = albedo.a; // reconstruct world space position from the depth at this location in screenspace float3 positionWS = ReconstructWorldPositionFromDepth(IN.m_position.xy, sampleIndex).xyz; @@ -136,6 +140,9 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // apply exposure setting specular *= pow(2.0, SceneSrg::m_iblExposure); + // maybe attenuate the specular + specular *= specularOcclusion; + PSOutput OUT; OUT.m_color = float4(specular, 1.0f); return OUT; diff --git a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake index 44b0b590b2..037149a988 100644 --- a/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake +++ b/Gems/Atom/Feature/Common/Assets/atom_feature_common_asset_files.cmake @@ -36,7 +36,6 @@ set(FILES Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.azsl Materials/Types/StandardMultilayerPBR_Shadowmap_WithPS.shader Materials/Types/StandardPBR.materialtype - Materials/Types/StandardPBR_AoState.lua Materials/Types/StandardPBR_ClearCoatEnableFeature.lua Materials/Types/StandardPBR_ClearCoatState.lua Materials/Types/StandardPBR_Common.azsli diff --git a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material index 4c91053515..1bc5c39e4a 100644 --- a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material +++ b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material @@ -4,9 +4,9 @@ "parentMaterial": "Materials/Presets/PBR/default_grid.material", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "textureMap": "TestData/Textures/cc0/Rock030_2K_AmbientOcclusion.jpg" + "diffuseTextureMap": "TestData/Textures/cc0/Rock030_2K_AmbientOcclusion.jpg" }, "baseColor": { "textureMap": "TestData/Textures/cc0/Rock030_2K_Color.jpg" diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index e84c6296be..19c87f193d 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -4,11 +4,6 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "layer1_ambientOcclusion": { - "enable": true, - "factor": 1.6399999856948853, - "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" - }, "layer1_baseColor": { "color": [ 0.3495536744594574, @@ -32,6 +27,11 @@ "flipY": true, "textureMap": "TestData/Textures/cc0/bark1_norm.jpg" }, + "layer1_occlusion": { + "diffuseFactor": 1.6399999856948853, + "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg", + "enable": true + }, "layer1_parallax": { "enable": true, "factor": 0.02500000037252903, @@ -53,10 +53,6 @@ "offsetU": 0.5, "offsetV": 0.25 }, - "layer2_ambientOcclusion": { - "factor": 1.2200000286102296, - "textureMap": "TestData/Textures/cc0/bark1_disp.jpg" - }, "layer2_baseColor": { "textureMap": "TestData/Textures/cc0/Lava004_1K_Color.jpg" }, @@ -76,6 +72,11 @@ "flipY": true, "textureMap": "TestData/Textures/cc0/Lava004_1K_Normal.jpg" }, + "layer2_occlusion": { + "enable": true, + "specularFactor": 2.0, + "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" + }, "layer2_parallax": { "enable": true, "factor": 0.01600000075995922, @@ -88,11 +89,6 @@ "offsetU": 0.5, "offsetV": 0.25 }, - "layer3_ambientOcclusion": { - "enable": true, - "factor": 1.0399999618530274, - "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" - }, "layer3_baseColor": { "color": [ 0.6315556764602661, @@ -115,6 +111,11 @@ "layer3_normal": { "textureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Normal.jpg" }, + "layer3_occlusion": { + "diffuseFactor": 1.0399999618530274, + "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg", + "enable": true + }, "layer3_parallax": { "enable": true, "factor": 0.004999999888241291, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material index 2c0b6767f3..ef75528284 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material @@ -1,21 +1,13 @@ { "description": "", "materialType": "Materials/Types/StandardPBR.materialtype", - "parentMaterial": "", + "parentMaterial": "010_OcclusionBase.material", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "factor": 2.0, - "textureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" - }, - "baseColor": { - "color": [ - 1.0, - 1.0, - 0.21223773062229157, - 1.0 - ] + "occlusion": { + "diffuseFactor": 2.0, + "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", + "enable": true } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material new file mode 100644 index 0000000000..d8dc4d8609 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material @@ -0,0 +1,15 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "010_OcclusionBase.material", + "propertyLayoutVersion": 3, + "properties": { + "occlusion": { + "enable": true, + "diffuseFactor": 2.0, + "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", + "specularFactor": 2.0, + "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material new file mode 100644 index 0000000000..9a41a7d191 --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_OcclusionBase.material @@ -0,0 +1,25 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "baseColor": { + "color": [ + 0.06784161180257797, + 0.2073090672492981, + 0.29570457339286806, + 1.0 + ] + }, + "clearCoat": { + "enable": true + }, + "normal": { + "textureMap": "TestData/Textures/cc0/Tiles009_1K_Normal.jpg" + }, + "roughness": { + "factor": 0.0 + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material new file mode 100644 index 0000000000..afaa9f9f4b --- /dev/null +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material @@ -0,0 +1,13 @@ +{ + "description": "", + "materialType": "Materials/Types/StandardPBR.materialtype", + "parentMaterial": "010_OcclusionBase.material", + "propertyLayoutVersion": 3, + "properties": { + "occlusion": { + "enable": true, + "specularFactor": 2.0, + "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" + } + } +} \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material index 9eec81823d..457f0b00e6 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material @@ -4,9 +4,9 @@ "parentMaterial": "TestData\\Materials\\StandardPbrTestCases\\UvTilingBase.material", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "textureMap": "TestData/Objects/cube/cube_diff.tif" + "diffuseTextureMap": "TestData/Objects/cube/cube_diff.tif" } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 6607228673..b7642054a8 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -163,7 +163,8 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) GetSurfaceShape(IN.m_uv, surfaceDepth, surfaceNormal); const float3 normal = TangentSpaceToWorld(surfaceNormal, normalize(IN.m_normal), normalize(IN.m_tangent), normalize(IN.m_bitangent)); - const float occlusion = 1.0f - surfaceDepth * AutoBrickSrg::m_aoFactor; + const float diffuseAmbientOcclusion = 1.0f - surfaceDepth * AutoBrickSrg::m_aoFactor; + const float specularOcclusion = 1; const float metallic = 0; const float roughness = 1; const float specularF0Factor = 0.5; @@ -178,7 +179,7 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normal, IN.m_tangent, IN.m_bitangent, anisotropy, - emissive, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); + emissive, diffuseAmbientOcclusion, specularOcclusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); OUT.m_diffuseColor = lightingOutput.m_diffuseColor; OUT.m_diffuseColor.w = -1; // Subsurface scattering is disabled diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 8f23239437..f08b167892 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -76,7 +76,7 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN) PbrLightingOutput lightingOutput = PbrLighting(IN, baseColor, metallic, roughness, specularF0Factor, normal, IN.m_tangent, IN.m_bitangent, anisotropy, - emissive, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); + emissive, occlusion, occlusion, transmissionTintThickness, transmissionParams, clearCoatFactor, clearCoatRoughness, clearCoatNormal, alpha, OpacityMode::Opaque); OUT.m_diffuseColor = lightingOutput.m_diffuseColor; OUT.m_diffuseColor.w = -1; // Subsurface scattering is disabled diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material index faf8e1f734..2650ee3081 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material @@ -4,9 +4,9 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" + "diffuseTextureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material index ed0230a3ca..4006b4ec51 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material @@ -4,10 +4,10 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "factor": 0.30000001192092898, - "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png" + "diffuseFactor": 0.30000001192092898, + "diffuseTextureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png" }, "baseColor": { "textureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_BaseColor.png" diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material index 233b35ab46..7e31eaa5b6 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/baseboards.material @@ -4,9 +4,6 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" - }, "baseColor": { "color": [ 0.496940553188324, diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material index a5c18d0d8b..121b27c021 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/crown.material @@ -4,9 +4,6 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "textureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" - }, "baseColor": { "color": [ 0.496940553188324, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material index 61a9974e0b..e5c3be3e8d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material @@ -4,9 +4,9 @@ "parentMaterial": "Materials/Presets/PBR/metal_brass.material", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "textureMap": "Objects/Lucy/Lucy_ao.tif" + "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif" }, "baseColor": { "color": [ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material index d48cb44721..79a7e507ec 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material @@ -4,9 +4,9 @@ "parentMaterial": "Materials/Presets/PBR/metal_brass.material", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "enable": true, - "textureMap": "Objects/Lucy/Lucy_ao.tif" + "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif" }, "baseColor": { "color": [ diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material index 4bf22b8762..8a74384d10 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material @@ -4,10 +4,9 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "factor": 1.0, - "useTexture": true, - "textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" + "diffuseTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" }, "baseColor": { "color": [ 1.0, 1.0, 1.0 ], diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material index 4bf22b8762..8a74384d10 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material @@ -4,10 +4,9 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { + "occlusion": { "factor": 1.0, - "useTexture": true, - "textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" + "diffuseTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" }, "baseColor": { "color": [ 1.0, 1.0, 1.0 ], diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/kitbash_converter/standardPBR.template.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/kitbash_converter/standardPBR.template.material index 5632c6fc0d..cc2c548174 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/kitbash_converter/standardPBR.template.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/kitbash_converter/standardPBR.template.material @@ -7,10 +7,13 @@ "general": { "texcoord": 0 }, - "ambientOcclusion": { - "factor": 1.0, - "useTexture": false, - "textureMap": "" + "occlusion": { + "diffuseFactor": 1.0, + "diffuseUseTexture": false, + "diffuseTextureMap": "", + "specularFactor": 1.0, + "specularUseTexture": false, + "specularTextureMap": "" }, "baseColor": { "color": [ diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/standardPBR.template.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/standardPBR.template.material index 1ac6fb2fcb..78891d6c46 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/standardPBR.template.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/legacy_asset_converter/standardPBR.template.material @@ -7,10 +7,13 @@ "general": { "texcoord": 0 }, - "ambientOcclusion": { - "factor": 1.0, - "useTexture": false, - "textureMap": "" + "occlusion": { + "diffuseFactor": 1.0, + "diffuseUseTexture": false, + "diffuseTextureMap": "", + "specularFactor": 1.0, + "specularUseTexture": false, + "specularTextureMap": "" }, "baseColor": { "color": [ diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/maya_dcc_materials/standardpbr.template.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/maya_dcc_materials/standardpbr.template.material index 4bf22b8762..30d895f9ac 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/maya_dcc_materials/standardpbr.template.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/maya_dcc_materials/standardpbr.template.material @@ -4,10 +4,13 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "factor": 1.0, - "useTexture": true, - "textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" + "occlusion": { + "diffuseFactor": 1.0, + "diffuseUseTexture": true, + "diffuseTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif", + "specularFactor": 1.0, + "specularUseTexture": true, + "specularTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" }, "baseColor": { "color": [ 1.0, 1.0, 1.0 ], diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/stingraypbs_converter/StandardPBR_AllProperties.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/stingraypbs_converter/StandardPBR_AllProperties.material index 4bf22b8762..00ff63829f 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/stingraypbs_converter/StandardPBR_AllProperties.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/stingraypbs_converter/StandardPBR_AllProperties.material @@ -4,10 +4,13 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "factor": 1.0, - "useTexture": true, - "textureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" + "occlusion": { + "diffuseFactor": 1.0, + "diffuseUseTexture": false, + "diffuseTextureMap": "", + "specularFactor": 1.0, + "specularUseTexture": false, + "specularTextureMap": "" }, "baseColor": { "color": [ 1.0, 1.0, 1.0 ], From 444d28a25e3fc4917070d0a2756257a8005fc2b3 Mon Sep 17 00:00:00 2001 From: scottr <scottr@amazon.com> Date: Tue, 20 Apr 2021 14:26:21 -0700 Subject: [PATCH 28/96] [SPEC-6436] added option to override the inclusion of test targets in build --- cmake/PAL.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index 734baad8a3..5131005c72 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -85,3 +85,9 @@ ly_include_cmake_file_list(${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_fi include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) include(${pal_dir}/Toolchain_${PAL_PLATFORM_NAME_LOWERCASE}.cmake OPTIONAL) + +set(LY_DISABLE_TEST_MODULES FALSE CACHE BOOL "Option to forcibly disable the inclusion of test targets in the build") + +if(LY_DISABLE_TEST_MODULES) + ly_set(PAL_TRAIT_BUILD_TESTS_SUPPORTED FALSE) +endif() From fa947d84f77424923d6d9613f301f6451904c7d5 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 20 Apr 2021 14:44:51 -0700 Subject: [PATCH 29/96] Reflect testing enum properly --- .../Include/ScriptCanvas/Translation/GraphToLua.cpp | 4 ++-- .../Code/Source/Framework/ScriptCanvasTestFixture.h | 12 +++--------- .../Code/Source/ScriptCanvasTestBus.cpp | 1 + .../Source/ScriptCanvasTestingSystemComponent.cpp | 6 +----- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp index 8f28a7f94b..ee55fff259 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Translation/GraphToLua.cpp @@ -869,10 +869,10 @@ namespace ScriptCanvas const bool hasResults = eventThread->HasReturnValues(); - AZStd::optional<size_t> eventIndex = ebusHandling->m_node->GetEventIndex(eventName); + AZStd::optional<size_t> eventIndex = ebusHandling->m_node->GetEventIndex(nameAndEventThread.first); if (!eventIndex) { - AddError(nullptr, aznew Internal::ParseError(ebusHandling->m_node->GetEntityId(), AZStd::string::format("EBus handler did not return a valid index for event %s", eventName.c_str()))); + AddError(nullptr, aznew Internal::ParseError(ebusHandling->m_node->GetEntityId(), AZStd::string::format("EBus handler did not return a valid index for event %s", nameAndEventThread.first.c_str()))); return; } diff --git a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h index ab00593dbc..cb3c9cdccb 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h +++ b/Gems/ScriptCanvasTesting/Code/Source/Framework/ScriptCanvasTestFixture.h @@ -108,15 +108,9 @@ namespace ScriptCanvasTests auto m_serializeContext = s_application->GetSerializeContext(); auto m_behaviorContext = s_application->GetBehaviorContext(); - ScriptCanvasTesting::GlobalBusTraits::Reflect(m_serializeContext); - ScriptCanvasTesting::GlobalBusTraits::Reflect(m_behaviorContext); - ScriptCanvasTesting::LocalBusTraits::Reflect(m_serializeContext); - ScriptCanvasTesting::LocalBusTraits::Reflect(m_behaviorContext); - ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(m_serializeContext); - ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(m_behaviorContext); - ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(m_serializeContext); - ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(m_behaviorContext); - ScriptCanvasTesting::TestTupleMethods::Reflect(m_behaviorContext); + + ScriptCanvasTesting::Reflect(m_serializeContext); + ScriptCanvasTesting::Reflect(m_behaviorContext); ::Nodes::InputMethodSharedDataSlotExampleNode::Reflect(m_serializeContext); ::Nodes::InputMethodSharedDataSlotExampleNode::Reflect(m_behaviorContext); diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp index dc43bb862d..39f6479c12 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestBus.cpp @@ -24,6 +24,7 @@ namespace ScriptCanvasTesting { ScriptCanvasTesting::GlobalBusTraits::Reflect(context); ScriptCanvasTesting::LocalBusTraits::Reflect(context); + ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(context); ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(context); ScriptCanvasTesting::TestTupleMethods::Reflect(context); diff --git a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp index 281ca211a3..e6bd4f53cf 100644 --- a/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp +++ b/Gems/ScriptCanvasTesting/Code/Source/ScriptCanvasTestingSystemComponent.cpp @@ -43,11 +43,7 @@ namespace ScriptCanvasTesting NodeableTestingLibrary::Reflect(context); ScriptCanvasTestingNodes::BehaviorContextObjectTest::Reflect(context); - ScriptCanvasTesting::GlobalBusTraits::Reflect(context); - ScriptCanvasTesting::LocalBusTraits::Reflect(context); - ScriptCanvasTesting::PerformanceStressBusTraits::Reflect(context); - ScriptCanvasTesting::NativeHandlingOnlyBusTraits::Reflect(context); - ScriptCanvasTesting::TestTupleMethods::Reflect(context); + ScriptCanvasTesting::Reflect(context); } void ScriptCanvasTestingSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) From 95533edc6c8e34e11870d1fc41ba0403f7e1ffde Mon Sep 17 00:00:00 2001 From: scottr <scottr@amazon.com> Date: Tue, 20 Apr 2021 15:10:37 -0700 Subject: [PATCH 30/96] [SPEC-6436] wrapped stray PrefabBuilder.Tests around PAL_TRAIT_BUILD_TESTS_SUPPORTED --- Gems/Prefab/PrefabBuilder/CMakeLists.txt | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/Gems/Prefab/PrefabBuilder/CMakeLists.txt b/Gems/Prefab/PrefabBuilder/CMakeLists.txt index 5ab614eecb..22b89287ca 100644 --- a/Gems/Prefab/PrefabBuilder/CMakeLists.txt +++ b/Gems/Prefab/PrefabBuilder/CMakeLists.txt @@ -38,23 +38,6 @@ ly_add_target( Gem::PrefabBuilder.Static ) -ly_add_target( - NAME PrefabBuilder.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - prefabbuilder_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - . - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::PrefabBuilder.Static -) -ly_add_googletest( - NAME Gem::PrefabBuilder.Tests -) - ly_add_target_dependencies( TARGETS AssetBuilder @@ -63,3 +46,22 @@ ly_add_target_dependencies( DEPENDENT_TARGETS Gem::PrefabBuilder ) + +if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) + ly_add_target( + NAME PrefabBuilder.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + prefabbuilder_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + Gem::PrefabBuilder.Static + ) + ly_add_googletest( + NAME Gem::PrefabBuilder.Tests + ) +endif() From cdab4da4195027271cb8182b15c8bd36b5908bf3 Mon Sep 17 00:00:00 2001 From: chcurran <chcurran@amazon.com> Date: Tue, 20 Apr 2021 15:44:04 -0700 Subject: [PATCH 31/96] Add mark complete to unit tests --- ...tentCallOfNotPureUserFunction.scriptcanvas | 363 ++++++++++++++++-- ..._LatentCallOfPureUserFunction.scriptcanvas | 361 +++++++++++++++-- 2 files changed, 659 insertions(+), 65 deletions(-) diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas index eb208d7fd2..e9c05c3831 100644 --- a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfNotPureUserFunction.scriptcanvas @@ -3,9 +3,9 @@ <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13541071503942" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7437740330467" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> - <Class name="AZStd::string" field="Name" value="DelayCallPure" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="Name" value="LY_SC_UnitTest_LatentCallOfNotPureUserFunction" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> @@ -16,7 +16,7 @@ <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7442035297763" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="SC-Node(Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -75,7 +75,7 @@ </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7446330265059" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="SC-Node(TimeDelayNodeableNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -319,12 +319,12 @@ </Class> </Class> </Class> - <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7450625232355" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="FunctionCallNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -481,6 +481,226 @@ </Class> </Class> </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7454920199651" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Mark Complete)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="8809084234328280515" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F603FD67-A8D0-468E-8480-00E8F2B5C317}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="EntityID: 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{E0505AE1-737C-4B80-803C-A4364A240CD2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="additional notes for the test report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BEF85627-1015-4B13-BC06-F1063DB4D4DC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{8BC6BC59-538A-430E-AE1D-C0CA2DF9216B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="EntityId" field="m_data" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4276206253" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="AZStd::string" field="m_data" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="Mark Complete" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> @@ -488,7 +708,7 @@ <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13558251373126" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7459215166947" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="srcEndpoint=(On Graph Start: Out), destEndpoint=(TimeDelay: Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -498,7 +718,7 @@ </Class> <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7442035297763" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -506,7 +726,7 @@ </Class> <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7446330265059" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -519,7 +739,7 @@ </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13562546340422" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7463510134243" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="srcEndpoint=(TimeDelay: Done), destEndpoint=(Function Call Node: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -529,7 +749,7 @@ </Class> <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7446330265059" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -537,7 +757,7 @@ </Class> <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7450625232355" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{8BF89FFE-4D6F-4A53-9CFB-1E9D32E20AD0}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -548,6 +768,37 @@ <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7467805101539" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Out), destEndpoint=(Mark Complete: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="9654104828115164517" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7450625232355" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{F12F8492-EDE6-4F0B-8A31-EC7944F1C779}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7454920199651" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{BEF85627-1015-4B13-BC06-F1063DB4D4DC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> </Class> <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> @@ -556,7 +807,7 @@ <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> - <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FB0BCBAE8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5F8014E487}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="unsigned int" field="m_variableCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> @@ -564,7 +815,7 @@ <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13553956405830" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7454920199651" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -572,7 +823,7 @@ <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{7BED9343-8F8D-4C4C-BF13-CF0E81082975}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{23A951FB-B4B8-40AD-9375-A16C015A2A61}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -592,7 +843,7 @@ <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="360.0000000 220.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="900.0000000 200.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -606,7 +857,28 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13545366471238" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7437740330467" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> + <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> + <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> + <Class name="double" field="Scale" value="0.9191536" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> + <Class name="float" field="AnchorX" value="-170.8093109" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="-195.8323364" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + </Class> + <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="7446330265059" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -619,7 +891,7 @@ <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="-180.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="20.0000000 20.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -640,7 +912,7 @@ <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> </Class> @@ -648,7 +920,7 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13549661438534" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7442035297763" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -656,7 +928,7 @@ <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -676,7 +948,7 @@ <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="20.0000000 20.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="-180.0000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -690,20 +962,41 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="13541071503942" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="7450625232355" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> - <Class name="AZ::Uuid" field="value1" value="{5F84B500-8C45-40D1-8EFC-A5306B241444}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> - <Class name="SceneComponentSaveData" field="value2" version="3" type="{5F84B500-8C45-40D1-8EFC-A5306B241444}"> - <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> - <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> - <Class name="double" field="Scale" value="0.9191536" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> - <Class name="float" field="AnchorX" value="-311.1558228" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> - <Class name="float" field="AnchorY" value="-34.8146400" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> - </Class> - <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="360.0000000 220.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{7BED9343-8F8D-4C4C-BF13-CF0E81082975}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> </Class> @@ -722,7 +1015,11 @@ <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> </Class> <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> - <Class name="AZ::u64" field="value1" value="7721683751185626951" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="value1" value="17189374120869440743" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="6840657073857873079" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> </Class> </Class> diff --git a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas index 1140c64bbd..bd570e3ec2 100644 --- a/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas +++ b/Gems/ScriptCanvasTesting/Assets/ScriptCanvas/UnitTests/LY_SC_UnitTest_LatentCallOfPureUserFunction.scriptcanvas @@ -3,9 +3,9 @@ <Class name="AZStd::unique_ptr" field="m_scriptCanvas" type="{8FFB6D85-994F-5262-BA1C-D0082A7F65C5}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9091485385286" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4792040476131" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> - <Class name="AZStd::string" field="Name" value="DelayCallPure" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="Name" value="LY_SC_UnitTest_LatentCallOfPureUserFunction" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> <Class name="Graph" field="element" version="8" type="{4D755CA9-AB92-462C-B24F-0B3376F19967}"> <Class name="Graph" field="BaseClass1" version="17" type="{C3267D77-EEDC-490E-9E42-F1D1F473E184}"> @@ -16,7 +16,7 @@ <Class name="AZStd::unordered_set" field="m_nodes" type="{27BF7BD3-6E17-5619-9363-3FC3D9A5369D}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4796335443427" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="SC-Node(Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -75,7 +75,7 @@ </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4800630410723" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="SC-Node(TimeDelayNodeableNode)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -319,12 +319,12 @@ </Class> </Class> </Class> - <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4804925378019" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="FunctionCallNode" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -481,6 +481,226 @@ </Class> </Class> </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4809220345315" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="SC-Node(Mark Complete)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Method" field="element" version="5" type="{E42861BD-1956-45AE-8DD7-CCFC1E3E5ACF}"> + <Class name="Node" field="BaseClass1" version="14" type="{52B454AE-FA7E-4FE9-87D3-A1CAB235C691}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="1417761892103721732" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::list" field="Slots" type="{E01B3091-9B44-571A-A87B-7D0E2768D774}"> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{7F333623-93C2-44E7-9589-48B78A9E99E9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="EntityID: 0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{233D398C-67B5-472A-BCF6-FC6C4E67C16A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="ExclusivePureDataContract" field="element" type="{E48A0B26-B6B7-4AF3-9341-9E5C5C1F0DE8}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="additional notes for the test report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{77092888-66FF-41B7-9FA4-929734197818}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="In" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + <Class name="Slot" field="element" version="21" type="{FBFE0F02-4C26-475F-A28B-18D3A533C13C}"> + <Class name="bool" field="IsOverload" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="isVisibile" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="SlotId" field="id" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3E9C52F2-24C3-42AA-ACE6-05766F30BA4F}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="DynamicTypeOverride" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::vector" field="contracts" type="{C87136AF-3259-590C-9519-D1C4C75F1C86}"> + <Class name="AZStd::unique_ptr" field="element" type="{75F9EC0D-D8D6-5410-BD79-960E22076B03}"> + <Class name="SlotTypeContract" field="element" type="{084B4F2A-AB34-4931-9269-E3614FC1CDFA}"> + <Class name="Contract" field="BaseClass1" type="{93846E60-BD7E-438A-B970-5C4AA591CF93}"/> + </Class> + </Class> + </Class> + <Class name="AZStd::string" field="slotName" value="Out" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="toolTip" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="Type" field="DisplayDataType" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="2" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="Crc32" field="DisplayGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="SlotDescriptor" field="Descriptor" version="1" type="{FBF1C3A7-AA74-420F-BBE4-29F78D6EA262}"> + <Class name="int" field="ConnectionType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="int" field="SlotType" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="bool" field="IsLatent" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Crc32" field="DynamicGroup" type="{9F4E062E-06A0-46D4-85DF-E0DA96467D3A}"> + <Class name="unsigned int" field="Value" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + </Class> + <Class name="int" field="DataType" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="bool" field="IsReference" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="VariableId" field="VariableReference" type="{CA57A57B-E510-4C09-B952-1F43742166AE}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="bool" field="IsUserAdded" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::list" field="Datums" type="{36259B04-FAAB-5E8A-B7BF-A5E2EA5A9B3A}"> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="EntityId" field="m_data" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4276206253" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="Datum" field="element" version="6" type="{8B836FC0-98A8-4A81-8651-35C7CA125451}"> + <Class name="bool" field="m_isUntypedStorage" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="Type" field="m_type" version="2" type="{0EADF8F5-8AB8-42E9-9C50-F5C78255C817}"> + <Class name="unsigned int" field="m_type" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> + <Class name="AZ::Uuid" field="m_azType" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + <Class name="int" field="m_originality" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="any" field="m_datumStorage" type="{03924488-C7F4-4D6D-948B-ABC2D1AE2FD3}"> + <Class name="AZStd::string" field="m_data" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + <Class name="AZStd::string" field="m_datumLabel" value="Report" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="int" field="NodeDisabledFlag" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="int" field="methodType" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + <Class name="AZStd::string" field="methodName" value="Mark Complete" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="className" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="namespaces" type="{99DAD0BC-740E-5E82-826B-8FC7968CC02C}"/> + <Class name="AZStd::vector" field="resultSlotIDs" type="{D0B13803-101B-54D8-914C-0DA49FDFA268}"> + <Class name="SlotId" field="element" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{00000000-0000-0000-0000-000000000000}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="AZStd::string" field="prettyClassName" value="Unit Testing" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> <Class name="bool" field="IsDependencyReady" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> @@ -488,7 +708,7 @@ <Class name="AZStd::vector" field="m_connections" type="{21786AF0-2606-5B9A-86EB-0892E2820E6C}"> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9108665254470" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4813515312611" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="srcEndpoint=(On Graph Start: Out), destEndpoint=(TimeDelay: Start)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -498,7 +718,7 @@ </Class> <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4796335443427" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{D0566322-ABB1-4DE3-BF2D-4ED1ED64E114}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -506,7 +726,7 @@ </Class> <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4800630410723" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{98881463-93EA-4134-B167-7570F78F526D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -519,7 +739,7 @@ </Class> <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9112960221766" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4817810279907" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="AZStd::string" field="Name" value="srcEndpoint=(TimeDelay: Done), destEndpoint=(Function Call Node: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> @@ -529,7 +749,7 @@ </Class> <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4800630410723" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{2042EA06-6AE4-49EA-B162-4C1EEB7C6F7A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -537,7 +757,7 @@ </Class> <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4804925378019" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> <Class name="AZ::Uuid" field="m_id" value="{B9BCC3F2-0B3B-448A-9535-1BEC67F90BEE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> @@ -548,6 +768,37 @@ <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> </Class> + <Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}"> + <Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4822105247203" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="AZStd::string" field="Name" value="srcEndpoint=(Function Call Node: Out), destEndpoint=(Mark Complete: In)" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::vector" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}"> + <Class name="Connection" field="element" type="{64CA5016-E803-4AC4-9A36-BDA2C890C6EB}"> + <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}"> + <Class name="AZ::u64" field="Id" value="15803796564312159315" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="Endpoint" field="sourceEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4804925378019" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{3D5A170D-0E7D-43C1-957D-FAA97B9E0907}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + <Class name="Endpoint" field="targetEndpoint" version="1" type="{91D4ADAC-56FE-4D82-B9AF-6975D21435C8}"> + <Class name="EntityId" field="nodeId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4809220345315" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="SlotId" field="slotId" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> + <Class name="AZ::Uuid" field="m_id" value="{77092888-66FF-41B7-9FA4-929734197818}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + <Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + <Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> </Class> <Class name="AZStd::unordered_map" field="m_dependentAssets" type="{1BC78FA9-1D82-5F17-BD28-C35D1F4FA737}"/> <Class name="AZStd::vector" field="m_scriptEventAssets" type="{479100D9-6931-5E23-8494-5A28EF2FCD8A}"/> @@ -556,7 +807,7 @@ <Class name="AZ::Uuid" field="m_assetType" value="{3E2AC8CD-713F-453E-967F-29517F331784}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="bool" field="isFunctionGraph" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> <Class name="SlotId" field="versionData" version="2" type="{14C629F6-467B-46FE-8B63-48FDFCA42175}"> - <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5FB0BCBAE8}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="m_id" value="{01000000-0100-0000-E7EF-7F5F90A3C087}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="unsigned int" field="m_variableCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> @@ -564,7 +815,7 @@ <Class name="AZStd::unordered_map" field="GraphCanvasData" type="{0005D26C-B35A-5C30-B60C-5716482946CB}"> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9095780352582" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4804925378019" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -577,28 +828,28 @@ <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="120.0000000 80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="640.0000000 200.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{A9407C52-FC80-4F58-B489-D37FF5871277}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> </Class> @@ -606,7 +857,7 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9100075319878" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4809220345315" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -614,27 +865,27 @@ <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{81B5C756-BF90-4CD6-8BC9-0D4CF8DB9D2E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="320.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="980.0000000 240.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -648,7 +899,7 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9091485385286" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4792040476131" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> @@ -658,8 +909,8 @@ <Class name="AZStd::vector" field="Constructs" type="{60BF495A-9BEF-5429-836B-37ADEA39CEA0}"/> <Class name="ViewParams" field="ViewParams" version="1" type="{D016BF86-DFBB-4AF0-AD26-27F6AB737740}"> <Class name="double" field="Scale" value="0.9191536" type="{110C4B14-11A8-4E9D-8638-5051013A56AC}"/> - <Class name="float" field="AnchorX" value="-311.1558228" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> - <Class name="float" field="AnchorY" value="-34.8146400" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorX" value="-3.2638724" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> + <Class name="float" field="AnchorY" value="-82.6847687" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/> </Class> <Class name="unsigned int" field="BookmarkCounter" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/> </Class> @@ -669,35 +920,77 @@ </Class> <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> - <Class name="AZ::u64" field="id" value="9104370287174" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="id" value="4800630410723" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> </Class> <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="NodeSaveData" field="value2" version="1" type="{24CB38BB-1705-4EC5-8F63-B574571B4DCD}"> + <Class name="bool" field="HideUnusedSlots" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> + <Class name="Vector2" field="Position" value="320.0000000 100.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + </Class> + </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZ::Uuid" field="PersistentId" value="{A9407C52-FC80-4F58-B489-D37FF5871277}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{BB5065C3-D90F-4D53-93E8-794C17FF1940}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + </Class> + </Class> + </Class> + </Class> + </Class> + <Class name="AZStd::pair" field="element" type="{22EBF919-A826-58E5-8EF6-15CA70D620BB}"> + <Class name="EntityId" field="value1" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}"> + <Class name="AZ::u64" field="id" value="4796335443427" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + </Class> + <Class name="EntitySaveDataContainer" field="value2" version="2" type="{DCCDA882-AF72-49C3-9AAD-BA601322BFBC}"> + <Class name="AZStd::unordered_map" field="ComponentData" type="{318313BB-1036-5630-AFC4-FCBD54818E6D}"> + <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> + <Class name="AZ::Uuid" field="value1" value="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> + <Class name="PersistentIdComponentSaveData" field="value2" version="1" type="{B1F49A35-8408-40DA-B79E-F1E3B64322CE}"> + <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> + <Class name="AZ::Uuid" field="PersistentId" value="{E9C674F1-C34C-4CE6-A7A4-081EF8BA834A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{328FF15C-C302-458F-A43D-E1794DE0904E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeneralNodeTitleComponentSaveData" field="value2" version="1" type="{328FF15C-C302-458F-A43D-E1794DE0904E}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="PaletteOverride" value="MethodNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="PaletteOverride" value="TimeNodeTitlePalette" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="StylingComponentSaveData" field="value2" version="1" type="{B0B99C8A-03AF-4CF6-A926-F65C874C3D97}"> <Class name="ComponentSaveData" field="BaseClass1" version="1" type="{359ACEC7-D0FA-4FC0-8B59-3755BB1A9836}"/> - <Class name="AZStd::string" field="SubStyle" value=".method" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> + <Class name="AZStd::string" field="SubStyle" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> <Class name="AZ::Uuid" field="value1" value="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/> <Class name="GeometrySaveData" field="value2" version="1" type="{7CC444B1-F9B3-41B5-841B-0C4F2179F111}"> - <Class name="Vector2" field="Position" value="640.0000000 200.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> + <Class name="Vector2" field="Position" value="120.0000000 80.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/> </Class> </Class> <Class name="AZStd::pair" field="element" type="{CE78FEBD-1B9D-5A3E-9B95-BD8DD8CCCD4B}"> @@ -722,7 +1015,11 @@ <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> </Class> <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> - <Class name="AZ::u64" field="value1" value="7721683751185626951" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="AZ::u64" field="value1" value="214951534038835990" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> + <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> + </Class> + <Class name="AZStd::pair" field="element" type="{0CE5EF6F-834D-519F-B2EC-C2763B8BB99C}"> + <Class name="AZ::u64" field="value1" value="6840657073857873079" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/> <Class name="int" field="value2" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/> </Class> </Class> From 94b11e5c8f0bd8fb77a2ea105a1a103b2da26731 Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Tue, 20 Apr 2021 16:40:10 -0700 Subject: [PATCH 32/96] Replaced StandardPBR_DiffuseOcclusionState and StandardPBR_SpecularOcclusionState functor scripts with just UseTexture functors. The behavior is the basically the same and a lot simpler. All we lose is the occlusion "enable" flag, which is cleaner anyway. ATOM-14040 Add Support for Cavity Maps --- .../Materials/Types/EnhancedPBR.materialtype | 21 +++-- .../Assets/Materials/Types/Skin.materialtype | 21 +++-- .../Types/StandardMultilayerPBR.materialtype | 81 +++++++------------ .../Materials/Types/StandardPBR.materialtype | 21 +++-- .../StandardPBR_DiffuseOcclusionState.lua | 52 ------------ .../StandardPBR_SpecularOcclusionState.lua | 52 ------------ .../TestData/Materials/ParallaxRock.material | 1 - .../001_ManyFeatures.material | 7 +- .../010_AmbientOcclusion.material | 3 +- .../010_BothOcclusion.material | 1 - .../010_SpecularOcclusion.material | 1 - .../100_UvTiling_AmbientOcclusion.material | 1 - .../Materials/Bricks038_8K/bricks038.material | 1 - .../PaintedPlaster015.material | 1 - .../Assets/Objects/Lucy/lucy_brass.material | 1 - .../Assets/Objects/Lucy/lucy_stone.material | 1 - .../Scripts/Python/DCC_Materials/pbr.material | 2 +- .../Scripts/Python/dcc_materials/pbr.material | 2 +- 18 files changed, 65 insertions(+), 205 deletions(-) delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua delete mode 100644 Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype index b3e4695880..cb66a987ae 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR.materialtype @@ -781,13 +781,6 @@ } ], "occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -1690,15 +1683,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua" + "textureProperty": "occlusion.diffuseTextureMap", + "useTextureProperty": "occlusion.diffuseUseTexture", + "dependentProperties": ["occlusion.diffuseTextureMapUv", "occlusion.diffuseFactor"], + "shaderOption": "o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua" + "textureProperty": "occlusion.specularTextureMap", + "useTextureProperty": "occlusion.specularUseTexture", + "dependentProperties": ["occlusion.specularTextureMapUv", "occlusion.specularFactor"], + "shaderOption": "o_specularOcclusion_useTexture" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 62b1f863dd..4ecf9389ba 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -384,13 +384,6 @@ } ], "occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -1069,15 +1062,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua" + "textureProperty": "occlusion.diffuseTextureMap", + "useTextureProperty": "occlusion.diffuseUseTexture", + "dependentProperties": ["occlusion.diffuseTextureMapUv", "occlusion.diffuseFactor"], + "shaderOption": "o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua" + "textureProperty": "occlusion.specularTextureMap", + "useTextureProperty": "occlusion.specularUseTexture", + "dependentProperties": ["occlusion.specularTextureMapUv", "occlusion.specularFactor"], + "shaderOption": "o_specularOcclusion_useTexture" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype index c7f0884d9f..7610a4c9db 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR.materialtype @@ -1170,13 +1170,6 @@ } ], "layer1_occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -1870,13 +1863,6 @@ } ], "layer2_occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -2570,13 +2556,6 @@ } ], "layer3_occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -3041,21 +3020,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" + "textureProperty": "layer1_occlusion.diffuseTextureMap", + "useTextureProperty": "layer1_occlusion.diffuseUseTexture", + "dependentProperties": ["layer1_occlusion.diffuseTextureMapUv", "layer1_occlusion.diffuseFactor"], + "shaderOption": "o_layer1_o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua", - "propertyNamePrefix": "layer1_", - "srgNamePrefix": "m_layer1_", - "optionsNamePrefix": "o_layer1_" + "textureProperty": "layer1_occlusion.specularTextureMap", + "useTextureProperty": "layer1_occlusion.specularUseTexture", + "dependentProperties": ["layer1_occlusion.specularTextureMapUv", "layer1_occlusion.specularFactor"], + "shaderOption": "o_layer1_o_specularOcclusion_useTexture" } }, { @@ -3178,21 +3157,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" + "textureProperty": "layer2_occlusion.diffuseTextureMap", + "useTextureProperty": "layer2_occlusion.diffuseUseTexture", + "dependentProperties": ["layer2_occlusion.diffuseTextureMapUv", "layer2_occlusion.diffuseFactor"], + "shaderOption": "o_layer2_o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua", - "propertyNamePrefix": "layer2_", - "srgNamePrefix": "m_layer2_", - "optionsNamePrefix": "o_layer2_" + "textureProperty": "layer2_occlusion.specularTextureMap", + "useTextureProperty": "layer2_occlusion.specularUseTexture", + "dependentProperties": ["layer2_occlusion.specularTextureMapUv", "layer2_occlusion.specularFactor"], + "shaderOption": "o_layer2_o_specularOcclusion_useTexture" } }, { @@ -3315,21 +3294,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" + "textureProperty": "layer3_occlusion.diffuseTextureMap", + "useTextureProperty": "layer3_occlusion.diffuseUseTexture", + "dependentProperties": ["layer3_occlusion.diffuseTextureMapUv", "layer3_occlusion.diffuseFactor"], + "shaderOption": "o_layer3_o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua", - "propertyNamePrefix": "layer3_", - "srgNamePrefix": "m_layer3_", - "optionsNamePrefix": "o_layer3_" + "textureProperty": "layer3_occlusion.specularTextureMap", + "useTextureProperty": "layer3_occlusion.specularUseTexture", + "dependentProperties": ["layer3_occlusion.specularTextureMapUv", "layer3_occlusion.specularFactor"], + "shaderOption": "o_layer3_o_specularOcclusion_useTexture" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype index f8c7edb2ed..e071a793a5 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR.materialtype @@ -725,13 +725,6 @@ } ], "occlusion": [ - { - "id": "enable", - "displayName": "Enable", - "description": "Whether to enable the occlusion features.", - "type": "Bool", - "defaultValue": false - }, { "id": "diffuseTextureMap", "displayName": "Diffuse AO", @@ -1319,15 +1312,21 @@ } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_DiffuseOcclusionState.lua" + "textureProperty": "occlusion.diffuseTextureMap", + "useTextureProperty": "occlusion.diffuseUseTexture", + "dependentProperties": ["occlusion.diffuseTextureMapUv", "occlusion.diffuseFactor"], + "shaderOption": "o_diffuseOcclusion_useTexture" } }, { - "type": "Lua", + "type": "UseTexture", "args": { - "file": "StandardPBR_SpecularOcclusionState.lua" + "textureProperty": "occlusion.specularTextureMap", + "useTextureProperty": "occlusion.specularUseTexture", + "dependentProperties": ["occlusion.specularTextureMapUv", "occlusion.specularFactor"], + "shaderOption": "o_specularOcclusion_useTexture" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua deleted file mode 100644 index aed13fa83f..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_DiffuseOcclusionState.lua +++ /dev/null @@ -1,52 +0,0 @@ --------------------------------------------------------------------------------------- --- --- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or --- its licensors. --- --- For complete copyright and license terms please see the LICENSE at the root of this --- distribution (the "License"). All use of this software is governed by the License, --- or, if provided, by the license below or the license accompanying this file. Do not --- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- --- ----------------------------------------------------------------------------------------------------- - -function GetMaterialPropertyDependencies() - return {"occlusion.enable", "occlusion.diffuseTextureMap", "occlusion.diffuseUseTexture"} -end - -function GetShaderOptionDependencies() - return {"o_diffuseOcclusion_useTexture"} -end - -function Process(context) - local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") - local textureMap = context:GetMaterialPropertyValue_image("occlusion.diffuseTextureMap") - local enableDiffuse = context:GetMaterialPropertyValue_bool("occlusion.diffuseUseTexture") - - context:SetShaderOptionValue_bool("o_diffuseOcclusion_useTexture", enableOcclusionMaps and textureMap ~= nil and enableDiffuse) -end - -function ProcessEditor(context) - local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") - - if(not enableOcclusionMaps) then - context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMap", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMap", MaterialPropertyVisibility_Enabled) - local textureMap = context:GetMaterialPropertyValue_image("occlusion.diffuseTextureMap") - if(textureMap == nil) then - context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("occlusion.diffuseUseTexture", MaterialPropertyVisibility_Enabled) - context:SetMaterialPropertyVisibility("occlusion.diffuseTextureMapUv", MaterialPropertyVisibility_Enabled) - context:SetMaterialPropertyVisibility("occlusion.diffuseFactor", MaterialPropertyVisibility_Enabled) - end - end -end diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua deleted file mode 100644 index d67f658c7b..0000000000 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_SpecularOcclusionState.lua +++ /dev/null @@ -1,52 +0,0 @@ --------------------------------------------------------------------------------------- --- --- All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or --- its licensors. --- --- For complete copyright and license terms please see the LICENSE at the root of this --- distribution (the "License"). All use of this software is governed by the License, --- or, if provided, by the license below or the license accompanying this file. Do not --- remove or modify any license notices. This file is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- --- ----------------------------------------------------------------------------------------------------- - -function GetMaterialPropertyDependencies() - return {"occlusion.enable", "occlusion.specularTextureMap", "occlusion.specularUseTexture"} -end - -function GetShaderOptionDependencies() - return {"o_specularOcclusion_useTexture"} -end - -function Process(context) - local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") - local textureMap = context:GetMaterialPropertyValue_image("occlusion.specularTextureMap") - local enableDiffuse = context:GetMaterialPropertyValue_bool("occlusion.specularUseTexture") - - context:SetShaderOptionValue_bool("o_specularOcclusion_useTexture", enableOcclusionMaps and textureMap ~= nil and enableDiffuse) -end - -function ProcessEditor(context) - local enableOcclusionMaps = context:GetMaterialPropertyValue_bool("occlusion.enable") - - if(not enableOcclusionMaps) then - context:SetMaterialPropertyVisibility("occlusion.specularTextureMap", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("occlusion.specularTextureMap", MaterialPropertyVisibility_Enabled) - local textureMap = context:GetMaterialPropertyValue_image("occlusion.specularTextureMap") - if(textureMap == nil) then - context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Hidden) - context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Hidden) - else - context:SetMaterialPropertyVisibility("occlusion.specularUseTexture", MaterialPropertyVisibility_Enabled) - context:SetMaterialPropertyVisibility("occlusion.specularTextureMapUv", MaterialPropertyVisibility_Enabled) - context:SetMaterialPropertyVisibility("occlusion.specularFactor", MaterialPropertyVisibility_Enabled) - end - end -end diff --git a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material index 1bc5c39e4a..f639534bfb 100644 --- a/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material +++ b/Gems/Atom/TestData/TestData/Materials/ParallaxRock.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseTextureMap": "TestData/Textures/cc0/Rock030_2K_AmbientOcclusion.jpg" }, "baseColor": { diff --git a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material index 19c87f193d..8f916ec490 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardMultilayerPbrTestCases/001_ManyFeatures.material @@ -29,8 +29,7 @@ }, "layer1_occlusion": { "diffuseFactor": 1.6399999856948853, - "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg", - "enable": true + "diffuseTextureMap": "TestData/Textures/cc0/bark1_disp.jpg" }, "layer1_parallax": { "enable": true, @@ -73,7 +72,6 @@ "textureMap": "TestData/Textures/cc0/Lava004_1K_Normal.jpg" }, "layer2_occlusion": { - "enable": true, "specularFactor": 2.0, "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" }, @@ -113,8 +111,7 @@ }, "layer3_occlusion": { "diffuseFactor": 1.0399999618530274, - "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg", - "enable": true + "diffuseTextureMap": "TestData/Textures/cc0/PaintedMetal003_1K_Displacement.jpg" }, "layer3_parallax": { "enable": true, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material index ef75528284..efc375dc81 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_AmbientOcclusion.material @@ -6,8 +6,7 @@ "properties": { "occlusion": { "diffuseFactor": 2.0, - "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", - "enable": true + "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg" } } } \ No newline at end of file diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material index d8dc4d8609..cee64dd107 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_BothOcclusion.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseFactor": 2.0, "diffuseTextureMap": "TestData/Textures/cc0/Tiles009_1K_AmbientOcclusion.jpg", "specularFactor": 2.0, diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material index afaa9f9f4b..703088d6f8 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/010_SpecularOcclusion.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "specularFactor": 2.0, "specularTextureMap": "TestData/Textures/cc0/Tiles009_1K_Displacement.jpg" } diff --git a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material index 457f0b00e6..e0e4019b8c 100644 --- a/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material +++ b/Gems/Atom/TestData/TestData/Materials/StandardPbrTestCases/100_UvTiling_AmbientOcclusion.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseTextureMap": "TestData/Objects/cube/cube_diff.tif" } } diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material index 2650ee3081..b4b1e10b2e 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/Bricks038_8K/bricks038.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseTextureMap": "Materials/Bricks038_8K/Bricks038_8K_AmbientOcclusion.png" }, "baseColor": { diff --git a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material index 4006b4ec51..2d622e8263 100644 --- a/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material +++ b/Gems/AtomContent/LookDevelopmentStudioPixar/Assets/Materials/PaintedPlaster015_8K/PaintedPlaster015.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseFactor": 0.30000001192092898, "diffuseTextureMap": "Materials/PaintedPlaster015_8K/PaintedPlaster015_8K_AmbientOcclusion.png" }, diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material index e5c3be3e8d..8b37245ae7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_brass.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif" }, "baseColor": { diff --git a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material index 79a7e507ec..4f6a9e1292 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material +++ b/Gems/AtomLyIntegration/CommonFeatures/Assets/Objects/Lucy/lucy_stone.material @@ -5,7 +5,6 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "enable": true, "diffuseTextureMap": "Objects/Lucy/Lucy_ao.tif" }, "baseColor": { diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material index 8a74384d10..94fc5a16bd 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Atom/Scripts/Python/DCC_Materials/pbr.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "factor": 1.0, + "diffuseFactor": 1.0, "diffuseTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" }, "baseColor": { diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material index 8a74384d10..94fc5a16bd 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/SDK/Maya/Scripts/Python/dcc_materials/pbr.material @@ -5,7 +5,7 @@ "propertyLayoutVersion": 3, "properties": { "occlusion": { - "factor": 1.0, + "diffuseFactor": 1.0, "diffuseTextureMap": "EngineAssets/TextureMsg/DefaultNoUVs.tif" }, "baseColor": { From e79b1b4af1b360e057f8b805c689155714913f70 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Tue, 20 Apr 2021 16:51:48 -0700 Subject: [PATCH 33/96] Moved hydra util package near editor python tests --- .../EditorPythonTestTools/README.txt | 49 ++++++++ .../EditorPythonTestTools/__init__.py | 0 .../PKG-INFO | 110 ++++++++++++++++++ .../SOURCES.txt | 7 ++ .../dependency_links.txt | 1 + .../requires.txt | 1 + .../top_level.txt | 1 + .../editor_python_test_tools/__init__.py | 0 .../editor_entity_utils.py | 0 .../editor_test_helper.py | 0 .../hydra_editor_utils.py | 0 .../hydra_test_utils.py | 0 .../pyside_component_utils.py | 0 .../editor_python_test_tools/pyside_utils.py | 0 .../editor_python_test_tools/utils.py | 0 .../EditorPythonTestTools/setup.py | 4 +- Tools/EditorPythonTestTools/README.txt | 100 ---------------- cmake/LYPython.cmake | 2 +- 18 files changed, 172 insertions(+), 103 deletions(-) create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/__init__.py (100%) create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/PKG-INFO create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/SOURCES.txt create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/dependency_links.txt create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/requires.txt create mode 100644 AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/top_level.txt rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/__init__.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/editor_python_test_tools/utils.py (100%) rename {Tools => AutomatedTesting/Gem/PythonTests}/EditorPythonTestTools/setup.py (91%) delete mode 100644 Tools/EditorPythonTestTools/README.txt diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt new file mode 100644 index 0000000000..8c86e22681 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/README.txt @@ -0,0 +1,49 @@ +All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +its licensors. + +For complete copyright and license terms please see the LICENSE at the root of this +distribution (the "License"). All use of this software is governed by the License, +or, if provided, by the license below or the license accompanying this file. Do not +remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + +INTRODUCTION +------------ + +EditorPythonBindings is a Python project that contains a collection of editor testing tools +developed by the Lumberyard feature teams. The project contains tools for system level +editor tests. + + +REQUIREMENTS +------------ + + * Python 3.7.5 (64-bit) + +It is recommended that you completely remove any other versions of Python +installed on your system. + + +INSTALL +----------- +It is recommended to set up these these tools with Lumberyard's CMake build commands. +Assuming CMake is already setup on your operating system, below are some sample build commands: + cd /path/to/od3e/ + mkdir windows_vs2019 + cd windows_vs2019 + cmake .. -G "Visual Studio 16 2019" -A x64 -T host=x64 -DLY_3RDPARTY_PATH="%3RDPARTYPATH%" -DLY_PROJECTS=AutomatedTesting +NOTE: +Using the above command also adds EditorPythonTestTools to the PYTHONPATH OS environment variable. +Additionally, some CTest scripts will add the Python interpreter path to the PYTHON OS environment variable. + +To manually install the project in development mode using your own installed Python interpreter: + cd /path/to/od3e/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools + /path/to/your/python -m pip install -e . + + +UNINSTALLATION +-------------- + +The preferred way to uninstall the project is: + /path/to/your/python -m pip uninstall editor_python_test_tools diff --git a/Tools/EditorPythonTestTools/__init__.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/__init__.py similarity index 100% rename from Tools/EditorPythonTestTools/__init__.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/PKG-INFO b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/PKG-INFO new file mode 100644 index 0000000000..4fb74423c2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/PKG-INFO @@ -0,0 +1,110 @@ +Metadata-Version: 1.0 +Name: editor-python-test-tools +Version: 1.0.0 +Summary: Lumberyard editor Python bindings test tools +Home-page: UNKNOWN +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Description: All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + its licensors. + + For complete copyright and license terms please see the LICENSE at the root of this + distribution (the "License"). All use of this software is governed by the License, + or, if provided, by the license below or the license accompanying this file. Do not + remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + + + INTRODUCTION + ------------ + + EditorPythonBindings is a Python project that contains a collection of testing tools + developed by the Lumberyard Test Tech team. The project contains + the following tools: + + * Workspace Manager: + A library to manipulate Lumberyard installations + * Launchers: + A library to test the game in a variety of platforms + + + REQUIREMENTS + ------------ + + * Python 3.7.5 (64-bit) + + It is recommended that you completely remove any other versions of Python + installed on your system. + + + INSTALL + ----------- + It is recommended to set up these these tools with Lumberyard's CMake build commands. + Assuming CMake is already setup on your operating system, below are some sample build commands: + cd /path/to/od3e/ + mkdir windows_vs2019 + cd windows_vs2019 + cmake .. -G "Visual Studio 16 2019" -A x64 -T host=x64 -DLY_3RDPARTY_PATH="%3RDPARTYPATH%" -DLY_PROJECTS=AutomatedTesting + NOTE: + Using the above command also adds LyTestTools to the PYTHONPATH OS environment variable. + Additionally, some CTest scripts will add the Python interpreter path to the PYTHON OS environment variable. + There is some LyTestTools functionality that will search for these, so feel free to populate them manually. + + To manually install the project in development mode using your own installed Python interpreter: + cd /path/to/lumberyard/dev/Tools/LyTestTools/ + /path/to/your/python -m pip install -e . + + For console/mobile testing, update the following .ini file in your root user directory: + i.e. C:/Users/myusername/ly_test_tools/devices.ini (a.k.a. %USERPROFILE%/ly_test_tools/devices.ini) + + You will need to add a section for the device, and a key holding the device identifier value (usually an IP or ID). + It should look similar to this for each device: + [android] + id = 988939353955305449 + + [gameconsole] + ip = 192.168.1.1 + + [gameconsole2] + ip = 192.168.1.2 + + + PACKAGE STRUCTURE + ----------------- + + The project is organized into packages. Each package corresponds to a tool: + + - LyTestTools.ly_test_tools._internal: contains logging setup, pytest fixture, and o3de workspace manager modules + - LyTestTools.ly_test_tools.builtin: builtin helpers and fixtures for quickly writing tests + - LyTestTools.ly_test_tools.console: modules used for consoles + - LyTestTools.ly_test_tools.environment: functions related to file/process management and cleanup + - LyTestTools.ly_test_tools.image: modules related to image capturing and processing + - LyTestTools.ly_test_tools.launchers: game launchers library + - LyTestTools.ly_test_tools.log: modules for interacting with generated or existing log files + - LyTestTools.ly_test_tools.o3de: modules used to interact with Open 3D Engine + - LyTestTools.ly_test_tools.mobile: modules used for android/ios + - LyTestTools.ly_test_tools.report: modules used for reporting + - LyTestTools.tests: LyTestTools integration, unit, and example usage tests + + + DIRECTORY STRUCTURE + ------------------- + + The directory structure corresponds to the package structure. For example, the + ly_test_tools.builtin package is located in the ly_test_tools/builtin/ directory. + + + ENTRY POINTS + ------------ + + Deploying the project in development mode installs only entry points for pytest fixtures. + + + UNINSTALLATION + -------------- + + The preferred way to uninstall the project is: + /path/to/your/python -m pip uninstall ly_test_tools + +Platform: UNKNOWN diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/SOURCES.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/SOURCES.txt new file mode 100644 index 0000000000..1143b74a7c --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/SOURCES.txt @@ -0,0 +1,7 @@ +README.txt +setup.py +editor_python_test_tools.egg-info/PKG-INFO +editor_python_test_tools.egg-info/SOURCES.txt +editor_python_test_tools.egg-info/dependency_links.txt +editor_python_test_tools.egg-info/requires.txt +editor_python_test_tools.egg-info/top_level.txt \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/dependency_links.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/dependency_links.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/requires.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/requires.txt new file mode 100644 index 0000000000..f11e5b3d82 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/requires.txt @@ -0,0 +1 @@ +ly_test_tools diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/top_level.txt b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/top_level.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools.egg-info/top_level.txt @@ -0,0 +1 @@ + diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/__init__.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/__init__.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/__init__.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_entity_utils.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/editor_test_helper.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_editor_utils.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/hydra_test_utils.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/pyside_component_utils.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/pyside_utils.py diff --git a/Tools/EditorPythonTestTools/editor_python_test_tools/utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py similarity index 100% rename from Tools/EditorPythonTestTools/editor_python_test_tools/utils.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py diff --git a/Tools/EditorPythonTestTools/setup.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py similarity index 91% rename from Tools/EditorPythonTestTools/setup.py rename to AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py index b11b5d32ad..f253ac98fb 100644 --- a/Tools/EditorPythonTestTools/setup.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py @@ -15,7 +15,7 @@ from setuptools import setup, find_packages from setuptools.command.develop import develop from setuptools.command.build_py import build_py -PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) +PACKAGE_ROOT = os.path.abspath(os.path.dirname(__file__)) PYTHON_64 = platform.architecture()[0] == '64bit' @@ -24,7 +24,7 @@ if __name__ == '__main__': if not PYTHON_64: raise RuntimeError("32-bit Python is not a supported platform.") - with open(os.path.join(PROJECT_ROOT, 'README.txt')) as f: + with open(os.path.join(PACKAGE_ROOT, 'README.txt')) as f: long_description = f.read() setup( diff --git a/Tools/EditorPythonTestTools/README.txt b/Tools/EditorPythonTestTools/README.txt deleted file mode 100644 index d32d3d21a3..0000000000 --- a/Tools/EditorPythonTestTools/README.txt +++ /dev/null @@ -1,100 +0,0 @@ -All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -its licensors. - -For complete copyright and license terms please see the LICENSE at the root of this -distribution (the "License"). All use of this software is governed by the License, -or, if provided, by the license below or the license accompanying this file. Do not -remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - - -INTRODUCTION ------------- - -EditorPythonBindings is a Python project that contains a collection of testing tools -developed by the Lumberyard Test Tech team. The project contains -the following tools: - - * Workspace Manager: - A library to manipulate Lumberyard installations - * Launchers: - A library to test the game in a variety of platforms - - -REQUIREMENTS ------------- - - * Python 3.7.5 (64-bit) - -It is recommended that you completely remove any other versions of Python -installed on your system. - - -INSTALL ------------ -It is recommended to set up these these tools with Lumberyard's CMake build commands. -Assuming CMake is already setup on your operating system, below are some sample build commands: - cd /path/to/od3e/ - mkdir windows_vs2019 - cd windows_vs2019 - cmake .. -G "Visual Studio 16 2019" -A x64 -T host=x64 -DLY_3RDPARTY_PATH="%3RDPARTYPATH%" -DLY_PROJECTS=AutomatedTesting -NOTE: -Using the above command also adds LyTestTools to the PYTHONPATH OS environment variable. -Additionally, some CTest scripts will add the Python interpreter path to the PYTHON OS environment variable. -There is some LyTestTools functionality that will search for these, so feel free to populate them manually. - -To manually install the project in development mode using your own installed Python interpreter: - cd /path/to/lumberyard/dev/Tools/LyTestTools/ - /path/to/your/python -m pip install -e . - -For console/mobile testing, update the following .ini file in your root user directory: - i.e. C:/Users/myusername/ly_test_tools/devices.ini (a.k.a. %USERPROFILE%/ly_test_tools/devices.ini) - -You will need to add a section for the device, and a key holding the device identifier value (usually an IP or ID). -It should look similar to this for each device: - [android] - id = 988939353955305449 - - [gameconsole] - ip = 192.168.1.1 - - [gameconsole2] - ip = 192.168.1.2 - - -PACKAGE STRUCTURE ------------------ - -The project is organized into packages. Each package corresponds to a tool: - -- LyTestTools.ly_test_tools._internal: contains logging setup, pytest fixture, and o3de workspace manager modules -- LyTestTools.ly_test_tools.builtin: builtin helpers and fixtures for quickly writing tests -- LyTestTools.ly_test_tools.console: modules used for consoles -- LyTestTools.ly_test_tools.environment: functions related to file/process management and cleanup -- LyTestTools.ly_test_tools.image: modules related to image capturing and processing -- LyTestTools.ly_test_tools.launchers: game launchers library -- LyTestTools.ly_test_tools.log: modules for interacting with generated or existing log files -- LyTestTools.ly_test_tools.o3de: modules used to interact with Open 3D Engine -- LyTestTools.ly_test_tools.mobile: modules used for android/ios -- LyTestTools.ly_test_tools.report: modules used for reporting -- LyTestTools.tests: LyTestTools integration, unit, and example usage tests - - -DIRECTORY STRUCTURE -------------------- - -The directory structure corresponds to the package structure. For example, the -ly_test_tools.builtin package is located in the ly_test_tools/builtin/ directory. - - -ENTRY POINTS ------------- - -Deploying the project in development mode installs only entry points for pytest fixtures. - - -UNINSTALLATION --------------- - -The preferred way to uninstall the project is: - /path/to/your/python -m pip uninstall ly_test_tools diff --git a/cmake/LYPython.cmake b/cmake/LYPython.cmake index 1fb6ac3790..ff5132097c 100644 --- a/cmake/LYPython.cmake +++ b/cmake/LYPython.cmake @@ -268,7 +268,7 @@ if (NOT CMAKE_SCRIPT_MODE_FILE) ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/LyTestTools ly-test-tools) ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/RemoteConsole/ly_remote_console ly-remote-console) - ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/Tools/EditorPythonTestTools editor-python-test-tools) + ly_pip_install_local_package_editable(${LY_ROOT_FOLDER}/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools editor-python-test-tools) endif() endif() From a2094e730813ffa943f0e0628e2bb2bdcbefb2d3 Mon Sep 17 00:00:00 2001 From: karlberg <karlberg@amazon.com> Date: Tue, 20 Apr 2021 17:20:37 -0700 Subject: [PATCH 34/96] Removing debug pragma --- .../EntityReplication/EntityReplicationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index 2d2c668497..8db582f6e5 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -9,7 +9,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ -#pragma optimize("", off) + #include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h> #include <Source/NetworkEntity/EntityReplication/EntityReplicator.h> #include <Source/NetworkEntity/EntityReplication/PropertyPublisher.h> From a6a65ec5c21b979751e989662e8ed08bc621a439 Mon Sep 17 00:00:00 2001 From: scottr <scottr@amazon.com> Date: Tue, 20 Apr 2021 17:30:20 -0700 Subject: [PATCH 35/96] [SPEC-6436] include LY_DISABLE_TEST_MODULES to the windows install job --- scripts/build/Platform/Windows/build_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 666c0ab5e7..4dd99686c5 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -290,7 +290,7 @@ "PARAMETERS": { "CONFIGURATION": "profile", "OUTPUT_DIRECTORY": "build\\windows_vs2019", - "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DCMAKE_INSTALL_PREFIX=build\\install", + "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DCMAKE_INSTALL_PREFIX=build\\install", "CMAKE_LY_PROJECTS": "", "CMAKE_TARGET": "INSTALL", "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo" From 4ae75a71d0091974cb81bef48d4623bb004ad7dd Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 20 Apr 2021 17:33:34 -0700 Subject: [PATCH 36/96] safety check on empty datum LYN-2855 --- Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h index e361e71415..781dcb9ed8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/Datum.h @@ -208,7 +208,13 @@ namespace ScriptCanvas static const t_Value* Help(Datum& datum) { static_assert(!AZStd::is_pointer<t_Value>::value, "no pointer types in the Datum::GetAsHelper<t_Value, false>"); - if (datum.m_type.GetType() == Data::eType::BehaviorContextObject) + + if (datum.m_storage.empty()) + { + // rare, but can be caused by removals or problems with reflection to BehaviorContext, so must be checked + return nullptr; + } + else if (datum.m_type.GetType() == Data::eType::BehaviorContextObject) { return (*AZStd::any_cast<BehaviorContextObjectPtr>(&datum.m_storage))->CastConst<t_Value>(); } From 58dcbe42e42b1e395862897b1a24ea52d4cbf2ca Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Tue, 20 Apr 2021 17:51:05 -0700 Subject: [PATCH 37/96] Check for string param types in single result slot. LYN-2855 --- .../Code/Include/ScriptCanvas/Core/MethodConfiguration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/MethodConfiguration.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/MethodConfiguration.cpp index 19b01c43cc..ab2f5ac8db 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/MethodConfiguration.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/MethodConfiguration.cpp @@ -57,7 +57,7 @@ namespace ScriptCanvas for (size_t resultIndex = 0; resultIndex < unpackedTypes.size(); ++resultIndex) { - const Data::Type outputType(Data::FromAZType(unpackedTypes[resultIndex])); + const Data::Type outputType = (unpackedTypes.size() == 1 && AZ::BehaviorContextHelper::IsStringParameter(*result)) ? Data::Type::String() : Data::FromAZType(unpackedTypes[resultIndex]); const AZStd::string resultSlotName(AZStd::string::format("Result: %s", Data::GetName(outputType).data())); SlotId addedSlotId; From 55304c8b9cd592ceeb75847084c8acc07d94afc6 Mon Sep 17 00:00:00 2001 From: karlberg <karlberg@amazon.com> Date: Tue, 20 Apr 2021 18:00:39 -0700 Subject: [PATCH 38/96] Renamed Multiplayer.Imgui to Multiplayer.Debug --- .../MultiplayerDebugModule.cpp} | 14 +++++------ .../MultiplayerDebugModule.h} | 10 ++++---- .../MultiplayerDebugSystemComponent.cpp} | 24 +++++++++---------- .../MultiplayerDebugSystemComponent.h} | 6 ++--- ...es.cmake => multiplayer_debug_files.cmake} | 8 +++---- 5 files changed, 31 insertions(+), 31 deletions(-) rename Gems/Multiplayer/Code/Source/{Imgui/MultiplayerImguiModule.cpp => Debug/MultiplayerDebugModule.cpp} (69%) rename Gems/Multiplayer/Code/Source/{Imgui/MultiplayerImguiModule.h => Debug/MultiplayerDebugModule.h} (75%) rename Gems/Multiplayer/Code/Source/{Imgui/MultiplayerImguiSystemComponent.cpp => Debug/MultiplayerDebugSystemComponent.cpp} (86%) rename Gems/Multiplayer/Code/Source/{Imgui/MultiplayerImguiSystemComponent.h => Debug/MultiplayerDebugSystemComponent.h} (90%) rename Gems/Multiplayer/Code/{multiplayer_imgui_files.cmake => multiplayer_debug_files.cmake} (76%) diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp similarity index 69% rename from Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp rename to Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp index 1b59a704dc..6ecb8e2ad6 100644 --- a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp @@ -11,26 +11,26 @@ */ #include <Source/Multiplayer_precompiled.h> -#include <Source/Imgui/MultiplayerImguiModule.h> -#include <Source/Imgui/MultiplayerImguiSystemComponent.h> +#include <Source/Imgui/MultiplayerDebugModule.h> +#include <Source/Imgui/MultiplayerDebugSystemComponent.h> namespace Multiplayer { - MultiplayerImguiModule::MultiplayerImguiModule() + MultiplayerDebugModule::MultiplayerDebugModule() : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { - MultiplayerImguiSystemComponent::CreateDescriptor(), + MultiplayerDebugSystemComponent::CreateDescriptor(), }); } - AZ::ComponentTypeList MultiplayerImguiModule::GetRequiredSystemComponents() const + AZ::ComponentTypeList MultiplayerDebugModule::GetRequiredSystemComponents() const { return AZ::ComponentTypeList { - azrtti_typeid<MultiplayerImguiSystemComponent>(), + azrtti_typeid<MultiplayerDebugSystemComponent>(), }; } } -AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerImguiModule); +AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerDebugModule); diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.h similarity index 75% rename from Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h rename to Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.h index ce0ed244be..94e96edf95 100644 --- a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiModule.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.h @@ -16,15 +16,15 @@ namespace Multiplayer { - class MultiplayerImguiModule + class MultiplayerDebugModule : public AZ::Module { public: - AZ_RTTI(MultiplayerImguiModule, "{9E1460FA-4513-4B5E-86B4-9DD8ADEFA714}", AZ::Module); - AZ_CLASS_ALLOCATOR(MultiplayerImguiModule, AZ::SystemAllocator, 0); + AZ_RTTI(MultiplayerDebugModule, "{9E1460FA-4513-4B5E-86B4-9DD8ADEFA714}", AZ::Module); + AZ_CLASS_ALLOCATOR(MultiplayerDebugModule, AZ::SystemAllocator, 0); - MultiplayerImguiModule(); - ~MultiplayerImguiModule() override = default; + MultiplayerDebugModule(); + ~MultiplayerDebugModule() override = default; AZ::ComponentTypeList GetRequiredSystemComponents() const override; }; diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp similarity index 86% rename from Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp rename to Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index a53dd2800f..106a8b1d03 100644 --- a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -10,45 +10,45 @@ * */ -#include <Source/Imgui/MultiplayerImguiSystemComponent.h> +#include <Source/Imgui/MultiplayerDebugSystemComponent.h> #include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Interface/Interface.h> #include <Include/IMultiplayer.h> namespace Multiplayer { - void MultiplayerImguiSystemComponent::Reflect(AZ::ReflectContext* context) + void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context) { if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { - serializeContext->Class<MultiplayerImguiSystemComponent, AZ::Component>() + serializeContext->Class<MultiplayerDebugSystemComponent, AZ::Component>() ->Version(1); } } - void MultiplayerImguiSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + void MultiplayerDebugSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) { - provided.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + provided.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent")); } - void MultiplayerImguiSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + void MultiplayerDebugSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) { ; } - void MultiplayerImguiSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile) + void MultiplayerDebugSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile) { - incompatbile.push_back(AZ_CRC_CE("MultiplayerImguiSystemComponent")); + incompatbile.push_back(AZ_CRC_CE("MultiplayerDebugSystemComponent")); } - void MultiplayerImguiSystemComponent::Activate() + void MultiplayerDebugSystemComponent::Activate() { #ifdef IMGUI_ENABLED ImGui::ImGuiUpdateListenerBus::Handler::BusConnect(); #endif } - void MultiplayerImguiSystemComponent::Deactivate() + void MultiplayerDebugSystemComponent::Deactivate() { #ifdef IMGUI_ENABLED ImGui::ImGuiUpdateListenerBus::Handler::BusDisconnect(); @@ -56,7 +56,7 @@ namespace Multiplayer } #ifdef IMGUI_ENABLED - void MultiplayerImguiSystemComponent::OnImGuiMainMenuUpdate() + void MultiplayerDebugSystemComponent::OnImGuiMainMenuUpdate() { if (ImGui::BeginMenu("Multiplayer")) { @@ -95,7 +95,7 @@ namespace Multiplayer } } - void MultiplayerImguiSystemComponent::OnImGuiUpdate() + void MultiplayerDebugSystemComponent::OnImGuiUpdate() { if (m_displayStats) { diff --git a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h similarity index 90% rename from Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h rename to Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 1650d62264..81940423d7 100644 --- a/Gems/Multiplayer/Code/Source/Imgui/MultiplayerImguiSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -21,21 +21,21 @@ namespace Multiplayer { - class MultiplayerImguiSystemComponent final + class MultiplayerDebugSystemComponent final : public AZ::Component #ifdef IMGUI_ENABLED , public ImGui::ImGuiUpdateListenerBus::Handler #endif { public: - AZ_COMPONENT(MultiplayerImguiSystemComponent, "{060BF3F1-0BFE-4FCE-9C3C-EE991F0DA581}"); + AZ_COMPONENT(MultiplayerDebugSystemComponent, "{060BF3F1-0BFE-4FCE-9C3C-EE991F0DA581}"); static void Reflect(AZ::ReflectContext* context); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatbile); - ~MultiplayerImguiSystemComponent() override = default; + ~MultiplayerDebugSystemComponent() override = default; //! AZ::Component overrides //! @{ diff --git a/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake similarity index 76% rename from Gems/Multiplayer/Code/multiplayer_imgui_files.cmake rename to Gems/Multiplayer/Code/multiplayer_debug_files.cmake index 57623772d2..8d0b121735 100644 --- a/Gems/Multiplayer/Code/multiplayer_imgui_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake @@ -12,8 +12,8 @@ set(FILES Source/Multiplayer_precompiled.cpp Source/Multiplayer_precompiled.h - Source/Imgui/MultiplayerImguiModule.cpp - Source/Imgui/MultiplayerImguiModule.h - Source/Imgui/MultiplayerImguiSystemComponent.cpp - Source/Imgui/MultiplayerImguiSystemComponent.h + Source/Debug/MultiplayerDebugModule.cpp + Source/Debug/MultiplayerDebugModule.h + Source/Debug/MultiplayerDebugSystemComponent.cpp + Source/Debug/MultiplayerDebugSystemComponent.h ) From 0da6d5ad613a2168d7ac367eae8dacfb9da915fd Mon Sep 17 00:00:00 2001 From: karlberg <karlberg@amazon.com> Date: Tue, 20 Apr 2021 18:23:17 -0700 Subject: [PATCH 39/96] Missed the associated cmake changes --- Gems/Multiplayer/Code/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/CMakeLists.txt b/Gems/Multiplayer/Code/CMakeLists.txt index 8cde5e01e2..cd0cfca40d 100644 --- a/Gems/Multiplayer/Code/CMakeLists.txt +++ b/Gems/Multiplayer/Code/CMakeLists.txt @@ -103,10 +103,10 @@ if (PAL_TRAIT_BUILD_TESTS_SUPPORTED) endif() ly_add_target( - NAME Multiplayer.Imgui ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} + NAME Multiplayer.Debug ${PAL_TRAIT_MONOLITHIC_DRIVEN_MODULE_TYPE} NAMESPACE Gem FILES_CMAKE - multiplayer_imgui_files.cmake + multiplayer_debug_files.cmake INCLUDE_DIRECTORIES PRIVATE Source From 7adbdb2889b6c3def78ec48f71c2f6dd7f94a9b6 Mon Sep 17 00:00:00 2001 From: karlberg <karlberg@amazon.com> Date: Tue, 20 Apr 2021 18:37:53 -0700 Subject: [PATCH 40/96] Fix some include paths after rename/refactor --- Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp | 4 ++-- .../Code/Source/Debug/MultiplayerDebugSystemComponent.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp index 6ecb8e2ad6..ec148d09b1 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugModule.cpp @@ -11,8 +11,8 @@ */ #include <Source/Multiplayer_precompiled.h> -#include <Source/Imgui/MultiplayerDebugModule.h> -#include <Source/Imgui/MultiplayerDebugSystemComponent.h> +#include <Source/Debug/MultiplayerDebugModule.h> +#include <Source/Debug/MultiplayerDebugSystemComponent.h> namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 106a8b1d03..67dd678c54 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -10,7 +10,7 @@ * */ -#include <Source/Imgui/MultiplayerDebugSystemComponent.h> +#include <Source/Debug/MultiplayerDebugSystemComponent.h> #include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Interface/Interface.h> #include <Include/IMultiplayer.h> From 5f4275336ccac4dc7f14ae6bb07976f00f18a4d0 Mon Sep 17 00:00:00 2001 From: mnaumov <mnaumov@amazon.com> Date: Tue, 20 Apr 2021 20:05:32 -0700 Subject: [PATCH 41/96] Fixing deadlock related to thumbnails Adding smoothing to thumbnails in AssetBrowser --- .../AssetBrowser/Views/EntryDelegate.cpp | 2 +- .../AzToolsFramework/Thumbnails/Thumbnail.cpp | 8 +++++++- .../AzToolsFramework/Thumbnails/ThumbnailContext.cpp | 12 +++++++++++- .../AzToolsFramework/Thumbnails/ThumbnailContext.h | 10 +++++++++- .../AzToolsFramework/Thumbnails/ThumbnailWidget.cpp | 3 +++ .../AzToolsFramework/Thumbnails/ThumbnailerBus.h | 12 ++++++++++++ 6 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp index 0a25d1cf25..abc290a406 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/Views/EntryDelegate.cpp @@ -140,7 +140,7 @@ namespace AzToolsFramework else { QPixmap pixmap = thumbnail->GetPixmap(size); - painter->drawPixmap(point.x(), point.y(), size.width(), size.height(), pixmap); + painter->drawPixmap(point, pixmap.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } return m_iconSize; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp index 939ca813b6..2892e4efce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/Thumbnail.cpp @@ -10,12 +10,14 @@ * */ +#include <AzToolsFramework/Thumbnails/ThumbnailerBus.h> #include <AzToolsFramework/Thumbnails/Thumbnail.h> AZ_PUSH_DISABLE_WARNING(4127 4251 4800 4244, "-Wunknown-warning-option") // 4127: conditional expression is constant // 4251: 'QTextCodec::ConverterState::flags': class 'QFlags<QTextCodec::ConversionFlag>' needs to have dll-interface to be used by clients of struct 'QTextCodec::ConverterState' // 4800: 'QTextBoundaryFinderPrivate *const ': forcing value to bool 'true' or 'false' (performance warning) // 4244: conversion from 'int' to 'qint8', possible loss of data #include <QtConcurrent/QtConcurrent> +#include <QThreadPool> AZ_POP_DISABLE_WARNING namespace AzToolsFramework @@ -80,7 +82,11 @@ namespace AzToolsFramework if (m_state == State::Unloaded) { m_state = State::Loading; - QFuture<void> future = QtConcurrent::run([this](){ LoadThread(); }); + QThreadPool* threadPool; + ThumbnailContextRequestBus::BroadcastResult( + threadPool, + &ThumbnailContextRequestBus::Handler::GetThreadPool); + QFuture<void> future = QtConcurrent::run(threadPool, [this](){ LoadThread(); }); m_watcher.setFuture(future); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp index 8f6b9c63fd..ae6d7c1178 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.cpp @@ -28,10 +28,15 @@ namespace AzToolsFramework : m_missingThumbnail(new MissingThumbnail(thumbnailSize)) , m_loadingThumbnail(new LoadingThumbnail(thumbnailSize)) , m_thumbnailSize(thumbnailSize) + , m_threadPool(this) { + ThumbnailContextRequestBus::Handler::BusConnect(); } - ThumbnailContext::~ThumbnailContext() = default; + ThumbnailContext::~ThumbnailContext() + { + ThumbnailContextRequestBus::Handler::BusDisconnect(); + } bool ThumbnailContext::IsLoading(SharedThumbnailKey key) { @@ -53,6 +58,11 @@ namespace AzToolsFramework AzToolsFramework::AssetBrowser::AssetBrowserViewRequestBus::Broadcast(&AzToolsFramework::AssetBrowser::AssetBrowserViewRequests::Update); } + QThreadPool* ThumbnailContext::GetThreadPool() + { + return &m_threadPool; + } + SharedThumbnail ThumbnailContext::GetThumbnail(SharedThumbnailKey key) { SharedThumbnail thumbnail; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h index 589abad0df..6ba3d637f6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailContext.h @@ -19,6 +19,7 @@ #include <QObject> #include <QList> +#include <QThreadPool> #endif class QString; @@ -40,6 +41,7 @@ namespace AzToolsFramework */ class ThumbnailContext : public QObject + , public ThumbnailContextRequestBus::Handler { Q_OBJECT public: @@ -58,10 +60,13 @@ namespace AzToolsFramework void UnregisterThumbnailProvider(const char* providerName); void RedrawThumbnail(); - + //! Default context used for most thumbnails static constexpr const char* DefaultContext = "Default"; + // ThumbnailContextRequestBus::Handler interface overrides... + QThreadPool* GetThreadPool() override; + private: struct ProviderCompare { bool operator() (const SharedThumbnailProvider& lhs, const SharedThumbnailProvider& rhs) const @@ -79,6 +84,9 @@ namespace AzToolsFramework SharedThumbnail m_loadingThumbnail; //! Thumbnail size (width and height in pixels) int m_thumbnailSize; + //! There is only a limited number of threads on global threadPool, because there can be many thumbnails rendering at once + //! an individual threadPool is needed to avoid deadlocks + QThreadPool m_threadPool; }; } // namespace Thumbnailer } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp index 1aefa6f189..038bfd5da5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailWidget.cpp @@ -81,6 +81,9 @@ namespace AzToolsFramework int x = (originalWidth - realWidth) / 2; // pixmap needs to be manually scaled to produce smoother result and avoid looking pixelated // using painter.setRenderHint(QPainter::SmoothPixmapTransform); does not seem to work + // Note: there is a potential issue with pixmap.scaled: + // it is multithreaded (using global threadPool) and blocking until finished. + // A deadlock will happen if global threadPool has no free threads available. painter.drawPixmap(QPoint(x, 0), pixmap.scaled(realWidth, realHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } QWidget::paintEvent(event); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h index ebc721bb4c..02264e61f8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h @@ -17,11 +17,23 @@ #include <AzToolsFramework/Thumbnails/Thumbnail.h> class QPixmap; +class QThreadPool; namespace AzToolsFramework { namespace Thumbnailer { + //! Interaction with thumbnail context + class ThumbnailContextRequests + : public AZ::EBusTraits + { + public: + //! Get thread pool for drawing thumbnails + virtual QThreadPool* GetThreadPool() = 0; + }; + + using ThumbnailContextRequestBus = AZ::EBus<ThumbnailContextRequests>; + //! Interaction with thumbnailer class ThumbnailerRequests : public AZ::EBusTraits From 8a8ecf25d6022f8bdf0adeb2151a70a5928d44c6 Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Tue, 20 Apr 2021 21:54:55 -0700 Subject: [PATCH 42/96] Fixed ATOM-15297 StandardPBR_ForwardPass.shadervariantlist Job Fails With Obscure Error ShaderVariantAssetBuilder::ProcessJob was not handling the should-exit-early flag, described at ValidateShaderVariantListLocation(). It was assuming that this flag would be set only during error conditions, which is not the case. I just had to rearrange the logic to handle deferred errors and should-exit-early separately. Testing: The problematic job now finishes successfully. I also edited the shadervariantlist file to give it a bad path to the shader and confirmed that we still get the "Error during CreateJobs" message. --- .../Source/Editor/ShaderVariantAssetBuilder.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp index 1e3c7b6759..ccb984b416 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderVariantAssetBuilder.cpp @@ -405,18 +405,20 @@ namespace AZ void ShaderVariantAssetBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const { const auto& jobParameters = request.m_jobDescription.m_jobParameters; + if (jobParameters.find(ShaderVariantLoadErrorParam) != jobParameters.end()) { - if (jobParameters.find(ShouldExitEarlyFromProcessJobParam) != jobParameters.end()) - { - AZ_TracePrintf(ShaderVariantAssetBuilderName, "Doing nothing on behalf of [%s] because it's been overriden by game project.", jobParameters.at(ShaderVariantLoadErrorParam).c_str()); - response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; - return; - } AZ_Error(ShaderVariantAssetBuilderName, false, "Error during CreateJobs: %s", jobParameters.at(ShaderVariantLoadErrorParam).c_str()); response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed; return; } + + if (jobParameters.find(ShouldExitEarlyFromProcessJobParam) != jobParameters.end()) + { + AZ_TracePrintf(ShaderVariantAssetBuilderName, "Doing nothing on behalf of [%s] because it's been overridden by game project.", jobParameters.at(ShaderVariantLoadErrorParam).c_str()); + response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; + return; + } AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId); if (jobCancelListener.IsCancelled()) From 041f68c238ae74552f36095fb33e7db6f68b6e3e Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 21 Apr 2021 07:54:37 +0200 Subject: [PATCH 43/96] [LYN-2859] EMotionFX: Getting active states from anim graph via script crashes the editor (#150) --- .../Components/AnimGraphComponent.cpp | 30 +++++++-- .../Components/AnimGraphComponent.h | 2 + .../Tests/AnimGraphNetworkingBusTests.cpp | 65 +++++++++++++++++++ .../Code/emotionfx_tests_files.cmake | 1 + 4 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 Gems/EMotionFX/Code/Tests/AnimGraphNetworkingBusTests.cpp diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp index 9dabade61f..7b444d3970 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.cpp @@ -378,18 +378,36 @@ namespace EMotionFX } } + NodeIndexContainer AnimGraphComponent::s_emptyNodeIndexContainer = {}; const NodeIndexContainer& AnimGraphComponent::GetActiveStates() const { - const AZStd::shared_ptr<AnimGraphSnapshot> snapshot = m_animGraphInstance->GetSnapshot(); - AZ_Error("EMotionFX", snapshot, "Call GetActiveStates function but no snapshot is created for this instance."); - return snapshot->GetActiveNodes(); + if (m_animGraphInstance) + { + const AZStd::shared_ptr<AnimGraphSnapshot> snapshot = m_animGraphInstance->GetSnapshot(); + if (snapshot) + { + AZ_Warning("EMotionFX", false, "Call GetActiveStates function but no snapshot is created for this instance."); + return snapshot->GetActiveNodes(); + } + } + + return s_emptyNodeIndexContainer; } + MotionNodePlaytimeContainer AnimGraphComponent::s_emptyMotionNodePlaytimeContainer = {}; const MotionNodePlaytimeContainer& AnimGraphComponent::GetMotionPlaytimes() const { - const AZStd::shared_ptr<AnimGraphSnapshot> snapshot = m_animGraphInstance->GetSnapshot(); - AZ_Error("EMotionFX", snapshot, "Call GetActiveStates function but no snapshot is created for this instance."); - return snapshot->GetMotionNodePlaytimes(); + if (m_animGraphInstance) + { + const AZStd::shared_ptr<AnimGraphSnapshot> snapshot = m_animGraphInstance->GetSnapshot(); + if (snapshot) + { + AZ_Warning("EMotionFX", false, "Call GetActiveStates function but no snapshot is created for this instance."); + return snapshot->GetMotionNodePlaytimes(); + } + } + + return s_emptyMotionNodePlaytimeContainer; } void AnimGraphComponent::UpdateActorExternal(float deltatime) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h index 37e6a57199..db4a2c62b9 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/AnimGraphComponent.h @@ -155,7 +155,9 @@ namespace EMotionFX bool HasSnapshot() const override; void CreateSnapshot(bool isAuthoritative) override; void SetActiveStates(const NodeIndexContainer& activeStates) override; + static NodeIndexContainer s_emptyNodeIndexContainer; const NodeIndexContainer& GetActiveStates() const override; + static MotionNodePlaytimeContainer s_emptyMotionNodePlaytimeContainer; void SetMotionPlaytimes(const MotionNodePlaytimeContainer& motionNodePlaytimes) override; const MotionNodePlaytimeContainer& GetMotionPlaytimes() const override; void UpdateActorExternal(float deltatime) override; diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphNetworkingBusTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphNetworkingBusTests.cpp new file mode 100644 index 0000000000..2c94a9689e --- /dev/null +++ b/Gems/EMotionFX/Code/Tests/AnimGraphNetworkingBusTests.cpp @@ -0,0 +1,65 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ + +#include <AzFramework/Components/TransformComponent.h> +#include <Include/Integration/AnimGraphNetworkingBus.h> +#include <Integration/Components/ActorComponent.h> +#include <Integration/Components/AnimGraphComponent.h> +#include <Tests/Integration/EntityComponentFixture.h> + +namespace EMotionFX +{ + class AnimGraphNetworkingBusTests + : public EntityComponentFixture + { + public: + void SetUp() override + { + EntityComponentFixture::SetUp(); + + m_entity = AZStd::make_unique<AZ::Entity>(); + m_entityId = AZ::EntityId(740216387); + m_entity->SetId(m_entityId); + + m_entity->CreateComponent<AzFramework::TransformComponent>(); + m_entity->CreateComponent<Integration::ActorComponent>(); + auto animGraphComponent = m_entity->CreateComponent<Integration::AnimGraphComponent>(); + + m_entity->Init(); + + m_entity->Activate(); + AnimGraphInstance* animGraphInstance = animGraphComponent->GetAnimGraphInstance(); + EXPECT_EQ(animGraphInstance, nullptr) << "Expecting an invalid anim graph instance as no asset has been set."; + } + + void TearDown() override + { + m_entity->Deactivate(); + EntityComponentFixture::TearDown(); + } + + AZ::EntityId m_entityId; + AZStd::unique_ptr<AZ::Entity> m_entity; + }; + + TEST_F(AnimGraphNetworkingBusTests, AnimGraphNetworkingBus_GetActiveStates_Test) + { + NodeIndexContainer result; + EMotionFX::AnimGraphComponentNetworkRequestBus::EventResult(result, m_entityId, &EMotionFX::AnimGraphComponentNetworkRequestBus::Events::GetActiveStates); + } + + TEST_F(AnimGraphNetworkingBusTests, AnimGraphNetworkingBus_GetMotionPlaytimes_Test) + { + MotionNodePlaytimeContainer result; + EMotionFX::AnimGraphComponentNetworkRequestBus::EventResult(result, m_entityId, &EMotionFX::AnimGraphComponentNetworkRequestBus::Events::GetMotionPlaytimes); + } +} // end namespace EMotionFX diff --git a/Gems/EMotionFX/Code/emotionfx_tests_files.cmake b/Gems/EMotionFX/Code/emotionfx_tests_files.cmake index fff931d98d..7017975a98 100644 --- a/Gems/EMotionFX/Code/emotionfx_tests_files.cmake +++ b/Gems/EMotionFX/Code/emotionfx_tests_files.cmake @@ -22,6 +22,7 @@ set(FILES Tests/AnimGraphActionCommandTests.cpp Tests/AnimGraphActionTests.cpp Tests/AnimGraphComponentBusTests.cpp + Tests/AnimGraphNetworkingBusTests.cpp Tests/AnimGraphCopyPasteTests.cpp Tests/AnimGraphDeferredInitTests.cpp Tests/AnimGraphEventHandlerCounter.h From 8fe1505d1d755f539407af16ff97f8304c593a90 Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Wed, 21 Apr 2021 00:32:41 -0700 Subject: [PATCH 44/96] Fixed up issues with my prior occlusion changes, after merging latest main, got everything working again. ATOM-14040 Add Support for Cavity Maps --- .../Assets/Materials/Types/StandardPBR_ForwardPass.azsl | 5 ++--- .../Atom/Features/PBR/Lighting/LightingData.azsli | 8 ++++++-- .../Atom/Features/PBR/Lighting/StandardLighting.azsli | 7 ++----- .../ShaderLib/Atom/Features/PBR/LightingModel.azsli | 3 ++- .../Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index fe465faec5..c08dc53c6a 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -213,9 +213,8 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float // ------- Occlusion ------- - float diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); - float specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); - + lightingData.diffuseAmbientOcclusion = GetOcclusionInput(MaterialSrg::m_diffuseOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_diffuseOcclusionMapUvIndex], MaterialSrg::m_diffuseOcclusionFactor, o_diffuseOcclusion_useTexture); + lightingData.specularOcclusion = GetOcclusionInput(MaterialSrg::m_specularOcclusionMap, MaterialSrg::m_sampler, IN.m_uv[MaterialSrg::m_specularOcclusionMapUvIndex], MaterialSrg::m_specularOcclusionFactor, o_specularOcclusion_useTexture); // ------- Clearcoat ------- diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli index aa5fa05bcf..37cae0acb1 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/LightingData.azsli @@ -47,8 +47,10 @@ class LightingData // Normal . View float NdotV; + // Occlusion factors // 0 = dark, 1 = light - float occlusion; + float diffuseAmbientOcclusion; + float specularOcclusion; void Init(float3 positionWS, float3 normal, float roughnessLinear); void CalculateMultiscatterCompensation(float3 specularF0, bool enabled); @@ -62,7 +64,8 @@ void LightingData::Init(float3 positionWS, float3 normal, float roughnessLinear) translucentBackLighting = 0; multiScatterCompensation = 1.0f; emissiveLighting = float3(0.0f, 0.0f, 0.0f); - occlusion = 1.0f; + diffuseAmbientOcclusion = 1.0f; + specularOcclusion = 1.0f; dirToCamera = normalize(ViewSrg::m_worldPosition.xyz - positionWS); @@ -79,6 +82,7 @@ void LightingData::CalculateMultiscatterCompensation(float3 specularF0, bool ena void LightingData::FinalizeLighting(float3 transmissionTint) { + specularLighting *= specularOcclusion; specularLighting += emissiveLighting; // Transmitted light diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli index 31fbbd2138..d0fb78a6d5 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lighting/StandardLighting.azsli @@ -45,8 +45,8 @@ PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingDat // albedo, specularF0, roughness, and normals for later passes (specular IBL, Diffuse GI, SSR, AO, etc) lightingOutput.m_specularF0 = float4(surface.specularF0, surface.roughnessLinear); - lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse; - lightingOutput.m_albedo.a = lightingData.occlusion; + lightingOutput.m_albedo.rgb = surface.albedo * lightingData.diffuseResponse * lightingData.diffuseAmbientOcclusion; + lightingOutput.m_albedo.a = lightingData.specularOcclusion; lightingOutput.m_normal.rgb = EncodeNormalSignedOctahedron(surface.normal); lightingOutput.m_normal.a = o_specularF0_enableMultiScatterCompensation ? 1.0f : 0.0f; @@ -58,6 +58,3 @@ PbrLightingOutput GetPbrLightingOutput(Surface surface, LightingData lightingDat - - - diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli index 5bdefca637..a3a9c9ffd1 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingModel.azsli @@ -109,7 +109,8 @@ PbrLightingOutput PbrLighting( VSOutput IN, lightingData.Init(surface.position, surface.normal, surface.roughnessLinear); lightingData.emissiveLighting = emissive; - lightingData.occlusion = occlusion; + lightingData.diffuseAmbientOcclusion = diffuseAmbientOcclusion; + lightingData.specularOcclusion = specularOcclusion; // Directional light shadow coordinates lightingData.shadowCoords = shadowCoords; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index f08acd2684..bbb6a33b55 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -76,7 +76,7 @@ void ApplyIBL(Surface surface, inout LightingData lightingData) // Adjust IBL lighting by exposure. float iblExposureFactor = pow(2.0, SceneSrg::m_iblExposure); - lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.occlusion); + lightingData.diffuseLighting += (iblDiffuse * iblExposureFactor * lightingData.diffuseAmbientOcclusion); lightingData.specularLighting += (iblSpecular * iblExposureFactor); } } From b95865b2d856f55f741eab9e8d310b7992e0e002 Mon Sep 17 00:00:00 2001 From: Tommy Walton <82672795+amzn-tommy@users.noreply.github.com> Date: Wed, 21 Apr 2021 00:37:51 -0700 Subject: [PATCH 45/96] Simple Motion component doesn't animate actors (#179) Buffers that have InputAssembly bind flags but also have ShaderRead flags should create buffer views --- Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp index afcf4670f3..470b66c28e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Buffer/Buffer.cpp @@ -205,7 +205,8 @@ namespace AZ void Buffer::InitBufferView() { // Skip buffer view creation for input assembly buffers - if(RHI::CheckBitsAny(m_rhiBuffer->GetDescriptor().m_bindFlags, RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly)) + if (m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::InputAssembly || + m_rhiBuffer->GetDescriptor().m_bindFlags == RHI::BufferBindFlags::DynamicInputAssembly) { return; } From 496891b4c05686879a883619a8ccf54a49d5b275 Mon Sep 17 00:00:00 2001 From: greerdv <greerdv@amazon.com> Date: Wed, 21 Apr 2021 10:55:05 +0100 Subject: [PATCH 46/96] feedback from PR --- .../Include/Atom/RHI/RayTracingAccelerationStructure.h | 2 +- Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp | 8 +++++--- .../Code/Source/Mesh/MeshComponentController.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index 317094e24c..5fde518cb2 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -12,7 +12,7 @@ #pragma once #include <AzCore/std/containers/vector.h> -#include <AzCore/Math/Matrix3x4.h> +#include <AzCore/Math/Transform.h> #include <Atom/RHI/IndexBufferView.h> #include <Atom/RHI/StreamBufferView.h> #include <Atom/RHI.Reflect/Format.h> diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp index 46059a3132..15c8aaf528 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Model/Model.cpp @@ -167,16 +167,18 @@ namespace AZ bool Model::RayIntersection(const AZ::Transform& modelTransform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& rayStart, const AZ::Vector3& dir, float& distanceFactor, AZ::Vector3& normal) const { AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); + const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale)); + const AZ::Transform inverseTM = modelTransform.GetInverse(); - const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / nonUniformScale; + const AZ::Vector3 raySrcLocal = inverseTM.TransformPoint(rayStart) / clampedScale; // Instead of just rotating 'dir' we need it to be scaled too, so that 'distanceFactor' will be in the target units rather than object local units. const AZ::Vector3 rayDest = rayStart + dir; - const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / nonUniformScale; + const AZ::Vector3 rayDestLocal = inverseTM.TransformPoint(rayDest) / clampedScale; const AZ::Vector3 rayDirLocal = rayDestLocal - raySrcLocal; bool result = LocalRayIntersection(raySrcLocal, rayDirLocal, distanceFactor, normal); - normal = (normal * nonUniformScale).GetNormalized(); + normal = (normal * clampedScale).GetNormalized(); return result; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index c99ca7b848..b0315fdf9c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -232,7 +232,7 @@ namespace AZ return m_configuration; } - void MeshComponentController::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, [[maybe_unused]] const AZ::Transform& world) + void MeshComponentController::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world) { if (m_meshFeatureProcessor) { From 7ac246bab50f388fe644c7af6e08915a710e836f Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Thu, 15 Apr 2021 12:00:09 +0100 Subject: [PATCH 47/96] Character controller now uses Add/Remove Simulated Body --- .../AzFramework/Physics/Character.h | 28 +++--- .../SimulatedBodyConfiguration.h | 2 +- .../AzFramework/Physics/SystemBus.h | 20 ---- .../API/CharacterController.cpp | 11 ++- .../PhysXCharacters/API/CharacterUtils.cpp | 95 +++++++++---------- .../PhysXCharacters/API/CharacterUtils.h | 8 +- .../CharacterControllerComponent.cpp | 67 ++++++------- .../Components/CharacterControllerComponent.h | 8 +- Gems/PhysX/Code/Source/Scene/PhysXScene.cpp | 74 ++++++++++----- Gems/PhysX/Code/Source/Scene/PhysXScene.h | 2 - Gems/PhysX/Code/Source/SystemComponent.cpp | 9 -- Gems/PhysX/Code/Source/SystemComponent.h | 5 - .../Benchmarks/PhysXCharactersBenchmarks.cpp | 45 +++++---- 13 files changed, 186 insertions(+), 188 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Character.h b/Code/Framework/AzFramework/AzFramework/Physics/Character.h index c43c6de9e8..d6f67706f4 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Character.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Character.h @@ -28,7 +28,7 @@ namespace Physics class CharacterColliderNodeConfiguration { public: - AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}"); + AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}"); AZ_CLASS_ALLOCATOR_DECL virtual ~CharacterColliderNodeConfiguration() = default; @@ -42,7 +42,7 @@ namespace Physics class CharacterColliderConfiguration { public: - AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}"); + AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}"); AZ_CLASS_ALLOCATOR_DECL virtual ~CharacterColliderConfiguration() = default; @@ -63,21 +63,23 @@ namespace Physics { public: AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0); - AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration); + AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration); virtual ~CharacterConfiguration() = default; static void Reflect(AZ::ReflectContext* context); - AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with. - AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on. - MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character. - AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior. - float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees. - float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb. - float m_minimumMovementDistance = 0.001f; ///< To avoid jittering, the controller will not attempt to move distances below this. - float m_maximumSpeed = 100.0f; ///< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped. - AZStd::string m_colliderTag; ///< Used to identify the collider associated with the character controller. + AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with. + AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on. + MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character. + AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior. + float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees. + float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb. + float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this. + float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped. + AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller. + AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller. + AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller. }; /// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready @@ -88,7 +90,7 @@ namespace Physics { public: AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0); - AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody); + AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody); ~Character() override = default; diff --git a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h index 47b05089de..203590adbb 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h @@ -29,7 +29,7 @@ namespace AzPhysics struct SimulatedBodyConfiguration { AZ_CLASS_ALLOCATOR_DECL; - AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}"); + AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}"); static void Reflect(AZ::ReflectContext* context); SimulatedBodyConfiguration() = default; diff --git a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h index 717f9e023c..f198551148 100644 --- a/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h +++ b/Code/Framework/AzFramework/AzFramework/Physics/SystemBus.h @@ -246,26 +246,6 @@ namespace Physics using SystemRequests = System; using SystemRequestBus = AZ::EBus<SystemRequests, SystemRequestsTraits>; - /// Physics character system global requests. - class CharacterSystemRequests - : public AZ::EBusTraits - { - public: - // EBusTraits - // singleton pattern - static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; - static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; - - virtual ~CharacterSystemRequests() = default; - - /// Creates the physics representation used to handle basic character interactions (also known as a character - /// controller). - virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig, - const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0; - }; - - typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus; - /// Physics system global debug requests. class SystemDebugRequests : public AZ::EBusTraits diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp index dba069ac29..9e5f92aa72 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterController.cpp @@ -311,7 +311,10 @@ namespace PhysX CreateShadowBody(configuration); SetTag(configuration.m_colliderTag); - m_simulating = true; + if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get()) + { + sceneInterface->EnableSimulationOfBody(m_sceneOwner, m_bodyHandle); + } } void CharacterController::DisablePhysics() @@ -323,7 +326,11 @@ namespace PhysX DestroyShadowBody(); RemoveControllerFromScene(); - m_simulating = false; + + if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get()) + { + sceneInterface->DisableSimulationOfBody(m_sceneOwner, m_bodyHandle); + } } void CharacterController::DestroyShadowBody() diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp index 2761980d1b..6523238430 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.cpp @@ -96,25 +96,17 @@ namespace PhysX } } - AZStd::unique_ptr<CharacterController> CreateCharacterController(const Physics::CharacterConfiguration& characterConfig, - const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle) + CharacterController* CreateCharacterController(PhysXScene* scene, + const Physics::CharacterConfiguration& characterConfig) { - physx::PxControllerManager* manager = nullptr; - AzPhysics::Scene* scene = nullptr; - PhysX::PhysXScene* physxScene = nullptr; - if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get()) + if (scene == nullptr) { - scene = physicsSystem->GetScene(sceneHandle); - if (scene) - { - physxScene = azrtti_cast<PhysX::PhysXScene*>(scene); - if (physxScene) - { - manager = physxScene->GetOrCreateControllerManager(); - } - } + AZ_Error("PhysX Character Controller", false, "Failed to create character controller as the scene is null"); + return nullptr; } - if (!manager || !scene) + + physx::PxControllerManager* manager = scene->GetOrCreateControllerManager(); + if (manager == nullptr) { AZ_Error("PhysX Character Controller", false, "Could not retrieve character controller manager."); return nullptr; @@ -123,41 +115,47 @@ namespace PhysX auto callbackManager = AZStd::make_unique<CharacterControllerCallbackManager>(); physx::PxController* pxController = nullptr; - auto* pxScene = static_cast<physx::PxScene*>(physxScene->GetNativePointer()); + auto* pxScene = static_cast<physx::PxScene*>(scene->GetNativePointer()); - if (shapeConfig.GetShapeType() == Physics::ShapeType::Capsule) + switch (characterConfig.m_shapeConfig->GetShapeType()) { - physx::PxCapsuleControllerDesc capsuleDesc; - - const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast<const Physics::CapsuleShapeConfiguration&>(shapeConfig); - // LY height means total height, PhysX means height of straight section - capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius); - capsuleDesc.radius = capsuleConfig.m_radius; - capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED; - - AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get()); - AppendPhysXSpecificProperties(capsuleDesc, characterConfig); - PHYSX_SCENE_WRITE_LOCK(pxScene); - pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene - } - else if (shapeConfig.GetShapeType() == Physics::ShapeType::Box) - { - physx::PxBoxControllerDesc boxDesc; + case Physics::ShapeType::Capsule: + { + physx::PxCapsuleControllerDesc capsuleDesc; + + const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast<const Physics::CapsuleShapeConfiguration&>(*characterConfig.m_shapeConfig); + // LY height means total height, PhysX means height of straight section + capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius); + capsuleDesc.radius = capsuleConfig.m_radius; + capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED; + + AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get()); + AppendPhysXSpecificProperties(capsuleDesc, characterConfig); + PHYSX_SCENE_WRITE_LOCK(pxScene); + pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene + } + break; + case Physics::ShapeType::Box: + { + physx::PxBoxControllerDesc boxDesc; - const Physics::BoxShapeConfiguration& boxConfig = static_cast<const Physics::BoxShapeConfiguration&>(shapeConfig); - boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ(); - boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY(); - boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX(); + const Physics::BoxShapeConfiguration& boxConfig = static_cast<const Physics::BoxShapeConfiguration&>(*characterConfig.m_shapeConfig); + boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ(); + boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY(); + boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX(); - AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get()); - AppendPhysXSpecificProperties(boxDesc, characterConfig); - PHYSX_SCENE_WRITE_LOCK(pxScene); - pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene - } - else - { - AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers."); - return nullptr; + AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get()); + AppendPhysXSpecificProperties(boxDesc, characterConfig); + PHYSX_SCENE_WRITE_LOCK(pxScene); + pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene + } + break; + default: + { + AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers."); + return nullptr; + } + break; } if (!pxController) @@ -166,8 +164,7 @@ namespace PhysX return nullptr; } - auto controller = AZStd::make_unique<CharacterController>(pxController, AZStd::move(callbackManager), sceneHandle); - return controller; + return aznew CharacterController(pxController, AZStd::move(callbackManager), scene->GetSceneHandle()); } AZStd::unique_ptr<Ragdoll> CreateRagdoll(Physics::RagdollConfiguration& configuration, diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h index 6eb10bd4eb..07aa4008d3 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/API/CharacterUtils.h @@ -25,6 +25,7 @@ namespace Physics namespace PhysX { class CharacterController; + class PhysXScene; namespace Utils { @@ -33,10 +34,9 @@ namespace PhysX AZ::Outcome<size_t> GetNodeIndex(const Physics::RagdollConfiguration& configuration, const AZStd::string& nodeName); //! Creates a character controller based on the supplied configuration in the specified world. - //! @param configuration Information required to create the controller such as shape, slope behavior etc. - //! @param sceneHandle A handle to the physics scene in which the character controller should be created. - AZStd::unique_ptr<CharacterController> CreateCharacterController(const Physics::CharacterConfiguration& - characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle); + //! @param scene The scene to add the character controller to. + //! @param characterConfig Information required to create the controller such as shape, slope behavior etc. + CharacterController* CreateCharacterController(PhysXScene* scene, const Physics::CharacterConfiguration& characterConfig); //! Creates a ragdoll based on the specified setup and initial pose. //! @param configuration Information about collider geometry and joint setup required to initialize the ragdoll. diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp index bd12b68ca3..26ef5f0032 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.cpp @@ -67,7 +67,7 @@ namespace PhysX CharacterControllerComponent::CharacterControllerComponent() = default; CharacterControllerComponent::CharacterControllerComponent(AZStd::unique_ptr<Physics::CharacterConfiguration> characterConfig, - AZStd::unique_ptr<Physics::ShapeConfiguration> shapeConfig) + AZStd::shared_ptr<Physics::ShapeConfiguration> shapeConfig) : m_characterConfig(AZStd::move(characterConfig)) , m_shapeConfig(AZStd::move(shapeConfig)) { @@ -188,7 +188,7 @@ namespace PhysX Physics::Character* CharacterControllerComponent::GetCharacter() { - return m_controller.get(); + return m_controller; } void CharacterControllerComponent::EnablePhysics() @@ -217,7 +217,7 @@ namespace PhysX AzPhysics::SimulatedBody* CharacterControllerComponent::GetWorldBody() { - return m_controller.get(); + return GetCharacter(); } AzPhysics::SceneQueryHit CharacterControllerComponent::RayCast(const AzPhysics::RayCastRequest& request) @@ -382,7 +382,7 @@ namespace PhysX void CharacterControllerComponent::CreateController() { - if (m_controller) + if (IsPhysicsEnabled()) { return; } @@ -397,22 +397,33 @@ namespace PhysX m_characterConfig->m_debugName = GetEntity()->GetName(); m_characterConfig->m_entityId = GetEntityId(); + m_characterConfig->m_shapeConfig = m_shapeConfig; + // get all the collider shapes and add it to the config + PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [this](PhysX::ColliderComponentRequests* handler) + { + auto shapes = handler->GetShapes(); + m_characterConfig->m_colliders.insert(m_characterConfig->m_colliders.end(), shapes.begin(), shapes.end()); + return true; + }); - m_controller = Utils::Characters::CreateCharacterController(*m_characterConfig, *m_shapeConfig, defaultSceneHandle); - if (!m_controller) + // It's usually more convenient to control the foot position rather than the centre of the capsule, so + // make the foot position coincide with the entity position. + AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero(); + AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + m_characterConfig->m_position = entityTranslation; + + AZ_Assert(m_controller == nullptr, "Calling create CharacterControllerComponent::CreateController() with an already created controller."); + if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get()) + { + AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, m_characterConfig.get()); + m_controller = azdynamic_cast<PhysX::CharacterController*>(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle)); + } + if (m_controller == nullptr) { AZ_Error("PhysX Character Controller Component", false, "Failed to create character controller."); return; } - m_controller->EnablePhysics(*m_characterConfig); - - AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero(); - AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); - // It's usually more convenient to control the foot position rather than the centre of the capsule, so - // make the foot position coincide with the entity position. - m_controller->SetBasePosition(entityTranslation); - AttachColliders(*m_controller); - + CharacterControllerRequestBus::Handler::BusConnect(GetEntityId()); m_preSimulateHandler = AzPhysics::SystemEvents::OnPresimulateEvent::Handler( @@ -426,26 +437,21 @@ namespace PhysX { physXSystem->RegisterPreSimulateEvent(m_preSimulateHandler); } - - Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsEnabled); } void CharacterControllerComponent::DestroyController() { - if (!m_controller) + if (!IsPhysicsEnabled()) { return; } m_controller->DisablePhysics(); - // The character is first removed from the scene, and then its deletion is deferred. - // This ensures trigger exit events are raised correctly on deleted objects. + if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get()) { - auto* scene = azdynamic_cast<PhysX::PhysXScene*>(m_controller->GetScene()); - AZ_Assert(scene, "Invalid PhysX scene"); - scene->DeferDelete(AZStd::move(m_controller)); - m_controller.reset(); + sceneInterface->RemoveSimulatedBody(m_controller->m_sceneOwner, m_controller->m_bodyHandle); + m_controller = nullptr; } m_preSimulateHandler.Disconnect(); @@ -454,17 +460,4 @@ namespace PhysX Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsDisabled); } - - void CharacterControllerComponent::AttachColliders(Physics::Character& character) - { - PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [&character](PhysX::ColliderComponentRequests* handler) - { - for (auto& shape : handler->GetShapes()) - { - character.AttachShape(shape); - } - return true; - }); - } - } // namespace PhysX diff --git a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h index 42ac5d4cce..ca956b1757 100644 --- a/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h +++ b/Gems/PhysX/Code/Source/PhysXCharacters/Components/CharacterControllerComponent.h @@ -47,7 +47,7 @@ namespace PhysX CharacterControllerComponent(); CharacterControllerComponent(AZStd::unique_ptr<Physics::CharacterConfiguration> characterConfig, - AZStd::unique_ptr<Physics::ShapeConfiguration> shapeConfig); + AZStd::shared_ptr<Physics::ShapeConfiguration> shapeConfig); ~CharacterControllerComponent(); static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) @@ -131,12 +131,12 @@ namespace PhysX private: void CreateController(); void DestroyController(); - void AttachColliders(Physics::Character& character); + void OnPreSimulate(float deltaTime); AZStd::unique_ptr<Physics::CharacterConfiguration> m_characterConfig; - AZStd::unique_ptr<Physics::ShapeConfiguration> m_shapeConfig; - AZStd::unique_ptr<PhysX::CharacterController> m_controller; + AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig; + PhysX::CharacterController* m_controller = nullptr; AzPhysics::SystemEvents::OnPresimulateEvent::Handler m_preSimulateHandler; }; } // namespace PhysX diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp index 28c8cc327b..1e6eee774e 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.cpp @@ -16,6 +16,7 @@ #include <AzCore/Debug/ProfilerBus.h> #include <AzCore/std/containers/variant.h> #include <AzCore/std/containers/vector.h> +#include <AzFramework/Physics/Character.h> #include <AzFramework/Physics/Collision/CollisionEvents.h> #include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h> #include <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h> @@ -27,6 +28,8 @@ #include <Common/PhysXSceneQueryHelpers.h> #include <PhysX/PhysXLocks.h> #include <PhysX/Utils.h> +#include <PhysXCharacters/API/CharacterController.h> +#include <PhysXCharacters/API/CharacterUtils.h> #include <System/PhysXSystem.h> namespace PhysX @@ -186,6 +189,26 @@ namespace PhysX return newBody; } + AzPhysics::SimulatedBody* CreateCharacterBody(PhysXScene* scene, + const Physics::CharacterConfiguration* characterConfig) + { + CharacterController* controller = Utils::Characters::CreateCharacterController(scene, *characterConfig); + if (controller == nullptr) + { + AZ_Error("PhysXScene", false, "Failed to create character controller."); + return nullptr; + } + controller->EnablePhysics(*characterConfig); + controller->SetBasePosition(characterConfig->m_position); + + for (auto shape : characterConfig->m_colliders) + { + controller->AttachShape(shape); + } + + return controller; + } + //helper to perform a ray cast AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest* raycastRequest, AZStd::vector<physx::PxRaycastHit>& raycastBuffer, @@ -595,6 +618,10 @@ namespace PhysX newBody = Internal::CreateSimulatedBody<StaticRigidBody, AzPhysics::StaticRigidBodyConfiguration>( azdynamic_cast<const AzPhysics::StaticRigidBodyConfiguration*>(simulatedBodyConfig), newBodyCrc); } + else if (azrtti_istypeof<Physics::CharacterConfiguration>(simulatedBodyConfig)) + { + newBody = Internal::CreateCharacterBody(this, azdynamic_cast<const Physics::CharacterConfiguration*>(simulatedBodyConfig)); + } if (newBody != nullptr) { @@ -850,20 +877,24 @@ namespace PhysX void PhysXScene::EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body) { - auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer()); - AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - + //character controller is a special actor and only needs the m_simulating flag set, + if (!azrtti_istypeof<PhysX::CharacterController>(body)) { - PHYSX_SCENE_WRITE_LOCK(m_pxScene); - m_pxScene->addActor(*pxActor); - } + auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer()); + AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - if (azrtti_istypeof<PhysX::RigidBody>(body)) - { - auto rigidBody = azdynamic_cast<PhysX::RigidBody*>(&body); - if (rigidBody->ShouldStartAsleep()) { - rigidBody->ForceAsleep(); + PHYSX_SCENE_WRITE_LOCK(m_pxScene); + m_pxScene->addActor(*pxActor); + } + + if (azrtti_istypeof<PhysX::RigidBody>(body)) + { + auto rigidBody = azdynamic_cast<PhysX::RigidBody*>(&body); + if (rigidBody->ShouldStartAsleep()) + { + rigidBody->ForceAsleep(); + } } } @@ -872,14 +903,17 @@ namespace PhysX void PhysXScene::DisableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body) { - auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer()); - AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); - + //character controller is a special actor and only needs the m_simulating flag set, + if (!azrtti_istypeof<PhysX::CharacterController>(body)) { - PHYSX_SCENE_WRITE_LOCK(m_pxScene); - m_pxScene->removeActor(*pxActor); - } + auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer()); + AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor"); + { + PHYSX_SCENE_WRITE_LOCK(m_pxScene); + m_pxScene->removeActor(*pxActor); + } + } body.m_simulating = false; } @@ -907,11 +941,6 @@ namespace PhysX return m_controllerManager; } - void PhysXScene::DeferDelete(AZStd::unique_ptr<AzPhysics::SimulatedBody> worldBody) - { - m_deferredDeletions_uniquePtrs.push_back(AZStd::move(worldBody)); - } - void* PhysXScene::GetNativePointer() const { return m_pxScene; @@ -924,7 +953,6 @@ namespace PhysX delete simulatedBody; } m_deferredDeletions.clear(); - m_deferredDeletions_uniquePtrs.clear(); } void PhysXScene::ProcessTriggerEvents() diff --git a/Gems/PhysX/Code/Source/Scene/PhysXScene.h b/Gems/PhysX/Code/Source/Scene/PhysXScene.h index ec708cee9e..8bf20fca55 100644 --- a/Gems/PhysX/Code/Source/Scene/PhysXScene.h +++ b/Gems/PhysX/Code/Source/Scene/PhysXScene.h @@ -73,7 +73,6 @@ namespace PhysX void* GetNativePointer() const override; physx::PxControllerManager* GetOrCreateControllerManager(); - void DeferDelete(AZStd::unique_ptr<AzPhysics::SimulatedBody> worldBody); private: void EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body); @@ -93,7 +92,6 @@ namespace PhysX AZStd::vector<AZStd::pair<AZ::Crc32, AzPhysics::SimulatedBody*>> m_simulatedBodies; //this will become a SimulatedBody with LYN-1334 AZStd::vector<AzPhysics::SimulatedBody*> m_deferredDeletions; - AZStd::vector<AZStd::unique_ptr<AzPhysics::SimulatedBody>> m_deferredDeletions_uniquePtrs; // this is to support Character as it stores itself in a unique pointer currently. AZStd::queue<AzPhysics::SimulatedBodyIndex> m_freeSceneSlots; AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physicsSystemConfigChanged; diff --git a/Gems/PhysX/Code/Source/SystemComponent.cpp b/Gems/PhysX/Code/Source/SystemComponent.cpp index 8210492fe7..9ef4dc5099 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.cpp +++ b/Gems/PhysX/Code/Source/SystemComponent.cpp @@ -211,7 +211,6 @@ namespace PhysX Physics::SystemRequestBus::Handler::BusConnect(); PhysX::SystemRequestsBus::Handler::BusConnect(); Physics::CollisionRequestBus::Handler::BusConnect(); - Physics::CharacterSystemRequestBus::Handler::BusConnect(); ActivatePhysXSystem(); } @@ -219,7 +218,6 @@ namespace PhysX void SystemComponent::Deactivate() { AZ::TickBus::Handler::BusDisconnect(); - Physics::CharacterSystemRequestBus::Handler::BusDisconnect(); Physics::CollisionRequestBus::Handler::BusDisconnect(); PhysX::SystemRequestsBus::Handler::BusDisconnect(); Physics::SystemRequestBus::Handler::BusDisconnect(); @@ -421,13 +419,6 @@ namespace PhysX } } - // Physics::CharacterSystemRequestBus - AZStd::unique_ptr<Physics::Character> SystemComponent::CreateCharacter(const Physics::CharacterConfiguration& - characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) - { - return Utils::Characters::CreateCharacterController(characterConfig, shapeConfig, sceneHandle); - } - AzPhysics::CollisionLayer SystemComponent::GetCollisionLayerByName(const AZStd::string& layerName) { return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.GetLayer(layerName); diff --git a/Gems/PhysX/Code/Source/SystemComponent.h b/Gems/PhysX/Code/Source/SystemComponent.h index 8c4ac0d836..8871adfeeb 100644 --- a/Gems/PhysX/Code/Source/SystemComponent.h +++ b/Gems/PhysX/Code/Source/SystemComponent.h @@ -57,7 +57,6 @@ namespace PhysX : public AZ::Component , public Physics::SystemRequestBus::Handler , public PhysX::SystemRequestsBus::Handler - , public Physics::CharacterSystemRequestBus::Handler , private Physics::CollisionRequestBus::Handler , private AZ::TickBus::Handler { @@ -96,10 +95,6 @@ namespace PhysX physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override; physx::PxCooking* GetCooking() override; - // Physics::CharacterSystemRequestBus - virtual AZStd::unique_ptr<Physics::Character> CreateCharacter(const Physics::CharacterConfiguration& characterConfig, - const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) override; - // CollisionRequestBus AzPhysics::CollisionLayer GetCollisionLayerByName(const AZStd::string& layerName) override; AZStd::string GetCollisionLayerName(const AzPhysics::CollisionLayer& layer) override; diff --git a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp index 892d7b2da0..c7b9bd5623 100644 --- a/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp +++ b/Gems/PhysX/Code/Tests/Benchmarks/PhysXCharactersBenchmarks.cpp @@ -130,7 +130,9 @@ namespace PhysX::Benchmarks //! @param colliderType, the collider type to use //! @param scene, the scene to spawn the characters controller into //! @param genSpawnPosFuncPtr - [optional] function pointer to allow caller to pick the spawn position - AZStd::vector<AZStd::unique_ptr<Physics::Character>> CreateCharacterControllers(int numCharacterControllers, CharacterConstants::CharacterSettings::ColliderType colliderType, + AZStd::vector<Physics::Character*> CreateCharacterControllers( + int numCharacterControllers, + CharacterConstants::CharacterSettings::ColliderType colliderType, AzPhysics::SceneHandle& sceneHandle, GenerateSpawnPositionFuncPtr* genSpawnPosFuncPtr = nullptr) { @@ -139,12 +141,11 @@ namespace PhysX::Benchmarks characterConfig.m_maximumSlopeAngle = CharacterConstants::CharacterSettings::MaximumSlopeAngle; characterConfig.m_stepHeight = CharacterConstants::CharacterSettings::StepHeight; - Physics::ShapeConfiguration* shapeConfig = nullptr; switch (colliderType) { case CharacterConstants::CharacterSettings::ColliderType::Box: { - shapeConfig = new Physics::BoxShapeConfiguration( + characterConfig.m_shapeConfig = AZStd::make_shared<Physics::BoxShapeConfiguration>( AZ::Vector3(CharacterConstants::CharacterSettings::CharacterBoxWidth, CharacterConstants::CharacterSettings::CharacterBoxDepth, CharacterConstants::CharacterSettings::CharacterBoxHeight) @@ -155,26 +156,32 @@ namespace PhysX::Benchmarks case CharacterConstants::CharacterSettings::ColliderType::Capsule: default: { - shapeConfig = new Physics::CapsuleShapeConfiguration(CharacterConstants::CharacterSettings::CharacterCylinderHeight, + characterConfig.m_shapeConfig = AZStd::make_shared<Physics::CapsuleShapeConfiguration>( + CharacterConstants::CharacterSettings::CharacterCylinderHeight, CharacterConstants::CharacterSettings::CharacterCylinderRadius); } break; } - AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers; + auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get(); + + AZStd::vector<Physics::Character*> controllers; controllers.reserve(numCharacterControllers); for (int i = 0; i < numCharacterControllers; i++) { - AZStd::unique_ptr<Physics::Character> controller; - Physics::CharacterSystemRequestBus::BroadcastResult(controller, - &Physics::CharacterSystemRequests::CreateCharacter, characterConfig, *shapeConfig, sceneHandle); - - const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero(); - controller->SetBasePosition(spawnPosition); - - controllers.emplace_back(AZStd::move(controller)); + const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero(); + characterConfig.m_position = spawnPosition; + AzPhysics::SimulatedBodyHandle newHandle = sceneInterface->AddSimulatedBody(sceneHandle, &characterConfig); + if (newHandle != AzPhysics::InvalidSimulatedBodyHandle) + { + if (auto* characterPtr = azdynamic_cast<Physics::Character*>( + sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, newHandle) + )) + { + controllers.emplace_back(characterPtr); + } + } } - delete shapeConfig; return controllers; } @@ -206,7 +213,7 @@ namespace PhysX::Benchmarks } return AZ::Vector3(x, y, z); }; - AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters, static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator); //setup the sub tick tracker @@ -262,7 +269,7 @@ namespace PhysX::Benchmarks } return AZ::Vector3(x, y, z); }; - AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters, static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator); //setup the sub tick tracker @@ -320,15 +327,15 @@ namespace PhysX::Benchmarks const float z = 0.0f; return AZ::Vector3(x, y, z); }; - AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters, + AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters, static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator); //pair up each character controller with a movement vector - using ControllerAndMovementDirPair = AZStd::pair<AZStd::unique_ptr<Physics::Character>, AZ::Vector3>; + using ControllerAndMovementDirPair = AZStd::pair<Physics::Character*, AZ::Vector3>; AZStd::vector<ControllerAndMovementDirPair> targetMoveAndControllers; for (auto& controller : controllers) { - targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(AZStd::move(controller), AZ::Vector3::CreateZero())); + targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(controller, AZ::Vector3::CreateZero())); } //setup the sub tick tracker From 8c3b52890524d2d104b82974c0084dfbac8b56d9 Mon Sep 17 00:00:00 2001 From: Ulugbek Adilbekov <adilbekov.ulugbek@gmail.com> Date: Wed, 21 Apr 2021 12:27:23 +0100 Subject: [PATCH 48/96] Re-reenable blast tests (#160) Co-authored-by: Ulugbek Adilbekov <ulugbek@amazon.com> --- AutomatedTesting/Gem/PythonTests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index c527aea98c..c23d92d60a 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -157,7 +157,7 @@ endif() if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_add_pytest( NAME AutomatedTesting::BlastTests - TEST_SUITE sandbox + TEST_SUITE periodic TEST_SERIAL TRUE PATH ${CMAKE_CURRENT_LIST_DIR}/Blast/TestSuite_Active.py TIMEOUT 3600 From 374f690b5dbed56590339013e560d17c86e7cf69 Mon Sep 17 00:00:00 2001 From: pereslav <pereslav@amazon.com> Date: Wed, 21 Apr 2021 13:34:44 +0100 Subject: [PATCH 49/96] tabs/whitespace fixes --- Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp | 2 +- .../Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp index 4c57924eb4..5a223d6214 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerToolsModule.cpp @@ -49,7 +49,7 @@ namespace Multiplayer : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { - MultiplayerToolsSystemComponent::CreateDescriptor(), + MultiplayerToolsSystemComponent::CreateDescriptor(), }); } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp index ad2e18e222..ebf5d2609b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkSpawnableLibrary.cpp @@ -46,7 +46,6 @@ namespace Multiplayer const AZ::Name name = AZ::Name(relativePath); m_spawnables[name] = id; m_spawnablesReverseLookup[id] = name; - } void NetworkSpawnableLibrary::OnCatalogLoaded([[maybe_unused]] const char* catalogFile) From 5524668f619eb9c7360f93e7b0db01649efdf24a Mon Sep 17 00:00:00 2001 From: Aaron Ruiz Mora <moraaar@amazon.com> Date: Wed, 21 Apr 2021 15:35:53 +0100 Subject: [PATCH 50/96] Updating O3DE to use 3rdParty PhysX package rev2 on iOS (#189) --- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index d7b4dc650d..7ef0b3b329 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) -ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-ios TARGETS PhysX PACKAGE_HASH a2a48a09128337c72b9c2c1b8f43187c6c914e8509c9c6cd91810108748d7e09) +ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev2-ios TARGETS PhysX PACKAGE_HASH 27e68bd90915dbd0bd5f26cae714e9a137f6b1aa8a8e0bf354a4a9176aa553d5) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googletest PACKAGE_HASH 2f121ad9784c0ab73dfaa58e1fee05440a82a07cc556bec162eeb407688111a7) ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-ios TARGETS GoogleBenchmark PACKAGE_HASH c2ffaed2b658892b1bcf81dee4b44cd1cb09fc78d55584ef5cb8ab87f2d8d1ae) From cb142107e73454b224162b6fcec7be4af6e2b3ab Mon Sep 17 00:00:00 2001 From: spham <spham@amazon.com> Date: Wed, 21 Apr 2021 09:27:34 -0700 Subject: [PATCH 51/96] Fixed targeting of cmake version --- scripts/build/build_node/Platform/Linux/install-ubuntu-awscli.sh | 0 .../build_node/Platform/Linux/install-ubuntu-build-libraries.sh | 0 .../build/build_node/Platform/Linux/install-ubuntu-build-tools.sh | 0 scripts/build/build_node/Platform/Linux/install-ubuntu-git.sh | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-awscli.sh mode change 100644 => 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-build-libraries.sh mode change 100644 => 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh mode change 100644 => 100755 scripts/build/build_node/Platform/Linux/install-ubuntu-git.sh diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-awscli.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-awscli.sh old mode 100644 new mode 100755 diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-build-libraries.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-build-libraries.sh old mode 100644 new mode 100755 diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh old mode 100644 new mode 100755 diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-git.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-git.sh old mode 100644 new mode 100755 From a14cd0102e70d549744a7abc8476b633fc749599 Mon Sep 17 00:00:00 2001 From: spham <spham@amazon.com> Date: Wed, 21 Apr 2021 09:28:28 -0700 Subject: [PATCH 52/96] Fixed cmake version targeting --- .../build_node/Platform/Linux/install-ubuntu-build-tools.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh b/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh index 36832bb9ac..0c65610cf5 100755 --- a/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh +++ b/scripts/build/build_node/Platform/Linux/install-ubuntu-build-tools.sh @@ -51,17 +51,17 @@ CMAKE_DEB_REPO="'deb https://apt.kitware.com/ubuntu/ $UBUNTU_DISTRO main'" # Add the appropriate kitware repository to apt if [ "$UBUNTU_DISTRO" == "bionic" ] then - CMAKE_DISTRO_VERSION=3.20.1-0kitware1ubuntu20.04.1 + CMAKE_DISTRO_VERSION=3.20.1-0kitware1ubuntu18.04.1 apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' elif [ "$UBUNTU_DISTRO" == "focal" ] then - CMAKE_DISTRO_VERSION=3.20.1-0kitware1ubuntu18.04.1 + CMAKE_DISTRO_VERSION=3.20.1-0kitware1ubuntu20.04.1 apt-add-repository 'deb https://apt.kitware.com/ubuntu/ focal main' fi apt-get update # Install cmake -apt-get install cmake $CMAKE_DISTRO_VERSION -y +apt-get install cmake=$CMAKE_DISTRO_VERSION -y # From 4faa64e31d79340ed80954011cd15e90ed2d1097 Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 21 Apr 2021 09:42:33 -0700 Subject: [PATCH 53/96] Fix string format build error --- .../Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp index e73c049780..957b8c64d1 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SubgraphInterface.cpp @@ -723,7 +723,7 @@ namespace ScriptCanvas { if (!AddOutKey(out.displayName)) { - return AZ::Failure(AZStd::string::format("Out %s was already in the list: %s", out.displayName.c_str())); + return AZ::Failure(AZStd::string::format("Out %s was already in the list", out.displayName.c_str())); } } } @@ -732,7 +732,7 @@ namespace ScriptCanvas { if (!AddOutKey(latent.displayName)) { - return AZ::Failure(AZStd::string::format("Out %s was already in the list: %s", latent.displayName.c_str())); + return AZ::Failure(AZStd::string::format("Out %s was already in the list", latent.displayName.c_str())); } } From 70b4938cffed004679b0bf6c0de9280cddab02a7 Mon Sep 17 00:00:00 2001 From: phistere <phistere@amazon.com> Date: Wed, 21 Apr 2021 11:55:01 -0500 Subject: [PATCH 54/96] LYN-2524: Launch AP from SDK when not found in the executable directory --- .../AssetSystemComponentHelper_Linux.cpp | 26 ++++++++++++++++--- .../Asset/AssetSystemComponentHelper_Mac.cpp | 22 ++++++++++++++++ .../AssetSystemComponentHelper_Windows.cpp | 21 +++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp index 1f71b97a57..4f9aeaf6c3 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp @@ -29,6 +29,29 @@ namespace AzFramework::AssetSystem::Platform bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot, AZStd::string_view projectPath) { + AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory }; + assetProcessorPath /= "AssetProcessor"; + + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. + assetProcessorPath.Assign(engineRoot); + assetProcessorPath /= "bin"; +#if defined(AZ_DEBUG_BUILD) + assetProcessorPath /= "debug"; +#elif defined(AZ_PROFILE_BUILD) + assetProcessorPath /= "profile"; +#else + assetProcessorPath /= "release"; +#endif + assetProcessorPath /= "AssetProcessor"; + + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + return false; + } + } + pid_t firstChildPid = fork(); if (firstChildPid == 0) { @@ -47,9 +70,6 @@ namespace AzFramework::AssetSystem::Platform pid_t secondChildPid = fork(); if (secondChildPid == 0) { - AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory }; - assetProcessorPath /= "AssetProcessor"; - AZStd::array args { assetProcessorPath.c_str(), assetProcessorPath.c_str(), "--start-hidden", static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), static_cast<const char*>(nullptr) diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp index 43f7599676..cc31cc9a0c 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp @@ -11,6 +11,7 @@ */ #include <AzCore/IO/Path/Path.h> +#include <AzCore/IO/SystemFile.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <sys/types.h> @@ -20,6 +21,7 @@ namespace AzFramework::AssetSystem::Platform { void AllowAssetProcessorToForeground() {} + bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot, AZStd::string_view projectPath) { @@ -29,6 +31,26 @@ namespace AzFramework::AssetSystem::Platform assetProcessorPath /= "../../../AssetProcessor.app"; assetProcessorPath = assetProcessorPath.LexicallyNormal(); + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. + assetProcessorPath.Assign(engineRoot); + assetProcessorPath /= "bin"; + #if defined(AZ_DEBUG_BUILD) + assetProcessorPath /= "debug"; +#elif defined(AZ_PROFILE_BUILD) + assetProcessorPath /= "profile"; +#else + assetProcessorPath /= "release"; +#endif + assetProcessorPath /= "AssetProcessor.app"; + + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + return false; + } + } + auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"(open -g "%s" --args --start-hidden)", assetProcessorPath.c_str()); // Add the engine path to the launch command if not empty if (!engineRoot.empty()) diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp index 3f4dbef22a..155a69a691 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp @@ -12,6 +12,7 @@ #include <AzCore/PlatformIncl.h> #include <AzCore/IO/Path/Path.h> +#include <AzCore/IO/SystemFile.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <Psapi.h> @@ -67,6 +68,26 @@ namespace AzFramework::AssetSystem::Platform AZ::IO::FixedMaxPath assetProcessorPath{ executableDirectory }; assetProcessorPath /= "AssetProcessor.exe"; + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. + assetProcessorPath.Assign(engineRoot); + assetProcessorPath /= "bin"; +#if defined(AZ_DEBUG_BUILD) + assetProcessorPath /= "debug"; +#elif defined(AZ_PROFILE_BUILD) + assetProcessorPath /= "profile"; +#else + assetProcessorPath /= "release"; +#endif + assetProcessorPath /= "AssetProcessor.exe"; + + if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) + { + return false; + } + } + auto fullLaunchCommand = AZ::IO::FixedMaxPathString::format(R"("%s" --start-hidden)", assetProcessorPath.c_str()); // Add the engine path to the launch command if not empty From a3e1d84566270ae09681e7e33f191f911d13ec03 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Wed, 21 Apr 2021 10:54:26 -0700 Subject: [PATCH 55/96] Test metrics uses both Jenkins endpoints fix --- scripts/build/Jenkins/Jenkinsfile | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 662ddc7454..4f4708aea3 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -349,6 +349,18 @@ def Build(Map options, String platform, String type, String workspace) { } } +def getJenkinsBaseUrl() { + def job_url = new URL(env.JOB_URL) + + // Return a new URL using the protocol, host and port only. + return new URL( + job_url.getProtocol(), + job_url.getHost(), + job_url.getPort(), + '' + ).toString() +} + def TestMetrics(Map options, String workspace, String branchName, String repoName, String buildJobName, String outputDirectory, String configuration) { catchError(buildResult: null, stageResult: null) { def cmakeBuildDir = [workspace, ENGINE_REPOSITORY_NAME, outputDirectory].join('/') @@ -360,7 +372,11 @@ def TestMetrics(Map options, String workspace, String branchName, String repoNam userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars', credentialsId: "${env.GITHUB_USER}"]] ] withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { - def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py -e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} ${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " + def jenkins_url = getJenkinsBaseUrl() + def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py" + + "-e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} " + + "-e jenkins.base_url ${jenkins_url}" + + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " bat label: "Publishing ${buildJobName} Test Metrics", script: command } From 92c77dca11cf5798172a4ea8131e108a57a6fb53 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Wed, 21 Apr 2021 11:16:27 -0700 Subject: [PATCH 56/96] LYN-3069 Revert some 3rdparty changes and address issue (#185) * renaming and organizing files * removed unused files * Removing unnecessary file * moved file * reverting movement of 3rdparty associations from gems to global * removing unnecessary calls to ly_add_external_target_path * fixing install prefix of ci_build * Fixes to get 3rdparties declared in gems to be installed * Allowing to install just one configuration * Adding empty line at the end * removing commented code * setting IMPORETD_LOCATION_<CONFIG> and defaulting IMPORTED_LOCATION to the profile config in case other configs are not installed --- CMakeLists.txt | 3 +- .../SceneAPI/FbxSDKWrapper/CMakeLists.txt | 4 +- .../3rdParty/cubemapgen.json | 9 - .../Asset/ImageProcessingAtom/CMakeLists.txt | 2 - Gems/Atom/Feature/Common/CMakeLists.txt | 2 - Gems/Atom/Utils/CMakeLists.txt | 2 - Gems/EMotionFX/CMakeLists.txt | 2 - .../Code/Platform/Windows/PAL_windows.cmake | 2 + Gems/PhysX/CMakeLists.txt | 2 - Gems/PhysX/Code/CMakeLists.txt | 3 + Gems/PythonAssetBuilder/CMakeLists.txt | 1 - .../{3rdParty => }/readme.md | 0 .../Windows/platform_windows_tools.cmake | 3 + .../Linux/BuiltInPackages_linux.cmake | 2 - .../Platform/Mac/BuiltInPackages_mac.cmake | 2 - .../Windows/BuiltInPackages_windows.cmake | 3 - cmake/3rdPartyPackages.cmake | 4 +- cmake/FindTarget.cmake.in | 37 ++- cmake/FindTargetTemplate.cmake | 45 ---- cmake/Findo3de.cmake.in | 2 +- cmake/Findo3deTemplate.cmake | 35 --- ...Initialize.cmake => GeneralSettings.cmake} | 6 - cmake/OutputDirectory.cmake | 16 ++ cmake/Platform/Common/Install_common.cmake | 221 +++++++++--------- .../build/Platform/Windows/build_config.json | 2 +- 25 files changed, 161 insertions(+), 249 deletions(-) delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/3rdParty/cubemapgen.json rename Gems/PythonAssetBuilder/{3rdParty => }/readme.md (100%) delete mode 100644 cmake/FindTargetTemplate.cmake delete mode 100644 cmake/Findo3deTemplate.cmake rename cmake/{Initialize.cmake => GeneralSettings.cmake} (69%) create mode 100644 cmake/OutputDirectory.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 6da92f9c2d..18fb86ff09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ if(CMAKE_VERSION VERSION_EQUAL 3.19) endif() include(cmake/Version.cmake) +include(cmake/OutputDirectory.cmake) if(NOT PROJECT_NAME) project(O3DE @@ -30,7 +31,7 @@ if(NOT PROJECT_NAME) ) endif() -include(cmake/Initialize.cmake) +include(cmake/GeneralSettings.cmake) include(cmake/FileUtil.cmake) include(cmake/PAL.cmake) include(cmake/PALTools.cmake) diff --git a/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt b/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt index ac8af3fdaa..ddbabe604d 100644 --- a/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt +++ b/Code/Tools/SceneAPI/FbxSDKWrapper/CMakeLists.txt @@ -9,13 +9,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -set(sdkwrapper_dir ${CMAKE_CURRENT_LIST_DIR}/../SDKWrapper) - if (NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() -ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) +set(sdkwrapper_dir ${CMAKE_CURRENT_LIST_DIR}/../SDKWrapper) ly_add_target( NAME FbxSDKWrapper STATIC diff --git a/Gems/Atom/Asset/ImageProcessingAtom/3rdParty/cubemapgen.json b/Gems/Atom/Asset/ImageProcessingAtom/3rdParty/cubemapgen.json deleted file mode 100644 index c5dc8a7486..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/3rdParty/cubemapgen.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "cubemapgen", - "source": "@GEM@/External/CubeMapGen", - "description": "CubeMapGen", - "defines": [], - "lib_required": "False", - "includes": [""] -} - diff --git a/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt index 7f322b615a..1126af2afa 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/CMakeLists.txt @@ -10,6 +10,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) - add_subdirectory(Code) diff --git a/Gems/Atom/Feature/Common/CMakeLists.txt b/Gems/Atom/Feature/Common/CMakeLists.txt index d96d812af0..20a680bce9 100644 --- a/Gems/Atom/Feature/Common/CMakeLists.txt +++ b/Gems/Atom/Feature/Common/CMakeLists.txt @@ -9,6 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) - add_subdirectory(Code) diff --git a/Gems/Atom/Utils/CMakeLists.txt b/Gems/Atom/Utils/CMakeLists.txt index d96d812af0..20a680bce9 100644 --- a/Gems/Atom/Utils/CMakeLists.txt +++ b/Gems/Atom/Utils/CMakeLists.txt @@ -9,6 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) - add_subdirectory(Code) diff --git a/Gems/EMotionFX/CMakeLists.txt b/Gems/EMotionFX/CMakeLists.txt index d96d812af0..20a680bce9 100644 --- a/Gems/EMotionFX/CMakeLists.txt +++ b/Gems/EMotionFX/CMakeLists.txt @@ -9,6 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) - add_subdirectory(Code) diff --git a/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake b/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake index e6c7c23614..5a4d953220 100644 --- a/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake +++ b/Gems/NvCloth/Code/Platform/Windows/PAL_windows.cmake @@ -10,3 +10,5 @@ # set(PAL_TRAIT_NVCLOTH_USE_STUB FALSE) + +ly_associate_package(PACKAGE_NAME NvCloth-1.1.6-rev1-multiplatform TARGETS NvCloth PACKAGE_HASH 05fc62634ca28644e7659a89e97f4520d791e6ddf4b66f010ac669e4e2ed4454) diff --git a/Gems/PhysX/CMakeLists.txt b/Gems/PhysX/CMakeLists.txt index d96d812af0..20a680bce9 100644 --- a/Gems/PhysX/CMakeLists.txt +++ b/Gems/PhysX/CMakeLists.txt @@ -9,6 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) - add_subdirectory(Code) diff --git a/Gems/PhysX/Code/CMakeLists.txt b/Gems/PhysX/Code/CMakeLists.txt index ac5fd902c2..e6f8fc7188 100644 --- a/Gems/PhysX/Code/CMakeLists.txt +++ b/Gems/PhysX/Code/CMakeLists.txt @@ -71,6 +71,9 @@ ly_add_target( if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) + ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) + ly_add_target( NAME PhysX.Editor.Static STATIC NAMESPACE Gem diff --git a/Gems/PythonAssetBuilder/CMakeLists.txt b/Gems/PythonAssetBuilder/CMakeLists.txt index d577738051..20a680bce9 100644 --- a/Gems/PythonAssetBuilder/CMakeLists.txt +++ b/Gems/PythonAssetBuilder/CMakeLists.txt @@ -9,5 +9,4 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # -ly_add_external_target_path(${CMAKE_CURRENT_LIST_DIR}/3rdParty) add_subdirectory(Code) diff --git a/Gems/PythonAssetBuilder/3rdParty/readme.md b/Gems/PythonAssetBuilder/readme.md similarity index 100% rename from Gems/PythonAssetBuilder/3rdParty/readme.md rename to Gems/PythonAssetBuilder/readme.md diff --git a/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake b/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake index 561ab67600..ef25fb2f63 100644 --- a/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake +++ b/Gems/WhiteBox/Code/Source/Platform/Windows/platform_windows_tools.cmake @@ -10,6 +10,9 @@ # if(PAL_TRAIT_BUILD_HOST_TOOLS) + + ly_associate_package(PACKAGE_NAME OpenMesh-8.1-rev1-windows TARGETS OpenMesh PACKAGE_HASH 1c1df639358526c368e790dfce40c45cbdfcfb1c9a041b9d7054a8949d88ee77) + set(LY_BUILD_DEPENDENCIES PRIVATE 3rdParty::OpenMesh) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index e42e8e40ea..890f4bcc3f 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -31,8 +31,6 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARG ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) -ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) -ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index d6d017d1d1..ff6227f88c 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -36,8 +36,6 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) -ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) -ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index ac2cb1d418..e79d6d9af1 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -37,9 +37,6 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) ly_associate_package(PACKAGE_NAME Blast-1.1.7-rev1-multiplatform TARGETS Blast PACKAGE_HASH 36b8f393bcd25d0f85cfc7a831ebbdac881e6054c4f0735649966aa6aa86e6f0) ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) -ly_associate_package(PACKAGE_NAME NvCloth-1.1.6-rev1-multiplatform TARGETS NvCloth PACKAGE_HASH 05fc62634ca28644e7659a89e97f4520d791e6ddf4b66f010ac669e4e2ed4454) -ly_associate_package(PACKAGE_NAME poly2tri-0.3.3-rev2-multiplatform TARGETS poly2tri PACKAGE_HASH 04092d06716f59b936b61906eaf3647db23b685d81d8b66131eb53e0aeaa1a38) -ly_associate_package(PACKAGE_NAME v-hacd-2.0-rev1-multiplatform TARGETS v-hacd PACKAGE_HASH 5c71aef19cc9787d018d64eec076e9f51ea5a3e0dc6b6e22e57c898f6cc4afe3) # platform-specific: ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) diff --git a/cmake/3rdPartyPackages.cmake b/cmake/3rdPartyPackages.cmake index 3984111996..b3545fd415 100644 --- a/cmake/3rdPartyPackages.cmake +++ b/cmake/3rdPartyPackages.cmake @@ -621,7 +621,6 @@ endfunction() # - this waill cause it to automatically download and activate this package if it finds a target that # depends on '3rdParty::zlib' in its runtime or its build time dependency list. # - note that '3rdParty' is implied, do not specify it in the TARGETS list. - function(ly_associate_package) set(_oneValueArgs PACKAGE_NAME PACKAGE_HASH) set(_multiValueArgs TARGETS) @@ -643,6 +642,9 @@ function(ly_associate_package) set_property(GLOBAL PROPERTY LY_PACKAGE_ASSOCIATION_${find_package_name} ${ly_associate_package_PACKAGE_NAME}) set_property(GLOBAL PROPERTY LY_PACKAGE_HASH_${ly_associate_package_PACKAGE_NAME} ${ly_associate_package_PACKAGE_HASH}) endforeach() + + set_property(GLOBAL APPEND PROPERTY LY_PACKAGE_NAMES ${ly_associate_package_PACKAGE_NAME}) + set_property(GLOBAL PROPERTY LY_PACKAGE_TARGETS_${ly_associate_package_PACKAGE_NAME} ${ly_associate_package_TARGETS}) endfunction() #! Given a package find_package name (eg, 'zlib' not the actual package name) diff --git a/cmake/FindTarget.cmake.in b/cmake/FindTarget.cmake.in index 7d0129d05a..8ad9822dae 100644 --- a/cmake/FindTarget.cmake.in +++ b/cmake/FindTarget.cmake.in @@ -14,32 +14,21 @@ include(FindPackageHandleStandardArgs) ly_add_target( - -NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED - -@NAMESPACE_PLACEHOLDER@ - + NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED + @NAMESPACE_PLACEHOLDER@ + COMPILE_DEFINITIONS + INTERFACE +@COMPILE_DEFINITIONS_PLACEHOLDER@ + INCLUDE_DIRECTORIES + INTERFACE @INCLUDE_DIRECTORIES_PLACEHOLDER@ - + BUILD_DEPENDENCIES + INTERFACE @BUILD_DEPENDENCIES_PLACEHOLDER@ - + RUNTIME_DEPENDENCIES @RUNTIME_DEPENDENCIES_PLACEHOLDER@ - -@COMPILE_DEFINITIONS_PLACEHOLDER@ ) -# The below if was generated from if (NOT HEADER_ONLY_PLACEHOLDER) -# HEADER_ONLY_PLACEHOLDER evaluates to TRUE or FALSE -if (NOT @HEADER_ONLY_PLACEHOLDER@) - # Load information for each installed configuration. - foreach(config @ALL_CONFIGS@) - set(@NAME_PLACEHOLDER@_${config}_FOUND FALSE) - include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake") - endforeach() - - find_package_handle_standard_args(@NAME_PLACEHOLDER@ - "Could not find package @NAME_PLACEHOLDER@" - @TARGET_CONFIG_FOUND_VARS_PLACEHOLDER@) -else() - set(@NAME_PLACEHOLDER@_FOUND TRUE) -endif() \ No newline at end of file +foreach(config @CMAKE_CONFIGURATION_TYPES@) + include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake" OPTIONAL) +endforeach() diff --git a/cmake/FindTargetTemplate.cmake b/cmake/FindTargetTemplate.cmake deleted file mode 100644 index 7d0129d05a..0000000000 --- a/cmake/FindTargetTemplate.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# Generated by O3DE - -include(FindPackageHandleStandardArgs) - -ly_add_target( - -NAME @NAME_PLACEHOLDER@ UNKNOWN IMPORTED - -@NAMESPACE_PLACEHOLDER@ - -@INCLUDE_DIRECTORIES_PLACEHOLDER@ - -@BUILD_DEPENDENCIES_PLACEHOLDER@ - -@RUNTIME_DEPENDENCIES_PLACEHOLDER@ - -@COMPILE_DEFINITIONS_PLACEHOLDER@ -) - -# The below if was generated from if (NOT HEADER_ONLY_PLACEHOLDER) -# HEADER_ONLY_PLACEHOLDER evaluates to TRUE or FALSE -if (NOT @HEADER_ONLY_PLACEHOLDER@) - # Load information for each installed configuration. - foreach(config @ALL_CONFIGS@) - set(@NAME_PLACEHOLDER@_${config}_FOUND FALSE) - include("${LY_ROOT_FOLDER}/cmake_autogen/@NAME_PLACEHOLDER@/@NAME_PLACEHOLDER@_${config}.cmake") - endforeach() - - find_package_handle_standard_args(@NAME_PLACEHOLDER@ - "Could not find package @NAME_PLACEHOLDER@" - @TARGET_CONFIG_FOUND_VARS_PLACEHOLDER@) -else() - set(@NAME_PLACEHOLDER@_FOUND TRUE) -endif() \ No newline at end of file diff --git a/cmake/Findo3de.cmake.in b/cmake/Findo3de.cmake.in index 7ecb73e874..5a56de0851 100644 --- a/cmake/Findo3de.cmake.in +++ b/cmake/Findo3de.cmake.in @@ -15,7 +15,7 @@ include(FindPackageHandleStandardArgs) # This will be called from within the installed engine's CMakeLists.txt macro(ly_find_o3de_packages) - @FIND_PACKAGES_PLACEHOLDER@ +@FIND_PACKAGES_PLACEHOLDER@ find_package(LauncherGenerator) endmacro() diff --git a/cmake/Findo3deTemplate.cmake b/cmake/Findo3deTemplate.cmake deleted file mode 100644 index 0e904fd95d..0000000000 --- a/cmake/Findo3deTemplate.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# Generated by O3DE - -include(FindPackageHandleStandardArgs) - -# This will be called from within the installed engine's CMakeLists.txt -macro(ly_find_o3de_packages) - @FIND_PACKAGES_PLACEHOLDER@ - find_package(LauncherGenerator) -endmacro() - - -function(o3de_current_file_path path) - set(${path} ${CMAKE_CURRENT_FUNCTION_LIST_DIR} PARENT_SCOPE) -endfunction() - - -# We are using the engine's CMakeLists.txt to handle initialization/importing targets -# Since this is external to the project's source, we need to specify an output directory -# even though we don't build -macro(o3de_initialize) - set(LY_PROJECTS ${CMAKE_SOURCE_DIR}) - o3de_current_file_path(current_path) - add_subdirectory(${current_path}/.. o3de) -endmacro() \ No newline at end of file diff --git a/cmake/Initialize.cmake b/cmake/GeneralSettings.cmake similarity index 69% rename from cmake/Initialize.cmake rename to cmake/GeneralSettings.cmake index 474ea39dd6..2083981291 100644 --- a/cmake/Initialize.cmake +++ b/cmake/GeneralSettings.cmake @@ -17,12 +17,6 @@ include(cmake/LySet.cmake) set_property(GLOBAL PROPERTY USE_FOLDERS ON) ly_set(CMAKE_WARN_DEPRECATED ON) -# Set output directories -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Build directory for static libraries and import libraries") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Build directory for shared libraries") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Build directory for executables") -set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "Installation prefix") - set(LY_EXTERNAL_SUBDIRS "" CACHE STRING "Additional list of subdirectory to recurse into via the cmake `add_subdirectory()` command. \ The subdirectories are included after the restricted platform folders have been visited by a call to `add_subdirectory(restricted/\${restricted_platform})`") diff --git a/cmake/OutputDirectory.cmake b/cmake/OutputDirectory.cmake new file mode 100644 index 0000000000..9055802d39 --- /dev/null +++ b/cmake/OutputDirectory.cmake @@ -0,0 +1,16 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + +# Set output directories +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib CACHE PATH "Build directory for static libraries and import libraries") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Build directory for shared libraries") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Build directory for executables") +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "Installation prefix") diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 7ac9a3afa8..286f449acd 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -9,6 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +set(CMAKE_INSTALL_MESSAGE NEVER) # Simplify messages to reduce output noise #! ly_install_target: registers the target to be installed by cmake install. # @@ -35,27 +36,16 @@ function(ly_install_target ly_install_target_NAME) install( TARGETS ${ly_install_target_NAME} - EXPORT ${ly_install_target_NAME}Targets LIBRARY DESTINATION lib/$<CONFIG> ARCHIVE DESTINATION lib/$<CONFIG> RUNTIME DESTINATION bin/$<CONFIG> PUBLIC_HEADER DESTINATION ${include_location} ) - - install(EXPORT ${ly_install_target_NAME}Targets + + ly_generate_target_config_file(${ly_install_target_NAME}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${ly_install_target_NAME}_$<CONFIG>.cmake" DESTINATION cmake_autogen/${ly_install_target_NAME} ) - - # Header only targets(i.e., INTERFACE) don't have outputs - get_target_property(target_type ${ly_install_target_NAME} TYPE) - if(NOT ${target_type} STREQUAL "INTERFACE_LIBRARY") - ly_generate_target_config_file(${ly_install_target_NAME}) - - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${ly_install_target_NAME}_$<CONFIG>.cmake" - DESTINATION cmake_autogen/${ly_install_target_NAME} - ) - endif() - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Find${ly_install_target_NAME}.cmake" DESTINATION cmake ) @@ -66,8 +56,8 @@ endfunction() #! ly_generate_target_find_file: generates the Find${target}.cmake file which is used when importing installed packages. # # \arg:NAME name of the target -# \arg:INCLUDE_DIRECTORIES paths to the include directories # \arg:NAMESPACE namespace declaration for this target. It will be used for IDE and dependencies +# \arg:INCLUDE_DIRECTORIES paths to the include directories # \arg:BUILD_DEPENDENCIES list of interfaces this target depends on (could be a compilation dependency # if the dependency is only exposing an include path, or could be a linking # dependency is exposing a lib) @@ -77,64 +67,38 @@ function(ly_generate_target_find_file) set(options) set(oneValueArgs NAME NAMESPACE) - set(multiValueArgs COMPILE_DEFINITIONS BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES INCLUDE_DIRECTORIES) + set(multiValueArgs INCLUDE_DIRECTORIES COMPILE_DEFINITIONS BUILD_DEPENDENCIES RUNTIME_DEPENDENCIES) cmake_parse_arguments(ly_generate_target_find_file "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) - # These targets will be imported. So we strip PRIVATE properties. - # We can only set INTERFACE properties on imported targets - unset(build_dependencies_interface_props) - unset(compile_definitions_interface_props) - unset(include_directories_interface_props) - unset(installed_include_directories_interface_props) - ly_strip_non_interface_properties(build_dependencies_interface_props ${ly_generate_target_find_file_BUILD_DEPENDENCIES}) - ly_strip_non_interface_properties(compile_definitions_interface_props ${ly_generate_target_find_file_COMPILE_DEFINITIONS}) - ly_strip_non_interface_properties(include_directories_interface_props ${ly_generate_target_find_file_INCLUDE_DIRECTORIES}) - set(NAME_PLACEHOLDER ${ly_generate_target_find_file_NAME}) + unset(NAMESPACE_PLACEHOLDER) + unset(COMPILE_DEFINITIONS_PLACEHOLDER) + unset(include_directories_interface_props) + unset(INCLUDE_DIRECTORIES_PLACEHOLDER) + set(RUNTIME_DEPENDENCIES_PLACEHOLDER ${ly_generate_target_find_file_RUNTIME_DEPENDENCIES}) - # Includes need additional processing to add the install root - foreach(include ${include_directories_interface_props}) - set(installed_include_prefix "\${LY_ROOT_FOLDER}/include/") - file(RELATIVE_PATH relative_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${include}) - string(APPEND installed_include_prefix ${relative_path}) - list(APPEND installed_include_directories_interface_props ${installed_include_prefix}) - endforeach() + # These targets will be imported. We will expose PUBLIC and INTERFACE properties as INTERFACE properties since + # only INTERFACE properties can be exposed on imported targets + ly_strip_private_properties(COMPILE_DEFINITIONS_PLACEHOLDER ${ly_generate_target_find_file_COMPILE_DEFINITIONS}) + ly_strip_private_properties(include_directories_interface_props ${ly_generate_target_find_file_INCLUDE_DIRECTORIES}) + ly_strip_private_properties(BUILD_DEPENDENCIES_PLACEHOLDER ${ly_generate_target_find_file_BUILD_DEPENDENCIES}) if(ly_generate_target_find_file_NAMESPACE) set(NAMESPACE_PLACEHOLDER "NAMESPACE ${ly_generate_target_find_file_NAMESPACE}") endif() - if(installed_include_directories_interface_props) - string(REPLACE ";" "\n" include_dirs "${installed_include_directories_interface_props}") - set(INCLUDE_DIRECTORIES_PLACEHOLDER "INCLUDE_DIRECTORIES\nINTERFACE\n${include_dirs}") - endif() - if(build_dependencies_interface_props) - string(REPLACE ";" "\n" build_deps "${build_dependencies_interface_props}") - set(BUILD_DEPENDENCIES_PLACEHOLDER "BUILD_DEPENDENCIES\nINTERFACE\n${build_deps}") - endif() - if(ly_generate_target_find_file_RUNTIME_DEPENDENCIES) - string(REPLACE ";" "\n" runtime_deps "${ly_generate_target_find_file_RUNTIME_DEPENDENCIES}") - set(RUNTIME_DEPENDENCIES_PLACEHOLDER "RUNTIME_DEPENDENCIES\n${runtime_deps}") - endif() - if(compile_definitions_interface_props) - string(REPLACE ";" "\n" compile_defs "${compile_definitions_interface_props}") - set(COMPILE_DEFINITIONS_PLACEHOLDER "COMPILE_DEFINITIONS\nINTERFACE\n${compile_defs}") - endif() - string(REPLACE ";" " " ALL_CONFIGS "${CMAKE_CONFIGURATION_TYPES}") + string(REPLACE ";" "\n" COMPILE_DEFINITIONS_PLACEHOLDER "${COMPILE_DEFINITIONS_PLACEHOLDER}") - set(target_config_found_vars "") - foreach(config ${CMAKE_CONFIGURATION_TYPES}) - string(APPEND target_config_found_vars "\n${ly_generate_target_find_file_NAME}_${config}_FOUND") + # Includes need additional processing to add the install root + foreach(include ${include_directories_interface_props}) + set(installed_include_prefix "\${LY_ROOT_FOLDER}/include/") + file(RELATIVE_PATH relative_path ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${include}) + list(APPEND INCLUDE_DIRECTORIES_PLACEHOLDER "include/${relative_path}") endforeach() - set(TARGET_CONFIG_FOUND_VARS_PLACEHOLDER "${target_config_found_vars}") - - # Interface libs aren't built so they don't generate a library. These are our HEADER_ONLY targets. - get_target_property(target_type ${ly_generate_target_find_file_NAME} TYPE) - if(NOT ${target_type} STREQUAL "INTERFACE_LIBRARY") - set(HEADER_ONLY_PLACEHOLDER FALSE) - else() - set(HEADER_ONLY_PLACEHOLDER TRUE) - endif() + string(REPLACE ";" "\n" INCLUDE_DIRECTORIES_PLACEHOLDER "${INCLUDE_DIRECTORIES_PLACEHOLDER}") + + string(REPLACE ";" "\n" BUILD_DEPENDENCIES_PLACEHOLDER "${BUILD_DEPENDENCIES_PLACEHOLDER}") + string(REPLACE ";" "\n" RUNTIME_DEPENDENCIES_PLACEHOLDER "${RUNTIME_DEPENDENCIES_PLACEHOLDER}") configure_file(${LY_ROOT_FOLDER}/cmake/FindTarget.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Find${ly_generate_target_find_file_NAME}.cmake @ONLY) @@ -148,37 +112,47 @@ endfunction() # \arg:NAME name of the target function(ly_generate_target_config_file NAME) - # SHARED_LIBRARY is omitted from this list because we link to the implib on Windows - set(BINARY_DIR_OUTPUTS EXECUTABLE APPLICATION) - set(target_file_contents "") - if(${target_type} IN_LIST BINARY_DIR_OUTPUTS) - set(out_file_generator TARGET_FILE_NAME) - set(out_dir bin) - else() - set(out_file_generator TARGET_LINKER_FILE_NAME) - set(out_dir lib) - endif() - - string(APPEND target_file_contents " -# Generated by O3DE + get_target_property(target_type ${NAME} TYPE) + + unset(target_file_contents) + if(NOT target_type STREQUAL INTERFACE_LIBRARY) + + set(BINARY_DIR_OUTPUTS EXECUTABLE APPLICATION) + set(target_file_contents "") + if(${target_type} IN_LIST BINARY_DIR_OUTPUTS) + set(out_file_generator TARGET_FILE_NAME) + set(out_dir bin) + else() + set(out_file_generator TARGET_LINKER_FILE_NAME) + set(out_dir lib) + endif() -set_target_properties(${NAME} PROPERTIES IMPORTED_LOCATION \"\${LY_ROOT_FOLDER}/${out_dir}/$<CONFIG>/$<${out_file_generator}:${NAME}>\") + string(APPEND target_file_contents +"# Generated by O3DE install -if(EXISTS \"\${LY_ROOT_FOLDER}/${out_dir}/$<CONFIG>/$<${out_file_generator}:${NAME}>\") +set(target_location \"\${LY_ROOT_FOLDER}/${out_dir}/$<CONFIG>/$<${out_file_generator}:${NAME}>\") +set_target_properties(${NAME} + PROPERTIES + $<$<CONFIG:profile>:IMPORTED_LOCATION \"\${target_location}>\" + IMPORTED_LOCATION_$<UPPER_CASE:$<CONFIG>> \"\${target_location}\" +) +if(EXISTS \"\${target_location}\") set(${NAME}_$<CONFIG>_FOUND TRUE) else() set(${NAME}_$<CONFIG>_FOUND FALSE) -endif()") +endif() +") + endif() - file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}_$<CONFIG>.cmake" CONTENT ${target_file_contents}) + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${NAME}_$<CONFIG>.cmake" CONTENT "${target_file_contents}") endfunction() -#! ly_strip_non_interface_properties: strips private properties since we're exporting an interface target +#! ly_strip_private_properties: strips private properties since we're exporting an interface target # # \arg:INTERFACE_PROPERTIES list of interface properties to be returned -function(ly_strip_non_interface_properties INTERFACE_PROPERTIES) +function(ly_strip_private_properties INTERFACE_PROPERTIES) set(reserved_keywords PRIVATE PUBLIC INTERFACE) unset(last_keyword) unset(stripped_props) @@ -196,36 +170,79 @@ function(ly_strip_non_interface_properties INTERFACE_PROPERTIES) endfunction() -#! ly_setup_o3de_install: generates the Findo3de.cmake file and setup install locations for scripts, tools, assets etc., +#! ly_setup_o3de_install: orchestrates the installation of the different parts. This is the entry point from the root CMakeLists.txt function(ly_setup_o3de_install) - get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) - unset(find_package_list) - foreach(target IN LISTS all_targets) - list(APPEND find_package_list "find_package(${target})") - endforeach() + ly_setup_cmake_install() + ly_setup_target_generator() + ly_setup_others() + +endfunction() + +#! ly_setup_cmake_install: install the "cmake" folder +function(ly_setup_cmake_install) - string(REPLACE ";" "\n" FIND_PACKAGES_PLACEHOLDER "${find_package_list}") + install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" + DESTINATION . + REGEX "Findo3de.cmake" EXCLUDE + REGEX "Platform\/.*\/BuiltInPackages_.*\.cmake" EXCLUDE + ) + install( + FILES + "${CMAKE_SOURCE_DIR}/CMakeLists.txt" + "${CMAKE_SOURCE_DIR}/engine.json" + DESTINATION . + ) - configure_file(${LY_ROOT_FOLDER}/cmake/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake @ONLY) + # Collect all Find files that were added with ly_add_external_target_path + unset(additional_find_files) + get_property(additional_module_paths GLOBAL PROPERTY LY_ADDITIONAL_MODULE_PATH) + foreach(additional_module_path ${additional_module_paths}) + unset(find_files) + file(GLOB find_files "${additional_module_path}/Find*.cmake") + list(APPEND additional_find_files "${find_files}") + endforeach() + install(FILES ${additional_find_files} + DESTINATION cmake/3rdParty + ) - ly_install_launcher_target_generator() + # Findo3de.cmake file: we generate a different Findo3de.camke file than the one we have in cmake. This one is going to expose all + # targets that are pre-built + get_property(all_targets GLOBAL PROPERTY LY_ALL_TARGETS) + unset(FIND_PACKAGES_PLACEHOLDER) + foreach(target IN LISTS all_targets) + string(APPEND FIND_PACKAGES_PLACEHOLDER " find_package(${target})\n") + endforeach() - ly_install_o3de_directories() + configure_file(${LY_ROOT_FOLDER}/cmake/Findo3de.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake @ONLY) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Findo3de.cmake" + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/Findo3de.cmake" DESTINATION cmake ) + + # BuiltInPackage_<platform>.cmake: since associations could happen in any cmake file across the engine. We collect + # all the associations in ly_associate_package and then generate them into BuiltInPackages_<platform>.cmake. This + # will consolidate all associations in one file + get_property(all_package_names GLOBAL PROPERTY LY_PACKAGE_NAMES) + set(builtinpackages "# Generated by O3DE install\n\n") + foreach(package_name IN LISTS all_package_names) + get_property(package_hash GLOBAL PROPERTY LY_PACKAGE_HASH_${package_name}) + get_property(targets GLOBAL PROPERTY LY_PACKAGE_TARGETS_${package_name}) + string(APPEND builtinpackages "ly_associate_package(PACKAGE_NAME ${package_name} TARGETS ${targets} PACKAGE_HASH ${package_hash})\n") + endforeach() - install(FILES "${CMAKE_SOURCE_DIR}/CMakeLists.txt" - DESTINATION . + ly_get_absolute_pal_filename(pal_builtin_file ${CMAKE_CURRENT_BINARY_DIR}/cmake/3rdParty/Platform/${PAL_PLATFORM_NAME}/BuiltInPackages_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) + file(GENERATE OUTPUT ${pal_builtin_file} + CONTENT ${builtinpackages} + ) + install(FILES "${pal_builtin_file}" + DESTINATION cmake/3rdParty/Platform/${PAL_PLATFORM_NAME} ) endfunction() - -#! ly_install_o3de_directories: install directories required by the engine -function(ly_install_o3de_directories) +#! ly_setup_others: install directories required by the engine +function(ly_setup_others) # List of directories we want to install relative to engine root set(DIRECTORIES_TO_INSTALL Tools/LyTestTools Tools/RemoteConsole ctest_scripts scripts) @@ -242,12 +259,6 @@ function(ly_install_o3de_directories) endforeach() - # Directories which have excludes - install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" - DESTINATION . - REGEX "Findo3de.cmake" EXCLUDE - ) - install(DIRECTORY "${CMAKE_SOURCE_DIR}/python" DESTINATION . REGEX "downloaded_packages" EXCLUDE @@ -257,8 +268,8 @@ function(ly_install_o3de_directories) endfunction() -#! ly_install_launcher_target_generator: install source files needed for project launcher generation -function(ly_install_launcher_target_generator) +#! ly_setup_target_generator: install source files needed for project launcher generation +function(ly_setup_target_generator) install(FILES ${CMAKE_SOURCE_DIR}/Code/LauncherUnified/launcher_generator.cmake diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 4dd99686c5..a4a5a52c4d 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -290,7 +290,7 @@ "PARAMETERS": { "CONFIGURATION": "profile", "OUTPUT_DIRECTORY": "build\\windows_vs2019", - "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DCMAKE_INSTALL_PREFIX=build\\install", + "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DCMAKE_INSTALL_PREFIX=install", "CMAKE_LY_PROJECTS": "", "CMAKE_TARGET": "INSTALL", "CMAKE_NATIVE_BUILD_ARGS": "/m /nologo" From e05b7d5bb5b4171010d13c097dbecefccb64925e Mon Sep 17 00:00:00 2001 From: rhhong <rhhong@amazon.com> Date: Wed, 21 Apr 2021 11:19:13 -0700 Subject: [PATCH 57/96] Animation Editor: Removing all layouts causes the Animation Editor to be unusable Making the anim graph layout the default layout, cannot be removed from the menu. --- .../Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index 5adec5e0a4..496b6b8e94 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -1866,6 +1866,12 @@ namespace EMStudio // add each layout in the remove menu for (uint32 i = 0; i < numLayoutNames; ++i) { + // User cannot remove the default layout. This layout is referenced in the qrc file, removing it will + // cause compiling issue too. + if (mLayoutNames[i] == "AnimGraph") + { + continue; + } QAction* action = removeMenu->addAction(mLayoutNames[i].c_str()); connect(action, &QAction::triggered, this, &MainWindow::OnRemoveLayout); } From 5906731cd16bf0f74c56643a49fd1a1cdffa92e7 Mon Sep 17 00:00:00 2001 From: spham <spham@amazon.com> Date: Tue, 20 Apr 2021 20:03:33 -0700 Subject: [PATCH 58/96] Update Lua package revs and hashes to use new re-built Lua packages that pass scrubbing validation --- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index 8ab270ec0d..8be3abbf3c 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -25,6 +24,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-android TARGETS freetype PACKAGE_HASH 74dd75382688323c3a2a5090f473840b5d7e9d2aed1a4fcdff05ed2a09a664f2) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-android TARGETS tiff PACKAGE_HASH a9b30a1980946390c2fad0ed94562476a1d7ba8c1f36934ae140a89c54a8efd0) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-android TARGETS AWSNativeSDK PACKAGE_HASH e2192157534cc8c4e22769545d88dff03ec6c1031599716ef63de3ebbb8c9a44) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-android TARGETS PhysX PACKAGE_HASH 9c494576c2d4ff04dee5a9e092fcd9d5af4b2845f15ffdfcaabb0dbc5b88a7a9) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-android TARGETS mikkelsen PACKAGE_HASH 075e8e4940884971063b5a9963014e2e517246fa269c07c7dc55b8cf2cd99705) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-android TARGETS googletest PACKAGE_HASH 95671be75287a61c9533452835c3647e9c1b30f81b34b43bcb0ec1997cc23894) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 890f4bcc3f..2d32ebd775 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -36,6 +35,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARG ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-linux TARGETS AWSNativeSDK PACKAGE_HASH e69c55682638dc1e7fa571a61a82c8a69d395c74a008543a5188f4bd2b6b10c4) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-linux TARGETS PhysX PACKAGE_HASH e3ca36106a8dbf1524709f8bb82d520920ebd3ff3a92672d382efff406c75ee3) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index ff6227f88c..53e7066e99 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -41,6 +40,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-mac TARGETS AWSNativeSDK PACKAGE_HASH 21920372e90355407578b45ac19580df1463a39a25a867bcd0ffd8b385c8254a) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-mac TARGETS Lua PACKAGE_HASH d63357a73f9f8f297cf770fa4b92dca1fdd5761d4a2215e38f6e96fa274b28aa) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-mac TARGETS PhysX PACKAGE_HASH 149f5e9b44bd27291b1c4772f5e89a1e0efa88eef73c7e0b188935ed4d0c4a70) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index e79d6d9af1..c16dee7854 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME ilmbase-2.3.0-rev4-multiplatform TARGETS ilmbase PACKAGE_HASH 97547fdf1fbc4d81b8ccf382261f8c25514ed3b3c4f8fd493f0a4fa873bba348) ly_associate_package(PACKAGE_NAME hdf5-1.0.11-rev2-multiplatform TARGETS hdf5 PACKAGE_HASH 11d5e04df8a93f8c52a5684a4cacbf0d9003056360983ce34f8d7b601082c6bd) ly_associate_package(PACKAGE_NAME alembic-1.7.11-rev3-multiplatform TARGETS alembic PACKAGE_HASH ba7a7d4943dd752f5a662374f6c48b93493df1d8e2c5f6a8d101f3b50700dd25) @@ -42,6 +41,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-windows TARGETS PhysX PACKAGE_HASH 198bed89d1aae7caaf5dadba24cee56235fe41725d004b64040d4e50d0f3aa1a) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index 7ef0b3b329..43858fa244 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -11,7 +11,6 @@ # shared by other platforms: ly_associate_package(PACKAGE_NAME zlib-1.2.8-rev2-multiplatform TARGETS zlib PACKAGE_HASH e6f34b8ac16acf881e3d666ef9fd0c1aee94c3f69283fb6524d35d6f858eebbb) -ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev3-multiplatform TARGETS Lua PACKAGE_HASH 171dcdd60bd91fb325feaab0e53dd185c9d6e7b701d53e66fc6c2c6ee91d8bff) ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5 PACKAGE_HASH 29e52ad22c78051551f78a40c2709594f0378762ae03b417adca3f4b700affdf) ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-multiplatform TARGETS RapidJSON PACKAGE_HASH 18b0aef4e6e849389916ff6de6682ab9c591ebe15af6ea6017014453c1119ea1) ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf) @@ -26,6 +25,7 @@ ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-ios TARGETS AWSNativeSDK PACKAGE_HASH 1246219a213ccfff76b526011febf521586d44dbc1753e474f8fb5fd861654a4) +ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev2-ios TARGETS PhysX PACKAGE_HASH 27e68bd90915dbd0bd5f26cae714e9a137f6b1aa8a8e0bf354a4a9176aa553d5) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-ios TARGETS mikkelsen PACKAGE_HASH 976aaa3ccd8582346132a10af253822ccc5d5bcc9ea5ba44d27848f65ee88a8a) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-ios TARGETS googletest PACKAGE_HASH 2f121ad9784c0ab73dfaa58e1fee05440a82a07cc556bec162eeb407688111a7) From 99e91e3e809f79f8073c3e1f26d5b2c0248f3a21 Mon Sep 17 00:00:00 2001 From: qingtao <qingtao@amazon.com> Date: Wed, 21 Apr 2021 11:30:24 -0700 Subject: [PATCH 59/96] LYN-2772 Atom: Adding White Box Component to an Entity silently crashes the Editor Fixed a buffer creation issue with white box mesh. --- Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h index bea6de5898..9d8f327616 100644 --- a/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h +++ b/Gems/WhiteBox/Code/Source/Rendering/Atom/WhiteBoxBuffer.h @@ -105,7 +105,7 @@ namespace WhiteBox // create the buffer with the specified data AZ::RPI::BufferAssetCreator bufferAssetCreator; bufferAssetCreator.Begin(AZ::Uuid::CreateRandom()); - bufferAssetCreator.SetUseCommonPool(AZ::RPI::CommonBufferPoolType::DynamicInputAssembly); + bufferAssetCreator.SetUseCommonPool(AZ::RPI::CommonBufferPoolType::StaticInputAssembly); bufferAssetCreator.SetBuffer(data.data(), bufferDescriptor.m_byteCount, bufferDescriptor); bufferAssetCreator.SetBufferViewDescriptor(m_bufferViewDescriptor); From 07c0f05abb31a7176e0c1b508c87ac2dd21fa5cb Mon Sep 17 00:00:00 2001 From: mriegger <mriegger@amazon.com> Date: Wed, 21 Apr 2021 11:54:37 -0700 Subject: [PATCH 60/96] Fix for directional light not having shadows in editor --- .../CoreLights/DirectionalLightFeatureProcessor.cpp | 2 ++ .../DirectionalLightComponentController.cpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index f44a56233e..04175c461f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -1238,6 +1238,8 @@ namespace AZ void DirectionalLightFeatureProcessor::SetFilterParameterToPass(LightHandle handle, const RPI::View* cameraView) { + AZ_ATOM_PROFILE_FUNCTION("DirectionalLightFeatureProcessor", "DirectionalLightFeatureProcessor::SetFilterParameterToPass"); + if (handle != m_shadowingLightHandle) { return; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp index c7d459c596..310e6e6eca 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/DirectionalLightComponentController.cpp @@ -19,6 +19,9 @@ #include <AzCore/Component/TransformBus.h> #include <AzCore/Serialization/SerializeContext.h> #include <AzCore/std/containers/vector.h> +#include <Atom/RPI.Public/ViewportContext.h> +#include <Atom/RPI.Public/ViewportContextBus.h> +#include <Atom/RPI.Public/ViewProviderBus.h> namespace AZ { @@ -586,9 +589,11 @@ namespace AZ } else { - Camera::ActiveCameraRequestBus::BroadcastResult( - cameraTransform, - &Camera::ActiveCameraRequestBus::Events::GetActiveCameraTransform); + if (const auto& viewportContext = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get()->GetDefaultViewportContext()) + { + cameraTransform = viewportContext->GetCameraTransform(); + } + } if (cameraTransform == m_lastCameraTransform) { From 0efa1e78172766677efee75cd9ff00045ab5117c Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Wed, 21 Apr 2021 13:57:16 -0500 Subject: [PATCH 61/96] [LYN-3105] Removed legacy CEditTool class and all sub-classes. --- .../API/ToolsApplicationAPI.h | 2 - Code/Sandbox/Editor/2DViewport.cpp | 6 - Code/Sandbox/Editor/Controls/QRollupCtrl.cpp | 588 ------- Code/Sandbox/Editor/Controls/QRollupCtrl.h | 126 -- Code/Sandbox/Editor/Controls/ToolButton.cpp | 171 -- Code/Sandbox/Editor/Controls/ToolButton.h | 60 - .../Editor/Core/LevelEditorMenuHandler.cpp | 1 - Code/Sandbox/Editor/CryEdit.cpp | 150 -- Code/Sandbox/Editor/CryEdit.h | 7 - Code/Sandbox/Editor/CryEditDoc.cpp | 1 - Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp | 123 -- Code/Sandbox/Editor/Dialogs/ButtonsPanel.h | 76 - Code/Sandbox/Editor/EditMode/ObjectMode.cpp | 1525 ----------------- Code/Sandbox/Editor/EditMode/ObjectMode.h | 134 -- .../EditMode/VertexSnappingModeTool.cpp | 430 ----- .../Editor/EditMode/VertexSnappingModeTool.h | 91 - Code/Sandbox/Editor/EditTool.cpp | 89 - Code/Sandbox/Editor/EditTool.h | 175 -- .../Editor/EditorPreferencesPageGeneral.cpp | 21 - .../Editor/EditorPreferencesPageGeneral.h | 9 - Code/Sandbox/Editor/EditorViewportWidget.cpp | 1 - Code/Sandbox/Editor/GameExporter.cpp | 3 - Code/Sandbox/Editor/IEditor.h | 9 - Code/Sandbox/Editor/IEditorImpl.cpp | 157 -- Code/Sandbox/Editor/IEditorImpl.h | 13 - Code/Sandbox/Editor/Include/IObjectManager.h | 2 - Code/Sandbox/Editor/InfoBar.cpp | 61 +- Code/Sandbox/Editor/InfoBar.h | 1 - Code/Sandbox/Editor/Lib/Tests/IEditorMock.h | 4 - Code/Sandbox/Editor/MainWindow.cpp | 23 - .../Editor/Material/MaterialPickTool.cpp | 170 -- .../Editor/Material/MaterialPickTool.h | 57 - Code/Sandbox/Editor/NullEditTool.cpp | 37 - Code/Sandbox/Editor/NullEditTool.h | 39 - Code/Sandbox/Editor/ObjectCloneTool.cpp | 336 ---- Code/Sandbox/Editor/ObjectCloneTool.h | 81 - Code/Sandbox/Editor/Objects/AxisGizmo.cpp | 25 - Code/Sandbox/Editor/Objects/BaseObject.cpp | 6 - Code/Sandbox/Editor/Objects/ObjectManager.cpp | 83 - Code/Sandbox/Editor/Objects/ObjectManager.h | 2 - .../Editor/RenderHelpers/AxisHelperShared.inl | 1 - Code/Sandbox/Editor/RenderViewport.cpp | 40 - Code/Sandbox/Editor/Resource.h | 2 - Code/Sandbox/Editor/RotateTool.cpp | 1059 ------------ Code/Sandbox/Editor/RotateTool.h | 283 --- Code/Sandbox/Editor/Settings.cpp | 12 - Code/Sandbox/Editor/Settings.h | 15 - Code/Sandbox/Editor/ToolbarManager.cpp | 3 - Code/Sandbox/Editor/Viewport.cpp | 93 +- Code/Sandbox/Editor/Viewport.h | 9 - Code/Sandbox/Editor/VoxelAligningTool.cpp | 151 -- Code/Sandbox/Editor/VoxelAligningTool.h | 75 - Code/Sandbox/Editor/editor_lib_files.cmake | 22 - .../ComponentEntityEditorPlugin_precompiled.h | 1 - .../Objects/ComponentEntityObject.cpp | 8 - .../Objects/ComponentEntityObject.h | 2 + .../SandboxIntegration.cpp | 5 - .../SandboxIntegration.h | 1 - .../UI/Outliner/OutlinerWidget.cpp | 13 - Gems/Camera/Code/Source/Camera_precompiled.h | 1 - 60 files changed, 14 insertions(+), 6677 deletions(-) delete mode 100644 Code/Sandbox/Editor/Controls/QRollupCtrl.cpp delete mode 100644 Code/Sandbox/Editor/Controls/QRollupCtrl.h delete mode 100644 Code/Sandbox/Editor/Controls/ToolButton.cpp delete mode 100644 Code/Sandbox/Editor/Controls/ToolButton.h delete mode 100644 Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp delete mode 100644 Code/Sandbox/Editor/Dialogs/ButtonsPanel.h delete mode 100644 Code/Sandbox/Editor/EditMode/ObjectMode.cpp delete mode 100644 Code/Sandbox/Editor/EditMode/ObjectMode.h delete mode 100644 Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp delete mode 100644 Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h delete mode 100644 Code/Sandbox/Editor/EditTool.cpp delete mode 100644 Code/Sandbox/Editor/EditTool.h delete mode 100644 Code/Sandbox/Editor/Material/MaterialPickTool.cpp delete mode 100644 Code/Sandbox/Editor/Material/MaterialPickTool.h delete mode 100644 Code/Sandbox/Editor/NullEditTool.cpp delete mode 100644 Code/Sandbox/Editor/NullEditTool.h delete mode 100644 Code/Sandbox/Editor/ObjectCloneTool.cpp delete mode 100644 Code/Sandbox/Editor/ObjectCloneTool.h delete mode 100644 Code/Sandbox/Editor/RotateTool.cpp delete mode 100644 Code/Sandbox/Editor/RotateTool.h delete mode 100644 Code/Sandbox/Editor/VoxelAligningTool.cpp delete mode 100644 Code/Sandbox/Editor/VoxelAligningTool.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h index f12ab71936..cca5d1b9e4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ToolsApplicationAPI.h @@ -815,8 +815,6 @@ namespace AzToolsFramework /// Hide or show the circular dependency error when saving slices virtual void SetShowCircularDependencyError(const bool& /*showCircularDependencyError*/) {} - virtual void SetEditTool(const char* /*tool*/) {} - /// Launches the Lua editor and opens the specified (space separated) files. virtual void LaunchLuaEditor(const char* /*files*/) {} diff --git a/Code/Sandbox/Editor/2DViewport.cpp b/Code/Sandbox/Editor/2DViewport.cpp index e6e62be1f1..d86ea03bdf 100644 --- a/Code/Sandbox/Editor/2DViewport.cpp +++ b/Code/Sandbox/Editor/2DViewport.cpp @@ -20,7 +20,6 @@ #include "2DViewport.h" #include "CryEditDoc.h" #include "DisplaySettings.h" -#include "EditTool.h" #include "GameEngine.h" #include "Settings.h" #include "ViewManager.h" @@ -1117,11 +1116,6 @@ void Q2DViewport::DrawObjects(DisplayContext& dc) GetIEditor()->GetObjectManager()->Display(dc); } - // Display editing tool. - if (GetEditTool()) - { - GetEditTool()->Display(dc); - } dc.PopMatrix(); } diff --git a/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp b/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp deleted file mode 100644 index ea91bdcd62..0000000000 --- a/Code/Sandbox/Editor/Controls/QRollupCtrl.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - -#include "EditorDefs.h" - -#include "QRollupCtrl.h" - -// Qt -#include <QMenu> -#include <QStylePainter> -#include <QVBoxLayout> -#include <QSettings> -#include <QToolButton> -#include <QStyleOptionToolButton> - -////////////////////////////////////////////////////////////////////////// - -class QRollupCtrlButton - : public QToolButton -{ -public: - QRollupCtrlButton(QWidget* parent); - - inline void setSelected(bool b) { selected = b; update(); } - inline bool isSelected() const { return selected; } - - QSize sizeHint() const override; - QSize minimumSizeHint() const override; - -protected: - void paintEvent(QPaintEvent*) override; - -private: - bool selected; -}; - -QRollupCtrlButton::QRollupCtrlButton(QWidget* parent) - : QToolButton(parent) - , selected(true) -{ - setBackgroundRole(QPalette::Window); - setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); - setFocusPolicy(Qt::NoFocus); - - setStyleSheet("* {margin: 2px 5px 2px 5px; border: 1px solid #CBA457;}"); -} - -QSize QRollupCtrlButton::sizeHint() const -{ - QSize iconSize(8, 8); - if (!icon().isNull()) - { - int icone = style()->pixelMetric(QStyle::PM_SmallIconSize); - iconSize += QSize(icone + 2, icone); - } - QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text()) + QSize(0, 8); - - QSize total(iconSize.width() + textSize.width(), qMax(iconSize.height(), textSize.height())); - return total.expandedTo(QApplication::globalStrut()); -} - -QSize QRollupCtrlButton::minimumSizeHint() const -{ - if (icon().isNull()) - { - return QSize(); - } - int icone = style()->pixelMetric(QStyle::PM_SmallIconSize); - return QSize(icone + 8, icone + 8); -} - -void QRollupCtrlButton::paintEvent(QPaintEvent*) -{ - QStylePainter p(this); - // draw the background manually, not to clash with UI 2.0 style shets - // the numbers here are taken from the stylesheet in the constructor - p.fillRect(QRect(5, 1, width() - 10, height() - 3), QColor(52, 52, 52)); - - { - QStyleOptionToolButton opt; - initStyleOption(&opt); - if (isSelected()) - { - if (opt.state & QStyle::State_MouseOver) - { - opt.state |= QStyle::State_Sunken; - } - opt.state |= QStyle::State_MouseOver; - } - p.drawComplexControl(QStyle::CC_ToolButton, opt); - } - - { - p.setPen(QPen(QColor(132, 128, 125))); - - int top = height() / 2 - 2; - p.drawLine(2, top, 4, top); - p.drawLine(width() - 5, top, width() - 3, top); - - int bottom = !isSelected() ? top + 4 : height(); - p.drawLine(2, bottom, 2, top); - p.drawLine(width() - 3, bottom, width() - 3, top); - - if (!isSelected()) - { - p.drawLine(2, bottom, 4, bottom); - p.drawLine(width() - 5, bottom, width() - 3, bottom); - } - } -} - -////////////////////////////////////////////////////////////////////////// - -QRollupCtrl::Page* QRollupCtrl::page(QWidget* widget) const -{ - if (!widget) - { - return 0; - } - - for (PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - if ((*i).widget == widget) - { - return (Page*)&(*i); - } - } - return 0; -} - -QRollupCtrl::Page* QRollupCtrl::page(int index) -{ - if (index >= 0 && index < m_pageList.size()) - { - return &m_pageList[index]; - } - return 0; -} - -const QRollupCtrl::Page* QRollupCtrl::page(int index) const -{ - if (index >= 0 && index < m_pageList.size()) - { - return &m_pageList.at(index); - } - return 0; -} - -inline void QRollupCtrl::Page::setText(const QString& text) { button->setText(text); } -inline void QRollupCtrl::Page::setIcon(const QIcon& is) { button->setIcon(is); } -inline void QRollupCtrl::Page::setToolTip(const QString& tip) { button->setToolTip(tip); } -inline QString QRollupCtrl::Page::text() const { return button->text(); } -inline QIcon QRollupCtrl::Page::icon() const { return button->icon(); } -inline QString QRollupCtrl::Page::toolTip() const { return button->toolTip(); } - -////////////////////////////////////////////////////////////////////////// - -QRollupCtrl::QRollupCtrl(QWidget* parent) - : QScrollArea(parent) - , m_layout(0) -{ - m_body = new QWidget(this); - m_body->setBackgroundRole(QPalette::Button); - setWidgetResizable(true); - setAlignment(Qt::AlignLeft | Qt::AlignTop); - setWidget(m_body); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - relayout(); -} - -QRollupCtrl::~QRollupCtrl() -{ - foreach(const QRollupCtrl::Page & c, m_pageList) - disconnect(c.widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); -} - -void QRollupCtrl::readSettings(const QString& qSettingsGroup) -{ - QSettings settings; - settings.beginGroup(qSettingsGroup); - - int i = 0; - foreach(const QRollupCtrl::Page & c, m_pageList) { - QString qObjectName = c.widget->objectName(); - - bool bHidden = settings.value(qObjectName, true).toBool(); - setIndexVisible(i++, !bHidden); - } - - settings.endGroup(); -} - -void QRollupCtrl::writeSettings(const QString& qSettingsGroup) -{ - QSettings settings; - settings.beginGroup(qSettingsGroup); - - for (int i = 0; i < count(); i++) - { - QString qObjectName; - bool bHidden = isPageHidden(i, qObjectName); - - settings.setValue(qObjectName, bHidden); - } -} - -void QRollupCtrl::updateTabs() -{ - for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - QRollupCtrlButton* tB = (*i).button; - QWidget* tW = (*i).sv; - tB->setSelected(tW->isVisible()); - tB->update(); - } -} - -int QRollupCtrl::insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text) -{ - if (!widget) - { - return -1; - } - - auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; }); - if (it != m_pageList.cend()) - { - return -1; - } - - connect(widget, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); - - QRollupCtrl::Page c; - c.widget = widget; - c.button = new QRollupCtrlButton(m_body); - c.button->setContextMenuPolicy(Qt::CustomContextMenu); - connect(c.button, &QRollupCtrlButton::clicked, this, &QRollupCtrl::_q_buttonClicked); - connect(c.button, &QRollupCtrlButton::customContextMenuRequested, this, &QRollupCtrl::_q_custumButtonMenu); - - c.sv = new QFrame(m_body); - c.sv->setObjectName("rollupPaneFrame"); - // c.sv->setFixedHeight(qMax(widget->sizeHint().height(), widget->size().height())); - QVBoxLayout* layout = new QVBoxLayout; - layout->setMargin(3); - layout->addWidget(widget); - c.sv->setLayout(layout); - c.sv->setStyleSheet("QFrame#rollupPaneFrame {margin: 0px 2px 2px 2px; border: 1px solid #84807D; border-top:0px;}"); - c.sv->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - c.sv->show(); - - c.setText(text); - c.setIcon(icon); - - const int numPages = m_pageList.count(); - if (index < 0 || index >= numPages) - { - m_pageList.append(c); - index = numPages - 1; - m_layout->insertWidget(m_layout->count() - 1, c.button); - m_layout->insertWidget(m_layout->count() - 1, c.sv); - } - else - { - m_pageList.insert(index, c); - relayout(); - } - - c.button->show(); - - updateTabs(); - itemInserted(index); - return index; -} - -void QRollupCtrl::_q_buttonClicked() -{ - QObject* tb = sender(); - QWidget* item = 0; - for (auto i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - if ((*i).button == tb) - { - item = (*i).widget; - break; - } - } - - if (item) - { - setIndexVisible(indexOf(item), !item->isVisible()); - } -} - -int QRollupCtrl::count() const -{ - return m_pageList.count(); -} - -bool QRollupCtrl::isPageHidden(int index, QString& qObjectName) const -{ - if (index < 0 || index >= m_pageList.size()) - { - return true; - } - const QRollupCtrl::Page& c = m_pageList.at(index); - qObjectName = c.widget->objectName(); - return c.sv->isHidden(); -} - -void QRollupCtrl::setIndexVisible(int index, bool visible) -{ - QRollupCtrl::Page* c = page(index); - if (!c) - { - return; - } - - if (c->sv->isHidden() && visible) - { - c->sv->show(); - } - else if (c->sv->isVisible() && !visible) - { - c->sv->hide(); - } - updateTabs(); -} - -void QRollupCtrl::setWidgetVisible(QWidget* widget, bool visible) -{ - setIndexVisible(indexOf(widget), visible); -} - -void QRollupCtrl::relayout() -{ - delete m_layout; - m_layout = new QVBoxLayout(m_body); - m_layout->setMargin(3); - m_layout->setSpacing(0); - for (QRollupCtrl::PageList::ConstIterator i = m_pageList.constBegin(); i != m_pageList.constEnd(); ++i) - { - m_layout->addWidget((*i).button); - m_layout->addWidget((*i).sv); - } - m_layout->addStretch(); - updateTabs(); -} - -void QRollupCtrl::_q_widgetDestroyed(QObject* object) -{ - // no verification - vtbl corrupted already - QWidget* p = (QWidget*)object; - - QRollupCtrl::Page* c = page(p); - if (!p || !c) - { - return; - } - - m_layout->removeWidget(c->sv); - m_layout->removeWidget(c->button); - c->sv->deleteLater(); // page might still be a child of sv - delete c->button; - - m_pageList.removeOne(*c); -} - -void QRollupCtrl::_q_custumButtonMenu([[maybe_unused]] const QPoint& pos) -{ - QMenu menu; - menu.addAction("Expand All")->setData(-1); - menu.addAction("Collapse All")->setData(-2); - menu.addSeparator(); - for (int i = 0; i < m_pageList.size(); ++i) - { - QRollupCtrl::Page* c = page(i); - QAction* action = menu.addAction(c->button->text()); - action->setCheckable(true); - action->setChecked(c->sv->isVisible()); - action->setData(i); - } - - QAction* action = menu.exec(QCursor::pos()); - if (!action) - { - return; - } - int res = action->data().toInt(); - switch (res) - { - case -1: // fall through - case -2: - expandAllPages(res == -1); - break; - default: - { - QRollupCtrl::Page* c = page(res); - if (c) - { - setIndexVisible(res, !c->sv->isVisible()); - } - } - break; - } -} - -void QRollupCtrl::expandAllPages(bool v) -{ - for (int i = 0; i < m_pageList.size(); i++) - { - setIndexVisible(i, v); - } -} - -////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////// -void QRollupCtrl::clear() -{ - while (!m_pageList.isEmpty()) - { - removeItem(0); - } -} - -void QRollupCtrl::removeItem(QWidget* widget) -{ - auto it = std::find_if(m_pageList.cbegin(), m_pageList.cend(), [widget](const Page& page) { return page.widget == widget; }); - if (it != m_pageList.cend()) - { - removeItem(it - m_pageList.cbegin()); - } -} - -void QRollupCtrl::removeItem(int index) -{ - if (QWidget* w = widget(index)) - { - disconnect(w, &QObject::destroyed, this, &QRollupCtrl::_q_widgetDestroyed); - w->setParent(this); - // destroy internal data - _q_widgetDestroyed(w); - itemRemoved(index); - } -} - -QWidget* QRollupCtrl::widget(int index) const -{ - if (index < 0 || index >= (int) m_pageList.size()) - { - return 0; - } - return m_pageList.at(index).widget; -} - -int QRollupCtrl::indexOf(QWidget* widget) const -{ - QRollupCtrl::Page* c = page(widget); - return c ? m_pageList.indexOf(*c) : -1; -} - -void QRollupCtrl::setItemEnabled(int index, bool enabled) -{ - QRollupCtrl::Page* c = page(index); - if (!c) - { - return; - } - - c->button->setEnabled(enabled); - if (!enabled) - { - int curIndexUp = index; - int curIndexDown = curIndexUp; - const int count = m_pageList.count(); - while (curIndexUp > 0 || curIndexDown < count - 1) - { - if (curIndexDown < count - 1) - { - if (page(++curIndexDown)->button->isEnabled()) - { - index = curIndexDown; - break; - } - } - if (curIndexUp > 0) - { - if (page(--curIndexUp)->button->isEnabled()) - { - index = curIndexUp; - break; - } - } - } - } -} - -void QRollupCtrl::setItemText(int index, const QString& text) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setText(text); - } -} - -void QRollupCtrl::setItemIcon(int index, const QIcon& icon) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setIcon(icon); - } -} - -void QRollupCtrl::setItemToolTip(int index, const QString& toolTip) -{ - QRollupCtrl::Page* c = page(index); - if (c) - { - c->setToolTip(toolTip); - } -} - -bool QRollupCtrl::isItemEnabled(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return c && c->button->isEnabled(); -} - -QString QRollupCtrl::itemText(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->text() : QString()); -} - -QIcon QRollupCtrl::itemIcon(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->icon() : QIcon()); -} - -QString QRollupCtrl::itemToolTip(int index) const -{ - const QRollupCtrl::Page* c = page(index); - return (c ? c->toolTip() : QString()); -} - -void QRollupCtrl::changeEvent(QEvent* ev) -{ - if (ev->type() == QEvent::StyleChange) - { - updateTabs(); - } - QFrame::changeEvent(ev); -} - -void QRollupCtrl::showEvent(QShowEvent* ev) -{ - if (isVisible()) - { - updateTabs(); - } - IEditor* pEditor = GetIEditor(); - pEditor->SetEditMode(EEditMode::eEditModeSelect); - QFrame::showEvent(ev); -} - -void QRollupCtrl::itemInserted(int index) -{ - Q_UNUSED(index) -} - -void QRollupCtrl::itemRemoved(int index) -{ - Q_UNUSED(index) -} - - -#include <Controls/moc_QRollupCtrl.cpp> diff --git a/Code/Sandbox/Editor/Controls/QRollupCtrl.h b/Code/Sandbox/Editor/Controls/QRollupCtrl.h deleted file mode 100644 index 3db8bdf860..0000000000 --- a/Code/Sandbox/Editor/Controls/QRollupCtrl.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H -#define CRYINCLUDE_EDITOR_CONTROLS_QROLLUPCTRL_H - -/* - * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or - * its licensors. - * - * For complete copyright and license terms please see the LICENSE at the root of this - * distribution (the "License"). All use of this software is governed by the License, - * or, if provided, by the license below or the license accompanying this file. Do not - * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - */ - - -#if !defined(Q_MOC_RUN) -#include <QFrame> -#include <QScrollArea> -#include <QIcon> -#endif - -class QVBoxLayout; -class QRollupCtrlButton; - -class QRollupCtrl - : public QScrollArea -{ - Q_OBJECT - Q_PROPERTY(int count READ count) - -public: - explicit QRollupCtrl(QWidget* parent = 0); - ~QRollupCtrl(); - - int addItem(QWidget* widget, const QString& text); - int addItem(QWidget* widget, const QIcon& icon, const QString& text); - int insertItem(int index, QWidget* widget, const QString& text); - int insertItem(int index, QWidget* widget, const QIcon& icon, const QString& text); - - void clear(); - void removeItem(QWidget* widget); - void removeItem(int index); - - void setItemEnabled(int index, bool enabled); - bool isItemEnabled(int index) const; - - void setItemText(int index, const QString& text); - QString itemText(int index) const; - - void setItemIcon(int index, const QIcon& icon); - QIcon itemIcon(int index) const; - - void setItemToolTip(int index, const QString& toolTip); - QString itemToolTip(int index) const; - - QWidget* widget(int index) const; - int indexOf(QWidget* widget) const; - int count() const; - - void readSettings (const QString& qSettingsGroup); - void writeSettings(const QString& qSettingsGroup); - -public slots: - void setIndexVisible(int index, bool visible); - void setWidgetVisible(QWidget* widget, bool visible); - void expandAllPages(bool v); - -protected: - virtual void itemInserted(int index); - virtual void itemRemoved(int index); - void changeEvent(QEvent*) override; - void showEvent(QShowEvent*) override; - -private: - Q_DISABLE_COPY(QRollupCtrl) - - struct Page - { - QRollupCtrlButton* button; - QFrame* sv; - QWidget* widget; - - void setText(const QString& text); - void setIcon(const QIcon& is); - void setToolTip(const QString& tip); - QString text() const; - QIcon icon() const; - QString toolTip() const; - - inline bool operator==(const Page& other) const - { - return widget == other.widget; - } - }; - typedef QList<Page> PageList; - - Page* page(QWidget* widget) const; - const Page* page(int index) const; - Page* page(int index); - - void updateTabs(); - void relayout(); - bool isPageHidden(int index, QString& qObjectName) const; - - QWidget* m_body; - PageList m_pageList; - QVBoxLayout* m_layout; - -private slots: - void _q_buttonClicked(); - void _q_widgetDestroyed(QObject*); - void _q_custumButtonMenu(const QPoint&); -}; - - -////////////////////////////////////////////////////////////////////////// - -inline int QRollupCtrl::addItem(QWidget* item, const QString& text) -{ return insertItem(-1, item, QIcon(), text); } -inline int QRollupCtrl::addItem(QWidget* item, const QIcon& iconSet, const QString& text) -{ return insertItem(-1, item, iconSet, text); } -inline int QRollupCtrl::insertItem(int index, QWidget* item, const QString& text) -{ return insertItem(index, item, QIcon(), text); } - -#endif diff --git a/Code/Sandbox/Editor/Controls/ToolButton.cpp b/Code/Sandbox/Editor/Controls/ToolButton.cpp deleted file mode 100644 index b74fe1a330..0000000000 --- a/Code/Sandbox/Editor/Controls/ToolButton.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : implementation file - - -#include "EditorDefs.h" - -// Editor -#include "CryEditDoc.h" -#include "EditTool.h" -#include "ToolButton.h" - - -QEditorToolButton::QEditorToolButton(QWidget* parent /* = nullptr */) - : QPushButton(parent) - , m_styleSheet(styleSheet()) - , m_toolClass(nullptr) - , m_toolCreated(nullptr) - , m_needDocument(true) -{ - setSizePolicy({ QSizePolicy::Expanding, QSizePolicy::Fixed }); - connect(this, &QAbstractButton::clicked, this, &QEditorToolButton::OnClicked); - GetIEditor()->RegisterNotifyListener(this); -} - -QEditorToolButton::~QEditorToolButton() -{ - GetIEditor()->UnregisterNotifyListener(this); -} - -void QEditorToolButton::SetToolName(const QString& editToolName, const QString& userDataKey, void* userData) -{ - IClassDesc* klass = GetIEditor()->GetClassFactory()->FindClass(editToolName.toUtf8().data()); - if (!klass) - { - Warning(QStringLiteral("Editor Tool %1 not registered.").arg(editToolName).toUtf8().data()); - return; - } - if (klass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL) - { - Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data()); - return; - } - - QScopedPointer<QObject> o(klass->CreateQObject()); - if (!qobject_cast<CEditTool*>(o.data())) - { - Warning(QStringLiteral("Class name %1 is not a valid Edit Tool class.").arg(editToolName).toUtf8().data()); - return; - } - SetToolClass(o->metaObject(), userDataKey, userData); -} - -////////////////////////////////////////////////////////////////////////// -void QEditorToolButton::SetToolClass(const QMetaObject* toolClass, const QString& userDataKey, void* userData) -{ - m_toolClass = toolClass; - - m_userData = userData; - if (!userDataKey.isEmpty()) - { - m_userDataKey = userDataKey; - } -} - -void QEditorToolButton::OnEditorNotifyEvent(EEditorNotifyEvent event) -{ - switch (event) - { - case eNotify_OnBeginNewScene: - case eNotify_OnBeginLoad: - case eNotify_OnBeginSceneOpen: - { - if (m_needDocument) - { - setEnabled(false); - } - break; - } - - case eNotify_OnEndNewScene: - case eNotify_OnEndLoad: - case eNotify_OnEndSceneOpen: - { - if (m_needDocument) - { - setEnabled(true); - } - break; - } - case eNotify_OnEditToolChange: - { - CEditTool* tool = GetIEditor()->GetEditTool(); - - if (!tool || tool != m_toolCreated || tool->metaObject() != m_toolClass) - { - m_toolCreated = nullptr; - SetSelected(false); - } - } - default: - break; - } -} - -void QEditorToolButton::OnClicked() -{ - if (!m_toolClass) - { - return; - } - - if (m_needDocument && !GetIEditor()->GetDocument()->IsDocumentReady()) - { - return; - } - - CEditTool* tool = GetIEditor()->GetEditTool(); - if (tool && tool->IsMoveToObjectModeAfterEnd() && tool->metaObject() == m_toolClass && tool == m_toolCreated) - { - GetIEditor()->SetEditTool(nullptr); - SetSelected(false); - } - else - { - CEditTool* newTool = qobject_cast<CEditTool*>(m_toolClass->newInstance()); - if (!newTool) - { - return; - } - - m_toolCreated = newTool; - - SetSelected(true); - - if (m_userData) - { - newTool->SetUserData(m_userDataKey.toUtf8().data(), (void*)m_userData); - } - - update(); - - // Must be last function, can delete this. - GetIEditor()->SetEditTool(newTool); - } -} - -void QEditorToolButton::SetSelected(bool selected) -{ - if (selected) - { - setStyleSheet(QStringLiteral("QPushButton { background-color: palette(highlight); color: palette(highlighted-text); }")); - } - else - { - setStyleSheet(m_styleSheet); - } -} - -#include <Controls/moc_ToolButton.cpp> diff --git a/Code/Sandbox/Editor/Controls/ToolButton.h b/Code/Sandbox/Editor/Controls/ToolButton.h deleted file mode 100644 index f32bd6678d..0000000000 --- a/Code/Sandbox/Editor/Controls/ToolButton.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H -#define CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H -#pragma once - -// ToolButton.h : header file -// - -#if !defined(Q_MOC_RUN) -#include <AzCore/PlatformDef.h> -#include <QPushButton> -#endif - -AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING -class SANDBOX_API QEditorToolButton - : public QPushButton - , public IEditorNotifyListener -{ -AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING - Q_OBJECT - // Construction -public: - QEditorToolButton(QWidget* parent = nullptr); - virtual ~QEditorToolButton(); - - void SetToolClass(const QMetaObject* toolClass, const QString& userDataKey = 0, void* userData = nullptr); - void SetToolName(const QString& editToolName, const QString& userDataKey = 0, void* userData = nullptr); - // Set if this tool button relies on a loaded level / ready document. By default every tool button only works if a level is loaded. - // However some tools are also used without a loaded level (e.g. UI Emulator) - void SetNeedDocument(bool needDocument) { m_needDocument = needDocument; } - - void SetSelected(bool selected); - void OnEditorNotifyEvent(EEditorNotifyEvent event) override; -protected: - void OnClicked(); - - const QString m_styleSheet; - - //! Tool associated with this button. - const QMetaObject* m_toolClass; - CEditTool* m_toolCreated; - QString m_userDataKey; - void* m_userData; - bool m_needDocument; -}; - - -#endif // CRYINCLUDE_EDITOR_CONTROLS_TOOLBUTTON_H diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index f00085d5ad..0863e1627f 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -580,7 +580,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe auto alignMenu = modifyMenu.AddMenu(tr("Align")); alignMenu.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID); - alignMenu.AddAction(ID_MODIFY_ALIGNOBJTOSURF); auto constrainMenu = modifyMenu.AddMenu(tr("Constrain")); constrainMenu.AddAction(ID_SELECT_AXIS_X); diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index 7aefcffb5a..b373ef0009 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -95,7 +95,6 @@ AZ_POP_DISABLE_WARNING #include "Core/QtEditorApplication.h" #include "StringDlg.h" -#include "VoxelAligningTool.h" #include "NewLevelDialog.h" #include "GridSettingsDialog.h" #include "LayoutConfigDialog.h" @@ -110,7 +109,6 @@ AZ_POP_DISABLE_WARNING #include "DisplaySettings.h" #include "GameEngine.h" -#include "ObjectCloneTool.h" #include "StartupTraceHandler.h" #include "ThumbnailGenerator.h" #include "ToolsConfigPage.h" @@ -153,7 +151,6 @@ AZ_POP_DISABLE_WARNING #include "LevelIndependentFileMan.h" #include "WelcomeScreen/WelcomeScreenDialog.h" #include "Dialogs/DuplicatedObjectsHandlerDlg.h" -#include "EditMode/VertexSnappingModeTool.h" #include "Controls/ReflectedPropertyControl/PropertyCtrl.h" #include "Controls/ReflectedPropertyControl/ReflectedVar.h" @@ -399,11 +396,8 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDITMODE_ROTATE, OnEditmodeRotate) ON_COMMAND(ID_EDITMODE_SCALE, OnEditmodeScale) ON_COMMAND(ID_EDITMODE_SELECT, OnEditmodeSelect) - ON_COMMAND(ID_EDIT_ESCAPE, OnEditEscape) ON_COMMAND(ID_OBJECTMODIFY_SETAREA, OnObjectSetArea) ON_COMMAND(ID_OBJECTMODIFY_SETHEIGHT, OnObjectSetHeight) - ON_COMMAND(ID_OBJECTMODIFY_VERTEXSNAPPING, OnObjectVertexSnapping) - ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel) ON_COMMAND(ID_OBJECTMODIFY_FREEZE, OnObjectmodifyFreeze) ON_COMMAND(ID_OBJECTMODIFY_UNFREEZE, OnObjectmodifyUnfreeze) ON_COMMAND(ID_EDITMODE_SELECTAREA, OnEditmodeSelectarea) @@ -413,11 +407,9 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_SELECT_AXIS_XY, OnSelectAxisXy) ON_COMMAND(ID_UNDO, OnUndo) ON_COMMAND(ID_TOOLBAR_WIDGET_REDO, OnUndo) // Can't use the same ID, because for the menu we can't have a QWidgetAction, while for the toolbar we want one - ON_COMMAND(ID_EDIT_CLONE, OnEditClone) ON_COMMAND(ID_SELECTION_SAVE, OnSelectionSave) ON_COMMAND(ID_IMPORT_ASSET, OnOpenAssetImporter) ON_COMMAND(ID_SELECTION_LOAD, OnSelectionLoad) - ON_COMMAND(ID_MODIFY_ALIGNOBJTOSURF, OnAlignToVoxel) ON_COMMAND(ID_OBJECTMODIFY_ALIGNTOGRID, OnAlignToGrid) ON_COMMAND(ID_LOCK_SELECTION, OnLockSelection) ON_COMMAND(ID_EDIT_LEVELDATA, OnEditLevelData) @@ -524,12 +516,10 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_OPEN_MATERIAL_EDITOR, OnOpenMaterialEditor) ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch) - ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool) ON_COMMAND(ID_DISPLAY_SHOWHELPERS, OnShowHelpers) ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView) ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor) ON_COMMAND(ID_GOTO_VIEWPORTSEARCH, OnGotoViewportSearch) - ON_COMMAND(ID_MATERIAL_PICKTOOL, OnMaterialPicktool) ON_COMMAND(ID_TERRAIN_TIMEOFDAY, OnTimeOfDay) ON_COMMAND(ID_TERRAIN_TIMEOFDAYBUTTON, OnTimeOfDay) @@ -2739,15 +2729,6 @@ void CCryEditApp::OnEditDelete() ////////////////////////////////////////////////////////////////////////// void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendants) { - // If Edit tool active cannot delete object. - if (GetIEditor()->GetEditTool()) - { - if (GetIEditor()->GetEditTool()->OnKeyDown(GetIEditor()->GetViewManager()->GetView(0), VK_DELETE, 0, 0)) - { - return; - } - } - GetIEditor()->BeginUndo(); CUndo undo("Delete Selected Object"); GetIEditor()->GetObjectManager()->DeleteSelection(); @@ -2756,75 +2737,6 @@ void CCryEditApp::DeleteSelectedEntities([[maybe_unused]] bool includeDescendant GetIEditor()->SetModifiedModule(eModifiedBrushes); } -void CCryEditApp::OnEditClone() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - if (GetIEditor()->GetObjectManager()->GetSelection()->IsEmpty()) - { - QMessageBox::critical(AzToolsFramework::GetActiveWindow(), QString(), - QObject::tr("You have to select objects before you can clone them!")); - return; - } - - // Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor is being edited. - if (QApplication::focusWidget()) - { - QApplication::focusWidget()->clearFocus(); - } - - CEditTool* tool = GetIEditor()->GetEditTool(); - if (tool && qobject_cast<CObjectCloneTool*>(tool)) - { - ((CObjectCloneTool*)tool)->Accept(); - } - - CObjectCloneTool* cloneTool = new CObjectCloneTool; - GetIEditor()->SetEditTool(cloneTool); - GetIEditor()->SetModifiedFlag(); - GetIEditor()->SetModifiedModule(eModifiedBrushes); - - // Accept the clone operation if users didn't choose to stick duplicated entities to the cursor - // This setting can be changed in the global preference of the editor - if (!gSettings.deepSelectionSettings.bStickDuplicate) - { - cloneTool->Accept(); - GetIEditor()->GetSelection()->FinishChanges(); - } - } -} - -void CCryEditApp::OnEditEscape() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - // Abort current operation. - if (pEditTool) - { - // If Edit tool active cannot delete object. - CViewport* vp = GetIEditor()->GetActiveView(); - if (GetIEditor()->GetEditTool()->OnKeyDown(vp, VK_ESCAPE, 0, 0)) - { - return; - } - - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - GetIEditor()->SetEditMode(eEditModeSelect); - } - - // Disable current tool. - GetIEditor()->SetEditTool(0); - } - else - { - // Clear selection on escape. - GetIEditor()->ClearSelection(); - } - } -} - void CCryEditApp::OnMoveObject() { //////////////////////////////////////////////////////////////////////// @@ -2986,14 +2898,6 @@ void CCryEditApp::OnUpdateEditmodeScale(QAction* action) } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateEditmodeVertexSnapping(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - action->setChecked(qobject_cast<CVertexSnappingModeTool*>(pEditTool) != nullptr); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnObjectSetArea() { @@ -3143,19 +3047,6 @@ void CCryEditApp::OnObjectSetHeight() } } -void CCryEditApp::OnObjectVertexSnapping() -{ - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (qobject_cast<CVertexSnappingModeTool*>(pEditTool)) - { - GetIEditor()->SetEditTool(NULL); - } - else - { - GetIEditor()->SetEditTool("EditTool.VertexSnappingMode"); - } -} - void CCryEditApp::OnObjectmodifyFreeze() { // Freeze selection. @@ -3480,37 +3371,8 @@ void CCryEditApp::OnAlignToGrid() } } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnAlignToVoxel() -{ - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr) - { - GetIEditor()->SetEditTool(nullptr); - } - else - { - GetIEditor()->SetEditTool(new CVoxelAligningTool()); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateAlignToVoxel(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - action->setChecked(qobject_cast<CVoxelAligningTool*>(pEditTool) != nullptr); - - action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty()); -} - void CCryEditApp::OnShowHelpers() { - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - return; - } GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()); GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate); } @@ -5136,12 +4998,6 @@ void CCryEditApp::OnOpenUICanvasEditor() QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnMaterialPicktool() -{ - GetIEditor()->SetEditTool("EditTool.PickMaterial"); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnTimeOfDay() { @@ -5296,12 +5152,6 @@ void CCryEditApp::OnOpenQuickAccessBar() return; } - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - return; - } - QRect geo = m_pQuickAccessBar->geometry(); geo.moveCenter(MainWindow::instance()->geometry().center()); m_pQuickAccessBar->setGeometry(geo); diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 94c39991e9..7c77a03bb4 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -225,11 +225,8 @@ public: void OnEditmodeRotate(); void OnEditmodeScale(); void OnEditmodeSelect(); - void OnEditEscape(); void OnObjectSetArea(); void OnObjectSetHeight(); - void OnObjectVertexSnapping(); - void OnUpdateEditmodeVertexSnapping(QAction* action); void OnUpdateEditmodeSelect(QAction* action); void OnUpdateEditmodeMove(QAction* action); void OnUpdateEditmodeRotate(QAction* action); @@ -247,14 +244,11 @@ public: void OnUpdateSelectAxisY(QAction* action); void OnUpdateSelectAxisZ(QAction* action); void OnUndo(); - void OnEditClone(); void OnSelectionSave(); void OnOpenAssetImporter(); void OnSelectionLoad(); void OnUpdateSelected(QAction* action); - void OnAlignToVoxel(); void OnAlignToGrid(); - void OnUpdateAlignToVoxel(QAction* action); void OnLockSelection(); void OnEditLevelData(); void OnFileEditLogFile(); @@ -491,7 +485,6 @@ private: void OnOpenAudioControlsEditor(); void OnOpenUICanvasEditor(); void OnGotoViewportSearch(); - void OnMaterialPicktool(); void OnTimeOfDay(); void OnChangeGameSpec(UINT nID); void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index 15269c1496..a94d588516 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -279,7 +279,6 @@ void CCryEditDoc::DeleteContents() // [LY-90904] move this to the EditorVegetationManager component InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData); - GetIEditor()->SetEditTool(0); // Turn off any active edit tools. GetIEditor()->SetEditMode(eEditModeSelect); ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp b/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp deleted file mode 100644 index 8314361585..0000000000 --- a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "ButtonsPanel.h" - -// Qt -#include <QGridLayout> - -// Editor -#include "Controls/ToolButton.h" - -///////////////////////////////////////////////////////////////////////////// -// CButtonsPanel dialog -CButtonsPanel::CButtonsPanel(QWidget* parent) - : QWidget(parent) -{ -} - -CButtonsPanel::~CButtonsPanel() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const SButtonInfo& button) -{ - SButton b; - b.info = button; - m_buttons.push_back(b); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const QString& name, const QString& toolClass) -{ - SButtonInfo bi; - bi.name = name; - bi.toolClassName = toolClass; - AddButton(bi); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::AddButton(const QString& name, const QMetaObject* pToolClass) -{ - SButtonInfo bi; - bi.name = name; - bi.pToolClass = pToolClass; - AddButton(bi); -} -////////////////////////////////////////////////////////////////////////// -void CButtonsPanel::ClearButtons() -{ - auto buttons = layout()->findChildren<QEditorToolButton*>(); - foreach(auto button, buttons) - { - layout()->removeWidget(button); - delete button; - } - m_buttons.clear(); -} - -void CButtonsPanel::UncheckAll() -{ - for (auto& button : m_buttons) - { - button.pButton->SetSelected(false); - } -} - -void CButtonsPanel::OnInitDialog() -{ - auto layout = new QGridLayout(this); - setLayout(layout); - - layout->setMargin(4); - layout->setHorizontalSpacing(4); - layout->setVerticalSpacing(1); - - // Create Buttons. - int index = 0; - for (auto& button : m_buttons) - { - button.pButton = new QEditorToolButton(this); - button.pButton->setObjectName(button.info.name); - button.pButton->setText(button.info.name); - button.pButton->SetNeedDocument(button.info.bNeedDocument); - button.pButton->setToolTip(button.info.toolTip); - - if (button.info.pToolClass) - { - button.pButton->SetToolClass(button.info.pToolClass, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str()); - } - else if (!button.info.toolClassName.isEmpty()) - { - button.pButton->SetToolName(button.info.toolClassName, button.info.toolUserDataKey, (void*)button.info.toolUserData.c_str()); - } - - layout->addWidget(button.pButton, index / 2, index % 2); - connect(button.pButton, &QEditorToolButton::clicked, this, [&]() { OnButtonPressed(button.info); }); - ++index; - } -} - -void CButtonsPanel::EnableButton(const QString& buttonName, bool enable) -{ - for (auto& button : m_buttons) - { - if (button.pButton->objectName() == buttonName) - { - button.pButton->setEnabled(enable); - } - } -} - -#include <Dialogs/moc_ButtonsPanel.cpp> diff --git a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h b/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h deleted file mode 100644 index c214c7625b..0000000000 --- a/Code/Sandbox/Editor/Dialogs/ButtonsPanel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H -#define CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include <QWidget> -#endif - -class QEditorToolButton; - -///////////////////////////////////////////////////////////////////////////// -// Panel with custom auto arranged buttons -class CButtonsPanel - : public QWidget -{ - Q_OBJECT -public: - - struct SButtonInfo - { - QString name; - QString toolClassName; - QString toolUserDataKey; - std::string toolUserData; - QString toolTip; - bool bNeedDocument; - const QMetaObject* pToolClass; - - SButtonInfo() - : pToolClass(nullptr) - , bNeedDocument(true) {}; - }; - - CButtonsPanel(QWidget* parent); - virtual ~CButtonsPanel(); - - virtual void AddButton(const SButtonInfo& button); - virtual void AddButton(const QString& name, const QString& toolClass); - virtual void AddButton(const QString& name, const QMetaObject* pToolClass); - virtual void EnableButton(const QString& buttonName, bool disable); - virtual void ClearButtons(); - - virtual void OnButtonPressed([[maybe_unused]] const SButtonInfo& button) {}; - virtual void UncheckAll(); - -protected: - void ReleaseGuiButtons(); - - virtual void OnInitDialog(); - - ////////////////////////////////////////////////////////////////////////// - struct SButton - { - SButtonInfo info; - QEditorToolButton* pButton; - SButton() - : pButton(nullptr) {}; - }; - - std::vector<SButton> m_buttons; -}; - -#endif // CRYINCLUDE_EDITOR_DIALOGS_BUTTONSPANEL_H diff --git a/Code/Sandbox/Editor/EditMode/ObjectMode.cpp b/Code/Sandbox/Editor/EditMode/ObjectMode.cpp deleted file mode 100644 index 3454cfefd3..0000000000 --- a/Code/Sandbox/Editor/EditMode/ObjectMode.cpp +++ /dev/null @@ -1,1525 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#if defined(AZ_PLATFORM_WINDOWS) -#include <InitGuid.h> -#endif - -#include "ObjectMode.h" - -// Qt -#include <QTimer> - -// AzToolsFramework -#include <AzToolsFramework/Entity/EditorEntityTransformBus.h> -#include <AzToolsFramework/ToolsComponents/EditorOnlyEntityComponentBus.h> -#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h> - -// Editor -#include "Viewport.h" -#include "ViewManager.h" -#include "Settings.h" -#include "Objects/SelectionGroup.h" - -#include "GameEngine.h" -#include "Objects/DisplayContext.h" -#include "Objects/EntityObject.h" -#include "AnimationContext.h" -#include "DeepSelection.h" -#include "SubObjectSelectionReferenceFrameCalculator.h" -#include "ITransformManipulator.h" -#include "SurfaceInfoPicker.h" -#include "RenderViewport.h" -#include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" - - -////////////////////////////////////////////////////////////////////////// -CObjectMode::CObjectMode(QObject* parent) - : CEditTool(parent) -{ - m_pClassDesc = GetIEditor()->GetClassFactory()->FindClass(OBJECT_MODE_GUID); - SetStatusText(tr("Object Selection")); - - m_openContext = false; - m_commandMode = NothingMode; - m_MouseOverObject = GuidUtil::NullGuid; - - m_pDeepSelection = new CDeepSelection(); - m_bMoveByFaceNormManipShown = false; - m_pHitObject = NULL; - - m_bTransformChanged = false; -} - -////////////////////////////////////////////////////////////////////////// -CObjectMode::~CObjectMode() -{ -} - -void CObjectMode::DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject) -{ - AABB bbox; - drawObject->GetBoundBox(bbox); - - AZStd::string cleanName = drawObject->GetName().toUtf8().data(); - - // Since we'll be passing this in as a format for a sprintf, need to cleanup any %'s so they display correctly - size_t index = cleanName.find("%", 0); - while (index != std::string::npos) - { - cleanName.insert(index, "%", 1); - - // Increment index past the replacement so it doesn't get picked up again on the next loop - index = cleanName.find("%", index + 2); - } - - // If CGroup/CPrefabObject - if (drawObject->GetChildCount() > 0) - { - // Draw object name label on top of object - Vec3 vTopEdgeCenterPos = bbox.GetCenter(); - - dc.SetColor(gSettings.objectColorSettings.groupHighlight); - vTopEdgeCenterPos(vTopEdgeCenterPos.x, vTopEdgeCenterPos.y, bbox.max.z); - dc.DrawTextLabel(vTopEdgeCenterPos, 1.3f, cleanName.c_str()); - // Draw bounding box wireframe - dc.DrawWireBox(bbox.min, bbox.max); - } - else - { - dc.SetColor(Vec3(1, 1, 1)); - dc.DrawTextLabel(bbox.GetCenter(), 1.5, cleanName.c_str()); - } - - // Object Geometry Highlight - - const float normalizedFloatToUint8 = 255.0f; - - // Default object - ColorB selColor = ColorB(gSettings.objectColorSettings.geometryHighlightColor.red(), gSettings.objectColorSettings.geometryHighlightColor.green(), gSettings.objectColorSettings.geometryHighlightColor.blue(), gSettings.objectColorSettings.fGeomAlpha * normalizedFloatToUint8); - - // In case it is a child object, use a different alpha value - if (drawObject->GetParent()) - { - selColor.a = (uint8)(gSettings.objectColorSettings.fChildGeomAlpha * normalizedFloatToUint8); - } - - // Draw geometry in custom color - SGeometryDebugDrawInfo dd; - dd.tm = drawObject->GetWorldTM(); - dd.color = selColor; - dd.lineColor = selColor; - dd.bExtrude = true; - - if (qobject_cast<CEntityObject*>(drawObject)) - { - dc.DepthTestOff(); - dc.SetColor(gSettings.objectColorSettings.entityHighlight, gSettings.objectColorSettings.fBBoxAlpha * normalizedFloatToUint8); - dc.DrawSolidBox(bbox.min, bbox.max); - dc.DepthTestOn(); - - CEntityObject* entityObj = (CEntityObject*)drawObject; - if (entityObj) - { - entityObj->DrawExtraLightInfo(dc); - } - } - - // Highlight also children objects if this object is opened - for (int gNo = 0; gNo < drawObject->GetChildCount(); ++gNo) - { - if (std::find(m_PreviewGUIDs.begin(), m_PreviewGUIDs.end(), drawObject->GetChild(gNo)->GetId()) == m_PreviewGUIDs.end()) - { - DrawSelectionPreview(dc, drawObject->GetChild(gNo)); - } - } -} - -void CObjectMode::DisplaySelectionPreview(struct DisplayContext& dc) -{ - CViewport* view = dc.view->asCViewport(); - IObjectManager* objMan = GetIEditor()->GetObjectManager(); - - if (!view) - { - return; - } - - QRect rc = view->GetSelectionRectangle(); - - if (GetCommandMode() == SelectMode) - { - if (rc.width() > 1 && rc.height() > 1) - { - GetIEditor()->GetObjectManager()->FindObjectsInRect(view, rc, m_PreviewGUIDs); - - QString selCountStr; - - // Do not include child objects in the count of object candidates - int childNo = 0; - for (int objNo = 0; objNo < m_PreviewGUIDs.size(); ++objNo) - { - if (objMan->FindObject(m_PreviewGUIDs[objNo])) - { - if (objMan->FindObject(m_PreviewGUIDs[objNo])->GetParent()) - { - ++childNo; - } - } - } - - selCountStr = QString::number(m_PreviewGUIDs.size() - childNo); - GetIEditor()->SetStatusText(tr("Selection Candidates Count: %1").arg(selCountStr)); - - // Draw Preview for objects - for (size_t i = 0; i < m_PreviewGUIDs.size(); ++i) - { - CBaseObject* curObj = GetIEditor()->GetObjectManager()->FindObject(m_PreviewGUIDs[i]); - - if (!curObj) - { - continue; - } - - DrawSelectionPreview(dc, curObj); - } - } - } -} - -void CObjectMode::DisplayExtraLightInfo(struct DisplayContext& dc) -{ - if (m_MouseOverObject != GUID_NULL) - { - IObjectManager* objMan = GetIEditor()->GetObjectManager(); - - if (objMan) - { - CBaseObject* hitObj = objMan->FindObject(m_MouseOverObject); - - if (hitObj) - { - if (objMan->IsLightClass(hitObj)) - { - CEntityObject* entityObj = (CEntityObject*)hitObj; - if (entityObj) - { - entityObj->DrawExtraLightInfo(dc); - } - } - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::EndEditParams() -{ - CBaseObject* pMouseOverObject = nullptr; - if (!GuidUtil::IsEmpty(m_MouseOverObject)) - { - pMouseOverObject = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject); - } - - if (pMouseOverObject) - { - pMouseOverObject->SetHighlight(false); - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::Display(struct DisplayContext& dc) -{ - // Selection Candidates Preview - DisplaySelectionPreview(dc); - DisplayExtraLightInfo(dc); - - GetIEditor()->GetSelection()->IndicateSnappingVertex(dc); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - switch (event) - { - case eMouseLDown: - return OnLButtonDown(view, flags, point); - break; - case eMouseLUp: - return OnLButtonUp(view, flags, point); - break; - case eMouseLDblClick: - return OnLButtonDblClk(view, flags, point); - break; - case eMouseRDown: - return OnRButtonDown(view, flags, point); - break; - case eMouseRUp: - return OnRButtonUp(view, flags, point); - break; - case eMouseMove: - return OnMouseMove(view, flags, point); - break; - case eMouseMDown: - return OnMButtonDown(view, flags, point); - break; - case eMouseLeave: - return OnMouseLeave(view); - break; - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->ClearSelection(); - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonDown(CViewport* view, int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (m_bMoveByFaceNormManipShown) - { - HideMoveByFaceNormGizmo(); - } - - // CPointF ptMarker; - QPoint ptCoord; - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore clicks while in game. - return false; - } - - // Allow interception of mouse clicks for custom behavior. - bool handledExternally = false; - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, - HandleObjectModeSelection, - AZ::Vector2(static_cast<float>(point.x()), static_cast<float>(point.y())), - nFlags, - handledExternally); - if (handledExternally) - { - return true; - } - - // Save the mouse down position - m_cMouseDownPos = point; - m_bDragThresholdExceeded = false; - - view->ResetSelectionRegion(); - - Vec3 pos = view->SnapToGrid(view->ViewToWorld(point)); - - // Swap X/Y - int unitSize = 1; - float hx = pos.y / unitSize; - float hy = pos.x / unitSize; - float hz = GetIEditor()->GetTerrainElevation(pos.x, pos.y); - - char szNewStatusText[512]; - sprintf_s(szNewStatusText, "Heightmap Coordinates: HX:%g HY:%g HZ:%g", hx, hy, hz); - GetIEditor()->SetStatusText(szNewStatusText); - - // Get control key status. - const bool bAltClick = (Qt::AltModifier & QApplication::queryKeyboardModifiers()); - bool bCtrlClick = (nFlags & MK_CONTROL); - bool bShiftClick = (nFlags & MK_SHIFT); - - bool bAddSelect = bCtrlClick; - bool bUnselect = bAltClick; - bool bNoRemoveSelection = bAddSelect || bUnselect; - - // Check deep selection mode activated - // The Deep selection has two mode. - // The normal mode pops the context menu, another is the cyclic selection on clinking. - const bool bTabPressed = CheckVirtualKey(Qt::Key_Tab); - const bool bZKeyPressed = CheckVirtualKey(Qt::Key_Z); - - CDeepSelection::EDeepSelectionMode dsMode = - (bTabPressed ? (bZKeyPressed ? CDeepSelection::DSM_POP : CDeepSelection::DSM_CYCLE) : CDeepSelection::DSM_NONE); - - bool bLockSelection = GetIEditor()->IsSelectionLocked(); - - int numUnselected = 0; - int numSelected = 0; - - // m_activeAxis = 0; - - HitContext hitInfo; - hitInfo.view = view; - if (bAddSelect || bUnselect) - { - // If adding or removing selection from the object, ignore hitting selection axis. - hitInfo.bIgnoreAxis = true; - } - - if (dsMode == CDeepSelection::DSM_POP) - { - m_pDeepSelection->Reset(true); - m_pDeepSelection->SetMode(dsMode); - hitInfo.pDeepSelection = m_pDeepSelection; - } - else if (dsMode == CDeepSelection::DSM_CYCLE) - { - if (!m_pDeepSelection->OnCycling(point)) - { - // Start of the deep selection cycling mode. - m_pDeepSelection->Reset(false); - m_pDeepSelection->SetMode(dsMode); - hitInfo.pDeepSelection = m_pDeepSelection; - } - } - else - { - if (m_pDeepSelection->GetPreviousMode() == CDeepSelection::DSM_NONE) - { - m_pDeepSelection->Reset(true); - } - - m_pDeepSelection->SetMode(CDeepSelection::DSM_NONE); - hitInfo.pDeepSelection = 0; - } - - if (view->HitTest(point, hitInfo)) - { - if (hitInfo.axis != 0) - { - GetIEditor()->SetAxisConstraints((AxisConstrains)hitInfo.axis); - bLockSelection = true; - } - if (hitInfo.axis != 0) - { - view->SetAxisConstrain(hitInfo.axis); - } - - - ////////////////////////////////////////////////////////////////////////// - // Deep Selection - CheckDeepSelection(hitInfo, view); - } - - CBaseObject* hitObj = hitInfo.object; - - int editMode = GetIEditor()->GetEditMode(); - - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - - if (hitObj) - { - Matrix34 tm = hitInfo.object->GetWorldTM(); - tm.OrthonormalizeFast(); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - if (hitInfo.object->GetParent()) - { - Matrix34 parentTM = hitInfo.object->GetParent()->GetWorldTM(); - parentTM.OrthonormalizeFast(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - else - { - Matrix34 parentTM; - parentTM.SetIdentity(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - userTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - Matrix34 viewTM = view->GetViewTM(); - viewTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_VIEW, viewTM); - } - else - { - Matrix34 tm; - tm.SetIdentity(); - tm.SetTranslation(pos); - userTM.SetTranslation(pos); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - view->SetConstructionMatrix(COORDS_PARENT, tm); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - } - - if (editMode != eEditModeTool) - { - // Check for Move to position. - if (bCtrlClick && bShiftClick && !hitInfo.object) - { - // Ctrl-Click on terrain will move selected objects to specified location. - MoveSelectionToPos(view, pos, bAltClick, point); - bLockSelection = true; - } - else if (bCtrlClick && bShiftClick && hitInfo.object) - { - const int nPickFlag = CSurfaceInfoPicker::ePOG_All; - view->BeginUndo(); - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - const int numObjects = pSelection->GetCount(); - for (int objectIndex = 0;objectIndex < numObjects;++objectIndex) - { - CBaseObject* m_curObj = pSelection->GetObject(objectIndex); - CSurfaceInfoPicker::CExcludedObjects excludeObjects; - excludeObjects.Add(m_curObj); - SRayHitInfo hitInfo2; - CSurfaceInfoPicker surfacePicker; - if (surfacePicker.Pick(point, hitInfo2, &excludeObjects, nPickFlag)) - { - m_curObj->SetPos(hitInfo2.vHitPos); - if (bAltClick) - { - Quat nq; - Vec3 zaxis = m_curObj->GetRotation() * Vec3(AZ::Vector3::CreateAxisZ()); - zaxis.Normalize(); - nq.SetRotationV0V1(zaxis, hitInfo2.vHitNormal); - m_curObj->SetRotation(nq * m_curObj->GetRotation()); - } - } - - } - AzToolsFramework::ScopedUndoBatch undo("Transform"); - view->AcceptUndo("Move Selection"); - bLockSelection = true; - } - } - - if (editMode == eEditModeMove) - { - if (!bNoRemoveSelection) - { - SetCommandMode(MoveMode); - } - - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (editMode == eEditModeRotate) - { - if (!bNoRemoveSelection) - { - SetCommandMode(RotateMode); - } - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (editMode == eEditModeScale) - { - if (!bNoRemoveSelection) - { - GetIEditor()->GetSelection()->StartScaling(); - SetCommandMode(ScaleMode); - } - - if (hitObj && hitObj->IsSelected() && !bNoRemoveSelection) - { - bLockSelection = true; - } - } - else if (hitObj != 0 && GetIEditor()->GetSelectedObject() == hitObj && !bAddSelect && !bUnselect) - { - bLockSelection = true; - } - - if (!bLockSelection) - { - // If not selection locked. - view->BeginUndo(); - - if (!bNoRemoveSelection) - { - // Current selection should be cleared - numUnselected = GetIEditor()->GetObjectManager()->ClearSelection(); - } - - if (hitObj) - { - numSelected = 1; - - if (!bUnselect) - { - if (hitObj->IsSelected()) - { - bUnselect = true; - } - } - - if (!bUnselect) - { - GetIEditor()->GetObjectManager()->SelectObject(hitObj, true); - } - else - { - GetIEditor()->GetObjectManager()->UnselectObject(hitObj); - } - } - if (view->IsUndoRecording()) - { - // When a designer object is selected, the update of the designer object can cause a change of a edit tool, which will makes this objectmode tool pointer invalid. - // so the update of objects must run on only pure idle time. - // view->AcceptUndo method calls the OnIdle() function in the app, which this is not a right timing to updates all, I think. - Jaesik Hwang. - GetIEditor()->GetObjectManager()->SetSkipUpdate(true); - view->AcceptUndo("Select Object(s)"); - GetIEditor()->GetObjectManager()->SetSkipUpdate(false); - } - - if ((numSelected == 0 || editMode == eEditModeSelect)) - { - // If object is not selected. - // Capture mouse input for this window. - SetCommandMode(SelectMode); - } - } - - if (GetCommandMode() == MoveMode || - GetCommandMode() == RotateMode || - GetCommandMode() == ScaleMode) - { - view->BeginUndo(); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - } - - ////////////////////////////////////////////////////////////////////////// - // Change cursor, must be before Capture mouse. - ////////////////////////////////////////////////////////////////////////// - SetObjectCursor(view, hitObj, true); - - ////////////////////////////////////////////////////////////////////////// - view->CaptureMouse(); - ////////////////////////////////////////////////////////////////////////// - - UpdateStatusText(); - - m_bTransformChanged = false; - - if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_POP) - { - return OnLButtonUp(view, nFlags, point); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonUp(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore clicks while in game. - return true; - } - - if (m_bTransformChanged) - { - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - if (pSelection) - { - pSelection->FinishChanges(); - } - m_bTransformChanged = false; - } - - if (GetCommandMode() == ScaleMode) - { - Vec3 scale; - GetIEditor()->GetSelection()->FinishScaling(GetScale(view, point, scale), - GetIEditor()->GetReferenceCoordSys()); - } - - if (GetCommandMode() == MoveMode) - { - m_bDragThresholdExceeded = false; - } - - // Reset the status bar caption - GetIEditor()->SetStatusText("Ready"); - - ////////////////////////////////////////////////////////////////////////// - if (view->IsUndoRecording()) - { - if (GetCommandMode() == MoveMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Move"); - } - view->AcceptUndo("Move Selection"); - } - else if (GetCommandMode() == RotateMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Rotate"); - } - view->AcceptUndo("Rotate Selection"); - } - else if (GetCommandMode() == ScaleMode) - { - { - AzToolsFramework::ScopedUndoBatch undo("Scale"); - } - view->AcceptUndo("Scale Selection"); - } - else - { - view->CancelUndo(); - } - } - ////////////////////////////////////////////////////////////////////////// - - if (GetCommandMode() == SelectMode && (!GetIEditor()->IsSelectionLocked())) - { - const bool bUnselect = (Qt::AltModifier & QApplication::queryKeyboardModifiers()); - QRect selectRect = view->GetSelectionRectangle(); - if (!selectRect.isEmpty()) - { - // Ignore too small rectangles. - if (selectRect.width() > 5 && selectRect.height() > 5) - { - GetIEditor()->GetObjectManager()->SelectObjectsInRect(view, selectRect, !bUnselect); - UpdateStatusText(); - } - } - - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - AABB box; - GetIEditor()->GetSelectedRegion(box); - - ////////////////////////////////////////////////////////////////////////// - GetIEditor()->ClearSelection(); - } - } - // Release the restriction of the cursor - view->ReleaseMouse(); - - if (GetCommandMode() == ScaleMode || GetCommandMode() == MoveMode || GetCommandMode() == RotateMode) - { - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, - selectedEntities); - } - - if (GetIEditor()->GetEditMode() != eEditModeSelectArea) - { - view->ResetSelectionRegion(); - } - // Reset selected rectangle. - view->SetSelectionRectangle(QRect()); - - // Restore default editor axis constrain. - if (GetIEditor()->GetAxisConstrains() != view->GetAxisConstrain()) - { - view->SetAxisConstrain(GetIEditor()->GetAxisConstrains()); - } - - SetCommandMode(NothingMode); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point) -{ - IEditor* editor = GetIEditor(); - - // If shift clicked, Move the camera to this place. - if (nFlags & MK_SHIFT) - { - // Get the heightmap coordinates for the click position - Vec3 v = view->ViewToWorld(point); - if (!(v.x == 0 && v.y == 0 && v.z == 0)) - { - Matrix34 tm = view->GetViewTM(); - Vec3 p = tm.GetTranslation(); - float height = p.z - editor->GetTerrainElevation(p.x, p.y); - if (height < 1) - { - height = 1; - } - p.x = v.x; - p.y = v.y; - p.z = editor->GetTerrainElevation(p.x, p.y) + height; - tm.SetTranslation(p); - view->SetViewTM(tm); - } - } - else - { - // Check if double clicked on object. - HitContext hitInfo; - view->HitTest(point, hitInfo); - - if (CBaseObject* hitObj = hitInfo.object) - { - // check if the object is an AZ::Entity - if ((hitObj->GetType() == OBJTYPE_AZENTITY)) - { - if (CRenderViewport* renderViewport = viewport_cast<CRenderViewport*>(view)) - { - // if we double clicked on an AZ::Entity/Component, build a mouse interaction and send a double - // click event to the EditorInteractionSystemViewportSelectionRequestBus. if we have double clicked - // on a component supporting ComponentMode, we will enter it. note: this is to support entering - // ComponentMode with a double click using the old viewport interaction model - const auto mouseInteraction = renderViewport->BuildMouseInteraction( - Qt::LeftButton, QGuiApplication::queryKeyboardModifiers(), - renderViewport->ViewportToWidget(point)); - - using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus; - using AzToolsFramework::ViewportInteraction::MouseInteractionEvent; - using AzToolsFramework::ViewportInteraction::MouseEvent; - - EditorInteractionSystemViewportSelectionRequestBus::Event( - AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, - MouseInteractionEvent(mouseInteraction, MouseEvent::DoubleClick)); - } - } - - // Fire double click event on hit object. - hitObj->OnEvent(EVENT_DBLCLICK); - } - else - { - if (!editor->IsSelectionLocked()) - { - editor->GetObjectManager()->ClearSelection(); - } - } - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnRButtonDown([[maybe_unused]] CViewport* view, [[maybe_unused]] int nFlags, [[maybe_unused]] const QPoint& point) -{ - if (gSettings.viewports.bEnableContextMenu && !GetIEditor()->IsInSimulationMode()) - { - m_openContext = true; - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnRButtonUp(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - if (m_openContext) - { - bool selectionLocked = GetIEditor()->IsSelectionLocked(); - - // Check if right clicked on object. - HitContext hitInfo; - hitInfo.bIgnoreAxis = true; // ignore gizmo - view->HitTest(point, hitInfo); - - QPointer<CBaseObject> object; - - if (selectionLocked) - { - if (hitInfo.object) - { - // Save so we can use this for the context menu later - object = hitInfo.object; - } - } - else - { - Vec3 pos = view->SnapToGrid(view->ViewToWorld(point)); - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - - if (hitInfo.object) - { - Matrix34 tm = hitInfo.object->GetWorldTM(); - tm.OrthonormalizeFast(); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - if (hitInfo.object->GetParent()) - { - Matrix34 parentTM = hitInfo.object->GetParent()->GetWorldTM(); - parentTM.OrthonormalizeFast(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - else - { - Matrix34 parentTM; - parentTM.SetIdentity(); - parentTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_PARENT, parentTM); - } - userTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - Matrix34 viewTM = view->GetViewTM(); - viewTM.SetTranslation(tm.GetTranslation()); - view->SetConstructionMatrix(COORDS_VIEW, viewTM); - - CSelectionGroup* selections = GetIEditor()->GetObjectManager()->GetSelection(); - - // hit object has not been selected - if (!selections->IsContainObject(hitInfo.object)) - { - view->BeginUndo(); - GetIEditor()->GetObjectManager()->ClearSelection(); - GetIEditor()->GetObjectManager()->SelectObject(hitInfo.object, true); - view->AcceptUndo("Select Object(s)"); - } - - // Save so we can use this for the context menu later - object = hitInfo.object; - } - else - { - Matrix34 tm; - tm.SetIdentity(); - tm.SetTranslation(pos); - userTM.SetTranslation(pos); - view->SetConstructionMatrix(COORDS_LOCAL, tm); - view->SetConstructionMatrix(COORDS_PARENT, tm); - view->SetConstructionMatrix(COORDS_USERDEFINED, userTM); - - view->BeginUndo(); - GetIEditor()->GetObjectManager()->ClearSelection(); - view->AcceptUndo("Select Object(s)"); - } - } - - // CRenderViewport hides the cursor when the mouse button is pressed - // and shows it when button is released. If we exec the context menu directly, then we block - // and the cursor stays invisible while the menu is open so instead, we queue it to happen - // after the mouse button release is finished - QTimer::singleShot(0, this, [point, view, object]() - { - QMenu menu(viewport_cast<QtViewport*>(view)); - - if (object) - { - object->OnContextMenu(&menu); - } - - // Populate global context menu. - int contextMenuFlag = 0; - EBUS_EVENT(AzToolsFramework::EditorEvents::Bus, - PopulateEditorGlobalContextMenu, - &menu, - AZ::Vector2(static_cast<float>(point.x()), static_cast<float>(point.y())), - contextMenuFlag); - - if (!menu.isEmpty()) - { - menu.exec(QCursor::pos()); - } - }); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMButtonDown(CViewport* view, [[maybe_unused]] int nFlags, const QPoint& point) -{ - if (GetIEditor()->GetGameEngine()->GetSimulationMode()) - { - // Get control key status. - const bool bCtrlClick = (Qt::ControlModifier & QApplication::queryKeyboardModifiers()); - - if (bCtrlClick) - { - // In simulation mode awake objects under the cursor when Ctrl+MButton pressed. - AwakeObjectAtPoint(view, point); - return true; - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::AwakeObjectAtPoint(CViewport* view, const QPoint& point) -{ - // In simulation mode awake objects under the cursor. - // Check if double clicked on object. - HitContext hitInfo; - view->HitTest(point, hitInfo); - CBaseObject* hitObj = hitInfo.object; - if (hitObj) - { - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point) -{ - view->BeginUndo(); - // Find center of selection. - Vec3 center = GetIEditor()->GetSelection()->GetCenter(); - GetIEditor()->GetSelection()->Move(pos - center, CSelectionGroup::eMS_None, true, point); - - if (align) - { - GetIEditor()->GetSelection()->Align(); - } - - // This will capture any entity state changes that occurred - // during the move. - { - AzToolsFramework::ScopedUndoBatch undo("Transform"); - } - - view->AcceptUndo("Move Selection"); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMouseMove(CViewport* view, int nFlags, const QPoint& point) -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore while in game. - return true; - } - - // Has the mouse been intentionally moved or could this be a small jump in movement due to right clicking? - if (std::abs(m_prevMousePos.x() - point.x()) > 2 || std::abs(m_prevMousePos.y() - point.y()) > 2) - { - // This was an intentional mouse movement, disable the context menu - m_openContext = false; - } - m_prevMousePos = point; - SetObjectCursor(view, 0); - - // get world/local coordinate system setting. - int coordSys = GetIEditor()->GetReferenceCoordSys(); - - // get current axis constrains. - if (GetCommandMode() == MoveMode) - { - if (!m_bDragThresholdExceeded) - { - int halfLength = gSettings.viewports.nDragSquareSize / 2; - QRect rcDrag(m_cMouseDownPos, QSize(0,0)); - rcDrag.adjust(-halfLength, -halfLength, halfLength, halfLength); - - if (!rcDrag.contains(point)) - { - m_bDragThresholdExceeded = true; - m_lastValidMoveVector = Vec3(0, 0, 0); - } - else - { - return true; - } - } - - GetIEditor()->RestoreUndo(); - - Vec3 v; - //m_cMouseDownPos = point; - CSelectionGroup::EMoveSelectionFlag selectionFlag = CSelectionGroup::eMS_None; - if (view->GetAxisConstrain() == AXIS_TERRAIN) - { - selectionFlag = CSelectionGroup::eMS_FollowTerrain; - Vec3 p1 = view->SnapToGrid(view->ViewToWorld(m_cMouseDownPos)); - Vec3 p2 = view->SnapToGrid(view->ViewToWorld(point)); - v = p2 - p1; - v.z = 0; - m_lastValidMoveVector = v; - } - else - { - Vec3 p1 = view->MapViewToCP(m_cMouseDownPos); - Vec3 p2 = view->MapViewToCP(point); - - if (p1.IsZero() || p2.IsZero()) - { - v = m_lastValidMoveVector; - } - else - { - v = view->GetCPVector(p1, p2); - m_lastValidMoveVector = v; - } - - //Matrix invParent = m_parentConstructionMatrix; - //invParent.Invert(); - //p1 = invParent.TransformVector(p1); - //p2 = invParent.TransformVector(p2); - //v = p2 - p1; - } - - if ((nFlags & MK_CONTROL) && !(nFlags & MK_SHIFT)) - { - selectionFlag = CSelectionGroup::eMS_FollowGeometryPosNorm; - } - - if (!v.IsEquivalent(Vec3(0, 0, 0))) - { - m_bTransformChanged = true; - } - - CTrackViewSequence* pSequence = GetIEditor()->GetAnimation()->GetSequence(); - { - CTrackViewSequenceNoNotificationContext context(pSequence); - GetIEditor()->GetSelection()->Move(v, selectionFlag, coordSys, point); - } - - if (pSequence) - { - pSequence->OnKeysChanged(); - } - - return true; - } - else if (GetCommandMode() == ScaleMode) - { - GetIEditor()->RestoreUndo(); - Vec3 scale; - GetIEditor()->GetSelection()->Scale(GetScale(view, point, scale), coordSys); - if (!scale.IsEquivalent(Vec3(0, 0, 0))) - { - m_bTransformChanged = true; - } - } - else if (GetCommandMode() == SelectMode) - { - // Ignore select when selection locked. - if (GetIEditor()->IsSelectionLocked()) - { - return true; - } - - QRect rc(m_cMouseDownPos, point - QPoint(1, 1)); - if (GetIEditor()->GetEditMode() == eEditModeSelectArea) - { - view->OnDragSelectRectangle(rc, false); - } - else - { - view->SetSelectionRectangle(rc); - } - //else - //OnDragSelectRectangle( CPoint(rc.left,rc.top),CPoint(rc.right,rc.bottom),true ); - } - - if (!(nFlags & MK_RBUTTON || nFlags & MK_MBUTTON)) - { - // Track mouse movements. - HitContext hitInfo; - if (view->HitTest(point, hitInfo)) - { - SetObjectCursor(view, hitInfo.object); - } - - HandleMoveByFaceNormal(hitInfo); - } - - if ((nFlags & MK_MBUTTON) && GetIEditor()->GetGameEngine()->GetSimulationMode()) - { - // Get control key status. - const bool bCtrlClick = (Qt::ControlModifier & QApplication::queryKeyboardModifiers()); - - if (bCtrlClick) - { - // In simulation mode awake objects under the cursor when Ctrl+MButton pressed. - AwakeObjectAtPoint(view, point); - } - } - - UpdateStatusText(); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectMode::OnMouseLeave(CViewport* view) -{ - if (GetIEditor()->IsInGameMode() || GetIEditor()->IsInSimulationMode()) - { - // Ignore while in game. - return true; - } - - m_openContext = false; - SetObjectCursor(view, 0); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::SetObjectCursor(CViewport* view, CBaseObject* hitObj, [[maybe_unused]] bool bChangeNow) -{ - EStdCursor cursor = STD_CURSOR_DEFAULT; - QString m_cursorStr; - QString supplementaryCursor = ""; - - CBaseObject* pMouseOverObject = NULL; - if (!GuidUtil::IsEmpty(m_MouseOverObject)) - { - pMouseOverObject = GetIEditor()->GetObjectManager()->FindObject(m_MouseOverObject); - } - - //HCURSOR hPrevCursor = m_hCurrCursor; - if (pMouseOverObject) - { - pMouseOverObject->SetHighlight(false); - } - if (hitObj) - { - m_MouseOverObject = hitObj->GetId(); - } - else - { - m_MouseOverObject = GUID_NULL; - } - pMouseOverObject = hitObj; - bool bHitSelectedObject = false; - if (pMouseOverObject) - { - if (GetCommandMode() != SelectMode && !GetIEditor()->IsSelectionLocked()) - { - if (pMouseOverObject->CanBeHightlighted()) - { - pMouseOverObject->SetHighlight(true); - } - - m_cursorStr = pMouseOverObject->GetName(); - - QString comment(pMouseOverObject->GetComment()); - if (!comment.isEmpty()) - { - m_cursorStr += "\n"; - m_cursorStr += comment; - } - - QString warnings(pMouseOverObject->GetWarningsText()); - if (!warnings.isEmpty()) - { - m_cursorStr += warnings; - } - - cursor = STD_CURSOR_HIT; - if (pMouseOverObject->IsSelected()) - { - bHitSelectedObject = true; - } - - if (pMouseOverObject->GetType() == OBJTYPE_AZENTITY) - { - CComponentEntityObject* componentEntity = static_cast<CComponentEntityObject*>(pMouseOverObject); - - bool isEditorOnly = false; - AzToolsFramework::EditorOnlyEntityComponentRequestBus::EventResult(isEditorOnly, componentEntity->GetAssociatedEntityId(), &AzToolsFramework::EditorOnlyEntityComponentRequests::IsEditorOnlyEntity); - AZ::Entity* entity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationBus::Events::FindEntity, componentEntity->GetAssociatedEntityId()); - const bool isInitiallyActive = entity ? entity->IsRuntimeActiveByDefault() : true; - - if (isEditorOnly) - { - supplementaryCursor = "\n[" + QObject::tr("Editor Only") + "]"; - } - else if (!isInitiallyActive) - { - supplementaryCursor = "\n[" + QObject::tr("Inactive") + "]"; - } - } - } - - QString tooltip = pMouseOverObject->GetTooltip(); - if (!tooltip.isEmpty()) - { - m_cursorStr += "\n"; - m_cursorStr += tooltip; - } - ; - } - else - { - m_cursorStr = ""; - cursor = STD_CURSOR_DEFAULT; - } - // Get control key status. - const auto modifiers = QApplication::queryKeyboardModifiers(); - const bool bAltClick = (Qt::AltModifier & modifiers); - const bool bCtrlClick = (Qt::ControlModifier & modifiers); - const bool bShiftClick = (Qt::ShiftModifier & modifiers); - - bool bAddSelect = bCtrlClick && !bShiftClick; - bool bUnselect = bAltClick; - bool bNoRemoveSelection = bAddSelect || bUnselect; - - bool bLockSelection = GetIEditor()->IsSelectionLocked(); - - if (GetCommandMode() == SelectMode || GetCommandMode() == NothingMode) - { - if (bAddSelect) - { - cursor = STD_CURSOR_SEL_PLUS; - } - if (bUnselect) - { - cursor = STD_CURSOR_SEL_MINUS; - } - - if ((bHitSelectedObject && !bNoRemoveSelection) || bLockSelection) - { - int editMode = GetIEditor()->GetEditMode(); - if (editMode == eEditModeMove) - { - cursor = STD_CURSOR_MOVE; - } - else if (editMode == eEditModeRotate) - { - cursor = STD_CURSOR_ROTATE; - } - else if (editMode == eEditModeScale) - { - cursor = STD_CURSOR_SCALE; - } - } - } - else if (GetCommandMode() == MoveMode) - { - cursor = STD_CURSOR_MOVE; - } - else if (GetCommandMode() == RotateMode) - { - cursor = STD_CURSOR_ROTATE; - } - else if (GetCommandMode() == ScaleMode) - { - cursor = STD_CURSOR_SCALE; - } - - AZ::u32 cursorId = static_cast<AZ::u32>(cursor); - AZStd::string cursorStr = m_cursorStr.toUtf8().data(); - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, - UpdateObjectModeCursor, - cursorId, - cursorStr); - cursor = static_cast<EStdCursor>(cursorId); - m_cursorStr = cursorStr.c_str(); - - view->SetCurrentCursor(cursor, m_cursorStr); - view->SetSupplementaryCursorStr(supplementaryCursor); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass<CObjectMode>("EditTool.ObjectMode", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::UpdateStatusText() -{ - QString str; - int nCount = GetIEditor()->GetSelection()->GetCount(); - if (nCount > 0) - { - str = tr("%1 Object(s) Selected").arg(nCount); - } - else - { - str = tr("No Selection"); - } - SetStatusText(str); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectMode::CheckDeepSelection(HitContext& hitContext, CViewport* view) -{ - if (hitContext.pDeepSelection) - { - m_pDeepSelection->CollectCandidate(hitContext.dist, gSettings.deepSelectionSettings.fRange); - } - - if (m_pDeepSelection->GetCandidateObjectCount() > 1) - { - // Deep Selection Pop Mode - if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_POP) - { - // Show a sorted pop-up menu for selecting a bone. - QMenu popUpDeepSelect(qobject_cast<QWidget*>(view->qobject())); - - for (int i = 0; i < m_pDeepSelection->GetCandidateObjectCount(); ++i) - { - QAction* action = popUpDeepSelect.addAction(QString(m_pDeepSelection->GetCandidateObject(i)->GetName())); - action->setData(i); - } - - QAction* userSelection = popUpDeepSelect.exec(QCursor::pos()); - if (userSelection) - { - int nSelect = userSelection->data().toInt(); - - // Update HitContext hitInfo. - hitContext.object = m_pDeepSelection->GetCandidateObject(nSelect); - m_pDeepSelection->ExcludeHitTest(nSelect); - } - } - else if (m_pDeepSelection->GetMode() == CDeepSelection::DSM_CYCLE) - { - int selPos = m_pDeepSelection->GetCurrentSelectPos(); - hitContext.object = m_pDeepSelection->GetCandidateObject(selPos + 1); - m_pDeepSelection->ExcludeHitTest(selPos + 1); - } - } -} - -Vec3& CObjectMode::GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale) -{ - float ay = 1.0f - 0.01f * (point.y() - m_cMouseDownPos.y()); - - if (ay < 0.01f) - { - ay = 0.01f; - } - - Vec3 scl(ay, ay, ay); - - int axisConstrain = view->GetAxisConstrain(); - - if (axisConstrain < AXIS_XYZ && GetIEditor()->IsAxisVectorLocked()) - { - axisConstrain = AXIS_XYZ; - } - - switch (axisConstrain) - { - case AXIS_X: - scl(ay, 1, 1); - break; - case AXIS_Y: - scl(1, ay, 1); - break; - case AXIS_Z: - scl(1, 1, ay); - break; - case AXIS_XY: - scl(ay, ay, ay); - break; - case AXIS_XZ: - scl(ay, ay, ay); - break; - case AXIS_YZ: - scl(ay, ay, ay); - break; - case AXIS_XYZ: - scl(ay, ay, ay); - break; - case AXIS_TERRAIN: - scl(ay, ay, ay); - break; - } - ; - - OutScale = scl; - - return OutScale; -} - -////////////////////////////////////////////////////////////////////////// -// This callback is currently called only to handle the case of the 'move by the face normal'. -// Other movements of the object are handled in the 'CObjectMode::OnMouseMove()' method. -void CObjectMode::OnManipulatorDrag(CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, QPoint& point0, [[maybe_unused]] QPoint& point1, const Vec3& value) -{ - RefCoordSys coordSys = GetIEditor()->GetReferenceCoordSys(); - int editMode = GetIEditor()->GetEditMode(); - - if (editMode == eEditModeMove) - { - GetIEditor()->RestoreUndo(); - CSelectionGroup* pSelGrp = GetIEditor()->GetSelection(); - - CSelectionGroup::EMoveSelectionFlag selectionFlag = view->GetAxisConstrain() == AXIS_TERRAIN ? CSelectionGroup::eMS_FollowTerrain : CSelectionGroup::eMS_None; - pSelGrp->Move(value, selectionFlag, coordSys, point0); - - if (m_pHitObject) - { - UpdateMoveByFaceNormGizmo(m_pHitObject); - } - } -} - -void CObjectMode::HandleMoveByFaceNormal([[maybe_unused]] HitContext& hitInfo) -{ - const bool bNKeyPressed = CheckVirtualKey(Qt::Key_N); - if (m_bMoveByFaceNormManipShown && !bNKeyPressed) - { - HideMoveByFaceNormGizmo(); - } -} - -void CObjectMode::UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject) -{ - Matrix34 refFrame; - refFrame.SetIdentity(); - SubObjectSelectionReferenceFrameCalculator calculator(SO_ELEM_FACE); - pHitObject->CalculateSubObjectSelectionReferenceFrame(&calculator); - if (calculator.GetFrame(refFrame) == false) - { - HideMoveByFaceNormGizmo(); - } - else - { - ITransformManipulator* pManipulator = GetIEditor()->ShowTransformManipulator(true); - m_bMoveByFaceNormManipShown = true; - m_pHitObject = pHitObject; - - Matrix34 parentTM = pHitObject->GetWorldTM(); - Matrix34 userTM = GetIEditor()->GetViewManager()->GetGrid()->GetMatrix(); - parentTM.SetTranslation(refFrame.GetTranslation()); - userTM.SetTranslation(refFrame.GetTranslation()); - pManipulator->SetTransformation(COORDS_LOCAL, refFrame); - pManipulator->SetTransformation(COORDS_PARENT, parentTM); - pManipulator->SetTransformation(COORDS_USERDEFINED, userTM); - pManipulator->SetAlwaysUseLocal(true); - } -} - -void CObjectMode::HideMoveByFaceNormGizmo() -{ - GetIEditor()->ShowTransformManipulator(false); - m_bMoveByFaceNormManipShown = false; - m_pHitObject = NULL; -} - -#include <EditMode/moc_ObjectMode.cpp> - diff --git a/Code/Sandbox/Editor/EditMode/ObjectMode.h b/Code/Sandbox/Editor/EditMode/ObjectMode.h deleted file mode 100644 index a7919b2c47..0000000000 --- a/Code/Sandbox/Editor/EditMode/ObjectMode.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Object edit mode describe viewport input behavior when operating on objects. - - -#ifndef CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H -#define CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H -#pragma once - -// {87109FED-BDB5-4874-936D-338400079F58} -DEFINE_GUID(OBJECT_MODE_GUID, 0x87109fed, 0xbdb5, 0x4874, 0x93, 0x6d, 0x33, 0x84, 0x0, 0x7, 0x9f, 0x58); - -#include "EditTool.h" - -class CBaseObject; -class CDeepSelection; -/*! -* CObjectMode is an abstract base class for All Editing Tools supported by Editor. -* Edit tools handle specific editing modes in viewports. -*/ -class SANDBOX_API CObjectMode - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CObjectMode(QObject* parent = nullptr); - virtual ~CObjectMode(); - - static const GUID& GetClassID() { return OBJECT_MODE_GUID; } - - // Registration function. - static void RegisterTool(CRegistrationContext& rc); - - ////////////////////////////////////////////////////////////////////////// - // CEditTool implementation. - ////////////////////////////////////////////////////////////////////////// - virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {}; - virtual void EndEditParams(); - virtual void Display(struct DisplayContext& dc); - virtual void DisplaySelectionPreview(struct DisplayContext& dc); - virtual void DrawSelectionPreview(struct DisplayContext& dc, CBaseObject* drawObject); - void DisplayExtraLightInfo(struct DisplayContext& dc); - - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; }; - - virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, QPoint& p0, QPoint& p1, const Vec3& value) override; - - bool IsUpdateUIPanel() override { return true; } - -protected: - enum ECommandMode - { - NothingMode = 0, - ScrollZoomMode, - SelectMode, - MoveMode, - RotateMode, - ScaleMode, - ScrollMode, - ZoomMode, - }; - - virtual bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnLButtonDblClk(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnRButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnRButtonUp(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMButtonDown(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point); - virtual bool OnMouseLeave(CViewport* view); - - void SetCommandMode(ECommandMode mode) { m_commandMode = mode; } - ECommandMode GetCommandMode() const { return m_commandMode; } - - //! Ctrl-Click in move mode to move selected objects to given pos. - void MoveSelectionToPos(CViewport* view, Vec3& pos, bool align, const QPoint& point); - void SetObjectCursor(CViewport* view, CBaseObject* hitObj, bool bChangeNow = false); - - virtual void DeleteThis() { delete this; }; - - void UpdateStatusText(); - void AwakeObjectAtPoint(CViewport* view, const QPoint& point); - - void HideMoveByFaceNormGizmo(); - void HandleMoveByFaceNormal(HitContext& hitInfo); - void UpdateMoveByFaceNormGizmo(CBaseObject* pHitObject); - -protected: - - bool m_openContext; - -private: - void CheckDeepSelection(HitContext& hitContext, CViewport* view); - Vec3& GetScale(const CViewport* view, const QPoint& point, Vec3& OutScale); - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QPoint m_cMouseDownPos; - bool m_bDragThresholdExceeded; - ECommandMode m_commandMode; - - GUID m_MouseOverObject; - typedef std::vector<GUID> TGuidContainer; - TGuidContainer m_PreviewGUIDs; - - _smart_ptr<CDeepSelection> m_pDeepSelection; - - bool m_bMoveByFaceNormManipShown; - CBaseObject* m_pHitObject; - - bool m_bTransformChanged; - - QPoint m_prevMousePos = QPoint(0, 0); - - Vec3 m_lastValidMoveVector = Vec3(0, 0, 0); - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - - - -#endif // CRYINCLUDE_EDITOR_EDITMODE_OBJECTMODE_H diff --git a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp b/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp deleted file mode 100644 index a0a5492f55..0000000000 --- a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#if defined(AZ_PLATFORM_WINDOWS) -#include <InitGuid.h> -#endif - -#include "VertexSnappingModeTool.h" - -// Editor -#include "Settings.h" -#include "Viewport.h" -#include "SurfaceInfoPicker.h" -#include "Material/Material.h" -#include "Util/KDTree.h" - - -// {3e008046-9269-41d7-82e2-07ffd7254c10} -DEFINE_GUID(VERTEXSNAPPING_MODE_GUID, 0x3e008046, 0x9269, 0x41d7, 0x82, 0xe2, 0x07, 0xff, 0xd7, 0x25, 0x4c, 0x10); - -bool FindNearestVertex(CBaseObject* pObject, CKDTree* pTree, const Vec3& vWorldRaySrc, const Vec3& vWorldRayDir, Vec3& outPos, Vec3& vOutHitPosOnCube) -{ - Matrix34 worldInvTM = pObject->GetWorldTM().GetInverted(); - Vec3 vRaySrc = worldInvTM.TransformPoint(vWorldRaySrc); - Vec3 vRayDir = worldInvTM.TransformVector(vWorldRayDir); - Vec3 vLocalCameraPos = worldInvTM.TransformPoint(gEnv->pRenderer->GetCamera().GetPosition()); - Vec3 vPos; - Vec3 vHitPosOnCube; - - if (pTree) - { - if (pTree->FindNearestVertex(vRaySrc, vRayDir, gSettings.vertexSnappingSettings.vertexCubeSize, vLocalCameraPos, vPos, vHitPosOnCube)) - { - outPos = pObject->GetWorldTM().TransformPoint(vPos); - vOutHitPosOnCube = pObject->GetWorldTM().TransformPoint(vHitPosOnCube); - return true; - } - } - else - { - // for objects without verts, the pivot is the nearest vertex - // return true if the ray hits the bounding box - outPos = pObject->GetWorldPos(); - - AABB bbox; - pObject->GetBoundBox(bbox); - if (bbox.IsContainPoint(vWorldRaySrc)) - { - // if ray starts inside bounding box, reject cases where pivot is behind the ray - float hitDistAlongRay = vWorldRayDir.Dot(outPos - vWorldRaySrc); - if (hitDistAlongRay >= 0.f) - { - vHitPosOnCube = vWorldRaySrc + (vWorldRayDir * hitDistAlongRay); - return true; - } - } - else if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, bbox, vOutHitPosOnCube)) - { - return true; - } - } - - return false; -} - -CVertexSnappingModeTool::CVertexSnappingModeTool() -{ - m_modeStatus = eVSS_SelectFirstVertex; - m_bHit = false; -} - -CVertexSnappingModeTool::~CVertexSnappingModeTool() -{ - std::map<CBaseObjectPtr, CKDTree*>::iterator ii = m_ObjectKdTreeMap.begin(); - for (; ii != m_ObjectKdTreeMap.end(); ++ii) - { - delete ii->second; - } -} - -const GUID& CVertexSnappingModeTool::GetClassID() -{ - return VERTEXSNAPPING_MODE_GUID; -} - -void CVertexSnappingModeTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass<CVertexSnappingModeTool>("EditTool.VertexSnappingMode", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -bool CVertexSnappingModeTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - CBaseObjectPtr pExcludedObject = NULL; - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex) - { - pExcludedObject = m_SelectionInfo.m_pObject; - } - - m_bHit = HitTest(view, point, pExcludedObject, m_vHitVertex, m_pHitObject, m_Objects); - - if (event == eMouseLDown && m_bHit && m_pHitObject && m_modeStatus == eVSS_SelectFirstVertex) - { - m_modeStatus = eVSS_MoveSelectVertexToAnotherVertex; - m_SelectionInfo.m_pObject = m_pHitObject; - m_SelectionInfo.m_vPos = m_vHitVertex; - - GetIEditor()->BeginUndo(); - m_pHitObject->StoreUndo("Vertex Snapping", true); - - view->SetCapture(); - } - - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex) - { - if (event == eMouseLUp) - { - m_modeStatus = eVSS_SelectFirstVertex; - - GetIEditor()->AcceptUndo("Vertex Snapping"); - view->ReleaseMouse(); - } - else if ((flags & MK_LBUTTON) && event == eMouseMove) - { - Vec3 vOffset = m_SelectionInfo.m_pObject->GetWorldPos() - m_SelectionInfo.m_vPos; - m_SelectionInfo.m_pObject->SetWorldPos(m_vHitVertex + vOffset); - m_SelectionInfo.m_vPos = m_SelectionInfo.m_pObject->GetWorldPos() - vOffset; - } - } - - return true; -} - -bool CVertexSnappingModeTool::HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects) -{ - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - m_DebugBoxes.clear(); - } - - pOutHitObject = NULL; - outObjects.clear(); - - // - // Collect valid objects that mouse is over - // - - CSurfaceInfoPicker picker; - CSurfaceInfoPicker::CExcludedObjects excludedObjects; - if (pExcludedObj) - { - excludedObjects.Add(pExcludedObj); - } - - int nPickFlag = CSurfaceInfoPicker::ePOG_Entity; - - std::vector<CBaseObjectPtr> penetratedObjects; - if (!picker.PickByAABB(point, nPickFlag, view, &excludedObjects, &penetratedObjects)) - { - return false; - } - - for (int i = 0, iCount(penetratedObjects.size()); i < iCount; ++i) - { - CMaterial* pMaterial = penetratedObjects[i]->GetMaterial(); - if (pMaterial) - { - QString matName = pMaterial->GetName(); - if (!QString::compare(matName, "Objects/sky/forest_sky_dome", Qt::CaseInsensitive)) - { - continue; - } - } - outObjects.push_back(penetratedObjects[i]); - } - - // - // Find the best vertex. - // - - Vec3 vWorldRaySrc, vWorldRayDir; - view->ViewToWorldRay(point, vWorldRaySrc, vWorldRayDir); - - std::vector<CBaseObjectPtr>::iterator ii = outObjects.begin(); - float fNearestDist = 3e10f; - Vec3 vNearestPos; - CBaseObjectPtr pNearestObject = NULL; - for (ii = outObjects.begin(); ii != outObjects.end(); ++ii) - { - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - // add to debug boxes: the penetrated nodes of each object's kd-tree - if (auto pTree = GetKDTree(*ii)) - { - Matrix34 invWorldTM = (*ii)->GetWorldTM().GetInverted(); - int nIndex = m_DebugBoxes.size(); - - Vec3 vLocalRaySrc = invWorldTM.TransformPoint(vWorldRaySrc); - Vec3 vLocalRayDir = invWorldTM.TransformVector(vWorldRayDir); - pTree->GetPenetratedBoxes(vLocalRaySrc, vLocalRayDir, m_DebugBoxes); - for (int i = nIndex; i < m_DebugBoxes.size(); ++i) - { - m_DebugBoxes[i].SetTransformedAABB((*ii)->GetWorldTM(), m_DebugBoxes[i]); - } - } - } - - // find the nearest vertex on this object - Vec3 vPos, vHitPosOnCube; - if (FindNearestVertex(*ii, GetKDTree(*ii), vWorldRaySrc, vWorldRayDir, vPos, vHitPosOnCube)) - { - // is this the best so far? - float fDistance = vHitPosOnCube.GetDistance(vWorldRaySrc); - if (fDistance < fNearestDist) - { - fNearestDist = fDistance; - vNearestPos = vPos; - pNearestObject = *ii; - } - } - } - - if (fNearestDist < 3e10f) - { - outHitPos = vNearestPos; - pOutHitObject = pNearestObject; - } - - // if the mouse is over the object's pivot, use that instead of a vertex - if (pOutHitObject) - { - Vec3 vPivotPos = pOutHitObject->GetWorldPos(); - Vec3 vPivotBox = GetCubeSize(view, pOutHitObject->GetWorldPos()); - AABB pivotAABB(vPivotPos - vPivotBox, vPivotPos + vPivotBox); - Vec3 vPosOnPivotCube; - if (Intersect::Ray_AABB(vWorldRaySrc, vWorldRayDir, pivotAABB, vPosOnPivotCube)) - { - outHitPos = vPivotPos; - return true; - } - } - - return pOutHitObject && pOutHitObject == pNearestObject; -} - -Vec3 CVertexSnappingModeTool::GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const -{ - if (!pView) - { - return Vec3(0, 0, 0); - } - float fScreenFactor = pView->GetScreenScaleFactor(pos); - return gSettings.vertexSnappingSettings.vertexCubeSize * Vec3(fScreenFactor, fScreenFactor, fScreenFactor); -} - -void CVertexSnappingModeTool::Display(struct DisplayContext& dc) -{ - const ColorB SnappedColor(0xFF00FF00); - const ColorB PivotColor(0xFF2020FF); - const ColorB VertexColor(0xFFFFAAAA); - - // draw all objects under mouse - dc.SetColor(VertexColor); - for (int i = 0, iCount(m_Objects.size()); i < iCount; ++i) - { - AABB worldAABB; - m_Objects[i]->GetBoundBox(worldAABB); - if (!dc.view->IsBoundsVisible(worldAABB)) - { - continue; - } - - if (auto pStatObj = m_Objects[i]->GetIStatObj()) - { - DrawVertexCubes(dc, m_Objects[i]->GetWorldTM(), pStatObj); - } - else - { - dc.DrawWireBox(worldAABB.min, worldAABB.max); - } - } - - // draw object being moved - if (m_modeStatus == eVSS_MoveSelectVertexToAnotherVertex && m_SelectionInfo.m_pObject) - { - dc.SetColor(QColor(0xaa, 0xaa, 0xaa)); - if (auto pStatObj = m_SelectionInfo.m_pObject->GetIStatObj()) - { - DrawVertexCubes(dc, m_SelectionInfo.m_pObject->GetWorldTM(), pStatObj); - } - else - { - AABB bounds; - m_SelectionInfo.m_pObject->GetBoundBox(bounds); - dc.DrawWireBox(bounds.min, bounds.max); - } - } - - // draw pivot of hit object - if (m_pHitObject && (!m_bHit || m_bHit && !m_pHitObject->GetWorldPos().IsEquivalent(m_vHitVertex, 0.001f))) - { - dc.SetColor(PivotColor); - dc.DepthTestOff(); - - Vec3 vBoxSize = GetCubeSize(dc.view, m_pHitObject->GetWorldPos()) * 1.2f; - AABB vertexBox(m_pHitObject->GetWorldPos() - vBoxSize, m_pHitObject->GetWorldPos() + vBoxSize); - dc.DrawBall((vertexBox.min + vertexBox.max) * 0.5f, (vertexBox.max.x - vertexBox.min.x) * 0.5f); - - dc.DepthTestOn(); - } - - // draw the vertex (or pivot) that's being hit - if (m_bHit) - { - dc.DepthTestOff(); - dc.SetColor(SnappedColor); - Vec3 vBoxSize = GetCubeSize(dc.view, m_vHitVertex); - if (m_vHitVertex.IsEquivalent(m_pHitObject->GetWorldPos(), 0.001f)) - { - dc.DrawBall(m_vHitVertex, vBoxSize.x * 1.2f); - } - else - { - dc.DrawSolidBox(m_vHitVertex - vBoxSize, m_vHitVertex + vBoxSize); - } - dc.DepthTestOn(); - } - - // draw wireframe of hit object - if (m_pHitObject && m_pHitObject->GetIStatObj()) - { - SGeometryDebugDrawInfo dd; - dd.tm = m_pHitObject->GetWorldTM(); - dd.color = ColorB(250, 0, 250, 30); - dd.lineColor = ColorB(255, 255, 0, 160); - dd.bExtrude = true; - m_pHitObject->GetIStatObj()->DebugDraw(dd); - } - - // draw debug boxes - if (gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox) - { - ColorB boxColor(40, 40, 40); - for (int i = 0, iCount(m_DebugBoxes.size()); i < iCount; ++i) - { - dc.SetColor(boxColor); - boxColor += ColorB(25, 25, 25); - dc.DrawWireBox(m_DebugBoxes[i].min, m_DebugBoxes[i].max); - } - } -} - -void CVertexSnappingModeTool::DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj) -{ - if (!pStatObj) - { - return; - } - - IIndexedMesh* pIndexedMesh = pStatObj->GetIndexedMesh(); - if (pIndexedMesh) - { - IIndexedMesh::SMeshDescription md; - pIndexedMesh->GetMeshDescription(md); - for (int k = 0; k < md.m_nVertCount; ++k) - { - Vec3 vPos(0, 0, 0); - if (md.m_pVerts) - { - vPos = md.m_pVerts[k]; - } - else if (md.m_pVertsF16) - { - vPos = md.m_pVertsF16[k].ToVec3(); - } - else - { - continue; - } - vPos = tm.TransformPoint(vPos); - Vec3 vBoxSize = GetCubeSize(dc.view, vPos); - if (!m_bHit || !m_vHitVertex.IsEquivalent(vPos, 0.001f)) - { - dc.DrawSolidBox(vPos - vBoxSize, vPos + vBoxSize); - } - } - } - - for (int i = 0, iSubStatObjNum(pStatObj->GetSubObjectCount()); i < iSubStatObjNum; ++i) - { - IStatObj::SSubObject* pSubObj = pStatObj->GetSubObject(i); - if (pSubObj) - { - DrawVertexCubes(dc, tm * pSubObj->localTM, pSubObj->pStatObj); - } - } -} - -CKDTree* CVertexSnappingModeTool::GetKDTree(CBaseObject* pObject) -{ - auto existingTree = m_ObjectKdTreeMap.find(pObject); - if (existingTree != m_ObjectKdTreeMap.end()) - { - return existingTree->second; - } - - // Don't build a kd-tree for objects without verts - CKDTree* pTree = nullptr; - if (auto pStatObj = pObject->GetIStatObj()) - { - pTree = new CKDTree(); - pTree->Build(pObject->GetIStatObj()); - } - - m_ObjectKdTreeMap[pObject] = pTree; - return pTree; -} - -#include <EditMode/moc_VertexSnappingModeTool.cpp> diff --git a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h b/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h deleted file mode 100644 index 943f6bceb4..0000000000 --- a/Code/Sandbox/Editor/EditMode/VertexSnappingModeTool.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H -#define CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H -#pragma once - -#include "EditTool.h" -#include "Objects/BaseObject.h" - -class CKDTree; -struct IDisplayViewport; - -class CVertexSnappingModeTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CVertexSnappingModeTool(); - ~CVertexSnappingModeTool(); - - static const GUID& GetClassID(); - - static void RegisterTool(CRegistrationContext& rc); - - void Display(DisplayContext& dc); - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - -protected: - - void DrawVertexCubes(DisplayContext& dc, const Matrix34& tm, IStatObj* pStatObj); - void DeleteThis(){ delete this; } - Vec3 GetCubeSize(IDisplayViewport* pView, const Vec3& pos) const; - -private: - - using CEditTool::HitTest; - bool HitTest(CViewport* view, const QPoint& point, CBaseObject* pExcludedObj, Vec3& outHitPos, CBaseObjectPtr& pOutHitObject, std::vector<CBaseObjectPtr>& outObjects); - CKDTree* GetKDTree(CBaseObject* pObject); - - enum EVertexSnappingStatus - { - eVSS_SelectFirstVertex, - eVSS_MoveSelectVertexToAnotherVertex - }; - EVertexSnappingStatus m_modeStatus; - - struct SSelectionInfo - { - SSelectionInfo() - { - m_pObject = NULL; - m_vPos = Vec3(0, 0, 0); - } - CBaseObjectPtr m_pObject; - Vec3 m_vPos; - }; - - /// Info on object being moved (when in eVSS_MoveSelectVertexToAnotherVertex mode). - SSelectionInfo m_SelectionInfo; - - /// Objects that mouse is over - std::vector<CBaseObjectPtr> m_Objects; - - /// Position of vertex that mouse is hitting. - /// Invalid when m_bHit is false. - Vec3 m_vHitVertex; - - /// Whether the mouse hit test succeeded - bool m_bHit; - - /// Object that mouse is hitting - CBaseObjectPtr m_pHitObject; - - /// Boxes to render for debug drawing - std::vector<AABB> m_DebugBoxes; - - /// For each object, a tree containing its vertices. - std::map<CBaseObjectPtr, CKDTree*> m_ObjectKdTreeMap; -}; -#endif // CRYINCLUDE_EDITOR_EDITMODE_VERTEXSNAPPINGMODETOOL_H diff --git a/Code/Sandbox/Editor/EditTool.cpp b/Code/Sandbox/Editor/EditTool.cpp deleted file mode 100644 index 31a59aa58f..0000000000 --- a/Code/Sandbox/Editor/EditTool.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "EditTool.h" - -// Editor -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" - -////////////////////////////////////////////////////////////////////////// -// Class description. -////////////////////////////////////////////////////////////////////////// -class CEditTool_ClassDesc - : public CRefCountClassDesc -{ - virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; } - virtual REFGUID ClassID() - { - // {0A43AB8E-B1AE-44aa-93B1-229F73D58CA4} - static const GUID guid = { - 0xa43ab8e, 0xb1ae, 0x44aa, { 0x93, 0xb1, 0x22, 0x9f, 0x73, 0xd5, 0x8c, 0xa4 } - }; - return guid; - } - virtual QString ClassName() { return "EditTool.Default"; }; - virtual QString Category() { return "EditTool"; }; -}; -CEditTool_ClassDesc g_stdClassDesc; - -////////////////////////////////////////////////////////////////////////// -CEditTool::CEditTool(QObject* parent) - : QObject(parent) -{ - m_pClassDesc = &g_stdClassDesc; - m_nRefCount = 0; -}; - -////////////////////////////////////////////////////////////////////////// -void CEditTool::SetParentTool(CEditTool* pTool) -{ - m_pParentTool = pTool; -} - -////////////////////////////////////////////////////////////////////////// -CEditTool* CEditTool::GetParentTool() -{ - return m_pParentTool; -} - -////////////////////////////////////////////////////////////////////////// -void CEditTool::Abort() -{ - if (m_pParentTool) - { - GetIEditor()->SetEditTool(m_pParentTool); - } - else - { - GetIEditor()->SetEditTool(0); - } -} - -////////////////////////////////////////////////////////////////////////// -void CEditTool::GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects) -{ - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection == NULL) - { - return; - } - for (int i = 0, iCount(pSelection->GetCount()); i < iCount; ++i) - { - outAffectedObjects.push_back(pSelection->GetObject(i)); - } -} - -#include <moc_EditTool.cpp> diff --git a/Code/Sandbox/Editor/EditTool.h b/Code/Sandbox/Editor/EditTool.h deleted file mode 100644 index b9d937ae0d..0000000000 --- a/Code/Sandbox/Editor/EditTool.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_EDITTOOL_H -#define CRYINCLUDE_EDITOR_EDITTOOL_H - -#pragma once - -#if !defined(Q_MOC_RUN) -#include "QtViewPaneManager.h" -#endif - -class CViewport; -struct IClassDesc; -struct ITransformManipulator; -struct HitContext; - -enum EEditToolType -{ - EDIT_TOOL_TYPE_PRIMARY, - EDIT_TOOL_TYPE_SECONDARY, -}; - -/*! - * CEditTool is an abstract base class for All Editing Tools supported by Editor. - * Edit tools handle specific editing modes in viewports. - */ -class SANDBOX_API CEditTool - : public QObject -{ - Q_OBJECT -public: - explicit CEditTool(QObject* parent = nullptr); - - ////////////////////////////////////////////////////////////////////////// - // For reference counting. - ////////////////////////////////////////////////////////////////////////// - void AddRef() { m_nRefCount++; }; - void Release() - { - AZ_Assert(m_nRefCount > 0, "Negative ref count"); - if (--m_nRefCount == 0) - { - DeleteThis(); - } - }; - - //! Returns class description for this tool. - IClassDesc* GetClassDesc() const { return m_pClassDesc; } - - virtual void SetParentTool(CEditTool* pTool); - virtual CEditTool* GetParentTool(); - - virtual EEditToolType GetType() { return EDIT_TOOL_TYPE_PRIMARY; } - virtual EOperationMode GetMode() { return eOperationModeNone; } - - // Abort tool. - virtual void Abort(); - - // Accept tool. - virtual void Accept([[maybe_unused]] bool resetPosition = false) {} - - //! Status text displayed when this tool is active. - void SetStatusText(const QString& text) { m_statusText = text; }; - QString GetStatusText() { return m_statusText; }; - - // Description: - // Activates tool. - // Arguments: - // pPreviousTool - Previously active edit tool. - // Return: - // True if the tool can be activated, - virtual bool Activate([[maybe_unused]] CEditTool* pPreviousTool) { return true; }; - - //! Used to pass user defined data to edit tool from ToolButton. - virtual void SetUserData([[maybe_unused]] const char* key, [[maybe_unused]] void* userData) {}; - - //! Called when user starts using this tool. - //! Flags is comnination of ObjectEditFlags flags. - virtual void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) {}; - //! Called when user ends using this tool. - virtual void EndEditParams() {}; - - // Called each frame to display tool for given viewport. - virtual void Display(struct DisplayContext& dc) = 0; - - //! Mouse callback sent from viewport. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Return false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport that sent this callback. - //! @param event Indicate what kind of event occured in viewport. - //! @param point 2D coordinate in viewport where event occured. - //! @param flags Additional flags (MK_LBUTTON,etc..) or from (MouseEventFlags) specified by viewport when calling callback. - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) = 0; - - //! Called when key in viewport is pressed while using this tool. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Returns false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport where key was pressed. - //! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h - //! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key. - //! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN) - virtual bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - - //! Called when key in viewport is released while using this tool. - //! Returns true if event processed by callback, and all other processing for this event should abort. - //! Returns false if event was not processed by callback, and other processing for this event should occur. - //! @param view Viewport where key was pressed. - //! @param nChar Specifies the virtual key code of the given key. For a list of standard virtual key codes, see Winuser.h - //! @param nRepCnt Specifies the repeat count, that is, the number of times the keystroke is repeated as a result of the user holding down the key. - //! @param nFlags Specifies the scan code, key-transition code, previous key state, and context code, (see WM_KEYDOWN) - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - - //! Called when mouse is moved and give oportunity to tool to set it own cursor. - //! @return true if cursor changed. or false otherwise. - virtual bool OnSetCursor([[maybe_unused]] CViewport* vp) { return false; }; - - // Return objects affected by this edit tool. The returned objects usually will be the selected objects. - virtual void GetAffectedObjects(DynArray<CBaseObject*>& outAffectedObjects); - - // Called in response to the dragging of the manipulator in the view. - // Allow edit tool to handle manipulator dragging the way it wants. - virtual void OnManipulatorDrag([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] QPoint& p0, [[maybe_unused]] QPoint& p1, [[maybe_unused]] const Vec3& value) {} - - virtual void OnManipulatorDrag(CViewport* view, ITransformManipulator* pManipulator, const Vec3& value) - { - // Overload with less boiler-plate - QPoint p0, p1; - OnManipulatorDrag(view, pManipulator, p0, p1, value); - } - - // Called in response to mouse event of the manipulator in the view - virtual void OnManipulatorMouseEvent([[maybe_unused]] CViewport* view, [[maybe_unused]] ITransformManipulator* pManipulator, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags, [[maybe_unused]] bool bHitGizmo = false) {} - - virtual bool IsNeedMoveTool() { return false; } - virtual bool IsNeedSpecificBehaviorForSpaceAcce() { return false; } - virtual bool IsNeedToSkipPivotBoxForObjects() { return false; } - virtual bool IsDisplayGrid() { return true; } - virtual bool IsUpdateUIPanel() { return false; } - virtual bool IsMoveToObjectModeAfterEnd() { return true; } - virtual bool IsCircleTypeRotateGizmo() { return false; } - - // Draws object specific helpers for this tool - virtual void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) {} - - // Hit test against edit tool - virtual bool HitTest([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] HitContext& hc) { return false; } - -protected: - virtual ~CEditTool() {}; - ////////////////////////////////////////////////////////////////////////// - // Delete edit tool. - ////////////////////////////////////////////////////////////////////////// - virtual void DeleteThis() = 0; - -protected: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - _smart_ptr<CEditTool> m_pParentTool; // Pointer to parent edit tool. - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - QString m_statusText; - IClassDesc* m_pClassDesc; - int m_nRefCount; -}; - -#endif // CRYINCLUDE_EDITOR_EDITTOOL_H diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp index b10d564031..a7420b79a4 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.cpp @@ -63,11 +63,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("DeepSelectionRange", &DeepSelection::m_deepSelectionRange) ->Field("StickDuplicate", &DeepSelection::m_stickDuplicate); - serialize.Class<VertexSnapping>() - ->Version(1) - ->Field("VertexCubeSize", &VertexSnapping::m_vertexCubeSize) - ->Field("RenderPenetratedBoundBox", &VertexSnapping::m_bRenderPenetratedBoundBox); - serialize.Class<SliceSettings>() ->Version(1) ->Field("DynamicByDefault", &SliceSettings::m_slicesDynamicByDefault); @@ -78,7 +73,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Field("Messaging", &CEditorPreferencesPage_General::m_messaging) ->Field("Undo", &CEditorPreferencesPage_General::m_undo) ->Field("Deep Selection", &CEditorPreferencesPage_General::m_deepSelection) - ->Field("Vertex Snapping", &CEditorPreferencesPage_General::m_vertexSnapping) ->Field("Slice Settings", &CEditorPreferencesPage_General::m_sliceSettings); @@ -119,12 +113,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Max, 1000.0f); - editContext->Class<VertexSnapping>("Vertex Snapping", "") - ->DataElement(AZ::Edit::UIHandlers::SpinBox, &VertexSnapping::m_vertexCubeSize, "Vertex Cube Size", "Vertex Cube Size") - ->Attribute(AZ::Edit::Attributes::Min, 0.0001f) - ->Attribute(AZ::Edit::Attributes::Max, 1.0f) - ->DataElement(AZ::Edit::UIHandlers::CheckBox, &VertexSnapping::m_bRenderPenetratedBoundBox, "Render Penetrated BoundBoxes", "Render Penetrated BoundBoxes"); - editContext->Class<SliceSettings>("Slices", "") ->DataElement(AZ::Edit::UIHandlers::CheckBox, &SliceSettings::m_slicesDynamicByDefault, "New Slices Dynamic By Default", "When creating slices, they will be set to dynamic by default"); @@ -135,7 +123,6 @@ void CEditorPreferencesPage_General::Reflect(AZ::SerializeContext& serialize) ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_messaging, "Messaging", "Messaging") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_undo, "Undo", "Undo Preferences") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_deepSelection, "Selection", "Selection") - ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_vertexSnapping, "Vertex Snapping", "Vertex Snapping") ->DataElement(AZ::Edit::UIHandlers::Default, &CEditorPreferencesPage_General::m_sliceSettings, "Slices", "Slice Settings"); } } @@ -189,10 +176,6 @@ void CEditorPreferencesPage_General::OnApply() gSettings.deepSelectionSettings.fRange = m_deepSelection.m_deepSelectionRange; gSettings.deepSelectionSettings.bStickDuplicate = m_deepSelection.m_stickDuplicate; - //vertex snapping - gSettings.vertexSnappingSettings.vertexCubeSize = m_vertexSnapping.m_vertexCubeSize; - gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox = m_vertexSnapping.m_bRenderPenetratedBoundBox; - //slices gSettings.sliceSettings.dynamicByDefault = m_sliceSettings.m_slicesDynamicByDefault; @@ -236,10 +219,6 @@ void CEditorPreferencesPage_General::InitializeSettings() m_deepSelection.m_deepSelectionRange = gSettings.deepSelectionSettings.fRange; m_deepSelection.m_stickDuplicate = gSettings.deepSelectionSettings.bStickDuplicate; - //vertex snapping - m_vertexSnapping.m_vertexCubeSize = gSettings.vertexSnappingSettings.vertexCubeSize; - m_vertexSnapping.m_bRenderPenetratedBoundBox = gSettings.vertexSnappingSettings.bRenderPenetratedBoundBox; - //slices m_sliceSettings.m_slicesDynamicByDefault = gSettings.sliceSettings.dynamicByDefault; } diff --git a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h index d996f410a7..31776e9c10 100644 --- a/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h +++ b/Code/Sandbox/Editor/EditorPreferencesPageGeneral.h @@ -88,14 +88,6 @@ private: bool m_stickDuplicate; }; - struct VertexSnapping - { - AZ_TYPE_INFO(VertexSnapping, "{20F16350-990C-4096-86E3-40D56DDDD702}") - - float m_vertexCubeSize; - bool m_bRenderPenetratedBoundBox; - }; - struct SliceSettings { AZ_TYPE_INFO(SliceSettings, "{8505CCC1-874C-4389-B51A-B9E5FF70CFDA}") @@ -107,7 +99,6 @@ private: Messaging m_messaging; Undo m_undo; DeepSelection m_deepSelection; - VertexSnapping m_vertexSnapping; SliceSettings m_sliceSettings; QIcon m_icon; }; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 91c70b720f..eaa692a645 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -65,7 +65,6 @@ #include "Util/fastlib.h" #include "CryEditDoc.h" #include "GameEngine.h" -#include "EditTool.h" #include "ViewManager.h" #include "Objects/DisplayContext.h" #include "DisplaySettings.h" diff --git a/Code/Sandbox/Editor/GameExporter.cpp b/Code/Sandbox/Editor/GameExporter.cpp index 5173071024..00836018cf 100644 --- a/Code/Sandbox/Editor/GameExporter.cpp +++ b/Code/Sandbox/Editor/GameExporter.cpp @@ -125,9 +125,6 @@ bool CGameExporter::Export(unsigned int flags, [[maybe_unused]] EEndian eExportE { QDir::setCurrent(pEditor->GetPrimaryCDFolder()); - // Close all Editor tools - pEditor->SetEditTool(0); - QString sLevelPath = Path::AddSlash(pGameEngine->GetLevelPath()); if (subdirectory && subdirectory[0] && strcmp(subdirectory, ".") != 0) { diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index 722f2a7c25..83a0029d9f 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -40,7 +40,6 @@ struct QMetaObject; class CBaseObject; class CCryEditDoc; class CSelectionGroup; -class CEditTool; class CAnimationContext; class CTrackViewSequenceManager; class CGameEngine; @@ -623,14 +622,6 @@ struct IEditor //! editMode - EEditMode virtual void SetEditMode(int editMode) = 0; virtual int GetEditMode() = 0; - //! Assign current edit tool, destroy previously used edit too. - virtual void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) = 0; - //! Assign current edit tool by class name. - virtual void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) = 0; - //! Reinitializes the current edit tool if one is selected. - virtual void ReinitializeEditTool() = 0; - //! Returns current edit tool. - virtual CEditTool* GetEditTool() = 0; //! Shows/Hides transformation manipulator. //! if bShow is true also returns a valid ITransformManipulator pointer. virtual ITransformManipulator* ShowTransformManipulator(bool bShow) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index 399ac45794..d4fd86312e 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -54,7 +54,6 @@ AZ_POP_DISABLE_WARNING #include "Export/ExportManager.h" #include "LevelIndependentFileMan.h" #include "Material/MaterialManager.h" -#include "Material/MaterialPickTool.h" #include "TrackView/TrackViewSequenceManager.h" #include "AnimationContext.h" #include "GameEngine.h" @@ -71,13 +70,9 @@ AZ_POP_DISABLE_WARNING #include "Objects/SelectionGroup.h" #include "Objects/ObjectManager.h" -#include "RotateTool.h" -#include "NullEditTool.h" - #include "BackgroundTaskManager.h" #include "BackgroundScheduleManager.h" #include "EditorFileMonitor.h" -#include "EditMode/VertexSnappingModeTool.h" #include "Mission.h" #include "MainStatusBar.h" @@ -451,12 +446,6 @@ void CEditorImpl::RegisterTools() rc.pCommandManager = m_pCommandManager; rc.pClassFactory = m_pClassFactory; - - CObjectMode::RegisterTool(rc); - CMaterialPickTool::RegisterTool(rc); - CVertexSnappingModeTool::RegisterTool(rc); - CRotateTool::RegisterTool(rc); - NullEditTool::RegisterTool(rc); } void CEditorImpl::ExecuteCommand(const char* sCommand, ...) @@ -682,14 +671,6 @@ void CEditorImpl::SetEditMode(int editMode) } } - if ((EEditMode)editMode == eEditModeRotate) - { - if (GetEditTool() && GetEditTool()->IsCircleTypeRotateGizmo()) - { - editMode = eEditModeRotateCircle; - } - } - EEditMode newEditMode = (EEditMode)editMode; if (m_currEditMode == newEditMode) { @@ -700,11 +681,6 @@ void CEditorImpl::SetEditMode(int editMode) AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0)); SetSelectedRegion(box); - if (GetEditTool() && !GetEditTool()->IsNeedMoveTool()) - { - SetEditTool(0, true); - } - Notify(eNotify_OnEditModeChange); } @@ -719,139 +695,6 @@ EOperationMode CEditorImpl::GetOperationMode() return m_operationMode; } -bool CEditorImpl::HasCorrectEditTool() const -{ - if (!m_pEditTool) - { - return false; - } - - switch (m_currEditMode) - { - case eEditModeRotate: - return qobject_cast<CRotateTool*>(m_pEditTool) != nullptr; - default: - return qobject_cast<CObjectMode*>(m_pEditTool) != nullptr && qobject_cast<CRotateTool*>(m_pEditTool) == nullptr; - } -} - -CEditTool* CEditorImpl::CreateCorrectEditTool() -{ - if (m_currEditMode == eEditModeRotate) - { - CBaseObject* selectedObj = nullptr; - CSelectionGroup* pSelection = GetIEditor()->GetObjectManager()->GetSelection(); - if (pSelection && pSelection->GetCount() > 0) - { - selectedObj = pSelection->GetObject(0); - } - - return (new CRotateTool(selectedObj)); - } - - return (new CObjectMode); -} - -void CEditorImpl::SetEditTool(CEditTool* tool, bool bStopCurrentTool) -{ - CViewport* pViewport = GetIEditor()->GetActiveView(); - if (pViewport) - { - pViewport->SetCurrentCursor(STD_CURSOR_DEFAULT); - } - - if (!tool) - { - if (HasCorrectEditTool()) - { - return; - } - else - { - tool = CreateCorrectEditTool(); - } - } - - if (!tool->Activate(m_pEditTool)) - { - return; - } - - if (bStopCurrentTool) - { - if (m_pEditTool && m_pEditTool != tool) - { - m_pEditTool->EndEditParams(); - SetStatusText("Ready"); - } - } - - m_pEditTool = tool; - if (m_pEditTool) - { - m_pEditTool->BeginEditParams(this, 0); - } - - Notify(eNotify_OnEditToolChange); -} - -void CEditorImpl::ReinitializeEditTool() -{ - if (m_pEditTool) - { - m_pEditTool->EndEditParams(); - m_pEditTool->BeginEditParams(this, 0); - } -} - -void CEditorImpl::SetEditTool(const QString& sEditToolName, [[maybe_unused]] bool bStopCurrentTool) -{ - CEditTool* pTool = GetEditTool(); - if (pTool && pTool->GetClassDesc()) - { - // Check if already selected. - if (QString::compare(pTool->GetClassDesc()->ClassName(), sEditToolName, Qt::CaseInsensitive) == 0) - { - return; - } - } - - IClassDesc* pClass = GetIEditor()->GetClassFactory()->FindClass(sEditToolName.toUtf8().data()); - if (!pClass) - { - Warning("Editor Tool %s not registered.", sEditToolName.toUtf8().data()); - return; - } - if (pClass->SystemClassID() != ESYSTEM_CLASS_EDITTOOL) - { - Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data()); - return; - } - - QScopedPointer<QObject> o(pClass->CreateQObject()); - if (CEditTool* pEditTool = qobject_cast<CEditTool*>(o.data())) - { - GetIEditor()->SetEditTool(pEditTool); - o.take(); - return; - } - else - { - Warning("Class name %s is not a valid Edit Tool class.", sEditToolName.toUtf8().data()); - return; - } -} - -CEditTool* CEditorImpl::GetEditTool() -{ - if (m_isNewViewportInteractionModelEnabled) - { - return nullptr; - } - - return m_pEditTool; -} - ITransformManipulator* CEditorImpl::ShowTransformManipulator(bool bShow) { if (bShow) diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index 4a8d5fa191..7bb864aaa3 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -229,18 +229,6 @@ public: void SetEditMode(int editMode); int GetEditMode(); - //! A correct tool is one that corresponds to the previously set edit mode. - bool HasCorrectEditTool() const; - - //! Returns the edit tool required for the edit mode specified. - CEditTool* CreateCorrectEditTool(); - - void SetEditTool(CEditTool* tool, bool bStopCurrentTool = true) override; - void SetEditTool(const QString& sEditToolName, bool bStopCurrentTool = true) override; - void ReinitializeEditTool() override; - //! Returns current edit tool. - CEditTool* GetEditTool() override; - ITransformManipulator* ShowTransformManipulator(bool bShow); ITransformManipulator* GetTransformManipulator(); void SetAxisConstraints(AxisConstrains axis); @@ -400,7 +388,6 @@ protected: CXmlTemplateRegistry m_templateRegistry; CDisplaySettings* m_pDisplaySettings; CShaderEnum* m_pShaderEnum; - _smart_ptr<CEditTool> m_pEditTool; CIconManager* m_pIconManager; std::unique_ptr<SGizmoParameters> m_pGizmoParameters; QString m_primaryCDFolder; diff --git a/Code/Sandbox/Editor/Include/IObjectManager.h b/Code/Sandbox/Editor/Include/IObjectManager.h index 184a080870..bf1bb97db9 100644 --- a/Code/Sandbox/Editor/Include/IObjectManager.h +++ b/Code/Sandbox/Editor/Include/IObjectManager.h @@ -188,8 +188,6 @@ public: virtual void SetSelection(const QString& name) = 0; //! Removes one of named selections. virtual void RemoveSelection(const QString& name) = 0; - //! Checks for changes to the current selection and makes adjustments accordingly - virtual void CheckAndFixSelection() = 0; //! Delete all objects in current selection group. virtual void DeleteSelection() = 0; diff --git a/Code/Sandbox/Editor/InfoBar.cpp b/Code/Sandbox/Editor/InfoBar.cpp index 60c24fe84e..9e50e4ed3e 100644 --- a/Code/Sandbox/Editor/InfoBar.cpp +++ b/Code/Sandbox/Editor/InfoBar.cpp @@ -25,7 +25,6 @@ #include "Objects/SelectionGroup.h" #include "Include/IObjectManager.h" #include "MathConversion.h" -#include "EditTool.h" AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include <ui_InfoBar.h> @@ -58,7 +57,6 @@ CInfoBar::CInfoBar(QWidget* parent) m_prevEditMode = 0; m_bSelectionLocked = false; m_bSelectionChanged = false; - m_editTool = 0; m_bDragMode = false; m_prevMoveSpeed = 0; m_currValue = Vec3(-111, +222, -333); //this wasn't initialized. I don't know what a good value is @@ -251,28 +249,6 @@ void CInfoBar::OnVectorUpdate(bool followTerrain) ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); if (pManipulator) { - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - - if (pEditTool) - { - Vec3 diff = v - m_lastValue; - if (emode == eEditModeMove) - { - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - if (emode == eEditModeRotate) - { - diff = DEG2RAD(diff); - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - if (emode == eEditModeScale) - { - //GetIEditor()->RestoreUndo(); - pEditTool->OnManipulatorDrag(GetIEditor()->GetActiveView(), pManipulator, diff); - } - } return; } @@ -421,39 +397,22 @@ void CInfoBar::IdleUpdate() updateUI = true; } - if (GetIEditor()->GetEditTool() != m_editTool) - { - updateUI = true; - m_editTool = GetIEditor()->GetEditTool(); - } - QString str; - if (m_editTool) + if (updateUI) { - str = m_editTool->GetStatusText(); - if (str != m_sLastText) + if (m_numSelected == 0) { - updateUI = true; + str = tr("None Selected"); } - } - - if (updateUI) - { - if (!m_editTool) + else if (m_numSelected == 1) { - if (m_numSelected == 0) - { - str = tr("None Selected"); - } - else if (m_numSelected == 1) - { - str = tr("1 Object Selected"); - } - else - { - str = tr("%1 Objects Selected").arg(m_numSelected); - } + str = tr("1 Object Selected"); } + else + { + str = tr("%1 Objects Selected").arg(m_numSelected); + } + ui->m_statusText->setText(str); m_sLastText = str; } diff --git a/Code/Sandbox/Editor/InfoBar.h b/Code/Sandbox/Editor/InfoBar.h index 6bf89099fe..aa0d0628a2 100644 --- a/Code/Sandbox/Editor/InfoBar.h +++ b/Code/Sandbox/Editor/InfoBar.h @@ -124,7 +124,6 @@ protected: bool m_bDragMode; QString m_sLastText; - CEditTool* m_editTool; Vec3 m_lastValue; Vec3 m_currValue; float m_oldMainVolume; diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index e48fb5fec1..a309a1a5f5 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -125,10 +125,6 @@ public: MOCK_METHOD0(GetOperationMode, EOperationMode()); MOCK_METHOD1(SetEditMode, void(int )); MOCK_METHOD0(GetEditMode, int()); - MOCK_METHOD2(SetEditTool, void(CEditTool*, bool)); - MOCK_METHOD2(SetEditTool, void(const QString&, bool)); - MOCK_METHOD0(ReinitializeEditTool, void()); - MOCK_METHOD0(GetEditTool, CEditTool* ()); MOCK_METHOD1(ShowTransformManipulator, ITransformManipulator* (bool)); MOCK_METHOD0(GetTransformManipulator, ITransformManipulator* ()); MOCK_METHOD1(SetAxisConstraints, void(AxisConstrains )); diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index 6acd8cfc20..d7659c2512 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -60,7 +60,6 @@ AZ_POP_DISABLE_WARNING // Editor #include "Resource.h" -#include "EditTool.h" #include "Core/LevelEditorMenuHandler.h" #include "ShortcutDispatcher.h" #include "LayoutWnd.h" @@ -270,15 +269,6 @@ namespace return QtViewPaneManager::instance()->IsVisible(viewClassName); } - AZStd::string PyGetStatusText() - { - if (GetIEditor()->GetEditTool()) - { - return AZStd::string(GetIEditor()->GetEditTool()->GetStatusText().toUtf8().data()); - } - return AZStd::string(""); - } - AZStd::vector<AZStd::string> PyGetViewPaneNames() { const QtViewPanes panes = QtViewPaneManager::instance()->GetRegisteredPanes(); @@ -693,7 +683,6 @@ void MainWindow::closeEvent(QCloseEvent* event) } // Close all edit panels. GetIEditor()->ClearSelection(); - GetIEditor()->SetEditTool(0); GetIEditor()->GetObjectManager()->EndEditParams(); // force clean up of all deferred deletes, so that we don't have any issues with windows from plugins not being deleted yet @@ -1104,11 +1093,6 @@ void MainWindow::InitActions() .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected) .SetIcon(Style::icon("Align_to_grid")) .SetApplyHoverEffect(); - am->AddAction(ID_MODIFY_ALIGNOBJTOSURF, tr("Align object to surface (Hold CTRL)")).SetCheckable(true) - .SetToolTip(tr("Align object to surface (Hold CTRL)")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateAlignToVoxel) - .SetIcon(Style::icon("Align_object_to_surface")) - .SetApplyHoverEffect(); } am->AddAction(ID_SNAP_TO_GRID, tr("Snap to grid")) @@ -1459,10 +1443,6 @@ void MainWindow::InitActions() .SetIcon(QIcon(":/MainWindow/toolbars/object_toolbar-03.svg")) .SetApplyHoverEffect() .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected); - // vertex snapping not yet supported when the new Viewport Interaction Model is enabled - am->AddAction(ID_OBJECTMODIFY_VERTEXSNAPPING, tr("Vertex snapping")) - .SetIcon(Style::icon("Vertex_snapping")) - .SetApplyHoverEffect(); } // Misc Toolbar Actions @@ -1510,8 +1490,6 @@ void MainWindow::OnEscapeAction() { AzToolsFramework::EditorEvents::Bus::Broadcast( &AzToolsFramework::EditorEvents::OnEscape); - - CCryEditApp::instance()->OnEditEscape(); } } } @@ -2640,7 +2618,6 @@ namespace AzToolsFramework addLegacyGeneral(behaviorContext->Method("exit", PyExit, nullptr, "Exits the editor.")); addLegacyGeneral(behaviorContext->Method("exit_no_prompt", PyExitNoPrompt, nullptr, "Exits the editor without prompting to save first.")); addLegacyGeneral(behaviorContext->Method("report_test_result", PyReportTest, nullptr, "Report test information.")); - addLegacyGeneral(behaviorContext->Method("get_status_text", PyGetStatusText, nullptr, "Gets the status text from the Editor's current edit tool")); } } } diff --git a/Code/Sandbox/Editor/Material/MaterialPickTool.cpp b/Code/Sandbox/Editor/Material/MaterialPickTool.cpp deleted file mode 100644 index 38e3d0612d..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPickTool.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "MaterialPickTool.h" - -// Editor -#include "MaterialManager.h" -#include "SurfaceInfoPicker.h" -#include "Viewport.h" - - -#define RENDER_MESH_TEST_DISTANCE 0.2f - -static IClassDesc * s_ToolClass = NULL; - -////////////////////////////////////////////////////////////////////////// -CMaterialPickTool::CMaterialPickTool() -{ - m_pClassDesc = s_ToolClass; - m_statusText = tr("Left Click To Pick Material"); -} - -////////////////////////////////////////////////////////////////////////// -CMaterialPickTool::~CMaterialPickTool() -{ - SetMaterial(0); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialPickTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - if (event == eMouseLDown) - { - if (m_pMaterial) - { - CMaterial* pMtl = GetIEditor()->GetMaterialManager()->FromIMaterial(m_pMaterial); - if (pMtl) - { - GetIEditor()->GetMaterialManager()->SetHighlightedMaterial(0); - GetIEditor()->OpenMaterialLibrary(pMtl); - Abort(); - return true; - } - } - } - else if (event == eMouseMove) - { - return OnMouseMove(view, flags, point); - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::Display(DisplayContext& dc) -{ - QPoint mousePoint = QCursor::pos(); - - dc.view->ScreenToClient(mousePoint); - - Vec3 wp = dc.view->ViewToWorld(mousePoint); - - if (m_pMaterial) - { - float color[4] = {1, 1, 1, 1}; - dc.renderer->Draw2dLabel(mousePoint.x() + 12, mousePoint.y ()+ 8, 1.2f, color, false, "%s", m_displayString.toUtf8().data()); - } - - float fScreenScale = dc.view->GetScreenScaleFactor(m_HitInfo.vHitPos) * 0.06f; - - dc.DepthTestOff(); - dc.SetColor(ColorB(0, 0, 255, 255)); - if (!m_HitInfo.vHitNormal.IsZero()) - { - dc.DrawLine(m_HitInfo.vHitPos, m_HitInfo.vHitPos + m_HitInfo.vHitNormal * fScreenScale); - - Vec3 raySrc, rayDir; - dc.view->ViewToWorldRay(mousePoint, raySrc, rayDir); - - Matrix34 tm; - - Vec3 zAxis = m_HitInfo.vHitNormal; - Vec3 xAxis = rayDir.Cross(zAxis); - if (!xAxis.IsZero()) - { - xAxis.Normalize(); - Vec3 yAxis = xAxis.Cross(zAxis).GetNormalized(); - tm.SetFromVectors(xAxis, yAxis, zAxis, m_HitInfo.vHitPos); - - dc.PushMatrix(tm); - dc.DrawCircle(Vec3(0, 0, 0), 0.5f * fScreenScale); - dc.PopMatrix(); - } - } - dc.DepthTestOn(); -} - -////////////////////////////////////////////////////////////////////////// -bool CMaterialPickTool::OnMouseMove(CViewport* view, [[maybe_unused]] UINT nFlags, const QPoint& point) -{ - view->SetCurrentCursor(STD_CURSOR_HIT, ""); - - _smart_ptr<IMaterial> pNearestMaterial(NULL); - - m_Mouse2DPosition = point; - - CSurfaceInfoPicker surfacePicker; - int nPickObjectGroupFlag = CSurfaceInfoPicker::ePOG_All; - if (surfacePicker.Pick(point, pNearestMaterial, m_HitInfo, NULL, nPickObjectGroupFlag)) - { - SetMaterial(pNearestMaterial); - return true; - } - - SetMaterial(0); - return false; -} - -const GUID& CMaterialPickTool::GetClassID() -{ - // {FD20F6F2-7B87-4349-A5D4-7533538E357F} - static const GUID guid = { - 0xfd20f6f2, 0x7b87, 0x4349, { 0xa5, 0xd4, 0x75, 0x33, 0x53, 0x8e, 0x35, 0x7f } - }; - return guid; -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(s_ToolClass = new CQtViewClass<CMaterialPickTool>("EditTool.PickMaterial", "Material", ESYSTEM_CLASS_EDITTOOL)); -} - -////////////////////////////////////////////////////////////////////////// -void CMaterialPickTool::SetMaterial(_smart_ptr<IMaterial> pMaterial) -{ - if (pMaterial == m_pMaterial) - { - return; - } - - m_pMaterial = pMaterial; - CMaterial* pCMaterial = GetIEditor()->GetMaterialManager()->FromIMaterial(m_pMaterial); - GetIEditor()->GetMaterialManager()->SetHighlightedMaterial(pCMaterial); - - m_displayString = ""; - if (pMaterial) - { - QString sfType; - sfType = QStringLiteral("%1 : %2").arg(pMaterial->GetSurfaceType()->GetId()).arg(pMaterial->GetSurfaceType()->GetName()); - - m_displayString = "\n"; - m_displayString += pMaterial->GetName(); - m_displayString += "\n"; - m_displayString += sfType; - } -} - -#include <Material/moc_MaterialPickTool.cpp> diff --git a/Code/Sandbox/Editor/Material/MaterialPickTool.h b/Code/Sandbox/Editor/Material/MaterialPickTool.h deleted file mode 100644 index 09c5691315..0000000000 --- a/Code/Sandbox/Editor/Material/MaterialPickTool.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of PickObjectTool, tool used to pick objects. - -#ifndef CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H -#define CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H -#pragma once - -#include "EditTool.h" - -////////////////////////////////////////////////////////////////////////// -class CMaterialPickTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CMaterialPickTool(); - - static const GUID& GetClassID(); - - static void RegisterTool(CRegistrationContext& rc); - - ////////////////////////////////////////////////////////////////////////// - // CEditTool implementation - ////////////////////////////////////////////////////////////////////////// - virtual bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - virtual void Display(DisplayContext& dc); - ////////////////////////////////////////////////////////////////////////// - -protected: - - bool OnMouseMove(CViewport* view, UINT nFlags, const QPoint& point); - void SetMaterial(_smart_ptr<IMaterial> pMaterial); - - virtual ~CMaterialPickTool(); - // Delete itself. - void DeleteThis() { delete this; }; - - _smart_ptr<IMaterial> m_pMaterial; - QString m_displayString; - QPoint m_Mouse2DPosition; - SRayHitInfo m_HitInfo; -}; - - -#endif // CRYINCLUDE_EDITOR_MATERIAL_MATERIALPICKTOOL_H diff --git a/Code/Sandbox/Editor/NullEditTool.cpp b/Code/Sandbox/Editor/NullEditTool.cpp deleted file mode 100644 index b848ed6364..0000000000 --- a/Code/Sandbox/Editor/NullEditTool.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" - -#include "NullEditTool.h" - - -NullEditTool::NullEditTool() {} - -const GUID& NullEditTool::GetClassID() -{ - // {65AFF87A-34E0-479B-B062-94B1B867B13D} - static const GUID guid = - { - 0x65AFF87A, 0x34E0, 0x479B,{ 0xB0, 0x62, 0x94, 0xB1, 0xB8, 0x67, 0xB1, 0x3D } - }; - - return guid; -} - -void NullEditTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass( - new CQtViewClass<NullEditTool>("EditTool.NullEditTool", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -#include <moc_NullEditTool.cpp> diff --git a/Code/Sandbox/Editor/NullEditTool.h b/Code/Sandbox/Editor/NullEditTool.h deleted file mode 100644 index 44bb4ce76d..0000000000 --- a/Code/Sandbox/Editor/NullEditTool.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#pragma once - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#endif - -/// An EditTool that does nothing - it provides the Null-Object pattern. -class SANDBOX_API NullEditTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE NullEditTool(); - virtual ~NullEditTool() = default; - - static const GUID& GetClassID(); - static void RegisterTool(CRegistrationContext& rc); - - // CEditTool - void BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) override {} - void EndEditParams() override {} - void Display([[maybe_unused]] DisplayContext& dc) override {} - bool MouseCallback([[maybe_unused]] CViewport* view, [[maybe_unused]] EMouseEvent event, [[maybe_unused]] QPoint& point, [[maybe_unused]] int flags) override { return false; } - bool OnKeyDown([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) override { return false; } - bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) override { return true; } - void DeleteThis() override { delete this; } -}; \ No newline at end of file diff --git a/Code/Sandbox/Editor/ObjectCloneTool.cpp b/Code/Sandbox/Editor/ObjectCloneTool.cpp deleted file mode 100644 index fd8256f4cb..0000000000 --- a/Code/Sandbox/Editor/ObjectCloneTool.cpp +++ /dev/null @@ -1,336 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "ObjectCloneTool.h" - -// Editor -#include "MainWindow.h" -#include "Viewport.h" -#include "ViewManager.h" -#include "Include/IObjectManager.h" -#include "Objects/SelectionGroup.h" -#include "Settings.h" - -////////////////////////////////////////////////////////////////////////// -// Class description. -////////////////////////////////////////////////////////////////////////// -class CObjectCloneTool_ClassDesc - : public CRefCountClassDesc -{ - virtual ESystemClassID SystemClassID() { return ESYSTEM_CLASS_EDITTOOL; } - virtual REFGUID ClassID() - { - // {6A73E865-71DF-4ED0-ABA2-457E66119B35} - static const GUID guid = { - 0x6a73e865, 0x71df, 0x4ed0,{ 0xab, 0xa2, 0x45, 0x7e, 0x66, 0x11, 0x9b, 0x35 } - }; - return guid; - } - virtual QString ClassName() { return "EditTool.Clone"; }; - virtual QString Category() { return "EditTool"; }; -}; -CObjectCloneTool_ClassDesc g_cloneClassDesc; - -////////////////////////////////////////////////////////////////////////// -CObjectCloneTool::CObjectCloneTool() - : m_currentUndoBatch(nullptr) -{ - m_pClassDesc = &g_cloneClassDesc; - m_bSetConstrPlane = true; - - GetIEditor()->SuperBeginUndo(); - - GetIEditor()->BeginUndo(); - m_selection = nullptr; - if (!GetIEditor()->GetSelection()->IsEmpty()) - { - QWaitCursor wait; - CloneSelection(); - m_selection = GetIEditor()->GetSelection(); - m_origin = m_selection->GetCenter(); - } - GetIEditor()->AcceptUndo("Clone"); - GetIEditor()->BeginUndo(); - - if (!gSettings.deepSelectionSettings.bStickDuplicate) - { - SetStatusText("Clone object at the same location"); - } - else - { - SetStatusText("Left click to clone object"); - } -} - -////////////////////////////////////////////////////////////////////////// -CObjectCloneTool::~CObjectCloneTool() -{ - EndUndoBatch(); - - if (GetIEditor()->IsUndoRecording()) - { - GetIEditor()->SuperCancelUndo(); - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::CloneSelection() -{ - // Allow component application to intercept cloning behavior. - // This is to allow support for "smart" cloning of prefabs, and other contextual features. - AZ_Assert(!m_currentUndoBatch, "CloneSelection undo batch already created."); - EBUS_EVENT_RESULT(m_currentUndoBatch, AzToolsFramework::ToolsApplicationRequests::Bus, BeginUndoBatch, "Clone Selection"); - bool handled = false; - EBUS_EVENT(AzToolsFramework::EditorRequests::Bus, CloneSelection, handled); - if (handled) - { - GetIEditor()->GetObjectManager()->CheckAndFixSelection(); - return; - } - - // This is the legacy case. We're not cloning AZ entities, so abandon the AZ undo batch. - EndUndoBatch(); - - CSelectionGroup selObjects; - CSelectionGroup sel; - - CSelectionGroup* currSelection = GetIEditor()->GetSelection(); - - currSelection->Clone(selObjects); - - GetIEditor()->ClearSelection(); - for (int i = 0; i < selObjects.GetCount(); i++) - { - if (selObjects.GetObject(i)) - { - GetIEditor()->SelectObject(selObjects.GetObject(i)); - } - } - MainWindow::instance()->setFocus(); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::SetConstrPlane(CViewport* view, [[maybe_unused]] const QPoint& point) -{ - Matrix34 originTM; - originTM.SetIdentity(); - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() == 1) - { - originTM = selection->GetObject(0)->GetWorldTM(); - } - else if (selection->GetCount() > 1) - { - originTM = selection->GetObject(0)->GetWorldTM(); - Vec3 center = view->SnapToGrid(originTM.GetTranslation()); - originTM.SetTranslation(center); - } - view->SetConstructionMatrix(COORDS_LOCAL, originTM); -} - -//static Vec3 gP1,gP2; -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Display([[maybe_unused]] DisplayContext& dc) -{ - //dc.SetColor( 1,1,0,1 ); - //dc.DrawBall( gP1,1.1f ); - //dc.DrawBall( gP2,1.1f ); -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectCloneTool::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - if (m_selection) - { - // Set construction plane origin to selection origin. - if (m_bSetConstrPlane) - { - SetConstrPlane(view, point); - m_bSetConstrPlane = false; - } - - if (event == eMouseLDown) - { - // Accept group. - Accept(); - GetIEditor()->GetSelection()->FinishChanges(); - return true; - } - if (event == eMouseMove) - { - // Move selection. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection != m_selection) - { - Abort(); - } - else if (!selection->IsEmpty()) - { - GetIEditor()->RestoreUndo(); - - Vec3 v; - bool followTerrain = false; - - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - Vec3 selectionCenter = view->SnapToGrid(pSelection->GetCenter()); - - int axis = GetIEditor()->GetAxisConstrains(); - if (axis == AXIS_TERRAIN) - { - bool hitTerrain; - v = view->ViewToWorld(point, &hitTerrain) - selectionCenter; - if (axis == AXIS_TERRAIN) - { - v = view->SnapToGrid(v); - if (hitTerrain) - { - followTerrain = true; - v.z = 0; - } - } - } - else - { - Vec3 p1 = selectionCenter; - Vec3 p2 = view->MapViewToCP(point); - if (p2.IsZero()) - { - return true; - } - - v = view->GetCPVector(p1, p2); - // Snap v offset to grid if its enabled. - view->SnapToGrid(v); - } - - CSelectionGroup::EMoveSelectionFlag selectionFlag = CSelectionGroup::eMS_None; - if (followTerrain) - { - selectionFlag = CSelectionGroup::eMS_FollowTerrain; - } - - // Disable undo recording for these move commands as the only operation we need - // to undo is the creation of the new object. Undo commands are queued so it's - // possible that the object creation could be undone before attempting to undo - // these move operations causing undesired behavior. - bool wasRecording = CUndo::IsRecording(); - if (wasRecording) - { - GetIEditor()->SuspendUndo(); - } - - GetIEditor()->GetSelection()->Move(v, selectionFlag, GetIEditor()->GetReferenceCoordSys(), point); - - if (wasRecording) - { - GetIEditor()->ResumeUndo(); - } - } - } - if (event == eMouseWheel) - { - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection != m_selection) - { - Abort(); - } - else if (!selection->IsEmpty()) - { - double angle = 1; - - if (view->GetViewManager()->GetGrid()->IsAngleSnapEnabled()) - { - angle = view->GetViewManager()->GetGrid()->GetAngleSnap(); - } - - for (int i = 0; i < selection->GetCount(); ++i) - { - CBaseObject* pObj = selection->GetFilteredObject(i); - Quat rot = pObj->GetRotation(); - rot.SetRotationXYZ(Ang3(0, 0, rot.GetRotZ() + DEG2RAD(flags > 0 ? angle * (-1) : angle))); - pObj->SetRotation(rot); - } - GetIEditor()->AcceptUndo("Rotate Selection"); - } - } - } - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Abort() -{ - EndUndoBatch(); - - // Abort - GetIEditor()->SetEditTool(0); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::Accept(bool resetPosition) -{ - // Close the az undo batch so it can add the appropriate objects to the cry undo stack - EndUndoBatch(); - - if (resetPosition) - { - GetIEditor()->GetSelection()->MoveTo(m_origin, CSelectionGroup::eMS_None, GetIEditor()->GetReferenceCoordSys()); - } - - if (GetIEditor()->IsUndoRecording()) - { - GetIEditor()->SuperAcceptUndo("Clone"); - } - - GetIEditor()->SetEditTool(0); -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::EndUndoBatch() -{ - if (m_currentUndoBatch) - { - AzToolsFramework::UndoSystem::URSequencePoint* undoBatch = nullptr; - EBUS_EVENT_RESULT(undoBatch, AzToolsFramework::ToolsApplicationRequests::Bus, GetCurrentUndoBatch); - AZ_Error("ObjectCloneTool", undoBatch == m_currentUndoBatch, "Undo batch is not in sync."); - if (undoBatch == m_currentUndoBatch) - { - EBUS_EVENT(AzToolsFramework::ToolsApplicationRequests::Bus, EndUndoBatch); - } - m_currentUndoBatch = nullptr; - } -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CObjectCloneTool::EndEditParams() -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CObjectCloneTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - Abort(); - } - return false; -} - -#include <moc_ObjectCloneTool.cpp> diff --git a/Code/Sandbox/Editor/ObjectCloneTool.h b/Code/Sandbox/Editor/ObjectCloneTool.h deleted file mode 100644 index f027456a4e..0000000000 --- a/Code/Sandbox/Editor/ObjectCloneTool.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of ObjectCloneTool, edit tool for cloning of objects.. - - -#ifndef CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H -#define CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H - -#pragma once - -#include "EditTool.h" - -class CBaseObject; - -namespace AzToolsFramework -{ - namespace UndoSystem - { - class URSequencePoint; - } -} - -/*! - * CObjectCloneTool, When created duplicate current selection, and manages cloned selection. - * - */ - -class CObjectCloneTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CObjectCloneTool(); - - ////////////////////////////////////////////////////////////////////////// - // Ovverides from CEditTool - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - - virtual void BeginEditParams(IEditor* ie, int flags); - virtual void EndEditParams(); - - virtual void Display(DisplayContext& dc); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - ////////////////////////////////////////////////////////////////////////// - - void Accept(bool resetPosition = false); - void Abort(); - -protected: - virtual ~CObjectCloneTool(); - // Delete itself. - void DeleteThis() { delete this; }; - -private: - void CloneSelection(); - void SetConstrPlane(CViewport* view, const QPoint& point); - - CSelectionGroup* m_selection; - Vec3 m_origin; - bool m_bSetConstrPlane; - //bool m_bSetCapture; - - void EndUndoBatch(); - - AzToolsFramework::UndoSystem::URSequencePoint* m_currentUndoBatch; -}; - - -#endif // CRYINCLUDE_EDITOR_OBJECTCLONETOOL_H diff --git a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp index 590b1256ac..44138b290d 100644 --- a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp +++ b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp @@ -24,7 +24,6 @@ #include "RenderHelpers/AxisHelper.h" #include "RenderHelpers/AxisHelperExtended.h" #include "IObjectManager.h" -#include "EditTool.h" ////////////////////////////////////////////////////////////////////////// // CAxisGizmo implementation. @@ -381,12 +380,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point break; } - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags); - } - return true; } } @@ -540,12 +533,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point break; } - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool && bCallBack) - { - pEditTool->OnManipulatorDrag(view, this, m_cMouseDownPos, point, vDragValue); - } - return true; } else @@ -573,12 +560,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point } bHit = true; } - - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags, bHit); - } } } else if (event == eMouseLUp) @@ -593,12 +574,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point { GetIEditor()->SetReferenceCoordSys(m_coordSysBackUp); } - - CEditTool* pEditTool = view->GetEditTool(); - if (pEditTool) - { - pEditTool->OnManipulatorMouseEvent(view, this, event, point, nFlags); - } } } diff --git a/Code/Sandbox/Editor/Objects/BaseObject.cpp b/Code/Sandbox/Editor/Objects/BaseObject.cpp index 36b954315e..a579f303a9 100644 --- a/Code/Sandbox/Editor/Objects/BaseObject.cpp +++ b/Code/Sandbox/Editor/Objects/BaseObject.cpp @@ -39,7 +39,6 @@ #include "ViewManager.h" #include "IEditorImpl.h" #include "GameEngine.h" -#include "EditTool.h" // To use the Andrew's algorithm in order to make convex hull from the points, this header is needed. #include "Util/GeometryUtil.h" @@ -3264,11 +3263,6 @@ ERotationWarningLevel CBaseObject::GetRotationWarningLevel() const bool CBaseObject::IsSkipSelectionHelper() const { - CEditTool* pEditTool(GetIEditor()->GetEditTool()); - if (pEditTool && pEditTool->IsNeedToSkipPivotBoxForObjects()) - { - return true; - } return false; } diff --git a/Code/Sandbox/Editor/Objects/ObjectManager.cpp b/Code/Sandbox/Editor/Objects/ObjectManager.cpp index aff6d51816..96d015e2c1 100644 --- a/Code/Sandbox/Editor/Objects/ObjectManager.cpp +++ b/Code/Sandbox/Editor/Objects/ObjectManager.cpp @@ -22,12 +22,10 @@ #include "Settings.h" #include "DisplaySettings.h" #include "EntityObject.h" -#include "NullEditTool.h" #include "Viewport.h" #include "GizmoManager.h" #include "AxisGizmo.h" #include "ObjectPhysicsManager.h" -#include "EditMode/ObjectMode.h" #include "GameEngine.h" #include "WaitProgress.h" #include "Util/Image.h" @@ -838,8 +836,6 @@ void CObjectManager::Update() QWidget* prevActiveWindow = QApplication::activeWindow(); - CheckAndFixSelection(); - // Restore focus if it changed. if (prevActiveWindow && QApplication::activeWindow() != prevActiveWindow) { @@ -1230,60 +1226,6 @@ void CObjectManager::RemoveSelection(const QString& name) } } -//! Checks the state of the current selection and fixes it if necessary - Used when AZ Code modifies the selection -void CObjectManager::CheckAndFixSelection() -{ - AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); - bool bObjectMode = qobject_cast<CObjectMode*>(GetIEditor()->GetEditTool()) != nullptr; - - if (m_currSelection->GetCount() == 0) - { - // Nothing selected. - EndEditParams(); - if (bObjectMode) - { - GetIEditor()->ShowTransformManipulator(false); - } - } - else if (m_currSelection->GetCount() == 1) - { - if (!m_bSingleSelection) - { - EndEditParams(); - } - - CBaseObject* newSelObject = m_currSelection->GetObject(0); - // Single object selected. - if (m_currEditObject != m_currSelection->GetObject(0)) - { - m_bSelectionChanged = false; - if (!m_currEditObject || (m_currEditObject->metaObject() != newSelObject->metaObject())) - { - // If old object and new objects are of different classes. - EndEditParams(); - } - if (GetIEditor()->GetEditTool() && GetIEditor()->GetEditTool()->IsUpdateUIPanel()) - { - BeginEditParams(newSelObject, OBJECT_EDIT); - } - - //AfxGetMainWnd()->SetFocus(); - } - } - else if (m_currSelection->GetCount() > 1) - { - // Multiple objects are selected. - if (m_bSelectionChanged && bObjectMode) - { - m_bSelectionChanged = false; - m_nLastSelCount = m_currSelection->GetCount(); - EndEditParams(); - - m_currEditObject = m_currSelection->GetObject(0); - } - } -} - void CObjectManager::SelectCurrent() { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); @@ -1404,8 +1346,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) pDispayedViewObjects->ClearObjects(); pDispayedViewObjects->Reserve(m_visibleObjects.size()); - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - const bool newViewportInteractionModelEnabled = GetIEditor()->IsNewViewportInteractionModelEnabled(); if (dc.flags & DISPLAY_2D) @@ -1426,11 +1366,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) { obj->Display(dc); } - - if (pEditTool) - { - pEditTool->DrawObjectHelpers(obj, dc); - } } } } @@ -1476,11 +1411,6 @@ void CObjectManager::FindDisplayableObjects(DisplayContext& dc, bool bDisplay) { obj->Display(dc); } - - if (pEditTool) - { - pEditTool->DrawObjectHelpers(obj, dc); - } } } } @@ -1737,12 +1667,6 @@ bool CObjectManager::HitTestObject(CBaseObject* obj, HitContext& hc) { return false; } - - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (pEditTool && pEditTool->HitTest(obj, hc)) - { - return true; - } } return (bSelectionHelperHit || obj->HitTest(hc)); @@ -2742,10 +2666,6 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/) { - // provide an EditTool that does nothing. - // note: will hide rotation gizmo when active (CRotateTool) - GetIEditor()->SetEditTool(new NullEditTool()); - // hide current gizmo for entity (translate/rotate/scale) IGizmoManager* gizmoManager = GetGizmoManager(); const size_t gizmoCount = static_cast<size_t>(gizmoManager->GetGizmoCount()); @@ -2757,9 +2677,6 @@ void CObjectManager::EnteredComponentMode(const AZStd::vector<AZ::Uuid>& /*compo void CObjectManager::LeftComponentMode(const AZStd::vector<AZ::Uuid>& /*componentModeTypes*/) { - // return to default EditTool (in whatever transform mode is set) - GetIEditor()->SetEditTool(nullptr); - // show translate/rotate/scale gizmo again if (IGizmoManager* gizmoManager = GetGizmoManager()) { diff --git a/Code/Sandbox/Editor/Objects/ObjectManager.h b/Code/Sandbox/Editor/Objects/ObjectManager.h index eca23bc92b..f13616451e 100644 --- a/Code/Sandbox/Editor/Objects/ObjectManager.h +++ b/Code/Sandbox/Editor/Objects/ObjectManager.h @@ -226,8 +226,6 @@ public: //! Set one of name selections as current selection. void SetSelection(const QString& name); void RemoveSelection(const QString& name); - //! Checks for changes to the current selection and makes adjustments accordingly - void CheckAndFixSelection() override; bool IsObjectDeletionAllowed(CBaseObject* pObject); diff --git a/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl b/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl index fa56a21a8b..a6ceaf578f 100644 --- a/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl +++ b/Code/Sandbox/Editor/RenderHelpers/AxisHelperShared.inl @@ -17,7 +17,6 @@ #include "Include/IDisplayViewport.h" #include "Include/HitContext.h" #include "Util/Math.h" -#include "EditTool.h" #include "IObjectManager.h" #include <Cry_Geo.h> diff --git a/Code/Sandbox/Editor/RenderViewport.cpp b/Code/Sandbox/Editor/RenderViewport.cpp index 213a4ed895..53355f4dd9 100644 --- a/Code/Sandbox/Editor/RenderViewport.cpp +++ b/Code/Sandbox/Editor/RenderViewport.cpp @@ -66,7 +66,6 @@ #include "Util/fastlib.h" #include "CryEditDoc.h" #include "GameEngine.h" -#include "EditTool.h" #include "ViewManager.h" #include "Objects/DisplayContext.h" #include "DisplaySettings.h" @@ -1948,12 +1947,6 @@ void CRenderViewport::RenderAll() m_entityVisibilityQuery.DisplayVisibility(*debugDisplay); - if (GetEditTool()) - { - // display editing tool - GetEditTool()->Display(displayContext); - } - if (m_manipulatorManager != nullptr) { using namespace AzToolsFramework::ViewportInteraction; @@ -2776,35 +2769,6 @@ void CRenderViewport::OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta handled = result != MouseInteractionResult::None; } - else - { - if (m_manipulatorManager == nullptr || m_manipulatorManager->ConsumeViewportMouseWheel(mouseInteraction)) - { - return; - } - - if (AzToolsFramework::ComponentModeFramework::InComponentMode()) - { - AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::EventResult( - handled, AzToolsFramework::GetEntityContextId(), - &EditorInteractionSystemViewportSelectionRequestBus::Events::InternalHandleMouseViewportInteraction, - MouseInteractionEvent(mouseInteraction, zDelta)); - } - else - { - ////////////////////////////////////////////////////////////////////////// - // Asks current edit tool to handle mouse callback. - CEditTool* pEditTool = GetEditTool(); - if (pEditTool && (modifiers & Qt::ControlModifier)) - { - QPoint tempPoint(scaledPoint.x(), scaledPoint.y()); - if (pEditTool->MouseCallback(this, eMouseWheel, tempPoint, zDelta)) - { - handled = true; - } - } - } - } if (!handled) { @@ -4347,10 +4311,6 @@ void CRenderViewport::RenderSnappingGrid() { return; } - if (GetIEditor()->GetEditTool() && !GetIEditor()->GetEditTool()->IsDisplayGrid()) - { - return; - } DisplayContext& dc = m_displayContext; diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index afcd0c7a6f..d72c2d76d4 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -123,7 +123,6 @@ #define ID_TOOL_SHELVE_LAST 33375 #define ID_EDIT_SELECTALL 33376 #define ID_EDIT_SELECTNONE 33377 -#define ID_OBJECTMODIFY_VERTEXSNAPPING 33384 #define ID_WIREFRAME 33410 #define ID_FILE_GENERATETERRAINTEXTURE 33445 #define ID_GENERATORS_LIGHTING 33446 @@ -275,7 +274,6 @@ #define ID_GAME_PC_ENABLEMEDIUMSPEC 33961 #define ID_GAME_PC_ENABLEHIGHSPEC 33962 #define ID_GAME_PC_ENABLEVERYHIGHSPEC 33963 -#define ID_MODIFY_ALIGNOBJTOSURF 33968 #define ID_PANEL_VEG_CREATE_SEL 33990 #define ID_TOOLS_UPDATEPROCEDURALVEGETATION 33999 #define ID_DISPLAY_GOTOPOSITION 34004 diff --git a/Code/Sandbox/Editor/RotateTool.cpp b/Code/Sandbox/Editor/RotateTool.cpp deleted file mode 100644 index e9b12d01af..0000000000 --- a/Code/Sandbox/Editor/RotateTool.cpp +++ /dev/null @@ -1,1059 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#include "EditorDefs.h" - -#include "RotateTool.h" - -// AzToolsFramework -#include <AzToolsFramework/Entity/EditorEntityTransformBus.h> - -// Editor -#include "Objects/SelectionGroup.h" -#include "NullEditTool.h" -#include "Viewport.h" -#include "Grid.h" -#include "ViewManager.h" -#include "Objects/BaseObject.h" - - -// This constant is used with GetScreenScaleFactor and was found experimentally. -static const float kViewDistanceScaleFactor = 0.06f; - -const GUID& CRotateTool::GetClassID() -{ - // {A50E5B95-05B9-41A3-8D8E-BDA3E930A396} - static const GUID guid = { - 0xA50E5B95, 0x05B9, 0x41A3, { 0x8D, 0x8E, 0xBD, 0xA3, 0xE9, 0x30, 0xA3, 0x96 } - }; - return guid; -} - -//! This method returns the human readable name of the class. -//! This method returns Category of this class, Category is specifying where this tool class fits best in create panel. -void CRotateTool::RegisterTool(CRegistrationContext& rc) -{ - rc.pClassFactory->RegisterClass(new CQtViewClass<CRotateTool>("EditTool.Rotate", "Select", ESYSTEM_CLASS_EDITTOOL)); -} - -CRotateTool::CRotateTool(CBaseObject* pObject, QWidget* parent /*= nullptr*/) - : CObjectMode(parent) - , m_initialViewAxisAngleRadians(0.f) - , m_angleToCursor(0.f) - , m_highlightAxis(AxisNone) - , m_draggingMouse(false) - , m_lastPosition(0, 0) - , m_rotationAngles(0, 0, 0) - , m_object(pObject) - , m_bTransformChanged(false) - , m_totalRotationAngle(0.f) - , m_basisAxisRadius(4.f) - , m_viewAxisRadius(5.f) - , m_arcRotationStepRadians(DEG2RAD(5.f)) -{ - m_axes[AxisX] = RotationDrawHelper::Axis(Col_Red, Col_Yellow); - m_axes[AxisY] = RotationDrawHelper::Axis(Col_Green, Col_Yellow); - m_axes[AxisZ] = RotationDrawHelper::Axis(Col_Blue, Col_Yellow); - m_axes[AxisView] = RotationDrawHelper::Axis(Col_White, Col_Yellow); - - if (m_object) - { - m_object->AddEventListener(this); - } - - GetIEditor()->GetObjectManager()->SetSelectCallback(this); -} - -bool CRotateTool::OnSelectObject(CBaseObject* object) -{ - m_object = object; - if (m_object) - { - m_object->AddEventListener(this); - } - return true; -} - -bool CRotateTool::CanSelectObject([[maybe_unused]] CBaseObject* object) -{ - return true; -} - -void CRotateTool::OnObjectEvent(CBaseObject* object, int event) -{ - if (event == CBaseObject::ON_DELETE || event == CBaseObject::ON_UNSELECT) - { - if (m_object && m_object == object) - { - m_object->RemoveEventListener(this); - m_object = nullptr; - } - } -} - -void CRotateTool::Display(DisplayContext& dc) -{ - if (!m_object) - { - return; - } - - const bool visible = - !m_object->IsHidden() - && !m_object->IsFrozen() - && m_object->IsSelected(); - - if (!visible) - { - GetIEditor()->SetEditTool(new NullEditTool()); - return; - } - - RotationDrawHelper::DisplayContextScope displayContextScope(dc); - m_hc.camera = dc.camera; - m_hc.view = dc.view; - m_hc.b2DViewport = static_cast<CViewport*>(dc.view)->GetType() != ET_ViewportCamera; - dc.SetLineWidth(m_lineThickness); - - // Calculate the screen space position from which we cast a ray (center of viewport). - int viewportWidth = 0; - int viewportHeight = 0; - dc.view->GetDimensions(&viewportWidth, &viewportHeight); - m_hc.point2d = QPoint(viewportWidth / 2, viewportHeight / 2); - - // Calculate the ray from the camera position to the selection. - dc.view->ViewToWorldRay(m_hc.point2d, m_hc.raySrc, m_hc.rayDir); - - Matrix34 objectTransform = GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view); - - AffineParts ap; - ap.Decompose(objectTransform); - - Vec3 position = ap.pos; - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - // X axis arc - Vec3 cameraViewDir = (m_hc.raySrc - position).GetNormalized(); - float cameraAngle = atan2f(cameraViewDir.y, cameraViewDir.x); - m_axes[AxisX].Draw(dc, position, ap.rot.GetColumn0(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisX, m_object, screenScale); - - // Y axis arc - cameraAngle = atan2f(-cameraViewDir.z, cameraViewDir.x); - m_axes[AxisY].Draw(dc, position, ap.rot.GetColumn1(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisY, m_object, screenScale); - - // View direction axis - Vec3 cameraPos = dc.camera->GetPosition(); - - Vec3 axis = cameraPos - position; - axis.NormalizeSafe(); - - // Z axis arc - cameraAngle = atan2f(axis.y, axis.x); - m_axes[AxisZ].Draw(dc, position, objectTransform.GetColumn2().GetNormalized(), cameraAngle, m_arcRotationStepRadians, m_basisAxisRadius, m_highlightAxis == AxisZ, m_object, screenScale); - - // FIXME: currently, rotating multiple selections using the view axis may result in severe rotation artifacts, it's necessary to make sure - // the calculated rotation angle is smooth. - if (!m_hc.b2DViewport && selection->GetCount() == 1 || m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - // Draw view direction axis - dc.SetColor(m_highlightAxis == AxisView ? Col_Yellow : Col_White); - - cameraViewDir = m_hc.camera->GetViewdir().normalized(); - dc.DrawArc(position, m_viewAxisRadius * GetScreenScale(dc.view, dc.camera), 0, 360.f, RAD2DEG(m_arcRotationStepRadians), cameraViewDir); - } - - // Draw angle decorator - if (RotationControlConfiguration::Get().RotationControl_DrawDecorators) - { - DrawAngleDecorator(dc); - } - - // Display total rotation angle in degrees. - if (!m_hc.b2DViewport && fabs(m_totalRotationAngle) > FLT_EPSILON) - { - QString label; - label = QString::number(RAD2DEG(m_totalRotationAngle), 'f', 2); - - const float textScale = 1.5f; - const ColorF textBackground = ColorF(0.2f, 0.2f, 0.2f, 0.6f); - - if (m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - dc.DrawTextLabel(ap.pos, textScale, label.toUtf8().data()); - } - else - { - dc.DrawTextOn2DBox(ap.pos, label.toUtf8().data(), textScale, Col_White, textBackground); - } - } - - // Draw debug diagnostics - if (RotationControlConfiguration::Get().RotationControl_DebugHitTesting) - { - DrawHitTestGeometry(dc, m_hc); - } - - // Draw debug tracking of the view direction angle - if (RotationControlConfiguration::Get().RotationControl_AngleTracking) - { - DrawViewDirectionAngleTracking(dc, m_hc); - } -} - -void CRotateTool::DrawAngleDecorator(DisplayContext& dc) -{ - if (m_highlightAxis == AxisView) - { - //Vec3 cameraViewDir = dc.view->GetViewTM().GetColumn1().GetNormalized(); - Vec3 cameraViewDir = dc.camera->GetViewMatrix().GetColumn1().GetNormalized(); //Get the viewDir from the camera instead of from the view - // FIXME: The angle and sweep calculation here is incorrect. - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - float angleDelta = (m_angleToCursor - g_PI2 * floor(m_initialViewAxisAngleRadians / g_PI2)) - (m_initialViewAxisAngleRadians - (cameraAngle - (g_PI / 2))); - - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), cameraViewDir, m_initialViewAxisAngleRadians, angleDelta, m_arcRotationStepRadians, m_viewAxisRadius, GetScreenScale(dc.view, dc.camera)); - } - else - { - if (fabs(m_totalRotationAngle) > FLT_EPSILON) - { - float screenScale = GetScreenScale(dc.view, dc.camera); - switch (m_highlightAxis) - { - case AxisX: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn0(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - case AxisY: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn1(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - case AxisZ: - RotationDrawHelper::AngleDecorator::Draw(dc, m_object->GetWorldPos(), m_object->GetRotation().GetColumn2(), m_initialViewAxisAngleRadians, m_totalRotationAngle, m_arcRotationStepRadians, m_basisAxisRadius, screenScale); - break; - default: - break; - } - } - } -} - -bool CRotateTool::HitTest(CBaseObject* object, HitContext& hc) -{ - if (!m_object) - { - return CObjectMode::HitTest(object, hc); - } - m_hc = hc; - m_highlightAxis = AxisNone; - - float screenScale = GetScreenScale(hc.view, hc.camera); - - // Determine intersection with the axis view direction. - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (!m_hc.b2DViewport && selection->GetCount() == 1 || m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - if (m_axes[AxisView].HitTest(object, hc, m_viewAxisRadius, m_arcRotationStepRadians, hc.camera ? hc.camera->GetViewMatrix().GetInverted().GetColumn1() : hc.view->GetViewTM().GetColumn1(), screenScale)) - { - m_highlightAxis = AxisView; - GetIEditor()->SetAxisConstraints(AXIS_XYZ); - return true; - } - } - - // Determine any intersection with a major axis. - AffineParts ap; - ap.Decompose(GetTransform(GetIEditor()->GetReferenceCoordSys(), hc.view)); - - if (m_axes[AxisX].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn0(), screenScale)) - { - m_highlightAxis = AxisX; - GetIEditor()->SetAxisConstraints(AXIS_X); - return true; - } - - if (m_axes[AxisY].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn1(), screenScale)) - { - m_highlightAxis = AxisY; - GetIEditor()->SetAxisConstraints(AXIS_Y); - return true; - } - - if (m_axes[AxisZ].HitTest(object, hc, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn2(), screenScale)) - { - m_highlightAxis = AxisZ; - GetIEditor()->SetAxisConstraints(AXIS_Z); - return true; - } - - return false; -} - -void CRotateTool::DeleteThis() -{ - delete this; -} - -bool CRotateTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->GetObjectManager()->ClearSelection(); - return true; - } - return false; -} - -Matrix34 CRotateTool::GetTransform(RefCoordSys referenceCoordinateSystem, IDisplayViewport* view) -{ - Matrix34 objectTransform = Matrix34::CreateIdentity(); - if (m_object) - { - switch (referenceCoordinateSystem) - { - case COORDS_VIEW: - if (view) - { - objectTransform = view->GetViewTM(); - } - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - break; - case COORDS_LOCAL: - objectTransform = m_object->GetWorldTM(); - break; - case COORDS_PARENT: - if (m_object->GetParent()) - { - Matrix34 parentTM = m_object->GetParent()->GetWorldTM(); - parentTM.SetTranslation(m_object->GetWorldTM().GetTranslation()); - objectTransform = parentTM; - } - else - { - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - } - break; - case COORDS_WORLD: - objectTransform.SetTranslation(m_object->GetWorldTM().GetTranslation()); - break; - } - } - return objectTransform; -} - -float CRotateTool::CalculateOrientation(const QPoint& p1, const QPoint& p2, const QPoint& p3) -{ - // Source: https://www.geeksforgeeks.org/orientation-3-ordered-points/ - float c = (p2.y() - p1.y()) * (p3.x() - p2.x()) - (p3.y() - p2.y()) * (p2.x() - p1.x()); - return c > 0 ? 1.0f : -1.0f; -} - -CRotateTool::~CRotateTool() -{ - if (m_object) - { - m_object->RemoveEventListener(this); - } - GetIEditor()->GetObjectManager()->SetSelectCallback(nullptr); -} - -bool CRotateTool::OnLButtonDown(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - m_hc.view = view; - m_hc.b2DViewport = view->GetType() != ET_ViewportCamera; - m_hc.point2d = point; - if (nFlags == OBJFLAG_IS_PARTICLE) - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - - if (m_hc.object && m_hc.object != m_object) - { - GetIEditor()->ClearSelection(); - return CObjectMode::OnLButtonDown(view, nFlags, point); - } - - if (m_highlightAxis != AxisNone) - { - view->BeginUndo(); - view->CaptureMouse(); - view->SetCurrentCursor(STD_CURSOR_ROTATE); - - m_draggingMouse = true; - - // Store the starting drag angle when we first click the mouse, we will need this to know - // how much of the rotation we need to apply. - if (m_highlightAxis == AxisView) - { - Vec3 cameraViewDir = m_hc.camera->GetViewdir().GetNormalized(); - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - m_initialViewAxisAngleRadians = m_angleToCursor - cameraAngle - (g_PI / 2); - m_initialViewAxisAngleRadians -= static_cast<float>(g_PI); - } - - m_lastPosition = point; - m_rotationAngles = Ang3(0, 0, 0); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanging, - selectedEntities); - - return true; - } - - return CObjectMode::OnLButtonDown(view, nFlags, point); -} - -bool CRotateTool::OnLButtonUp(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - if (nFlags == OBJFLAG_IS_PARTICLE) - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - - if (m_draggingMouse) - { - // We are no longer dragging the mouse, so we will release it and reset any state variables. - { - AzToolsFramework::ScopedUndoBatch undo("Rotate"); - } - view->AcceptUndo("Rotate Selection"); - view->ReleaseMouse(); - view->SetCurrentCursor(STD_CURSOR_DEFAULT); - - m_draggingMouse = false; - m_totalRotationAngle = 0.f; - m_initialViewAxisAngleRadians = 0.f; - m_angleToCursor = 0.f; - - // Apply the transform changes to the selection. - if (m_bTransformChanged) - { - CSelectionGroup* pSelection = GetIEditor()->GetSelection(); - if (pSelection) - { - pSelection->FinishChanges(); - } - - m_bTransformChanged = false; - - view->ResetSelectionRegion(); - // Reset selected rectangle. - view->SetSelectionRectangle(QRect()); - view->SetAxisConstrain(GetIEditor()->GetAxisConstrains()); - - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequests::Bus::BroadcastResult( - selectedEntities, - &AzToolsFramework::ToolsApplicationRequests::Bus::Events::GetSelectedEntities); - - AzToolsFramework::EditorTransformChangeNotificationBus::Broadcast( - &AzToolsFramework::EditorTransformChangeNotificationBus::Events::OnEntityTransformChanged, - selectedEntities); - } - } - - return CObjectMode::OnLButtonUp(view, nFlags, point); -} - -bool CRotateTool::OnMouseMove(CViewport* view, int nFlags, const QPoint& p) -{ - QPoint point = p; - if (!m_object) - { - return CObjectMode::OnMouseMove(view, nFlags, point); - } - - // Prevent the opening of the context menu during a mouse move. - m_openContext = false; - - // We calculate the mouse drag direction vector's angle from the object to the mouse position. - QPoint objectCenter; - if (nFlags != OBJFLAG_IS_PARTICLE) - { - objectCenter = view->WorldToView(GetIEditor()->GetSelection()->GetCenter()); - } - else - if (parent() && parent()->isWidgetType()) - { - QWidget *wParent = static_cast<QWidget*>(parent()); - - // HACK: This is only valid for the particle editor and needs refactored. - const QRect rect = wParent->contentsRect(); - objectCenter = view->WorldToViewParticleEditor(m_object->GetWorldPos(), rect.width(), rect.height()); - } - - Vec2 dragDirection = Vec2(point.x() - objectCenter.x(), point.y() - objectCenter.y()); - dragDirection.Normalize(); - - float angleToCursor = (atan2f(dragDirection.y, dragDirection.x)); - m_angleToCursor = angleToCursor - g_PI2 * floor(angleToCursor / g_PI2); - - if (m_draggingMouse) - { - GetIEditor()->RestoreUndo(); - - view->SetCurrentCursor(STD_CURSOR_ROTATE); - - RefCoordSys referenceCoordSys = GetIEditor()->GetReferenceCoordSys(); - - if (m_highlightAxis == AxisView) - { - // Calculate the angular difference between the starting rotation angle, taking into account the camera's angle to ensure a smooth rotation. - Vec3 cameraViewDir = m_hc.camera->GetViewdir(); - float cameraAngle = atan2f(cameraViewDir.y, cameraViewDir.x); - float angleDelta = (m_angleToCursor - g_PI2 * floor(m_initialViewAxisAngleRadians / g_PI2)) - (m_initialViewAxisAngleRadians - (cameraAngle - (g_PI / 2))); - - // Snap the angle is necessary - angleDelta = view->GetViewManager()->GetGrid()->SnapAngle(RAD2DEG(angleDelta)); - - if (nFlags != OBJFLAG_IS_PARTICLE) - { - Matrix34 viewRotation = Matrix34::CreateRotationAA(DEG2RAD(angleDelta), cameraViewDir); - GetIEditor()->GetSelection()->Rotate(viewRotation, COORDS_WORLD); - } - else - { - Quat quatRotation = Quat::CreateRotationAA(DEG2RAD(angleDelta), cameraViewDir); - m_object->SetRotation(quatRotation); - } - - m_bTransformChanged = true; - } - else - if (m_highlightAxis != AxisNone) - { - float distanceMoved = (point - m_lastPosition).manhattanLength(); // screen-space distance dragged - float distanceToCenter = (m_lastPosition - objectCenter).manhattanLength(); // screen-space distance to object center - float roationDelta = RAD2DEG(atan2f(distanceMoved, distanceToCenter)); // unsigned rotation angle - float orientation = CalculateOrientation(objectCenter, m_lastPosition, point); // Calculate if rotation dragging gizmo clockwise or counter-clockwise - - m_lastPosition = point; - - // Calculate orientation of the object's axis towards camera - Vec3 directionToObject = (GetIEditor()->GetSelection()->GetCenter() - m_hc.camera->GetMatrix().GetTranslation()).normalize(); - - float directionX = 1.0f; - float directionY = 1.0f; - float directionZ = 1.0f; - - switch (referenceCoordSys) - { - case COORDS_LOCAL: - directionX = directionToObject.Dot(m_object->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - break; - case COORDS_PARENT: - if (m_object->GetParent()) - { - directionX = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetParent()->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - } - else - { - directionX = directionToObject.Dot(m_object->GetWorldTM().GetColumn0()) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(m_object->GetWorldTM().GetColumn1()) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(m_object->GetWorldTM().GetColumn2()) > 0 ? -1.0f : 1.0f; - } - break; - case COORDS_VIEW: - case COORDS_WORLD: - directionX = directionToObject.Dot(Vec3(1, 0, 0)) > 0 ? -1.0f : 1.0f; - directionY = directionToObject.Dot(Vec3(0, 1, 0)) > 0 ? -1.0f : 1.0f; - directionZ = directionToObject.Dot(Vec3(0, 0, 1)) > 0 ? -1.0f : 1.0f; - break; - } - - switch (m_highlightAxis) - { - case AxisX: - m_rotationAngles.x += roationDelta * directionX * orientation; - break; - case AxisY: - m_rotationAngles.y += roationDelta * directionY * orientation; - break; - case AxisZ: - m_rotationAngles.z += roationDelta * directionZ * orientation; - break; - default: - break; - } - - // Snap the angle if necessary - m_rotationAngles = view->GetViewManager()->GetGrid()->SnapAngle(m_rotationAngles); - - // Compute the total amount rotated - Vec3 vDragValue = Vec3(m_rotationAngles); - m_totalRotationAngle = DEG2RAD(vDragValue.len()); - - // Apply the rotation - if (nFlags != OBJFLAG_IS_PARTICLE) - { - GetIEditor()->GetSelection()->Rotate(m_rotationAngles, referenceCoordSys); - } - else - { - Quat currentRotation = (m_object->GetRotation()); - Quat rotateTM = currentRotation * Quat::CreateRotationXYZ(DEG2RAD(-m_rotationAngles / 50.0f)); - m_object->SetRotation(rotateTM); - } - - m_bTransformChanged = fabs(m_totalRotationAngle) > FLT_EPSILON; - } - } - else - { - // If we are not yet dragging the mouse, do the hit testing to highlight the axis the mouse is over. - m_hc.view = view; - m_hc.b2DViewport = view->GetType() != ET_ViewportCamera; - m_hc.point2d = point; - - if (nFlags != OBJFLAG_IS_PARTICLE) - { - view->ViewToWorldRay(point, m_hc.raySrc, m_hc.rayDir); - } - else - { - view->setHitcontext(point, m_hc.raySrc, m_hc.rayDir); - } - - if (HitTest(m_object, m_hc)) - { - // Display a cursor that makes it clear to the user that he is over an axis that can be rotated. - view->SetCurrentCursor(STD_CURSOR_ROTATE); - } - else - { - // Nothing has been hit, reset the cursor back to default in case it was changed previously. - view->SetCurrentCursor(STD_CURSOR_DEFAULT); - } - } - - // We always consider the rotation tool's OnMove event handled - return true; -} - -float CRotateTool::GetScreenScale(IDisplayViewport* view, CCamera* camera /*=nullptr*/) -{ - Matrix34 objectTransform = GetTransform(GetIEditor()->GetReferenceCoordSys(), view); - - AffineParts ap; - ap.Decompose(objectTransform); - - if (m_object && m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - return view->GetScreenScaleFactor(*camera, ap.pos) * kViewDistanceScaleFactor; - } - - return static_cast<CViewport*>(view)->GetScreenScaleFactor(ap.pos) * kViewDistanceScaleFactor; -} - -void CRotateTool::DrawHitTestGeometry(DisplayContext& dc, HitContext& hc) -{ - AffineParts ap; - ap.Decompose(GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view)); - - Vec3 position = ap.pos; - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - // Draw debug test surface for each axis. - m_axes[AxisX].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn0(), screenScale); - m_axes[AxisY].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn1(), screenScale); - m_axes[AxisZ].DebugDrawHitTestSurface(dc, hc, position, m_basisAxisRadius, m_arcRotationStepRadians, ap.rot.GetColumn2(), screenScale); - - // We don't render the view axis rotation for multiple selection. - if (!hc.b2DViewport && selection->GetCount() == 1) - { - Vec3 cameraViewDir = hc.view->GetViewTM().GetColumn1().GetNormalized(); - m_axes[AxisView].DebugDrawHitTestSurface(dc, hc, position, m_viewAxisRadius, m_arcRotationStepRadians, cameraViewDir, screenScale); - } -} - -void CRotateTool::DrawViewDirectionAngleTracking(DisplayContext& dc, HitContext& hc) -{ - Vec3 a; - Vec3 b; - - // Calculate a basis for the camera view direction. - Vec3 cameraViewDir = hc.view->GetViewTM().GetColumn1().GetNormalized(); - GetBasisVectors(cameraViewDir, a, b); - - // Calculates the camera view direction angle. - float angle = m_angleToCursor; - float cameraAngle = atan2f(cameraViewDir.y, -cameraViewDir.x); - - // Ensures the angle remains camera aligned. - angle -= cameraAngle - (g_PI / 2); - - // The position will be either the object's center or the selection's center. - Vec3 position = GetTransform(GetIEditor()->GetReferenceCoordSys(), dc.view).GetTranslation(); - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !m_object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - float screenScale = GetScreenScale(dc.view, dc.camera); - - const float cosAngle = cos(angle); - const float sinAngle = sin(angle); - - // The resulting position will be in a circular orientation based on the resulting angle. - Vec3 p0; - p0.x = position.x + (cosAngle * a.x + sinAngle * b.x) * m_viewAxisRadius * screenScale; - p0.y = position.y + (cosAngle * a.y + sinAngle * b.y) * m_viewAxisRadius * screenScale; - p0.z = position.z + (cosAngle * a.z + sinAngle * b.z) * m_viewAxisRadius * screenScale; - - const float ballRadius = 0.1f * screenScale; - dc.SetColor(Col_Magenta); - dc.DrawBall(p0, ballRadius); -} - -namespace RotationDrawHelper -{ - Axis::Axis(const ColorF& defaultColor, const ColorF& highlightColor) - { - m_colors[StateDefault] = defaultColor; - m_colors[StateHighlight] = highlightColor; - } - - void Axis::Draw(DisplayContext& dc, const Vec3& position, const Vec3& axis, float angleRadians, float angleStepRadians, float radius, bool highlighted, CBaseObject* object, float screenScale) - { - if (static_cast<CViewport*>(dc.view)->GetType() != ET_ViewportCamera || object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - bool set = dc.SetDrawInFrontMode(true); - - // Draw the front facing arc - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, 0.f, 360.f, RAD2DEG(angleStepRadians), axis); - - dc.SetDrawInFrontMode(set); - } - else - { - // Draw the front facing arc - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, RAD2DEG(angleRadians) - 90.f, 180.f, RAD2DEG(angleStepRadians), axis); - - // Draw the back side - dc.SetColor(!highlighted ? Col_Gray : m_colors[StateHighlight]); - dc.DrawArc(position, radius * screenScale, RAD2DEG(angleRadians) + 90.f, 180.f, RAD2DEG(angleStepRadians), axis); - } - - static bool drawAxisMidPoint = false; - if (drawAxisMidPoint) - { - const float kBallRadius = 0.085f; - Vec3 a; - Vec3 b; - GetBasisVectors(axis, a, b); - - float cosAngle = cos(angleRadians); - float sinAngle = sin(angleRadians); - - Vec3 offset; - offset.x = position.x + (cosAngle * a.x + sinAngle * b.x) * screenScale * radius; - offset.y = position.y + (cosAngle * a.y + sinAngle * b.y) * screenScale * radius; - offset.z = position.z + (cosAngle * a.z + sinAngle * b.z) * screenScale * radius; - - dc.SetColor(!highlighted ? m_colors[StateDefault] : m_colors[StateHighlight]); - dc.DrawBall(offset, kBallRadius * screenScale); - } - } - - void Axis::GenerateHitTestGeometry([[maybe_unused]] HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - m_vertices.clear(); - - // The number of vertices relies on the angleStepRadians, the smaller the angle, the higher the vertex count. - int numVertices = static_cast<int>(std::ceil(g_PI2 / angleStepRadians)); - - Vec3 a; - Vec3 b; - GetBasisVectors(axis, a, b); - - // The geometry is calculated by computing a circle aligned to the specified axis. - float angle = 0.f; - for (int i = 0; i < numVertices; ++i) - { - float cosAngle = cos(angle); - float sinAngle = sin(angle); - - Vec3 p; - p.x = position.x + (cosAngle * a.x + sinAngle * b.x) * radius * screenScale; - p.y = position.y + (cosAngle * a.y + sinAngle * b.y) * radius * screenScale; - p.z = position.z + (cosAngle * a.z + sinAngle * b.z) * radius * screenScale; - m_vertices.push_back(p); - - angle += angleStepRadians; - } - } - - bool Axis::IntersectRayWithQuad(const Ray& ray, Vec3 quad[4], Vec3& contact) - { - contact = Vec3(); - - // Tests ray vs. two quads, the front facing quad and a back facing quad. - // will return true if an intersection occurs and the world space position of the contact. - return (Intersect::Ray_Triangle(ray, quad[0], quad[1], quad[2], contact) || Intersect::Ray_Triangle(ray, quad[0], quad[2], quad[3], contact) || - Intersect::Ray_Triangle(ray, quad[0], quad[2], quad[1], contact) || Intersect::Ray_Triangle(ray, quad[0], quad[3], quad[2], contact)); - } - - bool Axis::HitTest(CBaseObject* object, HitContext& hc, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - AffineParts ap; - ap.Decompose(object->GetWorldTM()); - - Vec3 position = ap.pos; - - CSelectionGroup* selection = GetIEditor()->GetSelection(); - if (selection->GetCount() > 1 && !object->CheckFlags(OBJFLAG_IS_PARTICLE)) - { - position = selection->GetCenter(); - } - - // Generate intersection testing geometry - GenerateHitTestGeometry(hc, position, radius, angleStepRadians, axis, screenScale); - - Ray ray; - ray.origin = hc.raySrc; - ray.direction = hc.rayDir; - - // Calculate the face normal with the first two vertices in the intersection geometry. - Vec3 vdir0 = (m_vertices[0] - m_vertices[1]).GetNormalized(); - Vec3 vdir1 = (m_vertices[2] - m_vertices[1]).GetNormalized(); - - Vec3 normal; - if (!hc.b2DViewport) - { - normal = hc.view->GetViewTM().GetColumn1(); - } - else - { - normal = hc.view->GetConstructionPlane()->n; - } - - float shortestDistance = std::numeric_limits<float>::max(); - size_t numVertices = m_vertices.size(); - for (size_t i = 0; i < numVertices; ++i) - { - const Vec3& v0 = m_vertices[i]; - const Vec3& v1 = m_vertices[(i + 1) % numVertices]; - Vec3 right = (v0 - v1).Cross(normal).GetNormalized() * screenScale * m_hitTestWidth; - - // Calculates the quad vertices aligned to the face normal. - Vec3 quad[4]; - quad[0] = v0 + right; - quad[1] = v1 + right; - quad[2] = v1 - right; - quad[3] = v0 - right; - - Vec3 contact; - if (IntersectRayWithQuad(ray, quad, contact)) - { - Vec3 intersectionPoint; - if (PointToLineDistance(v0, v1, contact, intersectionPoint)) - { - // Ensure the intersection is within the quad's extents - float distanceToIntersection = intersectionPoint.GetDistance(contact); - if (distanceToIntersection < shortestDistance) - { - shortestDistance = distanceToIntersection; - } - } - } - } - - // if shortestDistance is less than the maximum possible distance, we have an intersection. - if (shortestDistance < std::numeric_limits<float>::max() - FLT_EPSILON) - { - hc.object = object; - hc.dist = shortestDistance; - return true; - } - - return false; - } - - void Axis::DebugDrawHitTestSurface(DisplayContext& dc, HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale) - { - // Generate the geometry for rendering. - GenerateHitTestGeometry(hc, position, radius, angleStepRadians, axis, screenScale); - - // Calculate the face normal with the first two vertices in the intersection geometry. - Vec3 vdir0 = (m_vertices[0] - m_vertices[1]).GetNormalized(); - Vec3 vdir1 = (m_vertices[2] - m_vertices[1]).GetNormalized(); - - Vec3 normal; - if (!hc.b2DViewport) - { - normal = hc.view->GetViewTM().GetColumn1(); - } - else - { - normal = hc.view->GetConstructionPlane()->n; - } - - float shortestDistance = std::numeric_limits<float>::max(); - - Ray ray; - ray.origin = hc.raySrc; - ray.direction = hc.rayDir; - - size_t numVertices = m_vertices.size(); - for (size_t i = 0; i < numVertices; ++i) - { - const Vec3& v0 = m_vertices[i]; - const Vec3& v1 = m_vertices[(i + 1) % numVertices]; - Vec3 right = (v0 - v1).Cross(normal).GetNormalized() * screenScale * m_hitTestWidth; - - // Calculates the quad vertices aligned to the face normal. - Vec3 quad[4]; - quad[0] = v0 + right; - quad[1] = v1 + right; - quad[2] = v1 - right; - quad[3] = v0 - right; - - // Draw double sided quad to ensure it is always visible regardless of camera orientation. - dc.DrawQuad(quad[0], quad[1], quad[2], quad[3]); - dc.DrawQuad(quad[3], quad[2], quad[1], quad[0]); - - Vec3 contact; - if (IntersectRayWithQuad(ray, quad, contact)) - { - Vec3 intersectionPoint; - if (PointToLineDistance(v0, v1, contact, intersectionPoint)) - { - // Ensure the intersection is within the quad's extents - float distanceToIntersection = intersectionPoint.GetDistance(contact); - if (distanceToIntersection < shortestDistance) - { - shortestDistance = distanceToIntersection; - - // Highlight the quad at which an intersection occurred. - auto c = dc.GetColor(); - dc.SetColor(Col_Red); - dc.DrawQuad(quad[0], quad[1], quad[2], quad[3]); - dc.DrawQuad(quad[3], quad[2], quad[1], quad[0]); - dc.SetColor(c); - } - } - } - } - } - - - namespace AngleDecorator - { - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axisToAlign, float startAngleRadians, float sweepAngleRadians, float stepAngleRadians, float radius, float screenScale) - { - float angle = startAngleRadians; - - if (fabs(sweepAngleRadians) < FLT_EPSILON || sweepAngleRadians < stepAngleRadians) - { - return; - } - - if (sweepAngleRadians > g_PI) - { - sweepAngleRadians = g_PI - (fabs(sweepAngleRadians - g_PI)); - stepAngleRadians = -stepAngleRadians; - } - - Vec3 a; - Vec3 b; - GetBasisVectors(axisToAlign, a, b); - - float cosAngle = cos(angle); - float sinAngle = sin(angle); - - // Pre-calculate the first vertex, this is useful for rendering the first handle ball. - Vec3 p0; - p0.x = position.x + (cosAngle * a.x + sinAngle * b.x) * radius * screenScale; - p0.y = position.y + (cosAngle * a.y + sinAngle * b.y) * radius * screenScale; - p0.z = position.z + (cosAngle * a.z + sinAngle * b.z) * radius * screenScale; - - const float ballRadius = 0.1f * screenScale; - - // TODO: colors should be configurable properties - dc.SetColor(0.f, 1.f, 0.f, 1.f); - dc.DrawBall(p0, ballRadius); - - float alpha = 0.5f; - dc.SetColor(0.8f, 0.8f, 0.8f, 0.5f); - - // Number of vertices is defined by stepAngleRadians, the smaller the step the higher vertex count. - int numVertices = static_cast<int>(fabs(sweepAngleRadians / stepAngleRadians)); - if (numVertices >= 2) - { - Vec3 p1; - for (int i = 0; i < numVertices; ++i) - { - // We pre-calculated the first vertex, so we can advance the angle - angle += stepAngleRadians; - - const float cosAngle2 = cos(angle); - const float sinAngle2 = sin(angle); - - p1.x = position.x + (cosAngle2 * a.x + sinAngle2 * b.x) * radius * screenScale; - p1.y = position.y + (cosAngle2 * a.y + sinAngle2 * b.y) * radius * screenScale; - p1.z = position.z + (cosAngle2 * a.z + sinAngle2 * b.z) * radius * screenScale; - - // Draws a triangle from the object's position to p0 and p1. - dc.SetColor(0.8f, 0.8f, 0.8f, alpha); - dc.DrawTri(position, p0, p1); - - alpha += 0.5f * (i / numVertices); - p0 = p1; - } - - // Draw the end handle ball. - dc.SetColor(1.f, 0.f, 0.f, 1.f); - dc.DrawBall(p1, ballRadius); - } - } - } -} - -RotationControlConfiguration::RotationControlConfiguration() -{ - DefineConstIntCVar(RotationControl_DrawDecorators, 0, VF_NULL, "Toggles the display of the angular decorator."); - DefineConstIntCVar(RotationControl_DebugHitTesting, 0, VF_NULL, "Renders the hit testing geometry used for mouse input control."); - DefineConstIntCVar(RotationControl_AngleTracking, 0, VF_NULL, "Displays a sphere aligned to the mouse cursor direction for debugging."); -} - -#include <moc_RotateTool.cpp> diff --git a/Code/Sandbox/Editor/RotateTool.h b/Code/Sandbox/Editor/RotateTool.h deleted file mode 100644 index d24ff5ff39..0000000000 --- a/Code/Sandbox/Editor/RotateTool.h +++ /dev/null @@ -1,283 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#ifndef CRYINCLUDE_EDITOR_ROTATETOOL_H -#define CRYINCLUDE_EDITOR_ROTATETOOL_H -#pragma once - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#include "IObjectManager.h" -#include "EditMode/ObjectMode.h" -#include "Objects/BaseObject.h" // for CBaseObject::EventListener -#include "Objects/DisplayContext.h" -#include "Include/HitContext.h" -#endif - -//! Provides rendering utilities to support CRotateTool -namespace RotationDrawHelper -{ - //! Circle drawing and hit testing functionality over arbitrary axes - class Axis - { - public: - - //! \param defaultColor Color used to draw the camera aligned portion of the axis. - //! \param highlightColor Color used to draw the circle when it is in focus. - Axis(const ColorF& defaultColor = Col_White, const ColorF& highlightColor = Col_Yellow); - - //! Draws an axis aligned circle. - //! \param dc DisplayContext to use for rendering. - //! \param position World space position used as the center of the circle. - //! \param axis The axis by which to align the circle. - //! \param angleRadians The angle towards which the circle will be highlighted. - //! \param radius The radius of the circle. - //! \param highlighted If true it will draw the circle in the specified highlightColor. - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axis, float angleRadians, float angleStepRadians, float radius, bool highlighted, CBaseObject* object, float screenScale); - - //! Calculates a hit testing mesh (invisible) used for intersection testing. - //! \param object The object selected if hit testing return true. - //! \param hc The HitContext in which the hit object is set if an intersection is true. - //! \param radius The radius for the axis' circle. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis by which to align the intersection geometry. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - bool HitTest(CBaseObject* object, HitContext& hc, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - //! Draws the generated hit testing geometry, good for diagnostics and debugging. - //! \param dc DisplayContext to use for rendering. - //! \param hc The HitContext that contains the view direction raycast. - //! \param position World space position used as the center of the circle. - //! \param radius The radius for the axis' circle. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis by which to align the intersection geometry. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void DebugDrawHitTestSurface(DisplayContext& dc, HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - protected: - - enum States - { - StateDefault, - StateHighlight, - StateCount - }; - - ColorF m_colors[StateCount]; - - //! Defines the width of the generated hit testing geometry. - float m_hitTestWidth = 0.4f; - - //! Contains the vertices that make up the ring for the intersection testing geometry. - //! \remark Only contains the center positions, quads are generated by calculating the four vertices offset by m_hitTestWidth. - std::vector<Vec3> m_vertices; - - //! Generates the world space geometry necessary to perform hit testing. - //! \param hc The HitContext data. - //! \param position The world space position around which the geometry will be centered. - //! \param radius The radius of the ring. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param axis The axis to which the geometry will be aligned to. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void GenerateHitTestGeometry(HitContext& hc, const Vec3& position, float radius, float angleStepRadians, const Vec3& axis, float screenScale); - - //! Performs intersection testing between a ray and both sides of a quad - //! \param ray The ray to test (in world space) - //! \param quad An array of four Vec3 points in world space. - //! \param[out] contact The intersection position in world space at which the intersection occurred. - bool IntersectRayWithQuad(const Ray&ray, Vec3 quad[4], Vec3 & contact); - }; - - //! Provides the means to set and restore DisplayContext settings within a given scope. - class DisplayContextScope - { - public: - DisplayContextScope(DisplayContext& dc) - : m_dc(dc) - { - m_dc.DepthTestOff(); - m_dc.CullOff(); - } - - ~DisplayContextScope() - { - m_dc.DepthTestOn(); - m_dc.CullOn(); - } - - DisplayContext& m_dc; - }; - - //! Helper function that draws the representation of the inner angle of a rotation. - namespace AngleDecorator - { - //! \param dc - //! \param position World space position of the center of the decorator. - //! \param axisToAlign Axis to which the decorator will be aligned to. - //! \param startAngleRadians The starting angle from which the rotation will be performed. - //! \param sweepAngleRadians An angle that represents the sweep of the rotation arc. - //! \param angleStepRadians The angle for the step used to calculate the circle, a smaller angle results in a higher quality circle. - //! \param radius The radius of the decorator. - //! \param screenScale This is an internal parameter used to deduce the view distance ratio in order to scale the tool. - void Draw(DisplayContext& dc, const Vec3& position, const Vec3& axisToAlign, float startAngleRadians, float sweepAngleRadians, float stepAngleRadians, float radius, float screenScale); - } -} - -//! Provides rotation manipulation controls. -class SANDBOX_API CRotateTool - : public CObjectMode - , public IObjectSelectCallback - , public CBaseObject::EventListener -{ - Q_OBJECT -public: - Q_INVOKABLE CRotateTool(CBaseObject* pObject = nullptr, QWidget* parent = nullptr); - virtual ~CRotateTool(); - - static const GUID& GetClassID(); - - // Registration function. - static void RegisterTool(CRegistrationContext& rc); - - void Display(DisplayContext& dc) override; - void DrawObjectHelpers([[maybe_unused]] CBaseObject* pObject, [[maybe_unused]] DisplayContext& dc) override {} - bool HitTest(CBaseObject* pObject, HitContext& hc) override; - void DeleteThis() override; - bool OnLButtonDown(CViewport* view, int nFlags, const QPoint& point) override; - bool OnLButtonUp(CViewport* view, int nFlags, const QPoint& point) override; - bool OnMouseMove(CViewport* view, int nFlags, const QPoint& point) override; - -protected: - - //! Utility to calculate the view distance ratio used to scale the tool. - float GetScreenScale(IDisplayViewport* view, CCamera* camera = nullptr); - - enum Axis - { - AxisNone, - AxisX, //! X axis visualization and hit testing - AxisY, //! Y axis visualization and hit testing - AxisZ, //! Z axis visualization and hit testing - AxisView, //! View direction axis, used to rotate along the vector from the camera to the object. - AxisCount - }; - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - //! Axis visualization and hit testing - RotationDrawHelper::Axis m_axes[Axis::AxisCount]; - - //! We record the starting angle when we begin to drag an object - float m_initialViewAxisAngleRadians; - - //! The angle from the object's (or selection's) center to the mouse cursor. - float m_angleToCursor; - - //! Specified which axis is currently selected. - Axis m_highlightAxis; - - //! True when we are using the view direction rotation axis. - bool m_viewAxisRotation; - - //! True when the mouse has been pressed, becomes false on release. - bool m_draggingMouse; - - //! The last mouse position on screen when rotating. - QPoint m_lastPosition; - - //! Cumulative rotation angle in degrees. - Ang3 m_rotationAngles; - - //! The selected object. - CBaseObject* m_object; - - //! True if there has been a change in rotation that affects the object. - bool m_bTransformChanged; - - //! Sum of the total rotation angles. - float m_totalRotationAngle; - - //! Radius used to draw the XYZ axes - float m_basisAxisRadius; - - //! Radius used to draw the view direction axis - float m_viewAxisRadius; - - //! Rotation step controls the quality of the axes, a smaller angle represents a higher number of vertices. - float m_arcRotationStepRadians; - - //! Thickness of for the axis line rendering. - float m_lineThickness = 4.f; - - //! Draws angle decorator for the current rotation axis. - void DrawAngleDecorator(DisplayContext& dc); - - //! Useful for debugging and visualizing hit testing - void DrawHitTestGeometry(DisplayContext& dc, HitContext& hc); - - //! Diagnostic tool to examine view direction angle (follows mouse cursor) - void DrawViewDirectionAngleTracking(DisplayContext& dc, HitContext& hc); - - //! Callback registered to receive Selection callbacks to set m_object - bool OnSelectObject(CBaseObject* object) override; - - //! Callback to check that an object can be selected - bool CanSelectObject(CBaseObject* object) override; - - //! Callback installed on the object, used to determine destruction or deselection. - void OnObjectEvent(CBaseObject* object, int event) override; - - //! Handle key down events. - bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags) override; - - //! Retrieves the object's transformation according to the specified reference coordinate system. - Matrix34 GetTransform(RefCoordSys referenceCoordinateSystem, IDisplayViewport* view); - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - - //! Calculate orientation of 3 points on screen, return 1.0f if clockwise, -1.0f if counter-clockwise - float CalculateOrientation(const QPoint& p1, const QPoint& p2, const QPoint& p3); - -private: - - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - HitContext m_hc; //!< HACK: Cache the hitcontext given that it's values may differ depending on the viewport they are coming from. - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -//! Singleton that holds all the configuration cvars for the different features and debug options -//! used by the CRotationControl -class RotationControlConfiguration -{ -public: - - static RotationControlConfiguration& Get() - { - static RotationControlConfiguration instance; - return instance; - } - - //! If enabled it will draw the inner rotation decorator. - DeclareConstIntCVar(RotationControl_DrawDecorators, 0); - - //! If enabled the hit testing geometry is rendered. - DeclareConstIntCVar(RotationControl_DebugHitTesting, 0); - - //! If enabled a sphere will be drawn to represent the view axis angle to the mouse cursor. - DeclareConstIntCVar(RotationControl_AngleTracking, 0); - -private: - - RotationControlConfiguration(); - RotationControlConfiguration(const RotationControlConfiguration&) = delete; - RotationControlConfiguration& operator = (const RotationControlConfiguration&) = delete; - ~RotationControlConfiguration() {} -}; - -#endif // CRYINCLUDE_EDITOR_ROTATETOOL_H diff --git a/Code/Sandbox/Editor/Settings.cpp b/Code/Sandbox/Editor/Settings.cpp index 0f25b6ac6d..038af33129 100644 --- a/Code/Sandbox/Editor/Settings.cpp +++ b/Code/Sandbox/Editor/Settings.cpp @@ -653,12 +653,6 @@ void SEditorSettings::Save() SaveValue("Settings", "ForceSkyUpdate", gSettings.bForceSkyUpdate); - ////////////////////////////////////////////////////////////////////////// - // Vertex snapping settings - ////////////////////////////////////////////////////////////////////////// - SaveValue("Settings\\VertexSnapping", "VertexCubeSize", vertexSnappingSettings.vertexCubeSize); - SaveValue("Settings\\VertexSnapping", "RenderPenetratedBoundBox", vertexSnappingSettings.bRenderPenetratedBoundBox); - ////////////////////////////////////////////////////////////////////////// // Smart file open settings ////////////////////////////////////////////////////////////////////////// @@ -886,12 +880,6 @@ void SEditorSettings::Load() LoadValue("Settings", "ForceSkyUpdate", gSettings.bForceSkyUpdate); - ////////////////////////////////////////////////////////////////////////// - // Vertex snapping settings - ////////////////////////////////////////////////////////////////////////// - LoadValue("Settings\\VertexSnapping", "VertexCubeSize", vertexSnappingSettings.vertexCubeSize); - LoadValue("Settings\\VertexSnapping", "RenderPenetratedBoundBox", vertexSnappingSettings.bRenderPenetratedBoundBox); - ////////////////////////////////////////////////////////////////////////// // Smart file open settings ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Settings.h b/Code/Sandbox/Editor/Settings.h index 918647388a..512c6e3942 100644 --- a/Code/Sandbox/Editor/Settings.h +++ b/Code/Sandbox/Editor/Settings.h @@ -119,18 +119,6 @@ struct SDeepSelectionSettings bool bStickDuplicate; }; -////////////////////////////////////////////////////////////////////////// -// Settings for vertex snapping. -////////////////////////////////////////////////////////////////////////// -struct SVertexSnappingSettings -{ - SVertexSnappingSettings() - : vertexCubeSize(0.01f) - , bRenderPenetratedBoundBox(false) {} - float vertexCubeSize; - bool bRenderPenetratedBoundBox; -}; - ////////////////////////////////////////////////////////////////////////// struct SObjectColors { @@ -474,9 +462,6 @@ AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING // Object Highlight Settings SObjectColors objectColorSettings; - - // Vertex Snapping Settings - SVertexSnappingSettings vertexSnappingSettings; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING SSmartOpenDialogSettings smartOpenSettings; diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index d39dabf034..12fd9b1a03 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -625,7 +625,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const t.AddAction(ID_GOTO_SELECTED, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_OBJECTMODIFY_SETHEIGHT, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_MODIFY_ALIGNOBJTOSURF, ORIGINAL_TOOLBAR_VERSION); if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) { @@ -634,8 +633,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const t.AddAction(ID_EDIT_UNFREEZEALL, ORIGINAL_TOOLBAR_VERSION); } - t.AddAction(ID_OBJECTMODIFY_VERTEXSNAPPING, ORIGINAL_TOOLBAR_VERSION); - return t; } diff --git a/Code/Sandbox/Editor/Viewport.cpp b/Code/Sandbox/Editor/Viewport.cpp index ae2de224cb..1041a4f086 100644 --- a/Code/Sandbox/Editor/Viewport.cpp +++ b/Code/Sandbox/Editor/Viewport.cpp @@ -30,7 +30,6 @@ #include "Util/Ruler.h" #include "PluginManager.h" #include "Include/IRenderListener.h" -#include "EditTool.h" #include "GameEngine.h" #include "Settings.h" @@ -207,8 +206,6 @@ QtViewport::QtViewport(QWidget* parent) GetIEditor()->GetViewManager()->RegisterViewport(this); - m_pLocalEditTool = 0; - m_nCurViewportID = MAX_NUM_VIEWPORTS - 1; m_dropCallback = nullptr; // Leroy@Conffx @@ -232,8 +229,6 @@ QtViewport::QtViewport(QWidget* parent) ////////////////////////////////////////////////////////////////////////// QtViewport::~QtViewport() { - if (m_pLocalEditTool) - m_pLocalEditTool->deleteLater(); delete m_pVisibleObjectsCache; GetIEditor()->GetViewManager()->UnregisterViewport(this); @@ -258,42 +253,6 @@ void QtViewport::GetDimensions(int* pWidth, int* pHeight) const } } -////////////////////////////////////////////////////////////////////////// -CEditTool* QtViewport::GetEditTool() -{ - if (m_pLocalEditTool) - { - return m_pLocalEditTool; - } - return GetIEditor()->GetEditTool(); -} - -////////////////////////////////////////////////////////////////////////// -void QtViewport::SetEditTool(CEditTool* pEditTool, bool bLocalToViewport /*=false */) -{ - if (m_pLocalEditTool == pEditTool) - { - return; - } - - if (m_pLocalEditTool) - { - m_pLocalEditTool->EndEditParams(); - } - m_pLocalEditTool = 0; - - if (bLocalToViewport) - { - m_pLocalEditTool = pEditTool; - m_pLocalEditTool->BeginEditParams(GetIEditor(), 0); - } - else - { - m_pLocalEditTool = 0; - GetIEditor()->SetEditTool(pEditTool); - } -} - ////////////////////////////////////////////////////////////////////////// void QtViewport::RegisterRenderListener(IRenderListener* piListener) { @@ -466,12 +425,6 @@ void QtViewport::Update() m_bAdvancedSelectMode = false; bool bSpaceClick = false; - CEditTool* pEditTool = GetIEditor()->GetEditTool(); - if (pEditTool && pEditTool->IsNeedSpecificBehaviorForSpaceAcce()) - { - bSpaceClick = CheckVirtualKey(Qt::Key_Space); - } - else { bSpaceClick = CheckVirtualKey(Qt::Key_Space) & !CheckVirtualKey(Qt::Key_Shift) /*& !CheckVirtualKey(Qt::Key_Control)*/; } @@ -726,10 +679,6 @@ void QtViewport::OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons b ////////////////////////////////////////////////////////////////////////// void QtViewport::OnSetCursor() { - if (GetEditTool()) - { - GetEditTool()->OnSetCursor(this); - } } ////////////////////////////////////////////////////////////////////////// @@ -803,39 +752,23 @@ void QtViewport::OnRButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& } ////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +void QtViewport::OnKeyDown([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) { if (GetIEditor()->IsInGameMode()) { // Ignore key downs while in game. return; } - - if (GetEditTool()) - { - if (GetEditTool()->OnKeyDown(this, nChar, nRepCnt, nFlags)) - { - return; - } - } } ////////////////////////////////////////////////////////////////////////// -void QtViewport::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +void QtViewport::OnKeyUp([[maybe_unused]] UINT nChar, [[maybe_unused]] UINT nRepCnt, [[maybe_unused]] UINT nFlags) { if (GetIEditor()->IsInGameMode()) { // Ignore key downs while in game. return; } - - if (GetEditTool()) - { - if (GetEditTool()->OnKeyUp(this, nChar, nRepCnt, nFlags)) - { - return; - } - } } ////////////////////////////////////////////////////////////////////////// @@ -1454,28 +1387,6 @@ bool QtViewport::MouseCallback(EMouseEvent event, const QPoint& point, Qt::Keybo } } - ////////////////////////////////////////////////////////////////////////// - // Asks current edit tool to handle mouse callback. - CEditTool* pEditTool = GetEditTool(); - if (pEditTool) - { - if (pEditTool->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - - // Ask all chain of parent tools if they are handling mouse event. - CEditTool* pParentTool = pEditTool->GetParentTool(); - while (pParentTool) - { - if (pParentTool->MouseCallback(this, event, tempPoint, flags)) - { - return true; - } - pParentTool = pParentTool->GetParentTool(); - } - } - return false; } ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/Viewport.h b/Code/Sandbox/Editor/Viewport.h index acc5a3acfb..9979a3bb0a 100644 --- a/Code/Sandbox/Editor/Viewport.h +++ b/Code/Sandbox/Editor/Viewport.h @@ -45,7 +45,6 @@ struct DisplayContext; class CCryEditDoc; class CLayoutViewPane; class CViewManager; -class CEditTool; class CBaseObjectsCache; struct HitContext; struct IRenderListener; @@ -255,8 +254,6 @@ public: virtual void SetSupplementaryCursorStr(const QString& str) = 0; virtual void SetCursorString(const QString& str) = 0; - virtual CEditTool* GetEditTool() = 0; - virtual void SetFocus() = 0; virtual void Invalidate(BOOL bErase = 1) = 0; @@ -488,10 +485,6 @@ public: void ResetCursor(); void SetSupplementaryCursorStr(const QString& str); - virtual CEditTool* GetEditTool(); - // Assign an edit tool to viewport - virtual void SetEditTool(CEditTool* pEditTool, bool bLocalToViewport = false); - ////////////////////////////////////////////////////////////////////////// // Return visble objects cache. CBaseObjectsCache* GetVisibleObjectsCache() { return m_pVisibleObjectsCache; }; @@ -627,8 +620,6 @@ protected: // Same construction matrix is shared by all viewports. Matrix34 m_constructionMatrix[LAST_COORD_SYSTEM]; - QPointer<CEditTool> m_pLocalEditTool; - std::vector<IRenderListener*> m_cRenderListeners; typedef std::vector<_smart_ptr<IPostRenderer> > PostRenderers; diff --git a/Code/Sandbox/Editor/VoxelAligningTool.cpp b/Code/Sandbox/Editor/VoxelAligningTool.cpp deleted file mode 100644 index 1d45dd2d3f..0000000000 --- a/Code/Sandbox/Editor/VoxelAligningTool.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "VoxelAligningTool.h" - -// Editor -#include "SurfaceInfoPicker.h" -#include "Objects/SelectionGroup.h" - -////////////////////////////////////////////////////////////////////////// -CVoxelAligningTool::CVoxelAligningTool() -{ - m_curObj = 0; - m_PreviewMode = ePM_Idle; - - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (!sel->IsEmpty()) - { - m_curObj = sel->GetObject(0); - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - m_q = m_curObj->GetRotation(); - } -} - -////////////////////////////////////////////////////////////////////////// -CVoxelAligningTool::~CVoxelAligningTool() -{ -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::Display([[maybe_unused]] DisplayContext& dc) -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CVoxelAligningTool::MouseCallback([[maybe_unused]] CViewport* view, EMouseEvent event, QPoint& point, int flags) -{ - // Get contrl key status. - bool bCtrlClick = (flags & MK_CONTROL); - bool bShiftClick = (flags & MK_SHIFT); - bool bOnlyCtrlClick = bCtrlClick && !bShiftClick; - - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (sel->IsEmpty() || m_curObj != sel->GetObject(0)) - { - GetIEditor()->SetEditTool(0); - return true; - } - - if (event == eMouseMove) - { - if (m_PreviewMode == ePM_Idle) - { - if (bOnlyCtrlClick) - { - if (m_curObj) - { - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - } - m_PreviewMode = ePM_Previewing; - GetIEditor()->BeginUndo(); - } - } - else if (!bOnlyCtrlClick) - { - if (m_curObj) - { - m_curObj->SetWorldTM(m_CurObjTMBeforePreviewMode); - //m_curObj->SetRotation(m_extraRot); - } - m_PreviewMode = ePM_Idle; - GetIEditor()->CancelUndo(); - } - - if (m_PreviewMode == ePM_Previewing && bOnlyCtrlClick) - { // Preview align to normal - ApplyPickedTM2CurObj(point); - } - } - - if (event == eMouseLDown && m_PreviewMode == ePM_Previewing) - { - m_CurObjTMBeforePreviewMode = m_curObj->GetWorldTM(); - GetIEditor()->AcceptUndo("Surface Normal Aligning"); - GetIEditor()->SetEditTool(NULL); - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::ApplyPickedTM2CurObj(const QPoint& point, [[maybe_unused]] bool bPickOnlyTerrain) -{ - int nPickFlag = CSurfaceInfoPicker::ePOG_All; - SRayHitInfo hitInfo; - CSurfaceInfoPicker::CExcludedObjects excludeObjects; - if (m_curObj) - { - excludeObjects.Add(m_curObj); - } - CSurfaceInfoPicker surfacePicker; - if (surfacePicker.Pick(point, hitInfo, &excludeObjects, nPickFlag)) - { - m_curObj->SetPos(hitInfo.vHitPos, eObjectUpdateFlags_UserInput); - ApplyRotation(hitInfo.vHitNormal); - } -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::ApplyRotation(Vec3& normal) -{ - Vec3 zaxis = m_q * Vec3(0, 0, 1); - zaxis.Normalize(); - Quat nq; - nq.SetRotationV0V1(zaxis, normal); - m_curObj->SetRotation(nq * m_q, eObjectUpdateFlags_UserInput); -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::BeginEditParams([[maybe_unused]] IEditor* ie, [[maybe_unused]] int flags) -{ -} - -////////////////////////////////////////////////////////////////////////// -void CVoxelAligningTool::EndEditParams() -{ -} - -////////////////////////////////////////////////////////////////////////// -bool CVoxelAligningTool::OnKeyDown([[maybe_unused]] CViewport* view, uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) -{ - if (nChar == VK_ESCAPE) - { - GetIEditor()->SetEditTool(0); - } - return false; -} - -#include <moc_VoxelAligningTool.cpp> diff --git a/Code/Sandbox/Editor/VoxelAligningTool.h b/Code/Sandbox/Editor/VoxelAligningTool.h deleted file mode 100644 index bfa0e19d9a..0000000000 --- a/Code/Sandbox/Editor/VoxelAligningTool.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -// Description : Definition of VoxelAligningTool, edit tool for cloning of objects.. - - -#ifndef CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H -#define CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H - -#pragma once - -#if !defined(Q_MOC_RUN) -#include "EditTool.h" -#endif - -class CBaseObject; - -/*! - * CVoxelAligningTool, When created duplicate current selection, and manages cloned selection. - * - */ - -class CVoxelAligningTool - : public CEditTool -{ - Q_OBJECT -public: - Q_INVOKABLE CVoxelAligningTool(); - - ////////////////////////////////////////////////////////////////////////// - // Ovverides from CEditTool - bool MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int flags); - - virtual void BeginEditParams(IEditor* ie, int flags); - virtual void EndEditParams(); - - virtual void Display(DisplayContext& dc); - virtual bool OnKeyDown(CViewport* view, uint32 nChar, uint32 nRepCnt, uint32 nFlags); - virtual bool OnKeyUp([[maybe_unused]] CViewport* view, [[maybe_unused]] uint32 nChar, [[maybe_unused]] uint32 nRepCnt, [[maybe_unused]] uint32 nFlags) { return false; }; - ////////////////////////////////////////////////////////////////////////// - -protected: - virtual ~CVoxelAligningTool(); - // Delete itself. - void DeleteThis() { delete this; }; - - void ApplyPickedTM2CurObj(const QPoint& point, bool bPickOnlyTerrain = false); - void ApplyRotation(Vec3& normal); - -private: - - CBaseObject* m_curObj; - Quat m_q; - - enum EPreviewMode - { - ePM_Idle, - ePM_Previewing, - }; - EPreviewMode m_PreviewMode; - Matrix34 m_CurObjTMBeforePreviewMode; -}; - - -#endif // CRYINCLUDE_EDITOR_VOXELALIGNINGTOOL_H diff --git a/Code/Sandbox/Editor/editor_lib_files.cmake b/Code/Sandbox/Editor/editor_lib_files.cmake index 5696931f26..da32d6d062 100644 --- a/Code/Sandbox/Editor/editor_lib_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_files.cmake @@ -10,8 +10,6 @@ # set(FILES - NullEditTool.h - NullEditTool.cpp Translations/editor_en-us.ts Translations/assetbrowser_en-us.ts DPIAware.xml @@ -389,8 +387,6 @@ set(FILES Controls/NumberCtrl.h Controls/PreviewModelCtrl.cpp Controls/PreviewModelCtrl.h - Controls/QRollupCtrl.cpp - Controls/QRollupCtrl.h Controls/SplineCtrl.cpp Controls/SplineCtrl.h Controls/SplineCtrlEx.cpp @@ -401,8 +397,6 @@ set(FILES Controls/TimelineCtrl.h Controls/TimeOfDaySlider.cpp Controls/TimeOfDaySlider.h - Controls/ToolButton.cpp - Controls/ToolButton.h Controls/WndGridHelper.h Controls/ReflectedPropertyControl/PropertyAnimationCtrl.cpp Controls/ReflectedPropertyControl/PropertyAnimationCtrl.h @@ -451,8 +445,6 @@ set(FILES CustomResolutionDlg.cpp CustomResolutionDlg.ui CustomResolutionDlg.h - Dialogs/ButtonsPanel.cpp - Dialogs/ButtonsPanel.h ErrorReportDialog.ui ErrorReportDialog.cpp ErrorReportDialog.h @@ -533,18 +525,8 @@ set(FILES Dialogs/PythonScriptsDialog.ui Dialogs/Generic/UserOptions.cpp Dialogs/Generic/UserOptions.h - ObjectCloneTool.cpp - ObjectCloneTool.h EditMode/SubObjectSelectionReferenceFrameCalculator.cpp EditMode/SubObjectSelectionReferenceFrameCalculator.h - EditMode/ObjectMode.cpp - EditMode/ObjectMode.h - RotateTool.cpp - RotateTool.h - EditTool.cpp - EditTool.h - VoxelAligningTool.cpp - VoxelAligningTool.h Export/ExportManager.cpp Export/ExportManager.h Export/OBJExporter.cpp @@ -575,7 +557,6 @@ set(FILES Dialogs/DuplicatedObjectsHandlerDlg.h DocMultiArchive.h EditMode/DeepSelection.h - EditMode/VertexSnappingModeTool.h FBXExporterDialog.h FileTypeUtils.h GridUtils.h @@ -639,8 +620,6 @@ set(FILES Material/MaterialLibrary.h Material/MaterialManager.cpp Material/MaterialManager.h - Material/MaterialPickTool.cpp - Material/MaterialPickTool.h MaterialSender.h MaterialSender.cpp Material/MaterialPythonFuncs.h @@ -742,7 +721,6 @@ set(FILES ErrorReportTableModel.h ErrorReportTableModel.cpp EditMode/DeepSelection.cpp - EditMode/VertexSnappingModeTool.cpp FBXExporterDialog.cpp FBXExporterDialog.ui FileTypeUtils.cpp diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h index 581c453919..12757f5b24 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h @@ -21,7 +21,6 @@ #include <ISerialize.h> #include <CryName.h> #include <EditorDefs.h> -#include <EditTool.h> #include <Resource.h> ///////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp index 4a03dcd7dc..a97bdbf2ab 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.cpp @@ -320,14 +320,6 @@ void CComponentEntityObject::OnSelected() // Invoked when selected via tools application, so we notify sandbox. const bool wasSelected = IsSelected(); GetIEditor()->GetObjectManager()->SelectObject(this); - - // If we get here and we're not already selected in sandbox land it means - // the selection started in AZ land and we need to clear any edit tool - // the user may have selected from the rollup bar - if (GetIEditor()->GetEditTool() && !wasSelected) - { - GetIEditor()->SetEditTool(nullptr); - } } } diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h index 4bf55cfbe6..fa59ec8507 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h @@ -24,6 +24,8 @@ #include <AzToolsFramework/ToolsComponents/EditorEntityIconComponentBus.h> #include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h> +#include <QtViewPane.h> + #include "../Editor/Objects/EntityObject.h" #include <LmbrCentral/Rendering/MeshComponentBus.h> #include <LmbrCentral/Rendering/RenderBoundsBus.h> diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp index 9c917b25c0..89ef4ead7f 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.cpp @@ -1383,11 +1383,6 @@ void SandboxIntegrationManager::SetShowCircularDependencyError(const bool& showC } ////////////////////////////////////////////////////////////////////////// -void SandboxIntegrationManager::SetEditTool(const char* tool) -{ - GetIEditor()->SetEditTool(tool); -} - void SandboxIntegrationManager::LaunchLuaEditor(const char* files) { CCryEditApp::instance()->OpenLUAEditor(files); diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h index 36767605b2..ea4d2fe32b 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/SandboxIntegration.h @@ -162,7 +162,6 @@ private: bool GetUndoSliceOverrideSaveValue() override; bool GetShowCircularDependencyError() override; void SetShowCircularDependencyError(const bool& showCircularDependencyError) override; - void SetEditTool(const char* tool) override; void LaunchLuaEditor(const char* files) override; bool IsLevelDocumentOpen() override; AZStd::string GetLevelName() override; diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp index f735048ed0..fb8084cb6f 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp @@ -312,19 +312,6 @@ void OutlinerWidget::OnSelectionChanged(const QItemSelection& selected, const QI AzToolsFramework::EntityIdList newlyDeselected; ExtractEntityIdsFromSelection(deselected, newlyDeselected); - CEditTool* tool = GetIEditor()->GetEditTool(); - IClassDesc* classDescription = tool ? tool->GetClassDesc() : nullptr; - - if (classDescription && QString::compare(classDescription->ClassName(), "EditTool.Clone") == 0) - { - // if the user clicks an empty space or selects a different entity in the entity outliner, the clone operation will be accepted. - if ((newlySelected.empty() && !newlyDeselected.empty()) || !newlySelected.empty()) - { - tool->Accept(true); - GetIEditor()->GetSelection()->FinishChanges(); - } - } - AzToolsFramework::ScopedUndoBatch undo("Select Entity"); // initialize the selection command here to store the current selection before diff --git a/Gems/Camera/Code/Source/Camera_precompiled.h b/Gems/Camera/Code/Source/Camera_precompiled.h index 028ff586c6..2016c4b411 100644 --- a/Gems/Camera/Code/Source/Camera_precompiled.h +++ b/Gems/Camera/Code/Source/Camera_precompiled.h @@ -26,7 +26,6 @@ // Editor ///////////////////////////////////////////////////////////////////////////// #include <EditorDefs.h> -#include <EditTool.h> #include <Resource.h> ///////////////////////////////////////////////////////////////////////////// From 626f7c00fe2d32fc6e00d43ece5893960c6d14f1 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Wed, 21 Apr 2021 12:07:34 -0700 Subject: [PATCH 62/96] [SPEC-1856] Convert AWSGameLiftServerSDK to new 3rdparty system (#198) Remove old 3rdparty reference in code, and replace with new target. Lib has been promoted to prod bucket (https://jira.agscollab.com/browse/SPEC-6469) --- cmake/3rdParty/FindAWSGameLiftServerSDK.cmake | 20 -------- .../Linux/AWSGameLiftServerSDK_linux.cmake | 21 --------- .../Linux/BuiltInPackages_linux.cmake | 1 + .../Platform/Linux/cmake_linux_files.cmake | 1 - .../AWSGameLiftServerSDK_windows.cmake | 47 ------------------- .../Windows/BuiltInPackages_windows.cmake | 1 + .../Windows/cmake_windows_files.cmake | 1 - cmake/3rdParty/cmake_files.cmake | 1 - .../3rdParty/package_filelists/3rdParty.json | 1 - .../Windows/package_filelists/3rdParty.json | 6 --- 10 files changed, 2 insertions(+), 98 deletions(-) delete mode 100644 cmake/3rdParty/FindAWSGameLiftServerSDK.cmake delete mode 100644 cmake/3rdParty/Platform/Linux/AWSGameLiftServerSDK_linux.cmake delete mode 100644 cmake/3rdParty/Platform/Windows/AWSGameLiftServerSDK_windows.cmake diff --git a/cmake/3rdParty/FindAWSGameLiftServerSDK.cmake b/cmake/3rdParty/FindAWSGameLiftServerSDK.cmake deleted file mode 100644 index 48e7096480..0000000000 --- a/cmake/3rdParty/FindAWSGameLiftServerSDK.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# -ly_add_external_target( - NAME AWSGameLiftServerSDK - VERSION 3.4.0 - 3RDPARTY_DIRECTORY AWS/GameLift - INCLUDE_DIRECTORIES include - COMPILE_DEFINITIONS - AWS_CUSTOM_MEMORY_MANAGEMENT - PLATFORM_SUPPORTS_AWS_NATIVE_SDK - GAMELIFT_USE_STD -) diff --git a/cmake/3rdParty/Platform/Linux/AWSGameLiftServerSDK_linux.cmake b/cmake/3rdParty/Platform/Linux/AWSGameLiftServerSDK_linux.cmake deleted file mode 100644 index 405b4f4597..0000000000 --- a/cmake/3rdParty/Platform/Linux/AWSGameLiftServerSDK_linux.cmake +++ /dev/null @@ -1,21 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -# TODO AWSGameLiftServerSDK Linux shared libs are not compiled. -set(AWSGAMELIFTSERVERSDK_LIB_PATH ${BASE_PATH}/lib/linux/libstdcxx/intel64/clang-6.0.0/$<IF:$<CONFIG:Debug>,Debug,Release>) - -set(AWSGAMELIFTSERVERSDK_LIBS ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libaws-cpp-sdk-gamelift-server.a - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libsioclient.a - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_date_time.a - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_random.a - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_system.a - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libprotobuf.a -) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 890f4bcc3f..6d3499534c 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -33,6 +33,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARG ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) # platform-specific: +ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-linux TARGETS AWSNativeSDK PACKAGE_HASH e69c55682638dc1e7fa571a61a82c8a69d395c74a008543a5188f4bd2b6b10c4) diff --git a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake index 809e8b7198..69aa0a5a2f 100644 --- a/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake +++ b/cmake/3rdParty/Platform/Linux/cmake_linux_files.cmake @@ -10,7 +10,6 @@ # set(FILES - AWSGameLiftServerSDK_linux.cmake BuiltInPackages_linux.cmake dyad_linux.cmake FbxSdk_linux.cmake diff --git a/cmake/3rdParty/Platform/Windows/AWSGameLiftServerSDK_windows.cmake b/cmake/3rdParty/Platform/Windows/AWSGameLiftServerSDK_windows.cmake deleted file mode 100644 index 5f93ef7030..0000000000 --- a/cmake/3rdParty/Platform/Windows/AWSGameLiftServerSDK_windows.cmake +++ /dev/null @@ -1,47 +0,0 @@ -# -# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -# its licensors. -# -# For complete copyright and license terms please see the LICENSE at the root of this -# distribution (the "License"). All use of this software is governed by the License, -# or, if provided, by the license below or the license accompanying this file. Do not -# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# - -if (LY_MONOLITHIC_GAME) - # Import Libs - set(AWSGAMELIFTSERVERSDK_LIB_PATH ${BASE_PATH}/lib/windows/intel64/vs2017/$<IF:$<CONFIG:Debug>,Debug,Release>) -else() - # Static Libs - set(AWSGAMELIFTSERVERSDK_LIB_PATH ${BASE_PATH}/bin/windows/intel64/vs2017/$<IF:$<CONFIG:Debug>,Debug,Release>) -endif() - -set(AWSGAMELIFTSERVERSDK_LIBS - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/sioclient.lib - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_date_time.lib - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_random.lib - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libboost_system.lib - ${AWSGAMELIFTSERVERSDK_LIB_PATH}/libprotobuf$<$<CONFIG:Debug>:d>.lib -) - -set(AWSGAMELIFTSERVERSDK_COMPILE_DEFINITIONS - USE_IMPORT_EXPORT - AWS_CUSTOM_MEMORY_MANAGEMENT - PLATFORM_SUPPORTS_AWS_NATIVE_SDK - GAMELIFT_USE_STD -) - -if (NOT LY_MONOLITHIC_GAME) - - # Add 'USE_IMPORT_EXPORT' for external linkage - LIST(APPEND AWSGAMELIFTSERVERSDK_COMPILE_DEFINITIONS USE_IMPORT_EXPORT) - - # Import Lib - LIST(APPEND AWSGAMELIFTSERVERSDK_LIBS ${AWSGAMELIFTSERVERSDK_LIB_PATH}/aws-cpp-sdk-gamelift-server.lib) - - # Shared libs - set(AWSGAMELIFTSERVERSDK_SHARED_LIB_PATH ${BASE_PATH}/bin/windows/intel64/vs2017/$<IF:$<CONFIG:Debug>,Debug,Release>) - set(AWSGAMELIFTSERVERSDK_RUNTIME_DEPENDENCIES ${AWSGAMELIFTSERVERSDK_SHARED_LIB_PATH}/aws-cpp-sdk-gamelift-server.dll) - -endif() \ No newline at end of file diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index e79d6d9af1..1e2c80180d 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -39,6 +39,7 @@ ly_associate_package(PACKAGE_NAME Blast-1.1.7-rev1-multiplatform ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) # platform-specific: +ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3) ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48) diff --git a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake index fe4aa6bc82..25526b7aff 100644 --- a/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake +++ b/cmake/3rdParty/Platform/Windows/cmake_windows_files.cmake @@ -10,7 +10,6 @@ # set(FILES - AWSGameLiftServerSDK_windows.cmake BuiltInPackages_windows.cmake Crashpad_windows.cmake DirectXShaderCompiler_windows.cmake diff --git a/cmake/3rdParty/cmake_files.cmake b/cmake/3rdParty/cmake_files.cmake index 0d8e6d4bb1..fef363e9e4 100644 --- a/cmake/3rdParty/cmake_files.cmake +++ b/cmake/3rdParty/cmake_files.cmake @@ -11,7 +11,6 @@ set(FILES BuiltInPackages.cmake - FindAWSGameLiftServerSDK.cmake FindClang.cmake FindDirectXShaderCompiler.cmake Finddyad.cmake diff --git a/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json b/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json index cb974afd7e..97deb11ea6 100644 --- a/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json +++ b/scripts/build/package/Platform/3rdParty/package_filelists/3rdParty.json @@ -2,7 +2,6 @@ "@3rdParty": { "3rdParty.txt": "#include", "AWS/AWSNativeSDK/1.7.167-az.2/**": "#include", - "AWS/GameLift/3.4.0/**": "#include", "CMake/3.19.1/**": "#include", "DirectXShaderCompiler/1.0.1-az.1/**": "#include", "DirectXShaderCompiler/2020.08.07/**": "#include", diff --git a/scripts/build/package/Platform/Windows/package_filelists/3rdParty.json b/scripts/build/package/Platform/Windows/package_filelists/3rdParty.json index 75add157b4..d9e5d85090 100644 --- a/scripts/build/package/Platform/Windows/package_filelists/3rdParty.json +++ b/scripts/build/package/Platform/Windows/package_filelists/3rdParty.json @@ -17,12 +17,6 @@ "bin/linux/**":"#include", "lib/linux/**":"#include" }, - "AWS/GameLift/3.4.0":{ - "*":"#include", - "include/**":"#include", - "bin/windows/**":"#include", - "lib/linux/libstdcxx/**":"#include" - }, "DirectXShaderCompiler/1.0.1-az.1":{ "*":"#include", "src/**":"#include", From 7bfde0ddba9d025ee401e0d8362c1868f64d7ff1 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Wed, 21 Apr 2021 12:45:14 -0700 Subject: [PATCH 63/96] Using jenkins env var instead of extracting function --- scripts/build/Jenkins/Jenkinsfile | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 4f4708aea3..cdb7874231 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -349,18 +349,6 @@ def Build(Map options, String platform, String type, String workspace) { } } -def getJenkinsBaseUrl() { - def job_url = new URL(env.JOB_URL) - - // Return a new URL using the protocol, host and port only. - return new URL( - job_url.getProtocol(), - job_url.getHost(), - job_url.getPort(), - '' - ).toString() -} - def TestMetrics(Map options, String workspace, String branchName, String repoName, String buildJobName, String outputDirectory, String configuration) { catchError(buildResult: null, stageResult: null) { def cmakeBuildDir = [workspace, ENGINE_REPOSITORY_NAME, outputDirectory].join('/') @@ -372,10 +360,9 @@ def TestMetrics(Map options, String workspace, String branchName, String repoNam userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars', credentialsId: "${env.GITHUB_USER}"]] ] withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { - def jenkins_url = getJenkinsBaseUrl() def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py" + "-e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} " + - "-e jenkins.base_url ${jenkins_url}" + + "-e jenkins.base_url ${env.JENKINS_URL}" + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " bat label: "Publishing ${buildJobName} Test Metrics", script: command From 5f8ffdfdc1c4f5a1613551e9169f141386135896 Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Wed, 21 Apr 2021 14:48:00 -0500 Subject: [PATCH 64/96] [LYN-3137] Fixed EMFX floating dock widgets not responding to docking events. --- .../AzQtComponents/Components/FancyDocking.cpp | 6 ++++++ .../EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp index 76df971108..6cea9324c4 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/FancyDocking.cpp @@ -2298,6 +2298,12 @@ namespace AzQtComponents OptimizedSetParent(dock, mainWindow); mainWindow->addDockWidget(Qt::LeftDockWidgetArea, dock); dock->show(); + + // Make sure we listen for events on the dock widget being put into a floating dock window + // because this might be called programmatically, so the dock widget might have never been + // parented to our m_mainWindow initially, so it won't already have an event filter, + // which will prevent the docking functionality from working. + dock->installEventFilter(this); } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp index 6b8b22f78c..c10e3b06e2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/DockWidgetPlugin.cpp @@ -119,9 +119,7 @@ namespace EMStudio mDock->setFeatures(features); - // mDock->setFloating( true ); mainWindow->addDockWidget(Qt::RightDockWidgetArea, mDock); - mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); // put tabs on top? return mDock; } @@ -139,4 +137,4 @@ namespace EMStudio return widget; } -} // namespace EMStudio \ No newline at end of file +} // namespace EMStudio From efacc3c8bb69a5c3836d0711752129ab10a5453d Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Wed, 21 Apr 2021 13:28:12 -0700 Subject: [PATCH 65/96] Adding missing spaces in test metrics command string --- scripts/build/Jenkins/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index cdb7874231..4352cb1e6a 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -360,9 +360,9 @@ def TestMetrics(Map options, String workspace, String branchName, String repoNam userRemoteConfigs: [[url: "${env.MARS_REPO}", name: 'mars', credentialsId: "${env.GITHUB_USER}"]] ] withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { - def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py" + + def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " + "-e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} " + - "-e jenkins.base_url ${env.JENKINS_URL}" + + "-e jenkins.base_url ${env.JENKINS_URL} " + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " bat label: "Publishing ${buildJobName} Test Metrics", script: command From ee90a737444a413035ef4eda3f5b33ab1dbb458a Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Wed, 21 Apr 2021 16:04:55 -0500 Subject: [PATCH 66/96] [LYN-3105] Fixed missing include. --- .../UI/ComponentPalette/ComponentPaletteWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp index 734d490c6c..a1ec03c2b1 100644 --- a/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp +++ b/Code/Sandbox/Plugins/ComponentEntityEditorPlugin/UI/ComponentPalette/ComponentPaletteWindow.cpp @@ -28,6 +28,7 @@ #include <AzToolsFramework/ToolsComponents/ComponentMimeData.h> #include <AzCore/Component/ComponentApplicationBus.h> #include <AzToolsFramework/API/ToolsApplicationAPI.h> +#include <AzToolsFramework/API/ViewPaneOptions.h> #include <QLabel> From cd00d51bed78402432d76a30b2e1765e12149377 Mon Sep 17 00:00:00 2001 From: Chris Santora <santorac@amazon.com> Date: Wed, 21 Apr 2021 14:17:39 -0700 Subject: [PATCH 67/96] Updated more materials for renamed occlusion properties. I guess these were added to main recently. ATOM-14040 Add Support for Cavity Maps --- .../Sponza/Assets/objects/sponza_mat_arch.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_background.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_bricks.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_ceiling.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_columna.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_columnb.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_columnc.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_curtainblue.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_curtaingreen.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_curtainred.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_details.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_fabricblue.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_fabricgreen.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_fabricred.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_flagpole.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_floor.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_lion.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_roof.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_vase.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_vasehanging.material | 5 ++--- .../Sponza/Assets/objects/sponza_mat_vaseround.material | 5 ++--- 21 files changed, 42 insertions(+), 63 deletions(-) diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material index da72f8a430..770e8b92cf 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_arch.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/arch_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/arch_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material index 5a195fd0b6..1347f71c86 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_background.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/background_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/background_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material index d2089b5537..4671e3906d 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_bricks.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/bricks_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/bricks_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material index 40e476305d..3c15eb8227 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_ceiling.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/ceiling_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/ceiling_1k_ao.png" }, "baseColor": { "textureBlendMode": "Lerp", diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material index 6c89c94021..62ac3e7ed7 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columna.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/columnA_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/columnA_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material index 0be26ba553..bf1e9aea61 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnb.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/columnB_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/columnB_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material index 2f1512fa4a..9614428cd8 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_columnc.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/columnC_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/columnC_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material index e68bc7a41a..47cd16b0eb 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainblue.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/curtain_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/curtain_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material index 85a5ef9775..aba840ce9e 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtaingreen.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/curtain_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/curtain_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material index 086f34727c..7255e35e88 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_curtainred.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/curtain_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/curtain_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material index 18bd2a307b..5586d371a8 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_details.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/details_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/details_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material index fb0490f9a9..23168ff9b5 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricblue.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/fabric_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/fabric_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material index c6074bf894..5760004e39 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricgreen.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/fabric_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/fabric_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material index 4215d8dde5..bd3eea7ed3 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_fabricred.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/fabric_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/fabric_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material index cbba302103..b649ca13a2 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_flagpole.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/flagpole_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/flagpole_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material index 2c2abe3931..5cb52480ec 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_floor.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/floor_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/floor_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material index 55f44b2f63..32dd098c99 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_lion.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/lion_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/lion_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material index a64486309d..fda36db2a3 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_roof.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/roof_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/roof_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material index 867943642e..6538caf94b 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vase.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/vase_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/vase_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material index 9e96fb983d..7f090b54da 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vasehanging.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/vaseHanging_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/vaseHanging_1k_ao.png" }, "baseColor": { "color": [ diff --git a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material index ebb4e537f5..78c30d614f 100644 --- a/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material +++ b/Gems/AtomContent/Sponza/Assets/objects/sponza_mat_vaseround.material @@ -4,9 +4,8 @@ "parentMaterial": "", "propertyLayoutVersion": 3, "properties": { - "ambientOcclusion": { - "enable": true, - "textureMap": "Textures/vaseRound_1k_ao.png" + "occlusion": { + "diffuseTextureMap": "Textures/vaseRound_1k_ao.png" }, "baseColor": { "color": [ From 49322b040b46ffbd5e0938ec38e6de36d065afb5 Mon Sep 17 00:00:00 2001 From: luissemp <luissemp@amazon.com> Date: Wed, 21 Apr 2021 15:37:15 -0700 Subject: [PATCH 68/96] Fixed Lua IDE startup --- .../UI/LegacyFramework/Core/EditorFrameworkApplication.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp index 8cc6d46da8..0aec36b9b0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/LegacyFramework/Core/EditorFrameworkApplication.cpp @@ -192,6 +192,10 @@ namespace LegacyFramework // if we're in console mode, listen for CTRL+C ::SetConsoleCtrlHandler(CTRL_BREAK_HandlerRoutine, true); #endif + + m_ptrCommandLineParser = aznew AzFramework::CommandLine(); + m_ptrCommandLineParser->Parse(m_desc.m_argc, m_desc.m_argv); + // If we don't have one create a serialize context if (GetSerializeContext() == nullptr) { From 0e6fea21fcae344f15955e689a59001b27c00540 Mon Sep 17 00:00:00 2001 From: guthadam <guthadam@amazon.com> Date: Wed, 21 Apr 2021 10:30:27 -0500 Subject: [PATCH 69/96] ATOM-15221 Material Editor: Capturing trace warnings and errors to display in error message boxes https://jira.agscollab.com/browse/ATOM-15221 --- .../AtomToolsFramework/Debug/TraceRecorder.h | 41 ++++++++++ .../Code/Source/Debug/TraceRecorder.cpp | 66 ++++++++++++++++ .../Code/atomtoolsframework_files.cmake | 2 + .../MaterialDocumentSystemComponent.cpp | 79 +++++++++++++------ 4 files changed, 163 insertions(+), 25 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h new file mode 100644 index 0000000000..acc9d804bf --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -0,0 +1,41 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#pragma once + +#include <AzCore/Debug/TraceMessageBus.h> +#include <AzCore/std/string/string.h> + +namespace AtomToolsFramework +{ + // Records all TraceMessageBus activity to a string + class TraceRecorder + : private AZ::Debug::TraceMessageBus::Handler + { + public: + AZ_TYPE_INFO(AtomToolsFramework::TraceRecorder, "{7B49AFD0-D0AB-4CB7-A4B5-6D88D30DCBFD}"); + + TraceRecorder(); + ~TraceRecorder(); + + ////////////////////////////////////////////////////////////////////////// + // AZ::Debug::TraceMessageBus::Handler overrides... + bool OnAssert(const char* /*message*/) override; + bool OnException(const char* /*message*/) override; + bool OnError(const char* /*window*/, const char* /*message*/) override; + bool OnWarning(const char* /*window*/, const char* /*message*/) override; + bool OnPrintf(const char* /*window*/, const char* /*message*/) override; + ////////////////////////////////////////////////////////////////////////// + + AZStd::string m_messageSink; + }; +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp new file mode 100644 index 0000000000..3b22c16dcc --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp @@ -0,0 +1,66 @@ +/* + * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or + * its licensors. + * + * For complete copyright and license terms please see the LICENSE at the root of this + * distribution (the "License"). All use of this software is governed by the License, + * or, if provided, by the license below or the license accompanying this file. Do not + * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + */ + +#include <AtomToolsFramework/Debug/TraceRecorder.h> + +namespace AtomToolsFramework +{ + TraceRecorder::TraceRecorder() + { + AZ::Debug::TraceMessageBus::Handler::BusConnect(); + } + + TraceRecorder::~TraceRecorder() + { + AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); + } + + bool TraceRecorder::OnAssert(const char* message) + { + m_messageSink += "Assert: "; + m_messageSink += message; + m_messageSink += "\n"; + return false; + } + + bool TraceRecorder::OnException(const char* message) + { + m_messageSink += "Exception: "; + m_messageSink += message; + m_messageSink += "\n"; + return false; + } + + bool TraceRecorder::OnError(const char* /*window*/, const char* message) + { + m_messageSink += "Error: "; + m_messageSink += message; + m_messageSink += "\n"; + return false; + } + + bool TraceRecorder::OnWarning(const char* /*window*/, const char* message) + { + m_messageSink += "Warning: "; + m_messageSink += message; + m_messageSink += "\n"; + return false; + } + + bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message) + { + m_messageSink += message; + m_messageSink += "\n"; + return false; + } + +} // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake index 8c0ca71b78..e8539711f7 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/atomtoolsframework_files.cmake @@ -10,6 +10,7 @@ # set(FILES + Include/AtomToolsFramework/Debug/TraceRecorder.h Include/AtomToolsFramework/DynamicProperty/DynamicProperty.h Include/AtomToolsFramework/DynamicProperty/DynamicPropertyGroup.h Include/AtomToolsFramework/Inspector/InspectorWidget.h @@ -21,6 +22,7 @@ set(FILES Include/AtomToolsFramework/Util/MaterialPropertyUtil.h Include/AtomToolsFramework/Util/Util.h Include/AtomToolsFramework/Viewport/RenderViewportWidget.h + Source/Debug/TraceRecorder.cpp Source/DynamicProperty/DynamicProperty.cpp Source/DynamicProperty/DynamicPropertyGroup.cpp Source/Inspector/InspectorWidget.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 234afc6e27..7faeca3f27 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -12,32 +12,29 @@ #include <Document/MaterialDocumentSystemComponent.h> -#include <AzCore/Serialization/SerializeContext.h> -#include <AzCore/Serialization/EditContext.h> +#include <Atom/Document/MaterialDocumentNotificationBus.h> +#include <Atom/Document/MaterialDocumentRequestBus.h> +#include <Atom/Document/MaterialDocumentSystemRequestBus.h> +#include <Atom/RPI.Edit/Material/MaterialSourceData.h> +#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> +#include <AtomToolsFramework/Debug/TraceRecorder.h> +#include <AtomToolsFramework/Util/Util.h> #include <AzCore/RTTI/BehaviorContext.h> - +#include <AzCore/Serialization/EditContext.h> +#include <AzCore/Serialization/SerializeContext.h> #include <AzFramework/Asset/AssetSystemBus.h> - +#include <AzToolsFramework/API/EditorAssetSystemAPI.h> +#include <AzToolsFramework/API/ViewPaneOptions.h> +#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> #include <AzToolsFramework/AssetBrowser/AssetBrowserEntry.h> #include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h> -#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h> -#include <AzToolsFramework/API/ViewPaneOptions.h> -#include <AzToolsFramework/API/EditorAssetSystemAPI.h> -#include <AtomToolsFramework/Util/Util.h> - -#include <Atom/RPI.Edit/Material/MaterialSourceData.h> -#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h> - -#include <Atom/Document/MaterialDocumentSystemRequestBus.h> -#include <Atom/Document/MaterialDocumentRequestBus.h> -#include <Atom/Document/MaterialDocumentNotificationBus.h> AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include <QApplication> +#include <QFileDialog> +#include <QMessageBox> #include <QString> #include <QStyle> -#include <QMessageBox> -#include <QFileDialog> AZ_POP_DISABLE_WARNING namespace MaterialEditor @@ -212,11 +209,15 @@ namespace MaterialEditor QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + AtomToolsFramework::TraceRecorder traceRecorder; + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -232,11 +233,15 @@ namespace MaterialEditor QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + AtomToolsFramework::TraceRecorder traceRecorder; + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -308,11 +313,15 @@ namespace MaterialEditor } } + AtomToolsFramework::TraceRecorder traceRecorder; + bool closeResult = true; MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close); if (!closeResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be closed:\n%1").arg(documentPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be closed"), + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); return false; } @@ -370,11 +379,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder; + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); return false; } @@ -396,11 +409,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder; + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); return false; } @@ -422,11 +439,15 @@ namespace MaterialEditor return false; } + AtomToolsFramework::TraceRecorder traceRecorder; + bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath); if (!result) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be saved:\n%1").arg(saveMaterialPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be saved"), + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); return false; } @@ -476,19 +497,27 @@ namespace MaterialEditor } } + AtomToolsFramework::TraceRecorder traceRecorder; + AZ::Uuid documentId = AZ::Uuid::CreateNull(); MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument); if (documentId.IsNull()) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be created:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be created"), + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); return AZ::Uuid::CreateNull(); } + traceRecorder.m_messageSink.clear(); + bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath); if (!openResult) { - QMessageBox::critical(QApplication::activeWindow(), "Error", QString("Material document could not be opened:\n%1").arg(requestedPath.c_str())); + QMessageBox::critical( + QApplication::activeWindow(), QString("Material document could not be opened"), + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } From 215931a1ae726813ce4e0a8306db60bd581385bf Mon Sep 17 00:00:00 2001 From: guthadam <guthadam@amazon.com> Date: Wed, 21 Apr 2021 15:57:44 -0500 Subject: [PATCH 70/96] Updating trace recorder to allow limiting the number of messages stored --- .../AtomToolsFramework/Debug/TraceRecorder.h | 13 ++++-- .../Code/Source/Debug/TraceRecorder.cpp | 45 ++++++++++++------- .../MaterialDocumentSystemComponent.cpp | 32 ++++++------- .../MaterialDocumentSystemComponent.h | 1 + 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h index acc9d804bf..a4dba9229e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Debug/TraceRecorder.h @@ -13,20 +13,24 @@ #pragma once #include <AzCore/Debug/TraceMessageBus.h> +#include <AzCore/std/containers/list.h> #include <AzCore/std/string/string.h> namespace AtomToolsFramework { // Records all TraceMessageBus activity to a string - class TraceRecorder - : private AZ::Debug::TraceMessageBus::Handler + class TraceRecorder : private AZ::Debug::TraceMessageBus::Handler { public: AZ_TYPE_INFO(AtomToolsFramework::TraceRecorder, "{7B49AFD0-D0AB-4CB7-A4B5-6D88D30DCBFD}"); - TraceRecorder(); + TraceRecorder(size_t maxMessageCount = std::numeric_limits<size_t>::max()); ~TraceRecorder(); + //! Get the combined output of all messages + AZStd::string GetDump() const; + + private: ////////////////////////////////////////////////////////////////////////// // AZ::Debug::TraceMessageBus::Handler overrides... bool OnAssert(const char* /*message*/) override; @@ -36,6 +40,7 @@ namespace AtomToolsFramework bool OnPrintf(const char* /*window*/, const char* /*message*/) override; ////////////////////////////////////////////////////////////////////////// - AZStd::string m_messageSink; + size_t m_maxMessageCount = std::numeric_limits<size_t>::max(); + AZStd::list<AZStd::string> m_messages; }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp index 3b22c16dcc..e08dd3e48a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Debug/TraceRecorder.cpp @@ -11,10 +11,12 @@ */ #include <AtomToolsFramework/Debug/TraceRecorder.h> +#include <AzCore/StringFunc/StringFunc.h> namespace AtomToolsFramework { - TraceRecorder::TraceRecorder() + TraceRecorder::TraceRecorder(size_t maxMessageCount) + : m_maxMessageCount(maxMessageCount) { AZ::Debug::TraceMessageBus::Handler::BusConnect(); } @@ -24,42 +26,55 @@ namespace AtomToolsFramework AZ::Debug::TraceMessageBus::Handler::BusDisconnect(); } + AZStd::string TraceRecorder::GetDump() const + { + AZStd::string dump; + AZ::StringFunc::Join(dump, m_messages.begin(), m_messages.end(), "\n"); + return dump; + } + bool TraceRecorder::OnAssert(const char* message) { - m_messageSink += "Assert: "; - m_messageSink += message; - m_messageSink += "\n"; + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Assert: %s", message)); + } return false; } bool TraceRecorder::OnException(const char* message) { - m_messageSink += "Exception: "; - m_messageSink += message; - m_messageSink += "\n"; + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Exception: %s", message)); + } return false; } bool TraceRecorder::OnError(const char* /*window*/, const char* message) { - m_messageSink += "Error: "; - m_messageSink += message; - m_messageSink += "\n"; + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Error: %s", message)); + } return false; } bool TraceRecorder::OnWarning(const char* /*window*/, const char* message) { - m_messageSink += "Warning: "; - m_messageSink += message; - m_messageSink += "\n"; + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("Warning: %s", message)); + } return false; } bool TraceRecorder::OnPrintf(const char* /*window*/, const char* message) { - m_messageSink += message; - m_messageSink += "\n"; + if (m_messages.size() < m_maxMessageCount) + { + m_messages.push_back(AZStd::string::format("%s", message)); + } return false; } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp index 7faeca3f27..2fd1aac211 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.cpp @@ -209,7 +209,7 @@ namespace MaterialEditor QString("Would you like to reopen the document:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, documentPath); @@ -217,7 +217,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -233,7 +233,7 @@ namespace MaterialEditor QString("Would you like to update the document with these changes:\n%1?").arg(documentPath.c_str()), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Rebuild); @@ -241,7 +241,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to open: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::CloseDocument, documentId); } } @@ -313,7 +313,7 @@ namespace MaterialEditor } } - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool closeResult = true; MaterialDocumentRequestBus::EventResult(closeResult, documentId, &MaterialDocumentRequestBus::Events::Close); @@ -321,7 +321,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be closed"), - QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to close: \n%1\n\n%2").arg(documentPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -379,7 +379,7 @@ namespace MaterialEditor return false; } - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::Save); @@ -387,7 +387,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -409,7 +409,7 @@ namespace MaterialEditor return false; } - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsCopy, saveMaterialPath); @@ -417,7 +417,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -439,7 +439,7 @@ namespace MaterialEditor return false; } - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); bool result = false; MaterialDocumentRequestBus::EventResult(result, documentId, &MaterialDocumentRequestBus::Events::SaveAsChild, saveMaterialPath); @@ -447,7 +447,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be saved"), - QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to save: \n%1\n\n%2").arg(saveMaterialPath.c_str()).arg(traceRecorder.GetDump().c_str())); return false; } @@ -497,7 +497,7 @@ namespace MaterialEditor } } - AtomToolsFramework::TraceRecorder traceRecorder; + AtomToolsFramework::TraceRecorder traceRecorder(m_maxMessageBoxLineCount); AZ::Uuid documentId = AZ::Uuid::CreateNull(); MaterialDocumentSystemRequestBus::BroadcastResult(documentId, &MaterialDocumentSystemRequestBus::Events::CreateDocument); @@ -505,11 +505,11 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be created"), - QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to create: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); return AZ::Uuid::CreateNull(); } - traceRecorder.m_messageSink.clear(); + traceRecorder.GetDump().clear(); bool openResult = false; MaterialDocumentRequestBus::EventResult(openResult, documentId, &MaterialDocumentRequestBus::Events::Open, requestedPath); @@ -517,7 +517,7 @@ namespace MaterialEditor { QMessageBox::critical( QApplication::activeWindow(), QString("Material document could not be opened"), - QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.m_messageSink.c_str())); + QString("Failed to open: \n%1\n\n%2").arg(requestedPath.c_str()).arg(traceRecorder.GetDump().c_str())); MaterialDocumentSystemRequestBus::Broadcast(&MaterialDocumentSystemRequestBus::Events::DestroyDocument, documentId); return AZ::Uuid::CreateNull(); } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h index 933a3351ba..b6c541421d 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Document/MaterialDocumentSystemComponent.h @@ -98,5 +98,6 @@ namespace MaterialEditor AZStd::unordered_set<AZ::Uuid> m_documentIdsToRebuild; AZStd::unordered_set<AZ::Uuid> m_documentIdsToReopen; AZStd::unique_ptr<MaterialEditorSettings> m_settings; + const size_t m_maxMessageBoxLineCount = 15; }; } From f36bfd9db5ae5d9ef474a49b527aaf7c35762191 Mon Sep 17 00:00:00 2001 From: phistere <phistere@amazon.com> Date: Wed, 21 Apr 2021 19:53:07 -0500 Subject: [PATCH 71/96] LYN-2524: Adding more files to CMake install to help AP run from SDK. Fixes an issue configuring an external project. --- cmake/PAL.cmake | 10 +++--- cmake/Platform/Common/Install_common.cmake | 40 +++++++++++++++++++++- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/cmake/PAL.cmake b/cmake/PAL.cmake index 5131005c72..c7adb660f0 100644 --- a/cmake/PAL.cmake +++ b/cmake/PAL.cmake @@ -63,10 +63,12 @@ function(ly_get_absolute_pal_filename out_name in_name) set(full_name ${in_name}) if (NOT EXISTS ${full_name}) string(REGEX MATCH "${repo_dir}/(.*)/Platform/([^/]*)/?(.*)$" match ${full_name}) - if(${CMAKE_MATCH_2} IN_LIST PAL_RESTRICTED_PLATFORMS) - set(full_name ${repo_dir}/restricted/${CMAKE_MATCH_2}/${CMAKE_MATCH_1}) - if(NOT "${CMAKE_MATCH_3}" STREQUAL "") - string(APPEND full_name "/" ${CMAKE_MATCH_3}) + if(PAL_RESTRICTED_PLATFORMS) + if("${CMAKE_MATCH_2}" IN_LIST PAL_RESTRICTED_PLATFORMS) + set(full_name ${repo_dir}/restricted/${CMAKE_MATCH_2}/${CMAKE_MATCH_1}) + if(NOT "${CMAKE_MATCH_3}" STREQUAL "") + string(APPEND full_name "/" ${CMAKE_MATCH_3}) + endif() endif() endif() endif() diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 286f449acd..023b7369a7 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -184,7 +184,7 @@ function(ly_setup_cmake_install) install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" DESTINATION . - REGEX "Findo3de.cmake" EXCLUDE + REGEX "Findo3de.cmake" EXCLUDE REGEX "Platform\/.*\/BuiltInPackages_.*\.cmake" EXCLUDE ) install( @@ -265,6 +265,44 @@ function(ly_setup_others) REGEX "runtime" EXCLUDE ) + # Registry + install(DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/bin/$<CONFIG>/Registry + DESTINATION ./bin/$<CONFIG> + ) + install(DIRECTORY + # This one will change soon, Engine/Registry files will be relocated to Registry + ${CMAKE_SOURCE_DIR}/Engine/Registry + DESTINATION ./Engine + ) + install(FILES + ${CMAKE_SOURCE_DIR}/AssetProcessorPlatformConfig.setreg + DESTINATION ./Registry + ) + + # Qt Binaries + set(QT_BIN_DIRS bearer iconengines imageformats platforms styles translations) + foreach(qt_dir ${QT_BIN_DIRS}) + install(DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/bin/$<CONFIG>/${qt_dir} + DESTINATION ./bin/$<CONFIG> + ) + endforeach() + + # Templates + install(DIRECTORY + ${CMAKE_SOURCE_DIR}/Templates + DESTINATION . + ) + + # Misc + install(FILES + ${CMAKE_SOURCE_DIR}/ctest_pytest.ini + ${CMAKE_SOURCE_DIR}/LICENSE.txt + ${CMAKE_SOURCE_DIR}/README.md + DESTINATION . + ) + endfunction() From 134f07eb5a4de3c43ab3060e5c6c17b9d698e04b Mon Sep 17 00:00:00 2001 From: chcurran <82187351+carlitosan@users.noreply.github.com> Date: Wed, 21 Apr 2021 21:36:31 -0700 Subject: [PATCH 72/96] Fixes for node palette exclusion, restrict asset variable type to fix LYN-3090 --- .../Widgets/NodePalette/NodePaletteModel.cpp | 60 +++----- .../VariablePaletteTableView.cpp | 4 +- .../ScriptCanvas/Core/SlotConfigurations.cpp | 6 +- .../Code/Include/ScriptCanvas/Data/Data.cpp | 23 --- .../Code/Include/ScriptCanvas/Data/Data.h | 2 - .../ScriptCanvas/Data/DataRegistry.cpp | 29 +++- .../Include/ScriptCanvas/Data/DataRegistry.h | 12 +- .../Include/ScriptCanvas/SystemComponent.h | 3 + .../Code/Source/SystemComponent.cpp | 134 ++++++++++-------- 9 files changed, 140 insertions(+), 133 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp index 4154c3982e..2edc950e6f 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp @@ -57,7 +57,7 @@ namespace { if (excludeAttributeData) { - AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly | AZ::ScriptCanvasAttributes::VariableCreationForbidden; + AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly; if (typeId == AzToolsFramework::Components::EditorComponentBase::TYPEINFO_Uuid()) { @@ -143,11 +143,6 @@ namespace { return; } - - if (!ScriptCanvas::Data::IsAllowedBehaviorClassVariableType(behaviorClass->m_typeId)) - { - return; - } } const auto isExposableOutcome = ScriptCanvas::IsExposable(method); @@ -479,38 +474,24 @@ namespace continue; } - // Only bind Behavior Classes marked with the Scope type of Launcher + if (auto excludeFromPointer = AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes)) + { + AZ::Script::Attributes::ExcludeFlags excludeFlags{}; + AZ::AttributeReader(nullptr, excludeFromPointer).Read<AZ::Script::Attributes::ExcludeFlags>(excludeFlags); + + if ((excludeFlags & (AZ::Script::Attributes::ExcludeFlags::List | AZ::Script::Attributes::ExcludeFlags::ListOnly)) != 0) + { + continue; + } + } + if (!AZ::Internal::IsInScope(behaviorClass->m_attributes, AZ::Script::Attributes::ScopeFlags::Launcher)) { - continue; // skip this class + continue; } // Objects and Object methods { - bool canCreate = serializeContext->FindClassData(behaviorClass->m_typeId) != nullptr && - !HasAttribute(behaviorClass, AZ::ScriptCanvasAttributes::VariableCreationForbidden); - - // In order to create variables, the class must have full memory support - canCreate = canCreate && - (behaviorClass->m_allocate - && behaviorClass->m_cloner - && behaviorClass->m_mover - && behaviorClass->m_destructor - && behaviorClass->m_deallocate); - - if (canCreate) - { - // Do not allow variable creation for data that derives from AZ::Component - for (auto base : behaviorClass->m_baseClasses) - { - if (AZ::Component::TYPEINFO_Uuid() == base) - { - canCreate = false; - break; - } - } - } - AZStd::string categoryPath; AZStd::string translationContext = ScriptCanvasEditor::TranslationHelper::GetContextName(ScriptCanvasEditor::TranslationContextGroup::ClassMethod, behaviorClass->m_name); @@ -530,17 +511,14 @@ namespace } } - if (canCreate) - { - auto dataRegistry = ScriptCanvas::GetDataRegistry(); - ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(behaviorClass->m_typeId); + auto dataRegistry = ScriptCanvas::GetDataRegistry(); + ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(behaviorClass->m_typeId); - if (type.IsValid()) + if (type.IsValid()) + { + if (dataRegistry->m_creatableTypes.contains(type)) { - if (!AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes)) - { - ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type); - } + ScriptCanvasEditor::VariablePaletteRequestBus::Broadcast(&ScriptCanvasEditor::VariablePaletteRequests::RegisterVariableType, type); } } diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariablePaletteTableView.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariablePaletteTableView.cpp index a05468d565..9bec796f53 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariablePaletteTableView.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/VariablePanel/VariablePaletteTableView.cpp @@ -122,8 +122,8 @@ namespace ScriptCanvasEditor for (const AZ::Uuid& objectId : objectTypes) { - // Verify whether this is an allowed BC variable type - if (!ScriptCanvas::Data::IsAllowedBehaviorClassVariableType(objectId)) + ScriptCanvas::Data::Type type = dataRegistry->m_typeIdTraitMap[ScriptCanvas::Data::eType::BehaviorContextObject].m_dataTraits.GetSCType(objectId); + if (!type.IsValid() || !dataRegistry->m_creatableTypes.contains(type)) { continue; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotConfigurations.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotConfigurations.cpp index bc6445e6e3..17dd68c084 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotConfigurations.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Core/SlotConfigurations.cpp @@ -105,11 +105,9 @@ namespace ScriptCanvas void DataSlotConfiguration::SetType(const AZ::BehaviorParameter& typeDesc) { - auto dataRegistry = GetDataRegistry(); Data::Type scType = !AZ::BehaviorContextHelper::IsStringParameter(typeDesc) ? Data::FromAZType(typeDesc.m_typeId) : Data::Type::String(); - auto typeIter = dataRegistry->m_creatableTypes.find(scType); - - if (typeIter != dataRegistry->m_creatableTypes.end()) + auto dataRegistry = GetDataRegistry(); + if (dataRegistry->IsUseableInSlot(scType)) { m_datum.SetType(scType); } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.cpp index e71c97e89a..2653b1495f 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.cpp @@ -389,29 +389,6 @@ namespace ScriptCanvas return AZ::Utils::IsVectorContainerType(ToAZType(type)); } - bool IsAllowedBehaviorClassVariableType(const AZ::Uuid& id) - { - AZ::BehaviorContext* behaviorContext = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext); - AZ_Assert(behaviorContext, "Unable to retrieve behavior context."); - - const auto& classIterator = behaviorContext->m_typeToClassMap.find(id); - if (classIterator != behaviorContext->m_typeToClassMap.end()) - { - AZ::BehaviorClass* behaviorClass = classIterator->second; - if (behaviorClass->FindAttribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden)) - { - return false; - } - } - else - { - return false; - } - - return true; - } - bool IsSetContainerType(const AZ::Uuid& type) { return AZ::Utils::IsSetContainerType(type); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.h index 64dc8999f7..59530d934d 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/Data.h @@ -197,8 +197,6 @@ namespace ScriptCanvas bool IsVectorContainerType(const AZ::Uuid& type); bool IsVectorContainerType(const Type& type); - bool IsAllowedBehaviorClassVariableType(const AZ::Uuid& id); - AZStd::vector<AZ::Uuid> GetContainedTypes(const AZ::Uuid& type); AZStd::vector<Type> GetContainedTypes(const Type& type); AZStd::pair<AZ::Uuid, AZ::Uuid> GetOutcomeTypes(const AZ::Uuid& type); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.cpp index 85cdf56458..9068ba0172 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.cpp @@ -105,14 +105,24 @@ namespace ScriptCanvas AZ_Error("Script Canvas", it.second, "Cannot register a second Trait struct with the same ScriptCanvas type(%u)", it.first->first); } - void DataRegistry::RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties) + void DataRegistry::RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties, Createability registration) { Data::Type behaviorContextType = Data::FromAZType(typeId); if (behaviorContextType.GetType() == Data::eType::BehaviorContextObject && !behaviorContextType.GetAZType().IsNull()) { - if (m_creatableTypes.find(behaviorContextType) == m_creatableTypes.end()) + if (registration == Createability::SlotAndVariable) { - m_creatableTypes[behaviorContextType] = typeProperties; + if (m_creatableTypes.find(behaviorContextType) == m_creatableTypes.end()) + { + m_creatableTypes[behaviorContextType] = typeProperties; + } + } + else if (registration == Createability::SlotOnly) + { + if (m_slottableTypes.find(behaviorContextType) == m_slottableTypes.end()) + { + m_slottableTypes[behaviorContextType] = typeProperties; + } } } } @@ -125,4 +135,15 @@ namespace ScriptCanvas m_creatableTypes.erase(behaviorContextType); } } -} \ No newline at end of file + + bool DataRegistry::IsUseableInSlot(const Data::Type& scType) const + { + return m_creatableTypes.contains(scType) || m_slottableTypes.contains(scType); + } + + bool DataRegistry::IsUseableInSlot(const AZ::TypeId& typeId) const + { + Data::Type scType = Data::FromAZType(typeId); + return IsUseableInSlot(scType); + } +} diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.h index 57a67c79d9..c4837ebd27 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Data/DataRegistry.h @@ -34,11 +34,21 @@ namespace ScriptCanvas AZ_TYPE_INFO(DataRegistry, "{41049FA8-EA56-401F-9720-6FE9028A1C01}"); AZ_CLASS_ALLOCATOR(DataRegistry, AZ::SystemAllocator, 0); - void RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties); + enum class Createability + { + None, + SlotAndVariable, + SlotOnly, + }; + void RegisterType(const AZ::TypeId& typeId, TypeProperties typeProperties, Createability registration); void UnregisterType(const AZ::TypeId& typeId); + bool IsUseableInSlot(const AZ::TypeId& typeId) const; + bool IsUseableInSlot(const Data::Type& type) const; + AZStd::unordered_map<Data::eType, Data::TypeErasedTraits> m_typeIdTraitMap; // Creates a mapping of the Data::eType TypeId to the trait structure AZStd::unordered_map<Data::Type, TypeProperties> m_creatableTypes; + AZStd::unordered_map<Data::Type, TypeProperties> m_slottableTypes; }; void InitDataRegistry(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h index 3d5acfbee1..3c00562505 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/SystemComponent.h @@ -22,6 +22,7 @@ #include <ScriptCanvas/Core/ScriptCanvasBus.h> #include <ScriptCanvas/Variable/VariableCore.h> #include <ScriptCanvas/PerformanceTracker.h> +#include <ScriptCanvas/Data/DataRegistry.h> namespace AZ { @@ -65,6 +66,8 @@ namespace ScriptCanvas inline bool IsAnyScriptInterpreted() const { return true; } + AZStd::pair<DataRegistry::Createability, TypeProperties> GetCreatibility(AZ::SerializeContext* serializeContext, AZ::BehaviorClass* behaviorClass); + // SystemRequestBus::Handler... bool IsScriptUnitTestingInProgress() override; void MarkScriptUnitTestBegin() override; diff --git a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp index bbcbde5c6c..dd0c340357 100644 --- a/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp +++ b/Gems/ScriptCanvas/Code/Source/SystemComponent.cpp @@ -23,7 +23,6 @@ #include <ScriptCanvas/Core/Node.h> #include <ScriptCanvas/Core/Nodeable.h> #include <ScriptCanvas/Core/Slot.h> -#include <ScriptCanvas/Data/DataRegistry.h> #include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h> #include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h> #include <ScriptCanvas/Execution/RuntimeComponent.h> @@ -285,6 +284,72 @@ namespace ScriptCanvas m_ownedObjectsByAddress.erase(object); } + AZStd::pair<DataRegistry::Createability, TypeProperties> SystemComponent::GetCreatibility(AZ::SerializeContext* serializeContext, AZ::BehaviorClass* behaviorClass) + { + TypeProperties typeProperties; + + bool canCreate{}; + // BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable + const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List; + auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes)); + + const AZ::u64 flags = excludeClassAttributeData ? excludeClassAttributeData->Get(nullptr) : 0; + bool listOnly = ((flags & AZ::Script::Attributes::ExcludeFlags::ListOnly) == AZ::Script::Attributes::ExcludeFlags::ListOnly); // ListOnly exclusions may create variables + canCreate = listOnly || (!excludeClassAttributeData || (!(flags & exclusionFlags))); + canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId)); + canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes); + + if (canCreate) + { + for (auto base : behaviorClass->m_baseClasses) + { + if (AZ::Component::TYPEINFO_Uuid() == base) + { + canCreate = false; + break; // only out of the for : base classes loop. DO NOT break out of the parent loop. + } + } + } + + // Assets are not safe enough for variable creation, yet. They can be created with one Az type (Data::Asset<T>), but set to nothing. + // When read back in, they will (if lucky) just be Data::Asset<Data>, which breaks type safety at best, and requires a lot of sanity checking. + // This is NOT blacked at the createable types or BehaviorContext level, since they could be used to at least pass information through, + // and may be used other scripting contexts. + AZ::IRttiHelper* rttiHelper = behaviorClass->m_azRtti; + if (rttiHelper && rttiHelper->GetGenericTypeId() == azrtti_typeid<AZ::Data::Asset>()) + { + canCreate = false; + } + + if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes)) + { + canCreate = true; + typeProperties.m_isTransient = true; + } + + // create able variables must have full memory support + canCreate = canCreate && + (behaviorClass->m_allocate + && behaviorClass->m_cloner + && behaviorClass->m_mover + && behaviorClass->m_destructor + && behaviorClass->m_deallocate) && + AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; }); + + if (!canCreate) + { + return { DataRegistry::Createability::None , TypeProperties{} }; + } + else if (!AZ::FindAttribute(AZ::ScriptCanvasAttributes::VariableCreationForbidden, behaviorClass->m_attributes)) + { + return { DataRegistry::Createability::SlotAndVariable, typeProperties }; + } + else + { + return { DataRegistry::Createability::SlotOnly, typeProperties }; + } + } + void SystemComponent::RegisterCreatableTypes() { AZ::SerializeContext* serializeContext{}; @@ -297,40 +362,11 @@ namespace ScriptCanvas auto dataRegistry = ScriptCanvas::GetDataRegistry(); for (const auto& classIter : behaviorContext->m_classes) { - TypeProperties typeProperties; - - bool canCreate{}; - const AZ::BehaviorClass* behaviorClass = classIter.second; - // BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable - const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List; - auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes)); - - const AZ::u64 flags = excludeClassAttributeData ? excludeClassAttributeData->Get(nullptr) : 0; - bool listOnly = ((flags & AZ::Script::Attributes::ExcludeFlags::ListOnly) == AZ::Script::Attributes::ExcludeFlags::ListOnly); // ListOnly exclusions may create variables - - canCreate = listOnly || (!excludeClassAttributeData || (!(flags & exclusionFlags))); - canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId)); - canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes); - - if (AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes)) - { - canCreate = true; - typeProperties.m_isTransient = true; - } - - // create able variables must have full memory support - canCreate = canCreate && - ( behaviorClass->m_allocate - && behaviorClass->m_cloner - && behaviorClass->m_mover - && behaviorClass->m_destructor - && behaviorClass->m_deallocate) && - AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; }); - - if (canCreate) - { - dataRegistry->RegisterType(behaviorClass->m_typeId, typeProperties); - } + auto createability = GetCreatibility(serializeContext, classIter.second); + if (createability.first != DataRegistry::Createability::None) + { + dataRegistry->RegisterType(classIter.second->m_typeId, createability.second, createability.first); + } } } @@ -339,33 +375,19 @@ namespace ScriptCanvas auto dataRegistry = ScriptCanvas::GetDataRegistry(); if (!dataRegistry) { + AZ_Warning("ScriptCanvas", false, "Data registry not available. Can't register new class."); + return; } + AZ::SerializeContext* serializeContext{}; AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext); - AZ_Assert(serializeContext, "Serialize Context should not be missing at this point"); + AZ_Assert(serializeContext, "Serialize Context missing. Can't register new class."); - TypeProperties typeProperties; - - // BehaviorContext classes with the ExcludeFrom attribute with a value of the ExcludeFlags::List is not creatable - const AZ::u64 exclusionFlags = AZ::Script::Attributes::ExcludeFlags::List; - auto excludeClassAttributeData = azrtti_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, behaviorClass->m_attributes)); - bool canCreate = !excludeClassAttributeData || !(excludeClassAttributeData->Get(nullptr) & exclusionFlags); - canCreate = canCreate && (serializeContext->FindClassData(behaviorClass->m_typeId) || AZ::FindAttribute(AZ::ScriptCanvasAttributes::AllowInternalCreation, behaviorClass->m_attributes)); - canCreate = canCreate && !ScriptCanvasSystemComponentCpp::IsDeprecated(behaviorClass->m_attributes); - - // create able variables must have full memory support - canCreate = canCreate && - (behaviorClass->m_allocate - && behaviorClass->m_cloner - && behaviorClass->m_mover - && behaviorClass->m_destructor - && behaviorClass->m_deallocate) && - AZStd::none_of(behaviorClass->m_baseClasses.begin(), behaviorClass->m_baseClasses.end(), [](const AZ::TypeId& base) { return azrtti_typeid<AZ::Component>() == base; }); - - if (canCreate) + auto createability = GetCreatibility(serializeContext, behaviorClass); + if (createability.first != DataRegistry::Createability::None) { - dataRegistry->RegisterType(behaviorClass->m_typeId, typeProperties); + dataRegistry->RegisterType(behaviorClass->m_typeId, createability.second, createability.first); } } From 2fc1901d8fb7533d47ef1992f9b203718081e4c4 Mon Sep 17 00:00:00 2001 From: spham <spham@amazon.com> Date: Wed, 21 Apr 2021 19:57:41 -0700 Subject: [PATCH 73/96] Update AWSNativeSDK on Linux to rev4 to fix dependency issue with aws-cpp-sdk-event-stream --- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index bd6f8276f7..49628ef456 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -35,7 +35,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARG ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93) ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76) -ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-linux TARGETS AWSNativeSDK PACKAGE_HASH e69c55682638dc1e7fa571a61a82c8a69d395c74a008543a5188f4bd2b6b10c4) +ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-linux TARGETS AWSNativeSDK PACKAGE_HASH b4db38de49d35a5f7500aed7f4aee5ec511dd3b584ee06fe9097885690191a5d) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.0.25992954-rev1-linux TARGETS PhysX PACKAGE_HASH e3ca36106a8dbf1524709f8bb82d520920ebd3ff3a92672d382efff406c75ee3) ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) From c66e2f4bcfcbb274fd8a4bd7482ec0fe15415958 Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Wed, 21 Apr 2021 23:30:11 -0700 Subject: [PATCH 74/96] Initial phase of UI Canvas Editor rendering with Atom (#164) * Move Draw2d.h to Include folder * Initial phase of UI Canvas Editor rendering with Atom * Simplify Draw2d by removing BeginDraw2d/EndDraw2d which is no longer needed * Fix compile errors for non-unity builds --- Code/CryEngine/CryCommon/LyShine/IDraw2d.h | 353 +----------- .../CryEngine/CryCommon/LyShine/IUiRenderer.h | 79 --- .../CryCommon/LyShine/UiSerializeHelpers.h | 1 + .../Code/Editor/ViewportDragInteraction.h | 2 +- Gems/LyShine/Code/Editor/ViewportHelpers.h | 2 + Gems/LyShine/Code/Editor/ViewportIcon.cpp | 37 +- Gems/LyShine/Code/Editor/ViewportIcon.h | 5 +- Gems/LyShine/Code/Editor/ViewportWidget.cpp | 7 +- Gems/LyShine/Code/Editor/ViewportWidget.h | 2 + Gems/LyShine/Code/Include/LyShine/Draw2d.h | 517 ++++++++++++++++++ Gems/LyShine/Code/Source/Draw2d.cpp | 314 +++++++---- Gems/LyShine/Code/Source/Draw2d.h | 189 ------- Gems/LyShine/Code/Source/LyShine.cpp | 7 +- Gems/LyShine/Code/Source/LyShineDebug.cpp | 187 +++---- .../LyShine/Code/Source/UiCanvasComponent.cpp | 5 +- Gems/LyShine/Code/Source/UiCanvasComponent.h | 5 +- Gems/LyShine/Code/Source/UiCanvasManager.cpp | 26 +- Gems/LyShine/Code/Source/UiFaderComponent.cpp | 1 + Gems/LyShine/Code/Source/UiImageComponent.cpp | 2 +- .../Code/Source/UiImageSequenceComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiMaskComponent.cpp | 2 +- Gems/LyShine/Code/Source/UiTextComponent.cpp | 2 +- Gems/LyShine/Code/lyshine_static_files.cmake | 2 +- Gems/LyShineExamples/Code/CMakeLists.txt | 1 + .../Code/Source/UiCustomImageComponent.cpp | 2 +- 25 files changed, 880 insertions(+), 872 deletions(-) delete mode 100644 Code/CryEngine/CryCommon/LyShine/IUiRenderer.h create mode 100644 Gems/LyShine/Code/Include/LyShine/Draw2d.h delete mode 100644 Gems/LyShine/Code/Source/Draw2d.h diff --git a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h index e71c8421d3..16fdfceca3 100644 --- a/Code/CryEngine/CryCommon/LyShine/IDraw2d.h +++ b/Code/CryEngine/CryCommon/LyShine/IDraw2d.h @@ -11,7 +11,7 @@ */ #pragma once -#include <LyShine/ILyShine.h> +#include <IRenderer.h> #include <AzCore/Math/Vector2.h> #include <AzCore/Math/Vector3.h> #include <AzCore/Math/Color.h> @@ -115,355 +115,4 @@ public: // member functions //! Implement virtual destructor just for safety. virtual ~IDraw2d() {} - - //! Start a section of 2D drawing function calls. This will set appropriate render state. - // - //! \param deferCalls If true then actual render calls are deferred until the end of the frame - virtual void BeginDraw2d(bool deferCalls = false) = 0; - - //! Start a section of 2D drawing function calls. This will set appropriate render state. - //! This variant allows the viewport size to be specified - // - //! \param viewportSize The size of the viewport being rendered to - //! \param deferCalls If true then actual render calls are deferred until the end of the frame - virtual void BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls = false) = 0; - - //! End a section of 2D drawing function calls. This will reset some render state. - virtual void EndDraw2d() = 0; - - //! Draw a textured quad with the top left corner at the given position. - // - //! The image is drawn with the color specified by SetShapeColor and the opacity - //! passed as an argument. - //! If rotation is non-zero then the quad is rotated. If the pivot point is - //! provided then the points of the quad are rotated about that point, otherwise - //! they are rotated about the top left corner of the quad. - //! \param texId The texture ID returned by ITexture::GetTextureID() - //! \param position Position of the top left corner of the quad (before rotation) in pixels - //! \param size The width and height of the quad. Use texture width and height to avoid minification, - //! magnification or stretching (assuming the minMaxTexCoords are left to the default) - //! \param opacity The alpha value used when blending - //! \param rotation Angle of rotation in degrees counter-clockwise - //! \param pivotPoint The point about which the quad is rotated - //! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left - //! point of the quad and the second is the UV coord of the bottom right point of the quad - //! \param imageOptions Optional struct specifying options that tend to be the same from call to call - virtual void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f, - float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr, - ImageOptions* imageOptions = nullptr) = 0; - - //! Draw a textured quad where the position specifies the point specified by the alignment. - // - //! Rotation is always around the position. - //! \param texId The texture ID returned by ITexture::GetTextureID() - //! \param position Position align point of the quad (before rotation) in pixels - //! \param size The width and height of the quad. Use texture width and height to avoid minification, - //! magnification or stretching (assuming the minMaxTexCoords are left to the default) - //! \param horizontalAlignment Specifies how the quad is horizontally aligned to the given position - //! \param verticalAlignment Specifies how the quad is vertically aligned to the given position - //! \param opacity The alpha value used when blending - //! \param rotation Angle of rotation in degrees counter-clockwise - //! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left - //! point of the quad and the second is the UV coord of the bottom right point of the quad - //! \param imageOptions Optional struct specifying options that tend to be the same from call to call - virtual void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size, - HAlign horizontalAlignment, VAlign verticalAlignment, - float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr, - ImageOptions* imageOptions = nullptr) = 0; - - //! Draw a textured quad where the position, color and uv of each point is specified explicitly - // - //! \param texId The texture ID returned by ITexture::GetTextureID() - //! \param verts An array of 4 vertices, in clockwise order (e.g. top left, top right, bottom right, bottom left) - //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) - //! \param pixelRounding Whether and how to round pixel coordinates - //! \param baseState Additional render state to pass to or into value passed to renderer SetState - virtual void DrawQuad(int texId, VertexPosColUV* verts, - int blendMode = UseDefault, - Rounding pixelRounding = Rounding::Nearest, - int baseState = UseDefault) = 0; - - //! Draw a line - // - //! \param start The start position - //! \param end The end position - //! \param color The color of the line - //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) - //! \param pixelRounding Whether and how to round pixel coordinates - //! \param baseState Additional render state to pass to or into value passed to renderer SetState - virtual void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, - int blendMode = UseDefault, - IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, - int baseState = UseDefault) = 0; - - //! Draw a line with a texture so it can be dotted or dashed - // - //! \param texId The texture ID returned by ITexture::GetTextureID() - //! \param verts An array of 2 vertices for the start and end points of the line - //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) - //! \param pixelRounding Whether and how to round pixel coordinates - //! \param baseState Additional render state to pass to or into value passed to renderer SetState - virtual void DrawLineTextured(int texId, VertexPosColUV* verts, - int blendMode = UseDefault, - IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, - int baseState = UseDefault) = 0; - - //! Draw a text string. Only supports ASCII text. - // - //! The font and effect used to render the text are specified in the textOptions structure - //! \param textString A null terminated ASCII text string. May contain \n characters - //! \param position Position of the text in pixels. Alignment values in textOptions affect actual position - //! \param pointSize The size of the font to use - //! \param opacity The opacity (alpha value) to use to draw the text - //! \param textOptions Pointer to an options struct. If null the default options are used - virtual void DrawText(const char* textString, AZ::Vector2 position, float pointSize, - float opacity = 1.0f, TextOptions* textOptions = nullptr) = 0; - - //! Get the width and height (in pixels) that would be used to draw the given text string. - // - //! Pass the same parameter values that would be used to draw the string - virtual AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr) = 0; - - //! Get the width of the rendering viewport (in pixels). - // - //! If rendering full screen this is the native width from IRenderer - virtual float GetViewportWidth() const = 0; - - //! Get the height of the rendering viewport (in pixels). - // - //! If rendering full screen this is the native width from IRenderer - virtual float GetViewportHeight() const = 0; - - //! Get the default values that would be used if no image options were passed in - // - //! This is a convenient way to initialize the imageOptions struct - virtual const ImageOptions& GetDefaultImageOptions() const = 0; - - //! Get the default values that would be used if no text options were passed in - // - //! This is a convenient way to initialize the textOptions struct - virtual const TextOptions& GetDefaultTextOptions() const = 0; -}; - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//! Helper class for using the IDraw2d interface -//! -//! The Draw2dHelper class is an inline wrapper that provides two convenience features: -//! 1. It automatically calls BeginDraw2d/EndDraw2d in its construction/destruction. -//! 2. It automatically sets member options structures to their defaults and provides set functions -//! to set them. -class Draw2dHelper -{ -public: // member functions - - //! Start a section of 2D drawing function calls. This will set appropriate render state. - Draw2dHelper(bool deferCalls = false) - : m_draw2d(GetDraw2d()) - { - if (m_draw2d) - { - m_draw2d->BeginDraw2d(deferCalls); - m_imageOptions = m_draw2d->GetDefaultImageOptions(); - m_textOptions = m_draw2d->GetDefaultTextOptions(); - } - } - - //! End a section of 2D drawing function calls. This will reset some render state. - ~Draw2dHelper() - { - if (m_draw2d) - { - m_draw2d->EndDraw2d(); - } - } - - //! Draw a textured quad, optional rotation is counter-clockwise in degrees. - // - //! See IDraw2d:DrawImage for parameter descriptions - void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f, - float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr) - { - if (m_draw2d) - { - m_draw2d->DrawImage(texId, position, size, opacity, rotation, pivotPoint, minMaxTexCoords, &m_imageOptions); - } - } - - //! Draw a textured quad where the position specifies the point specified by the alignment. - // - //! See IDraw2d:DrawImageAligned for parameter descriptions - void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size, - IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment, - float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr) - { - if (m_draw2d) - { - m_draw2d->DrawImageAligned(texId, position, size, horizontalAlignment, verticalAlignment, - opacity, rotation, minMaxTexCoords, &m_imageOptions); - } - } - - //! Draw a textured quad where the position, color and uv of each point is specified explicitly - // - //! See IDraw2d:DrawQuad for parameter descriptions - void DrawQuad(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault, - IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, - int baseState = IDraw2d::UseDefault) - { - if (m_draw2d) - { - m_draw2d->DrawQuad(texId, verts, blendMode, pixelRounding, baseState); - } - } - - //! Draw a line - // - //! See IDraw2d:DrawLine for parameter descriptions - void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode = IDraw2d::UseDefault, - IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, - int baseState = IDraw2d::UseDefault) - { - if (m_draw2d) - { - m_draw2d->DrawLine(start, end, color, blendMode, pixelRounding, baseState); - } - } - - //! Draw a line with a texture so it can be dotted or dashed - // - //! See IDraw2d:DrawLineTextured for parameter descriptions - void DrawLineTextured(int texId, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault, - IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, - int baseState = IDraw2d::UseDefault) - { - if (m_draw2d) - { - m_draw2d->DrawLineTextured(texId, verts, blendMode, pixelRounding, baseState); - } - } - - //! Draw a text string. Only supports ASCII text. - // - //! See IDraw2d:DrawText for parameter descriptions - void DrawText(const char* textString, AZ::Vector2 position, float pointSize, float opacity = 1.0f) - { - if (m_draw2d) - { - m_draw2d->DrawText(textString, position, pointSize, opacity, &m_textOptions); - } - } - - //! Get the width and height (in pixels) that would be used to draw the given text string. - // - //! See IDraw2d:GetTextSize for parameter descriptions - AZ::Vector2 GetTextSize(const char* textString, float pointSize) - { - if (m_draw2d) - { - return m_draw2d->GetTextSize(textString, pointSize, &m_textOptions); - } - else - { - return AZ::Vector2(0, 0); - } - } - - // State management - - //! Set the blend mode used for images, default is GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA. - void SetImageBlendMode(int mode) { m_imageOptions.blendMode = mode; } - - //! Set the color used for DrawImage and other image drawing. - void SetImageColor(AZ::Vector3 color) { m_imageOptions.color = color; } - - //! Set whether images are rounded to have the points on exact pixel boundaries. - void SetImagePixelRounding(IDraw2d::Rounding round) { m_imageOptions.pixelRounding = round; } - - //! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST. - void SetImageBaseState(int state) { m_imageOptions.baseState = state; } - - //! Set the text font. - void SetTextFont(IFFont* font) { m_textOptions.font = font; } - - //! Set the text font effect index. - void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; } - - //! Set the text color. - void SetTextColor(AZ::Vector3 color) { m_textOptions.color = color; } - - //! Set the text alignment. - void SetTextAlignment(IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment) - { - m_textOptions.horizontalAlignment = horizontalAlignment; - m_textOptions.verticalAlignment = verticalAlignment; - } - - //! Set a drop shadow for text drawing. An alpha of zero disables drop shadow. - void SetTextDropShadow(AZ::Vector2 offset, AZ::Color color) - { - m_textOptions.dropShadowOffset = offset; - m_textOptions.dropShadowColor = color; - } - - //! Set a rotation for the text. The text rotates around its position (taking into account alignment). - void SetTextRotation(float rotation) - { - m_textOptions.rotation = rotation; - } - - //! Set the base state (that blend mode etc is combined with) used for text, default is GS_NODEPTHTEST. - void SetTextBaseState(int state) { m_textOptions.baseState = state; } - -public: // static member functions - - //! Helper to get the IDraw2d interface - static IDraw2d* GetDraw2d() { return (gEnv && gEnv->pLyShine) ? gEnv->pLyShine->GetDraw2d() : nullptr; } - - //! Get the width of the rendering viewport (in pixels). - static float GetViewportWidth() - { - IDraw2d* draw2d = GetDraw2d(); - return (draw2d) ? draw2d->GetViewportWidth() : 0.0f; - } - - //! Get the height of the rendering viewport (in pixels). - static float GetViewportHeight() - { - IDraw2d* draw2d = GetDraw2d(); - return (draw2d) ? draw2d->GetViewportHeight() : 0.0f; - } - - //! Round the X and Y coordinates of a point using the given rounding policy - template<typename T> - static T RoundXY(T value, IDraw2d::Rounding roundingType) - { - T result = value; - - switch (roundingType) - { - case IDraw2d::Rounding::None: - // nothing to do - break; - case IDraw2d::Rounding::Nearest: - result.SetX(floor(value.GetX() + 0.5f)); - result.SetY(floor(value.GetY() + 0.5f)); - break; - case IDraw2d::Rounding::Down: - result.SetX(floor(value.GetX())); - result.SetY(floor(value.GetY())); - break; - case IDraw2d::Rounding::Up: - result.SetX(ceil(value.GetX())); - result.SetY(ceil(value.GetY())); - break; - } - - return result; - } - -protected: // attributes - - IDraw2d::ImageOptions m_imageOptions; //!< image options are stored locally and updated by member functions - IDraw2d::TextOptions m_textOptions; //!< text options are stored locally and updated by member functions - IDraw2d* m_draw2d; }; diff --git a/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h b/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h deleted file mode 100644 index 797ea51b87..0000000000 --- a/Code/CryEngine/CryCommon/LyShine/IUiRenderer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include <LyShine/IDraw2d.h> - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//! Interface used by UI components to render to the canvas -// -//! The IUiRenderer provides helper functions for UI rendering and also manages state that -//! persists between UI elements when rendering a UI canvas. -//! For example one UI component can turn on stencil test and that affects all UI rendering -//! until it is turned off. -//! -//! This is a singleton class that is accessed via IUiRenderer::Get() which is a shortcut for -//! gEnv->pLyShine()->GetUiRenderer(); -class IUiRenderer -{ -public: // types - - -public: // member functions - - //! Implement virtual destructor for safety. - virtual ~IUiRenderer() {} - - //! Start the rendering of a UI canvas - virtual void BeginCanvasRender(AZ::Vector2 viewportSize) = 0; - - //! End the rendering of a UI canvas - virtual void EndCanvasRender() = 0; - - //! Get the current base state - virtual int GetBaseState() = 0; - - //! Set the base state - virtual void SetBaseState(int state) = 0; - - //! Get the current stencil test reference value - virtual uint32 GetStencilRef() = 0; - - //! Set the stencil test reference value - virtual void SetStencilRef(uint32) = 0; - - //! Increment the current stencil reference value - virtual void IncrementStencilRef() = 0; - - //! Decrement the current stencil reference value - virtual void DecrementStencilRef() = 0; - - //! Get flag that indicates we are rendering into a mask. Used to avoid masks on child mask elements. - virtual bool IsRenderingToMask() = 0; - - //! Set flag that we are rendering into a mask. Used to avoid masks on child mask elements. - virtual void SetIsRenderingToMask(bool isRenderingToMask) = 0; - - //! Push an alpha fade, this is multiplied with any existing alpha fade from parents - virtual void PushAlphaFade(float alphaFadeValue) = 0; - - //! Pop an alpha fade off the stack - virtual void PopAlphaFade() = 0; - - //! Get the current alpha fade value - virtual float GetAlphaFade() const = 0; - -public: // static member functions - - //! Helper function to get the singleton UiRenderer - static IUiRenderer* Get() { return gEnv->pLyShine->GetUiRenderer(); } -}; diff --git a/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h b/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h index 131671e2a5..91b5cc294c 100644 --- a/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h +++ b/Code/CryEngine/CryCommon/LyShine/UiSerializeHelpers.h @@ -20,6 +20,7 @@ #include <AzCore/Component/Entity.h> #include <LyShine/UiAssetTypes.h> +#include <LyShine/UiBase.h> //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h b/Gems/LyShine/Code/Editor/ViewportDragInteraction.h index f7574900a2..477720d0a2 100644 --- a/Gems/LyShine/Code/Editor/ViewportDragInteraction.h +++ b/Gems/LyShine/Code/Editor/ViewportDragInteraction.h @@ -12,7 +12,7 @@ #pragma once #include <AzCore/Math/Vector2.h> -#include <LyShine/IDraw2d.h> +#include <LyShine/Draw2d.h> //! Abstract base class for drag interactions in the UI Editor viewport window. class ViewportDragInteraction diff --git a/Gems/LyShine/Code/Editor/ViewportHelpers.h b/Gems/LyShine/Code/Editor/ViewportHelpers.h index d128603171..9a1aadead5 100644 --- a/Gems/LyShine/Code/Editor/ViewportHelpers.h +++ b/Gems/LyShine/Code/Editor/ViewportHelpers.h @@ -11,6 +11,8 @@ */ #pragma once +#include <LyShine/Draw2d.h> + namespace ViewportHelpers { //------------------------------------------------------------------------------- diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.cpp b/Gems/LyShine/Code/Editor/ViewportIcon.cpp index 5ce2bf37f7..1e137fe91b 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.cpp +++ b/Gems/LyShine/Code/Editor/ViewportIcon.cpp @@ -12,25 +12,34 @@ #include "UiCanvasEditor_precompiled.h" #include "EditorCommon.h" +#include <LyShine/Draw2d.h> + +#include <Atom/RPI.Public/Image/StreamingImage.h> +#include <Atom/RPI.Reflect/Image/StreamingImageAsset.h> ViewportIcon::ViewportIcon(const char* textureFilename) - : m_texture(gEnv->pRenderer->EF_LoadTexture(textureFilename, FT_DONT_STREAM)) { + m_image = CDraw2d::LoadTexture(textureFilename); } ViewportIcon::~ViewportIcon() { - gEnv->pRenderer->RemoveTexture(m_texture->GetTextureID()); } AZ::Vector2 ViewportIcon::GetTextureSize() const { - return AZ::Vector2(aznumeric_cast<float>(m_texture->GetWidth()), aznumeric_cast<float>(m_texture->GetHeight())); + if (m_image) + { + AZ::RHI::Size size = m_image->GetDescriptor().m_size; + return AZ::Vector2(size.m_width, size.m_height); + } + + return AZ::Vector2(0.0f, 0.0f); } void ViewportIcon::DrawImageAligned(Draw2dHelper& draw2d, AZ::Vector2& pivot, float opacity) { - draw2d.DrawImageAligned(m_texture->GetTextureID(), + draw2d.DrawImageAligned(m_image, pivot, GetTextureSize(), IDraw2d::HAlign::Center, @@ -43,7 +52,7 @@ void ViewportIcon::DrawImageTiled(Draw2dHelper& draw2d, IDraw2d::VertexPosColUV* // Use default blending and rounding modes int blendMode = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA; IDraw2d::Rounding rounding = IDraw2d::Rounding::Nearest; - draw2d.DrawQuad(m_texture->GetTextureID(), verts, blendMode, rounding); + draw2d.DrawQuad(m_image, verts, blendMode, rounding); } void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 bound0, AZ::Vector2 bound1) @@ -73,7 +82,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 verts[0].uv = AZ::Vector2(0.0f, 0.5f); verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f); - draw2d.DrawLineTextured(m_texture->GetTextureID(), verts); + draw2d.DrawLineTextured(m_image, verts); } // bound0 @@ -89,7 +98,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 verts[0].uv = AZ::Vector2(0.0f, 0.5f); verts[1].uv = AZ::Vector2(endTexCoordV, 0.5f); - draw2d.DrawLineTextured(m_texture->GetTextureID(), verts); + draw2d.DrawLineTextured(m_image, verts); } // bound0 @@ -105,7 +114,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 verts[0].uv = AZ::Vector2(0.0f, 0.5f); verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f); - draw2d.DrawLineTextured(m_texture->GetTextureID(), verts); + draw2d.DrawLineTextured(m_image, verts); } // bound0 @@ -121,7 +130,7 @@ void ViewportIcon::DrawAxisAlignedBoundingBox(Draw2dHelper& draw2d, AZ::Vector2 verts[0].uv = AZ::Vector2(0.0f, 0.5f); verts[1].uv = AZ::Vector2(endTexCoordV, 0.5f); - draw2d.DrawLineTextured(m_texture->GetTextureID(), verts); + draw2d.DrawLineTextured(m_image, verts); } } @@ -189,7 +198,7 @@ void ViewportIcon::Draw(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, const AZ::M verts[3].position = originPos - widthVec * originRatio.GetX() + heightVec * (1.0f - originRatio.GetY()); } - draw2d.DrawQuad(m_texture->GetTextureID(), verts); + draw2d.DrawQuad(m_image, verts); } void ViewportIcon::DrawAnchorLines(Draw2dHelper& draw2d, AZ::Vector2 anchorPos, AZ::Vector2 targetPos, const AZ::Matrix4x4& transform, @@ -252,7 +261,7 @@ void ViewportIcon::DrawDistanceLine(Draw2dHelper& draw2d, AZ::Vector2 start, AZ: verts[1].color = dottedColor; verts[1].uv = AZ::Vector2(endTexCoordU, 0.5f); - draw2d.DrawLineTextured(m_texture->GetTextureID(), verts); + draw2d.DrawLineTextured(m_image, verts); // Now draw the text rotated to match the angle of the line and slightly offset from the center point @@ -379,7 +388,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d, float rectHeight = heightVec.GetLength(); // the outline "width" will be based on the texture height - int textureHeight = m_texture->GetHeight(); + float textureHeight = GetTextureSize().GetY(); if (textureHeight <= 0) { return; // should never happen - avoiding possible divide by zero later @@ -464,6 +473,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d, 5, 1, 7, 1, 7, 3, // right quad }; +#ifdef LYSHINE_ATOM_TODO IRenderer* renderer = gEnv->pRenderer; renderer->SetTexture(m_texture->GetTextureID()); @@ -472,4 +482,7 @@ void ViewportIcon::DrawElementRectOutline([[maybe_unused]] Draw2dHelper& draw2d, // This will end up using DrawIndexedPrimitive to render the quad renderer->DrawDynVB(vertices, indicies, NUM_VERTS, NUM_INDICES, prtTriangleList); +#else + // LYSHINE_ATOM_TODO - add option in Draw2d to draw indexed primitive for this textured element outline +#endif } diff --git a/Gems/LyShine/Code/Editor/ViewportIcon.h b/Gems/LyShine/Code/Editor/ViewportIcon.h index 5f72c7562a..85fd2fe068 100644 --- a/Gems/LyShine/Code/Editor/ViewportIcon.h +++ b/Gems/LyShine/Code/Editor/ViewportIcon.h @@ -11,6 +11,8 @@ */ #pragma once +#include <Atom/RPI.Reflect/Image/Image.h> + class ViewportIcon { public: @@ -48,6 +50,5 @@ public: void DrawElementRectOutline(Draw2dHelper& draw2d, AZ::EntityId entityId, AZ::Color color); private: - - ITexture* m_texture; + AZ::Data::Instance<AZ::RPI::Image> m_image; }; diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.cpp b/Gems/LyShine/Code/Editor/ViewportWidget.cpp index c805d45bef..2b1ea16c97 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.cpp +++ b/Gems/LyShine/Code/Editor/ViewportWidget.cpp @@ -21,6 +21,7 @@ #include <QViewportSettings.h> #include <LyShine/Bus/UiEditorCanvasBus.h> +#include <LyShine/Draw2d.h> #include "LyShine.h" #include "UiRenderer.h" @@ -277,6 +278,8 @@ void ViewportWidget::InitUiRenderer() // Only one viewport/renderer is currently supported in the UI Editor CLyShine* lyShine = static_cast<CLyShine*>(gEnv->pLyShine); lyShine->SetUiRendererForEditor(m_uiRenderer); + + m_draw2d = AZStd::make_shared<CDraw2d>(GetViewportContext()); } ViewportInteraction* ViewportWidget::GetViewportInteraction() @@ -914,7 +917,7 @@ void ViewportWidget::RenderEditMode(float deltaTime) return; // this can happen if a render happens during a restart } - Draw2dHelper draw2d; // sets and resets 2D draw mode in constructor/destructor + Draw2dHelper draw2d(m_draw2d.get()); // sets and resets 2D draw mode in constructor/destructor QTreeWidgetItemRawPtrQList selection = m_editorWindow->GetHierarchy()->selectedItems(); @@ -1142,7 +1145,7 @@ void ViewportWidget::RenderPreviewMode(float deltaTime) AZ::Vector2 topLeftInViewportSpace = CanvasHelpers::GetViewportPoint(canvasEntityId, AZ::Vector2(0.0f, 0.0f)); AZ::Vector2 bottomRightInViewportSpace = CanvasHelpers::GetViewportPoint(canvasEntityId, canvasSize); AZ::Vector2 sizeInViewportSpace = bottomRightInViewportSpace - topLeftInViewportSpace; - Draw2dHelper draw2d; + Draw2dHelper draw2d(m_draw2d.get()) int texId = gEnv->pRenderer->GetBlackTextureId(); draw2d.DrawImage(texId, topLeftInViewportSpace, sizeInViewportSpace); #endif diff --git a/Gems/LyShine/Code/Editor/ViewportWidget.h b/Gems/LyShine/Code/Editor/ViewportWidget.h index e506a26d88..4d15f3dea4 100644 --- a/Gems/LyShine/Code/Editor/ViewportWidget.h +++ b/Gems/LyShine/Code/Editor/ViewportWidget.h @@ -25,6 +25,7 @@ class RulerWidget; class QMimeData; class UiRenderer; +class CDraw2d; class ViewportWidget : public AtomToolsFramework::RenderViewportWidget @@ -201,4 +202,5 @@ private: // data bool m_fontTextureHasChanged = false; AZStd::shared_ptr<UiRenderer> m_uiRenderer; + AZStd::shared_ptr<CDraw2d> m_draw2d; }; diff --git a/Gems/LyShine/Code/Include/LyShine/Draw2d.h b/Gems/LyShine/Code/Include/LyShine/Draw2d.h new file mode 100644 index 0000000000..ec636c3e3b --- /dev/null +++ b/Gems/LyShine/Code/Include/LyShine/Draw2d.h @@ -0,0 +1,517 @@ +/* +* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +* its licensors. +* +* For complete copyright and license terms please see the LICENSE at the root of this +* distribution (the "License"). All use of this software is governed by the License, +* or, if provided, by the license below or the license accompanying this file. Do not +* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* +*/ +#pragma once + +#include <LyShine/IDraw2d.h> +#include <LyShine/ILyShine.h> + +#include <Atom/Bootstrap/BootstrapNotificationBus.h> +#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h> +#include <Atom/RPI.Reflect/Image/Image.h> +#include <Atom/RPI.Public/ViewportContext.h> + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! Implementation of IDraw2d interface for 2D drawing in screen space +// +//! The CDraw2d class implements the IDraw2d interface for drawing 2D images, shapes and text. +//! Positions and sizes are specified in pixels in the associated 2D viewport. +class CDraw2d + : public IDraw2d // LYSHINE_ATOM_TODO - keep around until gEnv->pLyShine is replaced by bus interface + , public AZ::Render::Bootstrap::NotificationBus::Handler +{ +public: // member functions + + //! Constructor, constructed by the LyShine class + CDraw2d(AZ::RPI::ViewportContextPtr viewportContext = nullptr); + + // IDraw2d + + ~CDraw2d() override; + + // ~IDraw2d + + //! Draw a textured quad with the top left corner at the given position. + // + //! The image is drawn with the color specified by SetShapeColor and the opacity + //! passed as an argument. + //! If rotation is non-zero then the quad is rotated. If the pivot point is + //! provided then the points of the quad are rotated about that point, otherwise + //! they are rotated about the top left corner of the quad. + //! \param texId The texture ID returned by ITexture::GetTextureID() + //! \param position Position of the top left corner of the quad (before rotation) in pixels + //! \param size The width and height of the quad. Use texture width and height to avoid minification, + //! magnification or stretching (assuming the minMaxTexCoords are left to the default) + //! \param opacity The alpha value used when blending + //! \param rotation Angle of rotation in degrees counter-clockwise + //! \param pivotPoint The point about which the quad is rotated + //! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left + //! point of the quad and the second is the UV coord of the bottom right point of the quad + //! \param imageOptions Optional struct specifying options that tend to be the same from call to call + void DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f, + float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr, + ImageOptions* imageOptions = nullptr); + + //! Draw a textured quad where the position specifies the point specified by the alignment. + // + //! Rotation is always around the position. + //! \param texId The texture ID returned by ITexture::GetTextureID() + //! \param position Position align point of the quad (before rotation) in pixels + //! \param size The width and height of the quad. Use texture width and height to avoid minification, + //! magnification or stretching (assuming the minMaxTexCoords are left to the default) + //! \param horizontalAlignment Specifies how the quad is horizontally aligned to the given position + //! \param verticalAlignment Specifies how the quad is vertically aligned to the given position + //! \param opacity The alpha value used when blending + //! \param rotation Angle of rotation in degrees counter-clockwise + //! \param minMaxTexCoords An optional two component array. The first component is the UV coord for the top left + //! point of the quad and the second is the UV coord of the bottom right point of the quad + //! \param imageOptions Optional struct specifying options that tend to be the same from call to call + void DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, + HAlign horizontalAlignment, VAlign verticalAlignment, + float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr, + ImageOptions* imageOptions = nullptr); + + //! Draw a textured quad where the position, color and uv of each point is specified explicitly + // + //! \param texId The texture ID returned by ITexture::GetTextureID() + //! \param verts An array of 4 vertices, in clockwise order (e.g. top left, top right, bottom right, bottom left) + //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) + //! \param pixelRounding Whether and how to round pixel coordinates + //! \param baseState Additional render state to pass to or into value passed to renderer SetState + virtual void DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image, + VertexPosColUV* verts, + int blendMode = UseDefault, + Rounding pixelRounding = Rounding::Nearest, + int baseState = UseDefault); + + //! Draw a line + // + //! \param start The start position + //! \param end The end position + //! \param color The color of the line + //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) + //! \param pixelRounding Whether and how to round pixel coordinates + //! \param baseState Additional render state to pass to or into value passed to renderer SetState + virtual void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, + int blendMode = UseDefault, + IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + int baseState = UseDefault); + + //! Draw a line with a texture so it can be dotted or dashed + // + //! \param texId The texture ID returned by ITexture::GetTextureID() + //! \param verts An array of 2 vertices for the start and end points of the line + //! \param blendMode UseDefault means default blend mode (currently GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA) + //! \param pixelRounding Whether and how to round pixel coordinates + //! \param baseState Additional render state to pass to or into value passed to renderer SetState + virtual void DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image, + VertexPosColUV* verts, + int blendMode = UseDefault, + IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + int baseState = UseDefault); + //! Draw a text string. Only supports ASCII text. + // + //! The font and effect used to render the text are specified in the textOptions structure + //! \param textString A null terminated ASCII text string. May contain \n characters + //! \param position Position of the text in pixels. Alignment values in textOptions affect actual position + //! \param pointSize The size of the font to use + //! \param opacity The opacity (alpha value) to use to draw the text + //! \param textOptions Pointer to an options struct. If null the default options are used + void DrawText(const char* textString, AZ::Vector2 position, float pointSize, + float opacity = 1.0f, TextOptions* textOptions = nullptr); + + //! Get the width and height (in pixels) that would be used to draw the given text string. + // + //! Pass the same parameter values that would be used to draw the string + AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr); + + //! Get the width of the rendering viewport (in pixels). + float GetViewportWidth() const; + + //! Get the height of the rendering viewport (in pixels). + float GetViewportHeight() const; + + //! Get the default values that would be used if no image options were passed in + // + //! This is a convenient way to initialize the imageOptions struct + virtual const ImageOptions& GetDefaultImageOptions() const; + + //! Get the default values that would be used if no text options were passed in + // + //! This is a convenient way to initialize the textOptions struct + virtual const TextOptions& GetDefaultTextOptions() const; + + //! Render the primitives that have been deferred + void RenderDeferredPrimitives(); + + //! Specify whether to defer future primitives or render them right away + void SetDeferPrimitives(bool deferPrimitives); + + //! Return whether future primitives will be deferred or rendered right away + bool GetDeferPrimitives(); + +private: + + AZ_DISABLE_COPY_MOVE(CDraw2d); + + // AZ::Render::Bootstrap::NotificationBus overrides + void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override; + +public: // static member functions + + //! Given a position and size and an alignment return the top left corner of the aligned quad + static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment); + + //! Helper to load a texture + static AZ::Data::Instance<AZ::RPI::Image> LoadTexture(const AZStd::string& pathName); + +protected: // types and constants + + enum + { + MAX_VERTICES_IN_PRIM = 6 + }; + + // Cached shader data + struct Draw2dShaderData + { + AZ::RHI::ShaderInputImageIndex m_imageInputIndex; + AZ::RHI::ShaderInputConstantIndex m_viewProjInputIndex; + }; + + class DeferredPrimitive + { + public: + virtual ~DeferredPrimitive() {}; + virtual void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const = 0; + }; + + class DeferredQuad + : public DeferredPrimitive + { + public: + ~DeferredQuad() override {}; + void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const override; + + AZ::Vector2 m_points[4]; + AZ::Vector2 m_texCoords[4]; + uint32 m_packedColors[4]; + AZ::Data::Instance<AZ::RPI::Image> m_image; + int m_state; + }; + + class DeferredLine + : public DeferredPrimitive + { + public: + ~DeferredLine() override {}; + void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const override; + + AZ::Data::Instance<AZ::RPI::Image> m_image; + AZ::Vector2 m_points[2]; + AZ::Vector2 m_texCoords[2]; + uint32 m_packedColors[2]; + int m_state; + }; + + class DeferredText + : public DeferredPrimitive + { + public: + ~DeferredText() override {}; + void Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const override; + + STextDrawContext m_fontContext; + IFFont* m_font; + AZ::Vector2 m_position; + std::string m_string; + }; + +protected: // member functions + + //! Rotate an array of points around the z-axis at the pivot point. + // + //! Angle is in degrees counter-clockwise + void RotatePointsAboutPivot(AZ::Vector2* points, int numPoints, AZ::Vector2 pivot, float angle) const; + + //! Helper function to render a text string + void DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex, + AZ::Vector2 position, float pointSize, AZ::Color color, float rotation, + HAlign horizontalAlignment, VAlign verticalAlignment, int baseState); + + //! Draw or defer a quad + void DrawOrDeferQuad(const DeferredQuad* quad); + + //! Draw or defer a line + void DrawOrDeferLine(const DeferredLine* line); + + //! Get specified viewport context or default viewport context if not specified + AZ::RPI::ViewportContextPtr GetViewportContext() const; + +protected: // attributes + + ImageOptions m_defaultImageOptions; //!< The default image options used if nullptr is passed + TextOptions m_defaultTextOptions; //!< The default text options used if nullptr is passed + + //! True if the actual render of the primitives should be deferred to a RenderDeferredPrimitives call + bool m_deferCalls; + + std::vector<DeferredPrimitive*> m_deferredPrimitives; + + AZ::RPI::ViewportContextPtr m_viewportContext; + AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> m_dynamicDraw; + Draw2dShaderData m_shaderData; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +//! Helper class for using the IDraw2d interface +//! +//! The Draw2dHelper class is an inline wrapper that provides the convenience feature of +//! automatically setting member options structures to their defaults and providing set functions. +class Draw2dHelper +{ +public: // member functions + + //! Start a section of 2D drawing function calls that will render to the default viewport + Draw2dHelper(bool deferCalls = false) + { + InitCommon(nullptr, deferCalls); + } + + //! Start a section of 2D drawing function calls that will render to the viewport + //! associated with the specified Draw2d object + Draw2dHelper(CDraw2d* draw2d, bool deferCalls = false) + { + InitCommon(draw2d, deferCalls); + } + + void InitCommon(CDraw2d* draw2d, bool deferCalls) + { + m_draw2d = draw2d; + + if (!m_draw2d) + { + // Set to default which is the game's draw 2d object + m_draw2d = GetDefaultDraw2d(); + } + + if (m_draw2d) + { + m_previousDeferCalls = m_draw2d->GetDeferPrimitives(); + m_draw2d->SetDeferPrimitives(deferCalls); + m_imageOptions = m_draw2d->GetDefaultImageOptions(); + m_textOptions = m_draw2d->GetDefaultTextOptions(); + } + } + + //! End a section of 2D drawing function calls. + ~Draw2dHelper() + { + if (m_draw2d) + { + m_draw2d->SetDeferPrimitives(m_previousDeferCalls); + } + } + + //! Draw a textured quad, optional rotation is counter-clockwise in degrees. + // + //! See IDraw2d:DrawImage for parameter descriptions + void DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f, + float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr) + { + if (m_draw2d) + { + m_draw2d->DrawImage(image, position, size, opacity, rotation, pivotPoint, minMaxTexCoords, &m_imageOptions); + } + } + + //! Draw a textured quad where the position specifies the point specified by the alignment. + // + //! See IDraw2d:DrawImageAligned for parameter descriptions + void DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, + IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment, + float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr) + { + if (m_draw2d) + { + m_draw2d->DrawImageAligned(image, position, size, horizontalAlignment, verticalAlignment, + opacity, rotation, minMaxTexCoords, &m_imageOptions); + } + } + + //! Draw a textured quad where the position, color and uv of each point is specified explicitly + // + //! See IDraw2d:DrawQuad for parameter descriptions + void DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault, + IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + int baseState = IDraw2d::UseDefault) + { + if (m_draw2d) + { + m_draw2d->DrawQuad(image, verts, blendMode, pixelRounding, baseState); + } + } + + //! Draw a line + // + //! See IDraw2d:DrawLine for parameter descriptions + void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode = IDraw2d::UseDefault, + IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + int baseState = IDraw2d::UseDefault) + { + if (m_draw2d) + { + m_draw2d->DrawLine(start, end, color, blendMode, pixelRounding, baseState); + } + } + + //! Draw a line with a texture so it can be dotted or dashed + // + //! See IDraw2d:DrawLineTextured for parameter descriptions + void DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image, IDraw2d::VertexPosColUV* verts, int blendMode = IDraw2d::UseDefault, + IDraw2d::Rounding pixelRounding = IDraw2d::Rounding::Nearest, + int baseState = IDraw2d::UseDefault) + { + if (m_draw2d) + { + m_draw2d->DrawLineTextured(image, verts, blendMode, pixelRounding, baseState); + } + } + + //! Draw a text string. Only supports ASCII text. + // + //! See IDraw2d:DrawText for parameter descriptions + void DrawText(const char* textString, AZ::Vector2 position, float pointSize, float opacity = 1.0f) + { + if (m_draw2d) + { + m_draw2d->DrawText(textString, position, pointSize, opacity, &m_textOptions); + } + } + + //! Get the width and height (in pixels) that would be used to draw the given text string. + // + //! See IDraw2d:GetTextSize for parameter descriptions + AZ::Vector2 GetTextSize(const char* textString, float pointSize) + { + if (m_draw2d) + { + return m_draw2d->GetTextSize(textString, pointSize, &m_textOptions); + } + else + { + return AZ::Vector2(0, 0); + } + } + + // State management + + //! Set the blend mode used for images, default is GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA. + void SetImageBlendMode(int mode) { m_imageOptions.blendMode = mode; } + + //! Set the color used for DrawImage and other image drawing. + void SetImageColor(AZ::Vector3 color) { m_imageOptions.color = color; } + + //! Set whether images are rounded to have the points on exact pixel boundaries. + void SetImagePixelRounding(IDraw2d::Rounding round) { m_imageOptions.pixelRounding = round; } + + //! Set the base state (that blend mode etc is combined with) used for images, default is GS_NODEPTHTEST. + void SetImageBaseState(int state) { m_imageOptions.baseState = state; } + + //! Set the text font. + void SetTextFont(IFFont* font) { m_textOptions.font = font; } + + //! Set the text font effect index. + void SetTextEffectIndex(unsigned int effectIndex) { m_textOptions.effectIndex = effectIndex; } + + //! Set the text color. + void SetTextColor(AZ::Vector3 color) { m_textOptions.color = color; } + + //! Set the text alignment. + void SetTextAlignment(IDraw2d::HAlign horizontalAlignment, IDraw2d::VAlign verticalAlignment) + { + m_textOptions.horizontalAlignment = horizontalAlignment; + m_textOptions.verticalAlignment = verticalAlignment; + } + + //! Set a drop shadow for text drawing. An alpha of zero disables drop shadow. + void SetTextDropShadow(AZ::Vector2 offset, AZ::Color color) + { + m_textOptions.dropShadowOffset = offset; + m_textOptions.dropShadowColor = color; + } + + //! Set a rotation for the text. The text rotates around its position (taking into account alignment). + void SetTextRotation(float rotation) + { + m_textOptions.rotation = rotation; + } + + //! Set the base state (that blend mode etc is combined with) used for text, default is GS_NODEPTHTEST. + void SetTextBaseState(int state) { m_textOptions.baseState = state; } + +public: // static member functions + + //! Helper to get the default IDraw2d interface + static CDraw2d* GetDefaultDraw2d() + { + if (gEnv && gEnv->pLyShine) // LYSHINE_ATOM_TODO - remove pLyShine and use bus interface + { + IDraw2d* draw2d = gEnv->pLyShine->GetDraw2d(); + return reinterpret_cast<CDraw2d*>(draw2d); + } + + return nullptr; + } + + //! Round the X and Y coordinates of a point using the given rounding policy + template<typename T> + static T RoundXY(T value, IDraw2d::Rounding roundingType) + { + T result = value; + + switch (roundingType) + { + case IDraw2d::Rounding::None: + // nothing to do + break; + case IDraw2d::Rounding::Nearest: + result.SetX(floor(value.GetX() + 0.5f)); + result.SetY(floor(value.GetY() + 0.5f)); + break; + case IDraw2d::Rounding::Down: + result.SetX(floor(value.GetX())); + result.SetY(floor(value.GetY())); + break; + case IDraw2d::Rounding::Up: + result.SetX(ceil(value.GetX())); + result.SetY(ceil(value.GetY())); + break; + } + + return result; + } + +protected: // attributes + + IDraw2d::ImageOptions m_imageOptions; //!< image options are stored locally and updated by member functions + IDraw2d::TextOptions m_textOptions; //!< text options are stored locally and updated by member functions + CDraw2d* m_draw2d; + bool m_previousDeferCalls; +}; diff --git a/Gems/LyShine/Code/Source/Draw2d.cpp b/Gems/LyShine/Code/Source/Draw2d.cpp index 4beba0b1eb..cd15475039 100644 --- a/Gems/LyShine/Code/Source/Draw2d.cpp +++ b/Gems/LyShine/Code/Source/Draw2d.cpp @@ -10,17 +10,24 @@ * */ #include "LyShine_precompiled.h" -#include "Draw2d.h" #include "IFont.h" -#include "IRenderer.h" + +#include <LyShine/Draw2d.h> #include <AzCore/Math/Matrix3x3.h> +#include <AzCore/Math/MatrixUtils.h> + +#include <Atom/RPI.Public/Image/ImageSystemInterface.h> +#include <Atom/RPI.Public/RPISystemInterface.h> +#include <Atom/RHI/RHISystemInterface.h> +#include <Atom/RPI.Public/Shader/Shader.h> +#include <Atom/RPI.Public/Image/StreamingImage.h> +#include <Atom/RPI.Public/RPIUtils.h> +#include <Atom/RPI.Public/ViewportContextBus.h> static const int g_defaultBlendState = GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA; static const int g_defaultBaseState = GS_NODEPTHTEST; -static const int g_2dModeNotStarted = -1; - //////////////////////////////////////////////////////////////////////////////////////////////////// // LOCAL STATIC FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -37,9 +44,9 @@ static AZ::u32 PackARGB8888(const AZ::Color& color) //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -CDraw2d::CDraw2d() +CDraw2d::CDraw2d(AZ::RPI::ViewportContextPtr viewportContext) : m_deferCalls(false) - , m_nestLevelAtWhichStarted2dMode(g_2dModeNotStarted) + , m_viewportContext(viewportContext) { // These default options are set here and never change. They are stored so that if a null options // structure is passed into the draw functions then this default one can be used instead @@ -57,78 +64,75 @@ CDraw2d::CDraw2d() m_defaultTextOptions.dropShadowColor.Set(0.0f, 0.0f, 0.0f, 0.0f); m_defaultTextOptions.rotation = 0.0f; m_defaultTextOptions.baseState = g_defaultBaseState; -} -//////////////////////////////////////////////////////////////////////////////////////////////////// -CDraw2d::~CDraw2d() -{ + AZ::Render::Bootstrap::NotificationBus::Handler::BusConnect(); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::BeginDraw2d(bool deferCalls) +CDraw2d::~CDraw2d() { - IRenderer* renderer = gEnv->pRenderer; - AZ::Vector2 viewportSize( - static_cast<float>(renderer->GetOverlayWidth()), - static_cast<float>(renderer->GetOverlayHeight())); - BeginDraw2d(viewportSize, deferCalls); + AZ::Render::Bootstrap::NotificationBus::Handler::BusDisconnect(); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls) +void CDraw2d::OnBootstrapSceneReady([[maybe_unused]] AZ::RPI::Scene* bootstrapScene) { - // So that nested calls to BeginDraw2d/EndDraw2d do not end 2D drawmode prematurely we only - // switch to 2D mode once and do not do it again until the corresponding call to EndDraw2d - // is processed. - // It may seem overkill to allow nested calls rather than just asserting in that case. But - // a) it is more flexible to do so - // b) it can be useful to draw some debug primitives in deferred mode while rendering a - // canvas in non-deferred mode for example - - // Push the current state of the m_deferCalls onto a stack to support nested calls - m_deferCallsFlagStack.push(m_deferCalls); + // At this point the RPI is ready for use - m_deferCalls = deferCalls; + // Load the shader to be used for 2d drawing + const char* shaderFilepath = "Shaders/SimpleTextured.azshader"; + AZ::Data::Instance<AZ::RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath); - // if this is the outermost call with non-deferred rendering then switch to 2D mode - if (!m_deferCalls && m_nestLevelAtWhichStarted2dMode == g_2dModeNotStarted) + // Set scene to be associated with the dynamic draw context + AZ::RPI::ScenePtr scene; + if (m_viewportContext) { - IRenderer* renderer = gEnv->pRenderer; - - renderer->SetCullMode(R_CULL_DISABLE); - - renderer->Set2DMode(static_cast<uint32>(viewportSize.GetX()), static_cast<uint32>(viewportSize.GetY()), m_backupSceneMatrices); - - renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); - renderer->SetState(g_defaultBlendState | g_defaultBaseState); - - // remember the nesting level that we turned on 2D mode so we can turn it off as - // we unwind the stack - m_nestLevelAtWhichStarted2dMode = m_deferCallsFlagStack.size(); + // Use scene associated with the specified viewport context + scene = m_viewportContext->GetRenderScene(); } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::EndDraw2d() -{ - // if we are ending a non-deferred series of calls and we turned on 2D draw mode when we started - // this series then turn it off. - if (!m_deferCalls && m_nestLevelAtWhichStarted2dMode == m_deferCallsFlagStack.size()) + else { - IRenderer* renderer = gEnv->pRenderer; - renderer->Unset2DMode(m_backupSceneMatrices); - m_nestLevelAtWhichStarted2dMode = -1; + // No viewport context specified, use default scene + scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); } - - // unwind the nesting stack - m_deferCalls = m_deferCallsFlagStack.top(); - m_deferCallsFlagStack.pop(); + AZ_Assert(scene != nullptr, "Attempting to create a DynamicDrawContext for a viewport context that has not been associated with a scene yet."); + + // Create and initialize a DynamicDrawContext for 2d drawing + m_dynamicDraw = AZ::RPI::DynamicDrawInterface::Get()->CreateDynamicDrawContext(scene.get()); + AZ::RPI::ShaderOptionList shaderOptions; + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("true"))); + shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("false"))); + m_dynamicDraw->InitShaderWithVariant(shader, &shaderOptions); + m_dynamicDraw->InitVertexFormat( + { {"POSITION", AZ::RHI::Format::R32G32B32_FLOAT}, + {"COLOR", AZ::RHI::Format::B8G8R8A8_UNORM}, + {"TEXCOORD0", AZ::RHI::Format::R32G32_FLOAT} }); + m_dynamicDraw->AddDrawStateOptions(AZ::RPI::DynamicDrawContext::DrawStateOptions::PrimitiveType + | AZ::RPI::DynamicDrawContext::DrawStateOptions::BlendMode); + m_dynamicDraw->EndInit(); + + AZ::RHI::TargetBlendState targetBlendState; + targetBlendState.m_enable = true; + targetBlendState.m_blendSource = AZ::RHI::BlendFactor::AlphaSource; + targetBlendState.m_blendDest = AZ::RHI::BlendFactor::AlphaSourceInverse; + m_dynamicDraw->SetTarget0BlendState(targetBlendState); + + // Cache draw srg input indices for later use + static const char textureIndexName[] = "m_texture"; + static const char worldToProjIndexName[] = "m_worldToProj"; + AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = m_dynamicDraw->NewDrawSrg(); + const AZ::RHI::ShaderResourceGroupLayout* layout = drawSrg->GetAsset()->GetLayout(); + m_shaderData.m_imageInputIndex = layout->FindShaderInputImageIndex(AZ::Name(textureIndexName)); + AZ_Error("Draw2d", m_shaderData.m_imageInputIndex.IsValid(), "Failed to find shader input constant %s.", + textureIndexName); + m_shaderData.m_viewProjInputIndex = layout->FindShaderInputConstantIndex(AZ::Name(worldToProjIndexName)); + AZ_Error("Draw2d", m_shaderData.m_viewProjInputIndex.IsValid(), "Failed to find shader input constant %s.", + worldToProjIndexName); } - //////////////////////////////////////////////////////////////////////////////////////////////////// // Draw a textured quad with the top left corner at the given position. -void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity, +void CDraw2d::DrawImage(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, float opacity, float rotation, const AZ::Vector2* pivotPoint, const AZ::Vector2* minMaxTexCoords, ImageOptions* imageOptions) { @@ -169,7 +173,7 @@ void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float quad.m_texCoords[3].Set(0.0f, 1.0f); } - quad.m_texId = texId; + quad.m_image = image; // add the blendMode flags to the base state quad.m_state = blendMode | actualImageOptions->baseState; @@ -185,17 +189,17 @@ void CDraw2d::DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size, +void CDraw2d::DrawImageAligned(AZ::Data::Instance<AZ::RPI::Image> image, AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment, float opacity, float rotation, const AZ::Vector2* minMaxTexCoords, ImageOptions* imageOptions) { AZ::Vector2 alignedPosition = Align(position, size, horizontalAlignment, verticalAlignment); - DrawImage(texId, alignedPosition, size, opacity, rotation, &position, minMaxTexCoords, imageOptions); + DrawImage(image, alignedPosition, size, opacity, rotation, &position, minMaxTexCoords, imageOptions); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) +void CDraw2d::DrawQuad(AZ::Data::Instance<AZ::RPI::Image> image, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) { int actualBlendMode = (blendMode == -1) ? g_defaultBlendState : blendMode; int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState; @@ -208,7 +212,7 @@ void CDraw2d::DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding quad.m_texCoords[i] = verts[i].uv; quad.m_packedColors[i] = PackARGB8888(verts[i].color); } - quad.m_texId = texId; + quad.m_image = image; // add the blendMode flags to the base state quad.m_state = actualBlendMode | actualBaseState; @@ -221,9 +225,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int { int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState; - IRenderer* renderer = gEnv->pRenderer; - - int texId = renderer->GetWhiteTextureId(); + auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); int actualBlendMode = (blendMode == -1) ? g_defaultBlendState : blendMode; @@ -231,7 +233,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int uint32 packedColor = PackARGB8888(color); DeferredLine line; - line.m_texId = texId; + line.m_image = image; line.m_points[0] = Draw2dHelper::RoundXY(start, pixelRounding); line.m_points[1] = Draw2dHelper::RoundXY(end, pixelRounding); @@ -250,7 +252,7 @@ void CDraw2d::DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) +void CDraw2d::DrawLineTextured(AZ::Data::Instance<AZ::RPI::Image> image, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) { int actualBaseState = (baseState == -1) ? g_defaultBaseState : baseState; @@ -258,7 +260,7 @@ void CDraw2d::DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode, // define line DeferredLine line; - line.m_texId = texId; + line.m_image = image; for (int i = 0; i < 2; ++i) { @@ -327,15 +329,19 @@ AZ::Vector2 CDraw2d::GetTextSize(const char* textString, float pointSize, TextOp //////////////////////////////////////////////////////////////////////////////////////////////////// float CDraw2d::GetViewportWidth() const { - IRenderer* renderer = gEnv->pRenderer; - return (float)renderer->GetOverlayWidth(); + auto windowContext = GetViewportContext()->GetWindowContext(); + const AZ::RHI::Viewport& viewport = windowContext->GetViewport(); + const float viewWidth = viewport.m_maxX - viewport.m_minX; + return viewWidth; } //////////////////////////////////////////////////////////////////////////////////////////////////// float CDraw2d::GetViewportHeight() const { - IRenderer* renderer = gEnv->pRenderer; - return (float)renderer->GetOverlayHeight(); + auto windowContext = GetViewportContext()->GetWindowContext(); + const AZ::RHI::Viewport& viewport = windowContext->GetViewport(); + const float viewHeight = viewport.m_maxY - viewport.m_minY; + return viewHeight; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -353,27 +359,28 @@ const CDraw2d::TextOptions& CDraw2d::GetDefaultTextOptions() const //////////////////////////////////////////////////////////////////////////////////////////////////// void CDraw2d::RenderDeferredPrimitives() { - IRenderer* renderer = gEnv->pRenderer; - - // Set up the 2D drawing state - renderer->SetCullMode(R_CULL_DISABLE); - - renderer->Set2DMode(renderer->GetOverlayWidth(), renderer->GetOverlayHeight(), m_backupSceneMatrices); - renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); - renderer->SetState(g_defaultBlendState | g_defaultBaseState); - // Draw and delete the deferred primitives + AZ::RPI::ViewportContextPtr viewportContext = GetViewportContext(); for (auto primIter : m_deferredPrimitives) { - primIter->Draw(); + primIter->Draw(m_dynamicDraw, m_shaderData, viewportContext); delete primIter; } // clear the list of deferred primitives m_deferredPrimitives.clear(); +} - // Reset the render state - renderer->Unset2DMode(m_backupSceneMatrices); +//////////////////////////////////////////////////////////////////////////////////////////////////// +void CDraw2d::SetDeferPrimitives(bool deferPrimitives) +{ + m_deferCalls = deferPrimitives; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +bool CDraw2d::GetDeferPrimitives() +{ + return m_deferCalls; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -414,6 +421,30 @@ AZ::Vector2 CDraw2d::Align(AZ::Vector2 position, AZ::Vector2 size, return result; } +//////////////////////////////////////////////////////////////////////////////////////////////////// +AZ::Data::Instance<AZ::RPI::Image> CDraw2d::LoadTexture(const AZStd::string& pathName) +{ + AZStd::string sourceRelativePath(pathName); + AZStd::string cacheRelativePath = sourceRelativePath + ".streamingimage"; + + // The file may not be in the AssetCatalog at this point if it is still processing or doesn't exist on disk. + // Use GenerateAssetIdTEMP instead of GetAssetIdByPath so that it will return a valid AssetId anyways + AZ::Data::AssetId streamingImageAssetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + streamingImageAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GenerateAssetIdTEMP, + sourceRelativePath.c_str()); + streamingImageAssetId.m_subId = AZ::RPI::StreamingImageAsset::GetImageAssetSubId(); + + auto streamingImageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset<AZ::RPI::StreamingImageAsset>(streamingImageAssetId, AZ::Data::AssetLoadBehavior::PreLoad); + AZ::Data::Instance<AZ::RPI::Image> image = AZ::RPI::StreamingImage::FindOrCreate(streamingImageAsset); + if (!image) + { + AZ_Error("Draw2d", false, "Failed to find or create an image instance from image asset '%s'", streamingImageAsset.GetHint().c_str()); + } + + return image; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // PROTECTED MEMBER FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -542,7 +573,7 @@ void CDraw2d::DrawOrDeferQuad(const DeferredQuad* quad) } else { - quad->Draw(); + quad->Draw(m_dynamicDraw, m_shaderData, GetViewportContext()); } } @@ -557,16 +588,33 @@ void CDraw2d::DrawOrDeferLine(const DeferredLine* line) } else { - line->Draw(); + line->Draw(m_dynamicDraw, m_shaderData, GetViewportContext()); } } +//////////////////////////////////////////////////////////////////////////////////////////////////// +AZ::RPI::ViewportContextPtr CDraw2d::GetViewportContext() const +{ + if (!m_viewportContext) + { + // Return the default viewport context + auto viewContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get(); + return viewContextManager->GetDefaultViewportContext(); + } + + // Return the user specified viewport context + return m_viewportContext; + +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // CDraw2d::DeferredQuad //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DeferredQuad::Draw() const +void CDraw2d::DeferredQuad::Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const { const int32 NUM_VERTS = 6; @@ -585,17 +633,41 @@ void CDraw2d::DeferredQuad::Draw() const vertices[i].st = Vec2(m_texCoords[j].GetX(), m_texCoords[j].GetY()); } - IRenderer* renderer = gEnv->pRenderer; - renderer->SetTexture(m_texId); + // Set up per draw SRG + AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg(); - // Set the render state, can't rely on this being right because font rendering changes it - renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); + // Set texture + const AZ::RHI::ImageView* imageView = m_image ? m_image->GetImageView() : nullptr; + if (!imageView) + { + // Default to white texture + auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + imageView = image->GetImageView(); + } - // set the desired render state - renderer->SetState(m_state); + if (imageView) + { + drawSrg->SetImageView(shaderData.m_imageInputIndex, imageView, 0); + } - // This will end up using DrawPrimitive to render the quad - renderer->DrawDynVB(vertices, nullptr, NUM_VERTS, 0, prtTriangleList); + // Set projection matrix + auto windowContext = viewportContext->GetWindowContext(); + const AZ::RHI::Viewport& viewport = windowContext->GetViewport(); + const float viewX = viewport.m_minX; + const float viewY = viewport.m_minY; + const float viewWidth = viewport.m_maxX - viewport.m_minX; + const float viewHeight = viewport.m_maxY - viewport.m_minY; + const float zf = viewport.m_minZ; + const float zn = viewport.m_maxZ; + AZ::Matrix4x4 modelViewProjMat; + AZ::MakeOrthographicMatrixRH(modelViewProjMat, viewX, viewX + viewWidth, viewY + viewHeight, viewY, zn, zf); + drawSrg->SetConstant(shaderData.m_viewProjInputIndex, modelViewProjMat); + + drawSrg->Compile(); + + // Add the primitive to the dynamic draw context for drawing + dynamicDraw->SetPrimitiveType(AZ::RHI::PrimitiveTopology::TriangleList); + dynamicDraw->DrawLinear(vertices, NUM_VERTS, drawSrg); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -603,7 +675,9 @@ void CDraw2d::DeferredQuad::Draw() const //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DeferredLine::Draw() const +void CDraw2d::DeferredLine::Draw(AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + const Draw2dShaderData& shaderData, + AZ::RPI::ViewportContextPtr viewportContext) const { const float z = 1.0f; // depth test disabled, if writing Z this will write at far plane @@ -618,15 +692,41 @@ void CDraw2d::DeferredLine::Draw() const vertices[i].st = Vec2(m_texCoords[i].GetX(), m_texCoords[i].GetY()); } - IRenderer* renderer = gEnv->pRenderer; - renderer->SetTexture(m_texId); + // Set up per draw SRG + AZ::Data::Instance<AZ::RPI::ShaderResourceGroup> drawSrg = dynamicDraw->NewDrawSrg(); + + // Set texture + const AZ::RHI::ImageView* imageView = m_image ? m_image->GetImageView() : nullptr; + if (!imageView) + { + // Default to white texture + auto image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + imageView = image->GetImageView(); + } - // Set the render state, can't rely on this being right because font rendering changes it - renderer->SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0); - renderer->SetState(m_state); + if (imageView) + { + drawSrg->SetImageView(shaderData.m_imageInputIndex, imageView, 0); + } - // This will end up using DrawPrimitive to render the quad - renderer->DrawDynVB(vertices, nullptr, NUM_VERTS, 0, prtLineList); + // Set projection matrix + auto windowContext = viewportContext->GetWindowContext(); + const AZ::RHI::Viewport& viewport = windowContext->GetViewport(); + const float viewX = viewport.m_minX; + const float viewY = viewport.m_minY; + const float viewWidth = viewport.m_maxX - viewport.m_minX; + const float viewHeight = viewport.m_maxY - viewport.m_minY; + const float zf = viewport.m_minZ; + const float zn = viewport.m_maxZ; + AZ::Matrix4x4 modelViewProjMat; + AZ::MakeOrthographicMatrixRH(modelViewProjMat, viewX, viewX + viewWidth, viewY + viewHeight, viewY, zn, zf); + drawSrg->SetConstant(shaderData.m_viewProjInputIndex, modelViewProjMat); + + drawSrg->Compile(); + + // Add the primitive to the dynamic draw context for drawing + dynamicDraw->SetPrimitiveType(AZ::RHI::PrimitiveTopology::LineList); + dynamicDraw->DrawLinear(vertices, NUM_VERTS, drawSrg); } @@ -635,7 +735,9 @@ void CDraw2d::DeferredLine::Draw() const //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -void CDraw2d::DeferredText::Draw() const +void CDraw2d::DeferredText::Draw([[maybe_unused]] AZ::RHI::Ptr<AZ::RPI::DynamicDrawContext> dynamicDraw, + [[maybe_unused]] const Draw2dShaderData& shaderData, + [[maybe_unused]] AZ::RPI::ViewportContextPtr viewportContext) const { m_font->DrawString(m_position.GetX(), m_position.GetY(), m_string.c_str(), true, m_fontContext); } diff --git a/Gems/LyShine/Code/Source/Draw2d.h b/Gems/LyShine/Code/Source/Draw2d.h deleted file mode 100644 index a62dc22937..0000000000 --- a/Gems/LyShine/Code/Source/Draw2d.h +++ /dev/null @@ -1,189 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -#pragma once - -#include <LyShine/IDraw2d.h> -#include <IRenderer.h> -#include <stack> - -//////////////////////////////////////////////////////////////////////////////////////////////////// -//! Implementation of IDraw2d interface for 2D drawing in screen space -// -//! The CDraw2d class implements the IDraw2d interface for drawing 2D images, shapes and text. -//! Positions and sizes are specified in pixels in the current 2D viewport. -class CDraw2d - : public IDraw2d -{ -public: // member functions - - //! Constructor, constructed by the LyShine class - CDraw2d(); - - // IDraw2d - - ~CDraw2d() override; - - //! Start a section of 2D drawing function calls. This will set appropriate render state. - void BeginDraw2d(bool deferCalls = false) override; - - //! Start a section of 2D drawing function calls. This will set appropriate render state. - //! This variant allows the viewport size to be specified - void BeginDraw2d(AZ::Vector2 viewportSize, bool deferCalls = false) override; - - //! End a section of 2D drawing function calls. This will reset some render state. - void EndDraw2d() override; - - //! Draw a textured quad, optional rotation is counter-clockwise in degrees. - void DrawImage(int texId, AZ::Vector2 position, AZ::Vector2 size, float opacity = 1.0f, - float rotation = 0.0f, const AZ::Vector2* pivotPoint = nullptr, const AZ::Vector2* minMaxTexCoords = nullptr, - ImageOptions* imageOptions = nullptr) override; - - //! Draw a textured quad where the position specifies the point specified by the alignment. Rotation is around that point. - void DrawImageAligned(int texId, AZ::Vector2 position, AZ::Vector2 size, - HAlign horizontalAlignment, VAlign verticalAlignment, - float opacity = 1.0f, float rotation = 0.0f, const AZ::Vector2* minMaxTexCoords = nullptr, - ImageOptions* imageOptions = nullptr) override; - - //! Draw a textured quad where the position, color and uv of each point is specified explicitly - void DrawQuad(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) override; - - //! Draw a line - void DrawLine(AZ::Vector2 start, AZ::Vector2 end, AZ::Color color, int blendMode, Rounding pixelRounding, int baseState) override; - - //! Draw a line textured - void DrawLineTextured(int texId, VertexPosColUV* verts, int blendMode, Rounding pixelRounding, int baseState) override; - - //! Draw a text string. Only supports ASCII text. - void DrawText(const char* textString, AZ::Vector2 position, float pointSize, - float opacity = 1.0f, TextOptions* textOptions = nullptr) override; - - //! Get the width and height (in pixels) that would be used to draw the given text string. - AZ::Vector2 GetTextSize(const char* textString, float pointSize, TextOptions* textOptions = nullptr) override; - - //! Get the width of the rendering viewport (in pixels). - float GetViewportWidth() const override; - - //! Get the height of the rendering viewport (in pixels). - float GetViewportHeight() const override; - - //! Get the default values that would be used if no image options were passed in - const ImageOptions& GetDefaultImageOptions() const override; - - //! Get the default values that would be used if no text options were passed in - const TextOptions& GetDefaultTextOptions() const override; - - // ~IDraw2d - - //! Render the primitives that have been deferred - void RenderDeferredPrimitives(); - -private: - - AZ_DISABLE_COPY_MOVE(CDraw2d); - -public: // static member functions - - //! Given a position and size and an alignment return the top left corner of the aligned quad - static AZ::Vector2 Align(AZ::Vector2 position, AZ::Vector2 size, HAlign horizontalAlignment, VAlign verticalAlignment); - -protected: // types and constants - - enum - { - MAX_VERTICES_IN_PRIM = 6 - }; - - class DeferredPrimitive - { - public: - virtual ~DeferredPrimitive() {}; - virtual void Draw() const = 0; - }; - - class DeferredQuad - : public DeferredPrimitive - { - public: - ~DeferredQuad() override {}; - void Draw() const override; - - AZ::Vector2 m_points[4]; - AZ::Vector2 m_texCoords[4]; - uint32 m_packedColors[4]; - int m_texId; - int m_state; - }; - - class DeferredLine - : public DeferredPrimitive - { - public: - ~DeferredLine() override {}; - void Draw() const override; - - int m_texId; - AZ::Vector2 m_points[2]; - AZ::Vector2 m_texCoords[2]; - uint32 m_packedColors[2]; - int m_state; - }; - - class DeferredText - : public DeferredPrimitive - { - public: - ~DeferredText() override {}; - void Draw() const override; - - STextDrawContext m_fontContext; - IFFont* m_font; - AZ::Vector2 m_position; - std::string m_string; - }; - -protected: // member functions - - //! Rotate an array of points around the z-axis at the pivot point. - // - //! Angle is in degrees counter-clockwise - void RotatePointsAboutPivot(AZ::Vector2* points, int numPoints, AZ::Vector2 pivot, float angle) const; - - //! Helper function to render a text string - void DrawTextInternal(const char* textString, IFFont* font, unsigned int effectIndex, - AZ::Vector2 position, float pointSize, AZ::Color color, float rotation, - HAlign horizontalAlignment, VAlign verticalAlignment, int baseState); - - //! Draw or defer a quad - void DrawOrDeferQuad(const DeferredQuad* quad); - - //! Draw or defer a line - void DrawOrDeferLine(const DeferredLine* line); - -protected: // attributes - - ImageOptions m_defaultImageOptions; //!< The default image options used if nullptr is passed - TextOptions m_defaultTextOptions; //!< The default text options used if nullptr is passed - - bool m_deferCalls; //!< True if the actual render of the primitives should be deferred until end of frame - - std::vector<DeferredPrimitive*> m_deferredPrimitives; - - //! These two data members allows nested calls to BeginDraw2d/EndDraw2d. We will begin 2D mode only on the - //! outermost call to BeginDraw2d with deferCalls set to false and will end 2D mode on the corresposnding - //! call to EndDraw2d. The stack is used to detect that corresponding call and we need the level it occurred - //! to know when to end 2D mode. - int m_nestLevelAtWhichStarted2dMode; - std::stack<bool> m_deferCallsFlagStack; - -private: - TransformationMatrices m_backupSceneMatrices; -}; diff --git a/Gems/LyShine/Code/Source/LyShine.cpp b/Gems/LyShine/Code/Source/LyShine.cpp index cfea0cbdf7..286e756ffa 100644 --- a/Gems/LyShine/Code/Source/LyShine.cpp +++ b/Gems/LyShine/Code/Source/LyShine.cpp @@ -13,8 +13,6 @@ #include "LyShine.h" -#include "Draw2d.h" - #include "UiCanvasComponent.h" #include "UiCanvasManager.h" #include "LyShineDebug.h" @@ -55,6 +53,7 @@ #include <LyShine/Bus/UiCursorBus.h> #include <LyShine/Bus/UiDraggableBus.h> #include <LyShine/Bus/UiDropTargetBus.h> +#include <LyShine/Draw2d.h> #if defined(LYSHINE_INTERNAL_UNIT_TEST) #include "TextMarkup.h" @@ -455,7 +454,6 @@ void CLyShine::Render() // Render all the canvases loaded in game m_uiCanvasManager->RenderLoadedCanvases(); -#ifdef LYSHINE_ATOM_TODO // convert cursor support to use Atom m_draw2d->RenderDeferredPrimitives(); // Don't render the UI cursor when in edit mode. For example during UI Preview mode a script could turn on the @@ -466,7 +464,6 @@ void CLyShine::Render() { RenderUiCursor(); } -#endif GetUiRenderer()->EndUiFrameRender(); @@ -687,9 +684,11 @@ void CLyShine::RenderUiCursor() const AZ::Vector2 position = GetUiCursorPosition(); const AZ::Vector2 dimensions(static_cast<float>(m_uiCursorTexture->GetWidth()), static_cast<float>(m_uiCursorTexture->GetHeight())); +#ifdef LYSHINE_ATOM_TODO // Convert cursor to Atom image m_draw2d->BeginDraw2d(); m_draw2d->DrawImage(m_uiCursorTexture->GetTextureID(), position, dimensions); m_draw2d->EndDraw2d(); +#endif } #ifndef _RELEASE diff --git a/Gems/LyShine/Code/Source/LyShineDebug.cpp b/Gems/LyShine/Code/Source/LyShineDebug.cpp index f1ce411d83..5ea01c5c1e 100644 --- a/Gems/LyShine/Code/Source/LyShineDebug.cpp +++ b/Gems/LyShine/Code/Source/LyShineDebug.cpp @@ -12,8 +12,9 @@ #include "LyShine_precompiled.h" #include "LyShineDebug.h" #include "IConsole.h" -#include <LyShine/IDraw2d.h> -#include "IRenderer.h" +#include <LyShine/Draw2d.h> + +#include <Atom/RPI.Public/Image/ImageSystemInterface.h> #include <AzCore/Math/Crc.h> #include <AzCore/Serialization/SerializeContext.h> @@ -105,15 +106,24 @@ static bool g_deferDrawsToEndOfFrame = false; //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) +#ifdef LYSHINE_ATOM_TODO static int Create2DTexture(int width, int height, byte* data, ETEX_Format format) { IRenderer* renderer = gEnv->pRenderer; return renderer->DownLoadToVideoMemory(data, width, height, format, format, 1); } #endif +#endif + +static AZ::Vector2 GetTextureSize(AZ::Data::Instance<AZ::RPI::Image> image) +{ + AZ::RHI::Size size = image->GetDescriptor().m_size; + return AZ::Vector2(size.m_width, size.m_height); +} //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) +#ifdef LYSHINE_ATOM_TODO static void FillTextureRectWithCheckerboard(uint32* data, int textureWidth, int textureHeight, int minX, int minY, [[maybe_unused]] int rectWidth, int rectHeight, int tileWidth, int tileHeight, uint32* colors, bool varyAlpha) @@ -139,11 +149,13 @@ static void FillTextureRectWithCheckerboard(uint32* data, int textureWidth, int } } #endif +#endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* CreateMonoTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> CreateMonoTestTexture() { +#ifdef LYSHINE_ATOM_TODO const int width = 32; const int height = 32; uint32 data[width * height]; @@ -172,13 +184,18 @@ static ITexture* CreateMonoTestTexture() int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8); return gEnv->pRenderer->EF_GetTextureByID(textureId); +#else + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + return whiteTexture; +#endif } #endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* CreateColorTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> CreateColorTestTexture() { +#ifdef LYSHINE_ATOM_TODO const int width = 32; const int height = 32; uint32 data[width * height]; @@ -207,13 +224,18 @@ static ITexture* CreateColorTestTexture() int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8); return gEnv->pRenderer->EF_GetTextureByID(textureId); +#else + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + return whiteTexture; +#endif } #endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* CreateMonoAlphaTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> CreateMonoAlphaTestTexture() { +#ifdef LYSHINE_ATOM_TODO const int width = 32; const int height = 32; uint32 data[width * height]; @@ -242,13 +264,18 @@ static ITexture* CreateMonoAlphaTestTexture() int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8); return gEnv->pRenderer->EF_GetTextureByID(textureId); +#else + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + return whiteTexture; +#endif } #endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* CreateColorAlphaTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> CreateColorAlphaTestTexture() { +#ifdef LYSHINE_ATOM_TODO const int width = 32; const int height = 32; uint32 data[width * height]; @@ -277,14 +304,18 @@ static ITexture* CreateColorAlphaTestTexture() int textureId = Create2DTexture(width, height, (uint8*)data, eTF_R8G8B8A8); return gEnv->pRenderer->EF_GetTextureByID(textureId); +#else + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + return whiteTexture; +#endif } #endif //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* GetMonoTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> GetMonoTestTexture() { - static ITexture* testImageMono = nullptr; + static AZ::Data::Instance<AZ::RPI::Image> testImageMono = nullptr; if (!testImageMono) { @@ -297,9 +328,9 @@ static ITexture* GetMonoTestTexture() //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* GetColorTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> GetColorTestTexture() { - static ITexture* testImageColor = nullptr; + static AZ::Data::Instance<AZ::RPI::Image> testImageColor = nullptr; if (!testImageColor) { @@ -312,9 +343,9 @@ static ITexture* GetColorTestTexture() //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* GetMonoAlphaTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> GetMonoAlphaTestTexture() { - static ITexture* testImageMonoAlpha = nullptr; + static AZ::Data::Instance<AZ::RPI::Image> testImageMonoAlpha = nullptr; if (!testImageMonoAlpha) { @@ -327,9 +358,9 @@ static ITexture* GetMonoAlphaTestTexture() //////////////////////////////////////////////////////////////////////////////////////////////////// #if !defined(_RELEASE) -static ITexture* GetColorAlphaTestTexture() +static AZ::Data::Instance<AZ::RPI::Image> GetColorAlphaTestTexture() { - static ITexture* testImageColorAlpha = nullptr; + static AZ::Data::Instance<AZ::RPI::Image> testImageColorAlpha = nullptr; if (!testImageColorAlpha) { @@ -347,14 +378,12 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col IDraw2d::HAlign horizontalAlignment = IDraw2d::HAlign::Left, IDraw2d::VAlign verticalAlignment = IDraw2d::VAlign::Top) { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - IRenderer* renderer = gEnv->pRenderer; + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - int whiteTextureId = renderer->GetWhiteTextureId(); - imageOptions.color = color.GetAsVector3(); - draw2d->DrawImageAligned(whiteTextureId, pos, size, horizontalAlignment, verticalAlignment, + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); + draw2d->DrawImageAligned(whiteTexture, pos, size, horizontalAlignment, verticalAlignment, color.GetA(), 0.0f, nullptr, &imageOptions); } #endif @@ -364,7 +393,7 @@ static void DebugDrawColoredBox(AZ::Vector2 pos, AZ::Vector2 size, AZ::Color col static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, const char* sizeString, const char* testString, AZ::Vector2 pos, float spacing, float size) { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); IDraw2d::TextOptions textOptions = draw2d->GetDefaultTextOptions(); if (font) @@ -398,9 +427,7 @@ static void DebugDrawStringWithSizeBox(IFFont* font, unsigned int effectIndex, c #if !defined(_RELEASE) static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const char* fontName) { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); float xOffset = 20.0f; float yOffset = 20.0f; @@ -463,8 +490,6 @@ static void DebugDraw2dFontSizes(IFFont* font, unsigned int effectIndex, const c yOffset += 55.0f; DebugDrawStringWithSizeBox(font, effectIndex, "Size 49", testString, AZ::Vector2(xOffset, yOffset), xSpacing, 49); - - draw2d->EndDraw2d(); } #endif @@ -524,7 +549,7 @@ static void DebugDrawAlignedTextWithOriginBox(AZ::Vector2 pos, #if !defined(_RELEASE) static void DebugDraw2dFontAlignment() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); float w = draw2d->GetViewportWidth(); float yPos = 20; @@ -591,7 +616,7 @@ static void DebugDraw2dFontAlignment() #if !defined(_RELEASE) static AZ::Vector2 DebugDrawFontColorTestBox(AZ::Vector2 pos, const char* string, AZ::Vector3 color, float opacity) { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); float pointSize = 32.0f; const float spacing = 6.0f; @@ -626,9 +651,7 @@ static AZ::Vector2 DebugDrawFontColorTestBox(AZ::Vector2 pos, const char* string #if !defined(_RELEASE) static void DebugDraw2dFontColorAndOpacity() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); AZ::Vector2 size; AZ::Vector2 pos(20.0f, 20.0f); @@ -659,8 +682,6 @@ static void DebugDraw2dFontColorAndOpacity() draw2d->DrawText("Opacity=0.25f", pos, 24.0f); pos.SetX(pos.GetX() + 200.0f); draw2d->DrawText("Opacity=0.00f", pos, 24.0f); - - draw2d->EndDraw2d(); } #endif @@ -668,16 +689,11 @@ static void DebugDraw2dFontColorAndOpacity() #if !defined(_RELEASE) static void DebugDraw2dImageRotations() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - ITexture* texture = GetMonoTestTexture(); - int texId = texture->GetTextureID(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); + AZ::Data::Instance<AZ::RPI::Image> texture = GetMonoTestTexture(); - float width = (float)texture->GetWidth(); - float height = (float)texture->GetHeight(); - AZ::Vector2 size(width, height); + AZ::Vector2 size = GetTextureSize(texture); float row = 20.0f; float xSpacing = size.GetX() * 2.0f; @@ -690,7 +706,7 @@ static void DebugDraw2dImageRotations() for (int i = 0; i < 10; ++i) { AZ::Vector2 pos(xStart + xSpacing * i, row); - draw2d->DrawImage(texId, pos, size, 1.0f, 45.0f * i); + draw2d->DrawImage(texture, pos, size, 1.0f, 45.0f * i); DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor); } @@ -703,7 +719,7 @@ static void DebugDraw2dImageRotations() { AZ::Vector2 pos(xStart + xSpacing * i, row); AZ::Vector2 pivot = pos + pivotOffset; - draw2d->DrawImage(texId, pos, size, 1.0f, 45.0f * i, &pivot); + draw2d->DrawImage(texture, pos, size, 1.0f, 45.0f * i, &pivot); DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor); DebugDrawColoredBox(AZ::Vector2(pivot.GetX() - 2, pivot.GetY() - 2), AZ::Vector2(5, 5), pivotBoxColor); } @@ -715,11 +731,9 @@ static void DebugDraw2dImageRotations() for (int i = 0; i < 10; ++i) { AZ::Vector2 pos(xStart + xSpacing * i + size.GetX() * 0.5f, row + size.GetY() * 0.5f); - draw2d->DrawImageAligned(texId, pos, size, IDraw2d::HAlign::Center, IDraw2d::VAlign::Center, 1.0f, 45.0f * i); + draw2d->DrawImageAligned(texture, pos, size, IDraw2d::HAlign::Center, IDraw2d::VAlign::Center, 1.0f, 45.0f * i); DebugDrawColoredBox(AZ::Vector2(pos.GetX() - 2, pos.GetY() - 2), AZ::Vector2(5, 5), posBoxColor); } - - draw2d->EndDraw2d(); } #endif @@ -727,22 +741,17 @@ static void DebugDraw2dImageRotations() #if !defined(_RELEASE) static void DebugDraw2dImageColor() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - ITexture* texture = GetMonoAlphaTestTexture(); - int texId = texture->GetTextureID(); + AZ::Data::Instance<AZ::RPI::Image> texture = GetMonoAlphaTestTexture(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - draw2d->DrawText( "Testing image colors, image is black and white, top row is opacity=1, bottom row is opacity = 0.5", AZ::Vector2(20, 20), 16); - float width = texture->GetWidth() * 2.0f; - float height = texture->GetHeight() * 2.0f; - AZ::Vector2 size(width, height); + AZ::Vector2 size = GetTextureSize(texture) * 2.0f; float xStart = 20.0f; float yStart = 50.0f; @@ -755,14 +764,12 @@ static void DebugDraw2dImageColor() // Draw the image with this color imageOptions.color = g_colorVec3[color]; - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); // draw below with half opacity to test combination of color and opacity pos.SetY(pos.GetY() + ySpacing); - draw2d->DrawImage(texId, pos, size, 0.5f, 0.0f, 0, 0, &imageOptions); + draw2d->DrawImage(texture, pos, size, 0.5f, 0.0f, 0, 0, &imageOptions); } - - draw2d->EndDraw2d(); } #endif @@ -770,24 +777,20 @@ static void DebugDraw2dImageColor() #if !defined(_RELEASE) static void DebugDraw2dImageBlendMode() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - IRenderer* renderer = gEnv->pRenderer; + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - int whiteTextureId = renderer->GetWhiteTextureId(); + auto whiteTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::White); - ITexture* texture = GetColorAlphaTestTexture(); - int texId = texture->GetTextureID(); + AZ::Data::Instance<AZ::RPI::Image> texture = GetColorAlphaTestTexture(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - draw2d->DrawText("Testing blend modes, src blend changes across x-axis, dst blend changes across y axis", AZ::Vector2(20, 20), 16); - float width = (float)texture->GetWidth(); - float height = (float)texture->GetHeight(); - AZ::Vector2 size(width, height); + AZ::Vector2 size = GetTextureSize(texture); + float width = size.GetX(); + float height = size.GetY(); float xStart = 20.0f; float yStart = 60.0f; @@ -824,16 +827,14 @@ static void DebugDraw2dImageBlendMode() AZ::Vector2(0.0f, 1.0f) }, }; - draw2d->DrawQuad(whiteTextureId, verts); + draw2d->DrawQuad(whiteTexture, verts); // Draw the image with this color imageOptions.blendMode = g_srcBlendModes[srcIndex] | g_dstBlendModes[dstIndex]; - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); } } - - draw2d->EndDraw2d(); } #endif @@ -841,20 +842,17 @@ static void DebugDraw2dImageBlendMode() #if !defined(_RELEASE) static void DebugDraw2dImageUVs() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - ITexture* texture = GetColorTestTexture(); - int texId = texture->GetTextureID(); + AZ::Data::Instance<AZ::RPI::Image> texture = GetColorTestTexture(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - draw2d->DrawText( "Testing DrawImage with minMaxTexCoords. Full image, top left quadrant, middle section, full flipped", AZ::Vector2(20, 20), 16); - AZ::Vector2 size((float)texture->GetWidth() * 2.0f, (float)texture->GetHeight() * 2.0f); + AZ::Vector2 size = GetTextureSize(texture) * 2.0f; float xStart = 20.0f; float yStart = 50.0f; @@ -867,27 +865,25 @@ static void DebugDraw2dImageUVs() // full image minMaxTexCoords[0] = AZ::Vector2(0, 0); minMaxTexCoords[1] = AZ::Vector2(1, 1); - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); // top left quadrant of image pos.SetX(pos.GetX() + xSpacing); minMaxTexCoords[0] = AZ::Vector2(0, 0); minMaxTexCoords[1] = AZ::Vector2(0.5, 0.5); - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); // middle of image pos.SetX(pos.GetX() + xSpacing); minMaxTexCoords[0] = AZ::Vector2(0.25, 0.25); minMaxTexCoords[1] = AZ::Vector2(0.75, 0.75); - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); // flip of image pos.SetX(pos.GetX() + xSpacing); minMaxTexCoords[0] = AZ::Vector2(0.0, 1.0); minMaxTexCoords[1] = AZ::Vector2(1.0, 0.0); - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); - - draw2d->EndDraw2d(); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, minMaxTexCoords); } #endif @@ -895,18 +891,15 @@ static void DebugDraw2dImageUVs() #if !defined(_RELEASE) static void DebugDraw2dImagePixelRounding() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); - ITexture* texture = GetColorTestTexture(); - int texId = texture->GetTextureID(); + AZ::Data::Instance<AZ::RPI::Image> texture = GetColorTestTexture(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - draw2d->DrawText("Testing DrawImage pixel rounding options", AZ::Vector2(20, 20), 16); - AZ::Vector2 size((float)texture->GetWidth(), (float)texture->GetHeight()); + AZ::Vector2 size = GetTextureSize(texture); float xStart = 20.0f; float yStart = 50.0f; @@ -929,11 +922,9 @@ static void DebugDraw2dImagePixelRounding() imageOptions.pixelRounding = roundings[j]; - draw2d->DrawImage(texId, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); + draw2d->DrawImage(texture, pos, size, 1.0f, 0.0f, 0, 0, &imageOptions); } } - - draw2d->EndDraw2d(); } #endif @@ -941,12 +932,10 @@ static void DebugDraw2dImagePixelRounding() #if !defined(_RELEASE) static void DebugDraw2dLineBasic() { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); IDraw2d::ImageOptions imageOptions = draw2d->GetDefaultImageOptions(); - draw2d->BeginDraw2d(g_deferDrawsToEndOfFrame); - draw2d->DrawText("Testing DrawLine", AZ::Vector2(20, 20), 16); AZ::Vector2 center = AZ::Vector2(draw2d->GetViewportWidth() * 0.5f, draw2d->GetViewportHeight() * 0.5f); @@ -963,8 +952,6 @@ static void DebugDraw2dLineBasic() draw2d->DrawLine(center, center + AZ::Vector2(-offset, -offset), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)); draw2d->DrawLine(center, center + AZ::Vector2(0, -offset), AZ::Color(1.0f, 0.0f, 1.0f, 1.0f)); draw2d->DrawLine(center, center + AZ::Vector2(offset, -offset), AZ::Color(0.0f, 0.0f, 0.0f, 1.0f)); - - draw2d->EndDraw2d(); } #endif @@ -1436,13 +1423,17 @@ void LyShineDebug::RenderDebug() #if !defined(_RELEASE) #ifndef EXCLUDE_DOCUMENTATION_PURPOSE - if (!Draw2dHelper::GetDraw2d()) + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); + if (!draw2d) { return; } g_deferDrawsToEndOfFrame = (CV_r_DebugUIDraw2dDefer) ? true : false; + // Set whether to defer draws or render immediately during scope of this helper + Draw2dHelper draw2dHelper(g_deferDrawsToEndOfFrame); + if (CV_r_DebugUIDraw2dFont) { switch (CV_r_DebugUIDraw2dFont) diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp index f386d5756b..2af773734c 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.cpp @@ -33,6 +33,7 @@ #include <LyShine/Bus/UiEntityContextBus.h> #include <LyShine/Bus/UiCanvasUpdateNotificationBus.h> #include <LyShine/UiSerializeHelpers.h> +#include <LyShine/Draw2d.h> #include <AzCore/Math/Crc.h> #include <AzCore/Memory/Memory.h> @@ -2224,13 +2225,13 @@ void UiCanvasComponent::DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LySh } //////////////////////////////////////////////////////////////////////////////////////////////////// -void UiCanvasComponent::DebugDisplayElemBounds(IDraw2d* draw2d) const +void UiCanvasComponent::DebugDisplayElemBounds(CDraw2d* draw2d) const { DebugDisplayChildElemBounds(draw2d, m_rootElement); } //////////////////////////////////////////////////////////////////////////////////////////////////// -void UiCanvasComponent::DebugDisplayChildElemBounds(IDraw2d* draw2d, const AZ::EntityId entity) const +void UiCanvasComponent::DebugDisplayChildElemBounds(CDraw2d* draw2d, const AZ::EntityId entity) const { AZ::u64 time = AZStd::GetTimeUTCMilliSecond(); uint32 fractionsOfOneSecond = time % 1000; diff --git a/Gems/LyShine/Code/Source/UiCanvasComponent.h b/Gems/LyShine/Code/Source/UiCanvasComponent.h index 6e59a0899f..3e7171c642 100644 --- a/Gems/LyShine/Code/Source/UiCanvasComponent.h +++ b/Gems/LyShine/Code/Source/UiCanvasComponent.h @@ -42,6 +42,7 @@ namespace AZ } struct SDepthTexture; +class CDraw2d; //////////////////////////////////////////////////////////////////////////////////////////////////// class UiCanvasComponent @@ -287,8 +288,8 @@ public: // member functions void DebugReportDrawCalls(AZ::IO::HandleType fileHandle, LyShineDebug::DebugInfoDrawCallReport& reportInfo, void* context) const; - void DebugDisplayElemBounds(IDraw2d* draw2d) const; - void DebugDisplayChildElemBounds(IDraw2d* draw2d, const AZ::EntityId entity) const; + void DebugDisplayElemBounds(CDraw2d* draw2d) const; + void DebugDisplayChildElemBounds(CDraw2d* draw2d, const AZ::EntityId entity) const; #endif public: // static member functions diff --git a/Gems/LyShine/Code/Source/UiCanvasManager.cpp b/Gems/LyShine/Code/Source/UiCanvasManager.cpp index 380095a289..6575a1d2f0 100644 --- a/Gems/LyShine/Code/Source/UiCanvasManager.cpp +++ b/Gems/LyShine/Code/Source/UiCanvasManager.cpp @@ -11,6 +11,7 @@ */ #include "LyShine_precompiled.h" #include "UiCanvasManager.h" +#include <LyShine/Draw2d.h> #include "UiCanvasFileObject.h" #include "UiCanvasComponent.h" @@ -33,6 +34,8 @@ #include <LyShine/Bus/World/UiCanvasOnMeshBus.h> #include <LyShine/Bus/World/UiCanvasRefBus.h> +#include <Atom/RPI.Public/Image/ImageSystemInterface.h> + #ifndef _RELEASE #include <AzFramework/IO/LocalFileIO.h> #endif @@ -998,16 +1001,15 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const { bool onlyShowEnabledCanvases = (setting == 2) ? true : false; - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - draw2d->BeginDraw2d(false); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); float xOffset = 20.0f; float yOffset = 20.0f; const int elementNameFieldLength = 20; - int blackTexture = gEnv->pRenderer->GetBlackTextureId(); + auto blackTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Black); + float textOpacity = 1.0f; float backgroundRectOpacity = 0.75f; @@ -1152,21 +1154,17 @@ void UiCanvasManager::DebugDisplayCanvasData(int setting) const totalEnabledIntrs, totalEnabledUpdates); WriteLine(buffer, red); - - draw2d->EndDraw2d(); } //////////////////////////////////////////////////////////////////////////////////////////////////// void UiCanvasManager::DebugDisplayDrawCallData() const { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - draw2d->BeginDraw2d(false); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); float xOffset = 20.0f; float yOffset = 20.0f; - int blackTexture = gEnv->pRenderer->GetBlackTextureId(); + auto blackTexture = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Black); float textOpacity = 1.0f; float backgroundRectOpacity = 0.75f; const float lineSpacing = 20.0f; @@ -1293,8 +1291,6 @@ void UiCanvasManager::DebugDisplayDrawCallData() const totalDueToMaxVerts, totalDueToTextures); WriteLine(buffer, red); - - draw2d->EndDraw2d(); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -1492,9 +1488,7 @@ void UiCanvasManager::DebugReportDrawCalls(const AZStd::string& name) const //////////////////////////////////////////////////////////////////////////////////////////////////// void UiCanvasManager::DebugDisplayElemBounds(int canvasIndexFilter) const { - IDraw2d* draw2d = Draw2dHelper::GetDraw2d(); - - draw2d->BeginDraw2d(false); + CDraw2d* draw2d = Draw2dHelper::GetDefaultDraw2d(); int canvasIndex = 0; for (auto canvas : m_loadedCanvases) @@ -1515,8 +1509,6 @@ void UiCanvasManager::DebugDisplayElemBounds(int canvasIndexFilter) const ++canvasIndex; // only increments for enabled canvases so index matches "ui_DisplayCanvasData 2" } - - draw2d->EndDraw2d(); } #endif diff --git a/Gems/LyShine/Code/Source/UiFaderComponent.cpp b/Gems/LyShine/Code/Source/UiFaderComponent.cpp index 96690db7c9..3259da0480 100644 --- a/Gems/LyShine/Code/Source/UiFaderComponent.cpp +++ b/Gems/LyShine/Code/Source/UiFaderComponent.cpp @@ -11,6 +11,7 @@ */ #include "LyShine_precompiled.h" #include "UiFaderComponent.h" +#include <LyShine/Draw2d.h> #include <AzCore/Math/Crc.h> #include <AzCore/Math/MathUtils.h> diff --git a/Gems/LyShine/Code/Source/UiImageComponent.cpp b/Gems/LyShine/Code/Source/UiImageComponent.cpp index b5b407c421..02ea1467dc 100644 --- a/Gems/LyShine/Code/Source/UiImageComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageComponent.cpp @@ -20,7 +20,7 @@ #include <IRenderer.h> -#include <LyShine/IDraw2d.h> +#include <LyShine/Draw2d.h> #include <LyShine/UiSerializeHelpers.h> #include <LyShine/Bus/UiElementBus.h> #include <LyShine/Bus/UiCanvasBus.h> diff --git a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp index 518be03751..e6cbef8386 100644 --- a/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp +++ b/Gems/LyShine/Code/Source/UiImageSequenceComponent.cpp @@ -12,7 +12,7 @@ #include "LyShine_precompiled.h" #include "UiImageSequenceComponent.h" -#include <LyShine/IDraw2d.h> +#include <LyShine/Draw2d.h> #include <LyShine/ISprite.h> #include <LyShine/IRenderGraph.h> #include <LyShine/Bus/UiElementBus.h> diff --git a/Gems/LyShine/Code/Source/UiMaskComponent.cpp b/Gems/LyShine/Code/Source/UiMaskComponent.cpp index df49673858..f7452108e7 100644 --- a/Gems/LyShine/Code/Source/UiMaskComponent.cpp +++ b/Gems/LyShine/Code/Source/UiMaskComponent.cpp @@ -11,6 +11,7 @@ */ #include "LyShine_precompiled.h" #include "UiMaskComponent.h" +#include <LyShine/Draw2d.h> #include <AzCore/Math/Crc.h> #include <AzCore/Serialization/SerializeContext.h> @@ -23,7 +24,6 @@ #include <LyShine/Bus/UiRenderBus.h> #include <LyShine/Bus/UiVisualBus.h> #include <LyShine/Bus/UiCanvasBus.h> -#include <LyShine/IDraw2d.h> //////////////////////////////////////////////////////////////////////////////////////////////////// // PUBLIC MEMBER FUNCTIONS diff --git a/Gems/LyShine/Code/Source/UiTextComponent.cpp b/Gems/LyShine/Code/Source/UiTextComponent.cpp index a718cc8e53..b1092ab92f 100644 --- a/Gems/LyShine/Code/Source/UiTextComponent.cpp +++ b/Gems/LyShine/Code/Source/UiTextComponent.cpp @@ -28,11 +28,11 @@ #include <LyShine/Bus/UiCanvasBus.h> #include <LyShine/UiSerializeHelpers.h> #include <LyShine/IRenderGraph.h> +#include <LyShine/Draw2d.h> #include <ILocalizationManager.h> #include "UiSerialize.h" -#include "Draw2d.h" #include "TextMarkup.h" #include "UiTextComponentOffsetsSelector.h" #include "StringUtfUtils.h" diff --git a/Gems/LyShine/Code/lyshine_static_files.cmake b/Gems/LyShine/Code/lyshine_static_files.cmake index 140debff84..8491a66030 100644 --- a/Gems/LyShine/Code/lyshine_static_files.cmake +++ b/Gems/LyShine/Code/lyshine_static_files.cmake @@ -11,7 +11,7 @@ set(FILES Source/Draw2d.cpp - Source/Draw2d.h + Include/LyShine/Draw2d.h Source/LyShine.cpp Source/LyShine.h Source/LyShineDebug.cpp diff --git a/Gems/LyShineExamples/Code/CMakeLists.txt b/Gems/LyShineExamples/Code/CMakeLists.txt index ccf49ba467..372bfa948b 100644 --- a/Gems/LyShineExamples/Code/CMakeLists.txt +++ b/Gems/LyShineExamples/Code/CMakeLists.txt @@ -23,6 +23,7 @@ ly_add_target( PUBLIC Legacy::CryCommon Gem::LmbrCentral + Gem::LyShine.Static ) ly_add_target( diff --git a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp index 4ff8128d47..80750efe7f 100644 --- a/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp +++ b/Gems/LyShineExamples/Code/Source/UiCustomImageComponent.cpp @@ -20,7 +20,7 @@ #include <IRenderer.h> -#include <LyShine/IDraw2d.h> +#include <LyShine/Draw2d.h> #include <LyShine/ISprite.h> #include <LyShine/Bus/UiElementBus.h> #include <LyShine/Bus/UiCanvasBus.h> From a177067e9b1aa60288f9d1c7648d9d0fa4691d69 Mon Sep 17 00:00:00 2001 From: moudgils <moudgils@amazon.com> Date: Thu, 22 Apr 2021 08:52:44 -0700 Subject: [PATCH 75/96] Bump shader builder --- .../Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index d50e5ff719..a0f9f7db22 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -102,7 +102,7 @@ namespace AZ // Register Shader Resource Group Layout Builder AssetBuilderSDK::AssetBuilderDesc srgLayoutBuilderDescriptor; srgLayoutBuilderDescriptor.m_name = "Shader Resource Group Layout Builder"; - srgLayoutBuilderDescriptor.m_version = 53; // ATOM-15196 + srgLayoutBuilderDescriptor.m_version = 54; // Enable Null Rhi for AutomatedTesting srgLayoutBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.azsl", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); srgLayoutBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.azsli", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); @@ -118,7 +118,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 97; // ATOM-15196 + shaderAssetBuilderDescriptor.m_version = 98; // Enable Null Rhi for AutomatedTesting // .shader file changes trigger rebuilds shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderAssetBuilder>(); @@ -133,7 +133,7 @@ namespace AZ shaderVariantAssetBuilderDescriptor.m_name = "Shader Variant Asset Builder"; // Both "Shader Variant Asset Builder" and "Shader Asset Builder" produce ShaderVariantAsset products. If you update // ShaderVariantAsset you will need to update BOTH version numbers, not just "Shader Variant Asset Builder". - shaderVariantAssetBuilderDescriptor.m_version = 18; // ATOM-15196 + shaderVariantAssetBuilderDescriptor.m_version = 19; // Enable Null Rhi for AutomatedTesting shaderVariantAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string::format("*.%s", RPI::ShaderVariantListSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderVariantAssetBuilderDescriptor.m_busId = azrtti_typeid<ShaderVariantAssetBuilder>(); shaderVariantAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderVariantAssetBuilder::CreateJobs, &m_shaderVariantAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); From 61fd73b4670b8b17c40a6364114631fed5df9787 Mon Sep 17 00:00:00 2001 From: Chris Burel <burelc@amazon.com> Date: Thu, 22 Apr 2021 09:01:55 -0700 Subject: [PATCH 76/96] Enable the mesh optimizer (#231) --- .../Components/MeshOptimizer/MeshOptimizerComponent.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp index 64ea69f4e4..464ac1e334 100644 --- a/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp +++ b/Gems/SceneProcessing/Code/Source/Generation/Components/MeshOptimizer/MeshOptimizerComponent.cpp @@ -102,6 +102,7 @@ namespace AZ::SceneGenerationComponents MeshOptimizerComponent::MeshOptimizerComponent() { + BindToCall(&MeshOptimizerComponent::OptimizeMeshes); } void MeshOptimizerComponent::Reflect(AZ::ReflectContext* context) @@ -109,7 +110,7 @@ namespace AZ::SceneGenerationComponents auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context); if (serializeContext) { - serializeContext->Class<MeshOptimizerComponent, GenerationComponent>()->Version(1); + serializeContext->Class<MeshOptimizerComponent, GenerationComponent>()->Version(2); } } From 93ba2ea25175164b20a2458d258887edaf12b5ea Mon Sep 17 00:00:00 2001 From: phistere <phistere@amazon.com> Date: Thu, 22 Apr 2021 11:42:58 -0500 Subject: [PATCH 77/96] LYN-2524: Updates for PR feedback. Simplify path building, fix whitespace. --- .../Asset/AssetSystemComponentHelper_Linux.cpp | 11 +---------- .../Asset/AssetSystemComponentHelper_Mac.cpp | 11 +---------- .../Asset/AssetSystemComponentHelper_Windows.cpp | 11 +---------- cmake/Platform/Common/Install_common.cmake | 2 +- 4 files changed, 4 insertions(+), 31 deletions(-) diff --git a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp index 4f9aeaf6c3..1ae3945bd6 100644 --- a/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp +++ b/Code/Framework/AzFramework/Platform/Linux/AzFramework/Asset/AssetSystemComponentHelper_Linux.cpp @@ -35,16 +35,7 @@ namespace AzFramework::AssetSystem::Platform if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. - assetProcessorPath.Assign(engineRoot); - assetProcessorPath /= "bin"; -#if defined(AZ_DEBUG_BUILD) - assetProcessorPath /= "debug"; -#elif defined(AZ_PROFILE_BUILD) - assetProcessorPath /= "profile"; -#else - assetProcessorPath /= "release"; -#endif - assetProcessorPath /= "AssetProcessor"; + assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor"; if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { diff --git a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp index cc31cc9a0c..6f1f860932 100644 --- a/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp +++ b/Code/Framework/AzFramework/Platform/Mac/AzFramework/Asset/AssetSystemComponentHelper_Mac.cpp @@ -34,16 +34,7 @@ namespace AzFramework::AssetSystem::Platform if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. - assetProcessorPath.Assign(engineRoot); - assetProcessorPath /= "bin"; - #if defined(AZ_DEBUG_BUILD) - assetProcessorPath /= "debug"; -#elif defined(AZ_PROFILE_BUILD) - assetProcessorPath /= "profile"; -#else - assetProcessorPath /= "release"; -#endif - assetProcessorPath /= "AssetProcessor.app"; + assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.app"; if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { diff --git a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp index 155a69a691..b716778cf4 100644 --- a/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp +++ b/Code/Framework/AzFramework/Platform/Windows/AzFramework/Asset/AssetSystemComponentHelper_Windows.cpp @@ -71,16 +71,7 @@ namespace AzFramework::AssetSystem::Platform if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { // Check for existence of one under a "bin" directory, i.e. engineRoot is an SDK structure. - assetProcessorPath.Assign(engineRoot); - assetProcessorPath /= "bin"; -#if defined(AZ_DEBUG_BUILD) - assetProcessorPath /= "debug"; -#elif defined(AZ_PROFILE_BUILD) - assetProcessorPath /= "profile"; -#else - assetProcessorPath /= "release"; -#endif - assetProcessorPath /= "AssetProcessor.exe"; + assetProcessorPath = AZ::IO::FixedMaxPath{engineRoot} / "bin" / AZ_BUILD_CONFIGURATION_TYPE / "AssetProcessor.exe"; if (!AZ::IO::SystemFile::Exists(assetProcessorPath.c_str())) { diff --git a/cmake/Platform/Common/Install_common.cmake b/cmake/Platform/Common/Install_common.cmake index 023b7369a7..105b208338 100644 --- a/cmake/Platform/Common/Install_common.cmake +++ b/cmake/Platform/Common/Install_common.cmake @@ -184,7 +184,7 @@ function(ly_setup_cmake_install) install(DIRECTORY "${CMAKE_SOURCE_DIR}/cmake" DESTINATION . - REGEX "Findo3de.cmake" EXCLUDE + REGEX "Findo3de.cmake" EXCLUDE REGEX "Platform\/.*\/BuiltInPackages_.*\.cmake" EXCLUDE ) install( From dbcb2f9916737d1a6d5af60be5b05639fee0cbc2 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:46:37 +0100 Subject: [PATCH 78/96] Added sys_assert level 3 which will make asserts to crash the application(#208) Co-authored-by: aljanru <aljanru@amazon.com> --- Code/CryEngine/CrySystem/SystemInit.cpp | 1 + Code/Framework/AzCore/AzCore/Debug/Trace.cpp | 11 +++++++++-- .../Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Code/CryEngine/CrySystem/SystemInit.cpp b/Code/CryEngine/CrySystem/SystemInit.cpp index 5e43d6a1df..77d4039052 100644 --- a/Code/CryEngine/CrySystem/SystemInit.cpp +++ b/Code/CryEngine/CrySystem/SystemInit.cpp @@ -4094,6 +4094,7 @@ void CSystem::CreateSystemVars() "0 = Suppress Asserts\n" "1 = Log Asserts\n" "2 = Show Assert Dialog\n" + "3 = Crashes the Application on Assert\n" "Note: when set to '0 = Suppress Asserts', assert expressions are still evaluated. To turn asserts into a no-op, undefine AZ_ENABLE_TRACING and recompile.", OnAssertLevelCvarChanged); CSystem::SetAssertLevel(defaultAssertValue); diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp index 18db84e326..635db26465 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp +++ b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp @@ -70,6 +70,7 @@ namespace AZ static const char* logVerbosityUID = "sys_LogLevel"; static const int assertLevel_log = 1; static const int assertLevel_nativeUI = 2; + static const int assertLevel_crash = 3; static const int logLevel_errorWarning = 1; static const int logLevel_full = 2; static AZ::EnvironmentVariable<AZStd::unordered_set<size_t>> g_ignoredAsserts; @@ -289,8 +290,8 @@ namespace AZ } #if AZ_ENABLE_TRACE_ASSERTS - //display native UI dialogs at verbosity level 2 or higher - if (currentLevel >= assertLevel_nativeUI) + //display native UI dialogs at verbosity level 2 + if (currentLevel == assertLevel_nativeUI) { AZ::NativeUI::AssertAction buttonResult; EBUS_EVENT_RESULT(buttonResult, AZ::NativeUI::NativeUIRequestBus, DisplayAssertDialog, dialogBoxText); @@ -314,7 +315,13 @@ namespace AZ break; } } + else #endif //AZ_ENABLE_TRACE_ASSERTS + // Crash the application directly at assert level 3 + if (currentLevel >= assertLevel_crash) + { + AZ_Crash(); + } } g_alreadyHandlingAssertOrFatal = false; } diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp index c157189400..6a00990ffa 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp @@ -539,8 +539,8 @@ namespace ImGui { int assertLevelValue = gAssertLevelCVAR->GetIVal(); int dragIntVal = assertLevelValue; - ImGui::Text("sys_asserts: %d ( 0-off | 1-log | 2-popup )", assertLevelValue); - ImGui::SliderInt("##sys_asserts", &dragIntVal, 0, 2); + ImGui::Text("sys_asserts: %d ( 0-off | 1-log | 2-popup | 3-crash )", assertLevelValue); + ImGui::SliderInt("##sys_asserts", &dragIntVal, 0, 3); if (dragIntVal != assertLevelValue) { gAssertLevelCVAR->Set(dragIntVal); From ba324b8806d60aa241141e296cc5459e8d4d6668 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Thu, 22 Apr 2021 18:53:27 +0200 Subject: [PATCH 79/96] [LYN-3013] Github TQO Animation: MorphTarget has data integrity issue (#237) * Added error reporting for data integrity issues for non-uniform motion data. * The actual issue was a mismatch between the end times of the morph and the skeletal animations. They need to match in EMotionFX. * The morph target animation exported a keyframe too much. --- .../Importers/AssImpAnimationImporter.cpp | 25 ++++++----- .../MotionData/NonUniformMotionData.cpp | 45 ++++++++++++++++--- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp index 9522512619..e456f2dbab 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpAnimationImporter.cpp @@ -51,6 +51,7 @@ namespace AZ AZ_Warning("AnimationImporter", false, "Animation ticks per second should not be zero, defaulting to %d keyframes for animation.", keysSize); return keysSize; } + const double totalTicks = duration / ticksPerSecond; AZ::u32 numKeys = keysSize; // +1 because the animation is from [0, duration] - we have a keyframe at the end of the duration which needs to be included @@ -422,10 +423,12 @@ namespace AZ // If there is no bone animation on the current node, then generate one here. AZStd::shared_ptr<SceneData::GraphData::AnimationData> createdAnimationData = AZStd::make_shared<SceneData::GraphData::AnimationData>(); - createdAnimationData->ReserveKeyFrames( - animation->mDuration + - 1); // +1 because we start at 0 and the last keyframe is at mDuration instead of mDuration-1 - createdAnimationData->SetTimeStepBetweenFrames(1.0 / animation->mTicksPerSecond); + + const size_t numKeyframes = animation->mDuration + 1; // +1 because we start at 0 and the last keyframe is at mDuration instead of mDuration-1 + createdAnimationData->ReserveKeyFrames(numKeyframes); + + const double timeStepBetweenFrames = 1.0 / animation->mTicksPerSecond; + createdAnimationData->SetTimeStepBetweenFrames(timeStepBetweenFrames); // Set every frame of the animation to the start location of the node. aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode); @@ -527,7 +530,7 @@ namespace AZ // are less predictable than just using a fixed time step. // AssImp documentation claims animation->mDuration is the duration of the animation in ticks, but // not all animations we've tested follow that pattern. Sometimes duration is in seconds. - const AZ::u32 numKeyFrames = GetNumKeyFrames( + const size_t numKeyFrames = GetNumKeyFrames( AZStd::max(AZStd::max(anim->mNumScalingKeys, anim->mNumPositionKeys), anim->mNumRotationKeys), animation->mDuration, animation->mTicksPerSecond); @@ -543,8 +546,10 @@ namespace AZ for (AZ::u32 frame = 0; frame < numKeyFrames; ++frame) { const double time = GetTimeForFrame(frame, animation->mTicksPerSecond); - aiVector3D scale = aiVector3D(1.f, 1.f, 1.f), position = aiVector3D(0.f, 0.f, 0.f); - aiQuaternion rotation(1.f, 0.f, 0.f, 0.f); + + aiVector3D scale(1.0f, 1.0f, 1.0f); + aiVector3D position(0.0f, 0.0f, 0.0f); + aiQuaternion rotation(1.0f, 0.0f, 0.0f, 0.0f); if (!SampleKeyFrame(scale, anim->mScalingKeys, anim->mNumScalingKeys, time, lastScaleIndex) || !SampleKeyFrame(position, anim->mPositionKeys, anim->mNumPositionKeys, time, lastPositionIndex) || !SampleKeyFrame(rotation, anim->mRotationKeys, anim->mNumRotationKeys, time, lastRotationIndex)) @@ -553,7 +558,6 @@ namespace AZ } aiMatrix4x4 transform(scale, rotation, position); - DataTypes::MatrixType animTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(transform); context.m_sourceSceneSystem.SwapTransformForUpAxis(animTransform); @@ -618,7 +622,7 @@ namespace AZ AZStd::shared_ptr<SceneData::GraphData::BlendShapeAnimationData> morphAnimNode = AZStd::make_shared<SceneData::GraphData::BlendShapeAnimationData>(); - const AZ::u32 numKeyFrames = GetNumKeyFrames(keys.size(), animation->mDuration, animation->mTicksPerSecond); + const size_t numKeyFrames = GetNumKeyFrames(keys.size(), animation->mDuration, animation->mTicksPerSecond); morphAnimNode->ReserveKeyFrames(numKeyFrames); morphAnimNode->SetTimeStepBetweenFrames(s_defaultTimeStepBetweenFrames); @@ -627,7 +631,7 @@ namespace AZ const AZ::u32 maxKeys = keys.size(); AZ::u32 keyIdx = 0; - for (AZ::u32 frame = 0; frame <= numKeyFrames; ++frame) + for (AZ::u32 frame = 0; frame < numKeyFrames; ++frame) { const double time = GetTimeForFrame(frame, animation->mTicksPerSecond); @@ -640,7 +644,6 @@ namespace AZ morphAnimNode->AddKeyFrame(weight); } - const size_t dotIndex = nodeName.find_last_of('.'); nodeName = nodeName.substr(dotIndex + 1); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp index fbe8a78cba..8a58300b88 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionData/NonUniformMotionData.cpp @@ -258,8 +258,16 @@ namespace EMotionFX } else if (!timeValues.empty()) { - if (!AZ::IsClose(timeValues.front(), startTime, AZ::Constants::FloatEpsilon) || !AZ::IsClose(timeValues.back(), endTime, AZ::Constants::FloatEpsilon)) + if (!AZ::IsClose(timeValues.front(), startTime, AZ::Constants::FloatEpsilon)) { + AZ_Error("EMotionFX", false, "No keyframe present at the start of the animation (%f). The first keyframe is at %f.", + startTime, timeValues.front()); + return false; + } + if (!AZ::IsClose(timeValues.back(), endTime, AZ::Constants::FloatEpsilon)) + { + AZ_Error("EMotionFX", false, "No keyframe present at the end of the animation (%f). The last keyframe is at %f.", + endTime, timeValues.back()); return false; } } @@ -271,14 +279,25 @@ namespace EMotionFX { for (const JointData& jointData : m_jointData) { - if ((jointData.m_positionTrack.m_times.size() != jointData.m_positionTrack.m_values.size()) || (jointData.m_rotationTrack.m_times.size() != jointData.m_rotationTrack.m_values.size())) + if (jointData.m_positionTrack.m_times.size() != jointData.m_positionTrack.m_values.size()) + { + AZ_Error("EMotionFX", false, "Number of position keyframe times (%d) does not match the number of keyframe values (%d).", + jointData.m_positionTrack.m_times.size(), jointData.m_positionTrack.m_values.size()); + return false; + } + + if (jointData.m_rotationTrack.m_times.size() != jointData.m_rotationTrack.m_values.size()) { + AZ_Error("EMotionFX", false, "Number of rotation keyframe times (%d) does not match the number of keyframe values (%d).", + jointData.m_rotationTrack.m_times.size(), jointData.m_rotationTrack.m_values.size()); return false; } #ifndef EMFX_SCALE_DISABLED if (jointData.m_scaleTrack.m_times.size() != jointData.m_scaleTrack.m_values.size()) { + AZ_Error("EMotionFX", false, "Number of scale keyframe times (%d) does not match the number of keyframe values (%d).", + jointData.m_scaleTrack.m_times.size(), jointData.m_scaleTrack.m_values.size()); return false; } @@ -288,7 +307,8 @@ namespace EMotionFX } #endif - if (!VerifyKeyTrackTimeIntegrity(jointData.m_positionTrack.m_times) || !VerifyKeyTrackTimeIntegrity(jointData.m_rotationTrack.m_times)) + if (!VerifyKeyTrackTimeIntegrity(jointData.m_positionTrack.m_times) || + !VerifyKeyTrackTimeIntegrity(jointData.m_rotationTrack.m_times)) { return false; } @@ -300,7 +320,8 @@ namespace EMotionFX bool firstCheck = true; for (const JointData& jointData : m_jointData) { - if (!VerifyStartEndTimeIntegrity(jointData.m_positionTrack.m_times, firstCheck, startTime, endTime) || !VerifyStartEndTimeIntegrity(jointData.m_rotationTrack.m_times, firstCheck, startTime, endTime)) + if (!VerifyStartEndTimeIntegrity(jointData.m_positionTrack.m_times, firstCheck, startTime, endTime) || + !VerifyStartEndTimeIntegrity(jointData.m_rotationTrack.m_times, firstCheck, startTime, endTime)) { return false; } @@ -317,6 +338,8 @@ namespace EMotionFX { if (morphData.m_track.m_times.size() != morphData.m_track.m_values.size()) { + AZ_Error("EMotionFX", false, "Number of morph keyframe times (%d) does not match the number of keyframe values (%d).", + morphData.m_track.m_times.size(), morphData.m_track.m_values.size()); return false; } @@ -333,7 +356,17 @@ namespace EMotionFX for (const FloatData& floatData : m_floatData) { - if (floatData.m_track.m_times.size() != floatData.m_track.m_values.size() || !VerifyStartEndTimeIntegrity(floatData.m_track.m_times, firstCheck, startTime, endTime) || !VerifyKeyTrackTimeIntegrity(floatData.m_track.m_times)) + if (floatData.m_track.m_times.size() != floatData.m_track.m_values.size()) + { + AZ_Error("EMotionFX", false, "Number of float keyframe times (%d) does not match the number of keyframe values (%d).", + floatData.m_track.m_times.size(), floatData.m_track.m_values.size()); + return false; + } + if (!VerifyStartEndTimeIntegrity(floatData.m_track.m_times, firstCheck, startTime, endTime)) + { + return false; + } + if (!VerifyKeyTrackTimeIntegrity(floatData.m_track.m_times)) { return false; } @@ -657,6 +690,8 @@ namespace EMotionFX { if (curTime < prevKeyTime) { + AZ_Error("EMotionFX", false, "Keyframe times need to be ascending. Current keyframe time (%f) is smaller than the previous (%f).", + curTime, prevKeyTime); return false; } prevKeyTime = curTime; From 3aa05440764b2892a1ca31480c7420340e6c12fc Mon Sep 17 00:00:00 2001 From: amzn-sj <srikkant@amazon.com> Date: Thu, 22 Apr 2021 10:06:28 -0700 Subject: [PATCH 80/96] Fix AssetProcessor crash on Mac --- .../ScriptCanvas/Libraries/UnitTesting/UnitTestBusSender.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/UnitTesting/UnitTestBusSender.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/UnitTesting/UnitTestBusSender.cpp index e6ab482ef4..9cac7bd021 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/UnitTesting/UnitTestBusSender.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/UnitTesting/UnitTestBusSender.cpp @@ -388,9 +388,8 @@ namespace ScriptCanvas { AZ::ScriptCanvasAttributes::HiddenIndices uniqueIdIndex = { 0 }; - auto builder = behaviorContext->Class<EventSender>("Unit Testing") - ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) - ; + auto builder = behaviorContext->Class<EventSender>("Unit Testing"); + builder->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common); builder->Method("Add Failure", &EventSender::AddFailure, { { {"", "", behaviorContext->MakeDefaultValue(UniqueId)}, {"Report", "additional notes for the test report"} } }) ->Attribute(AZ::ScriptCanvasAttributes::HiddenParameterIndex, uniqueIdIndex) From e5a990b05c962b56c6b07fc42f7e5e4e810839c6 Mon Sep 17 00:00:00 2001 From: jckand <jckand@amazon.com> Date: Thu, 22 Apr 2021 13:20:44 -0500 Subject: [PATCH 81/96] LYN-3120: Temporarily disabling reset of view pane layout in editor_test_helper.py teardown. Updating view of planting area for several DynVeg tests that was changed with the addition of the default level entity. --- .../PythonTests/automatedtesting_shared/editor_test_helper.py | 3 ++- .../dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py | 2 ++ .../AreaComponentSlices_SliceCreationAndVisibilityToggle.py | 2 ++ ...ceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py | 2 ++ .../DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py | 2 ++ .../DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py | 1 + .../EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py | 2 ++ .../EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py | 2 ++ .../EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py | 1 + .../dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py | 2 ++ .../EditorScripts/MeshBlocker_InstancesBlockedByMesh.py | 3 +++ .../RotationModifierOverrides_InstancesRotateWithinRange.py | 2 +- .../RotationModifier_InstancesRotateWithinRange.py | 2 +- .../dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py | 3 +++ .../dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py | 2 ++ .../dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py | 2 ++ .../dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py | 3 +++ .../dyn_veg/EditorScripts/SystemSettings_SectorSize.py | 3 +++ 18 files changed, 36 insertions(+), 3 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py index 64a19aafdf..ed9a8a58fa 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/editor_test_helper.py @@ -117,7 +117,8 @@ class EditorTestHelper: # Set the viewport back to whatever size it was at the start and restore the pane layout general.set_viewport_size(int(self.viewport_size.x), int(self.viewport_size.y)) general.set_viewport_expansion_policy("AutoExpand") - general.set_view_pane_layout(self.viewport_layout) + # Temporarily disabling reset of view pane layout: LYN-3120 + # general.set_view_pane_layout(self.viewport_layout) general.update_viewport() self.log("test finished") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py index 1c51cc9554..50511811f1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AltitudeFilter_FilterStageToggle.py @@ -53,6 +53,8 @@ class TestAltitudeFilterFilterStageToggle(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # Create basic vegetation entity position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PinkFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py index d1fe82e3f7..1123a63ae4 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/AreaComponentSlices_SliceCreationAndVisibilityToggle.py @@ -59,6 +59,8 @@ class TestAreaComponentsSliceCreationAndVisibilityToggle(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) C2627900 Verifies if a slice containing the Vegetation Layer Spawner component can be created. # 2.1) Create basic vegetation entity position = math.Vector3(512.0, 512.0, 32.0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py index 82b2fc8407..5fed50ced9 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilterOverrides_InstancesPlantAtSpecifiedRadius.py @@ -63,6 +63,8 @@ class TestDistanceBetweenFilterComponentOverrides(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create a new entity with required vegetation area components spawner_center_point = math.Vector3(520.0, 520.0, 32.0) asset_path = os.path.join("Slices", "1m_cube.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py index 9f15215358..ab4863e636 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DistanceBetweenFilter_InstancesPlantAtSpecifiedRadius.py @@ -61,6 +61,8 @@ class TestDistanceBetweenFilterComponent(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create a new entity with required vegetation area components spawner_center_point = math.Vector3(520.0, 520.0, 32.0) asset_path = os.path.join("Slices", "1m_cube.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py index b58c7488e5..366dd057bc 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks.py @@ -43,6 +43,7 @@ class TestDynamicSliceInstanceSpawner(EditorTestHelper): use_terrain=False, ) general.idle_wait(1.0) + general.set_current_view_position(512.0, 480.0, 38.0) # Grab the UUID that we need for creating an Dynamic Slice Instance Spawner dynamic_slice_spawner_uuid = azlmbr.math.Uuid_CreateString('{BBA5CC1E-B4CA-4792-89F7-93711E98FBD1}', 0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py index f25fbb2b6d..dc5b5798a1 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_Embedded_E2E.py @@ -65,6 +65,8 @@ class TestDynamicSliceInstanceSpawnerEmbeddedEditor(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create a new entity with required vegetation area components and Script Canvas component for launcher test center_point = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PinkFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py index 8af75f2d17..0deb63d374 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/DynamicSliceInstanceSpawner_External_E2E.py @@ -65,6 +65,8 @@ class TestDynamicSliceInstanceSpawnerExternalEditor(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create a new entity with required vegetation area components and switch the Vegetation Asset List Source # Type to External entity_position = math.Vector3(512.0, 512.0, 32.0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py index 4067de90fc..fd45fdcf2f 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/EmptyInstanceSpawner_EmptySpawnerWorks.py @@ -43,6 +43,7 @@ class TestEmptyInstanceSpawner(EditorTestHelper): use_terrain=False, ) general.idle_wait(1.0) + general.set_current_view_position(512.0, 480.0, 38.0) # Grab the UUID that we need for creating an Empty Spawner empty_spawner_uuid = azlmbr.math.Uuid_CreateString('{23C40FD4-A55F-4BD3-BE5B-DC5423F217C2}', 0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py index f55243bc9c..59e20169e7 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/LayerSpawner_InheritBehaviorFlag.py @@ -60,6 +60,8 @@ class TestLayerSpawnerInheritBehavior(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # Create Emitter entity and add the required components position = math.Vector3(512.0, 512.0, 32.0) emitter_entity = dynveg.create_surface_entity("emitter_entity", position, 16.0, 16.0, 1.0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py index 02dcc1f067..437dc31118 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/MeshBlocker_InstancesBlockedByMesh.py @@ -61,6 +61,9 @@ class test_MeshBlocker_InstancesBlockedByMesh(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(500.49, 498.69, 46.66) + general.set_current_view_rotation(-42.05, 0.00, -36.33) + # Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape" entity_position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py index b63692527c..64fee5d657 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifierOverrides_InstancesRotateWithinRange.py @@ -90,7 +90,7 @@ class TestRotationModifierOverrides_InstancesRotateWithinRange(EditorTestHelper) terrain_texture_resolution=4096, use_terrain=False, ) - general.run_console("e_WaterOcean=0") + general.set_current_view_position(512.0, 480.0, 38.0) # 2) Create vegetation entity and add components entity_position = math.Vector3(512.0, 512.0, 32.0) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py index a14363d5e9..b867b3a02c 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/RotationModifier_InstancesRotateWithinRange.py @@ -103,7 +103,7 @@ class TestRotationModifier_InstancesRotateWithinRange(EditorTestHelper): terrain_texture_resolution=4096, use_terrain=False, ) - general.run_console("e_WaterOcean=0") + general.set_current_view_position(512.0, 480.0, 38.0) # 2) Set up vegetation entities asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py index a907c7a0af..91617c0567 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SlopeFilter_FilterStageToggle.py @@ -17,6 +17,7 @@ import azlmbr.paths import azlmbr.editor as editor import azlmbr.entity as EntityId import azlmbr.components as components +import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import automatedtesting_shared.hydra_editor_utils as hydra @@ -48,6 +49,8 @@ class TestSlopeFilterFilterStageToggle(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # Create basic vegetation entity position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PinkFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py index 1bec5e46ae..bc5b441513 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_ExclusionList.py @@ -103,6 +103,8 @@ class TestExclusiveSurfaceMasksTag(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape" entity_position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py index fbaecf1972..e9682edbc8 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SurfaceMaskFilter_InclusionList.py @@ -104,6 +104,8 @@ class TestInclusiveSurfaceMasksTag(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # 2) Create entity with components "Vegetation Layer Spawner", "Vegetation Asset List", "Box Shape" entity_position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PurpleFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py index f1e6a93760..af477d19ff 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorPointDensity.py @@ -15,6 +15,7 @@ import azlmbr.math as math import azlmbr.paths import azlmbr.editor as editor import azlmbr.bus as bus +import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import automatedtesting_shared.hydra_editor_utils as hydra @@ -52,6 +53,8 @@ class TestSystemSettingsSectorPointDensity(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # Create basic vegetation entity position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PinkFlower.dynamicslice") diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py index 5e80bd6b33..8c001b90ea 100755 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/dyn_veg/EditorScripts/SystemSettings_SectorSize.py @@ -15,6 +15,7 @@ import azlmbr.math as math import azlmbr.paths import azlmbr.editor as editor import azlmbr.bus as bus +import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import automatedtesting_shared.hydra_editor_utils as hydra @@ -48,6 +49,8 @@ class TestSystemSettingsSectorSize(EditorTestHelper): use_terrain=False, ) + general.set_current_view_position(512.0, 480.0, 38.0) + # Create basic vegetation entity position = math.Vector3(512.0, 512.0, 32.0) asset_path = os.path.join("Slices", "PinkFlower.dynamicslice") From d6809950744fd79b34b8732388e6af70aaae101c Mon Sep 17 00:00:00 2001 From: Terry Michaels <81711813+tjmichaels@users.noreply.github.com> Date: Thu, 22 Apr 2021 13:31:26 -0500 Subject: [PATCH 82/96] Renamed several non-inclusive terms (#236) --- .../AzCore/AzCore/Debug/AssetTracking.cpp | 24 ++++++------- .../AzCore/AzCore/Debug/AssetTrackingTypes.h | 8 ++--- .../AzCore/Debug/AssetTrackingTypesImpl.h | 12 +++---- .../AzCore/Tests/Debug/AssetTracking.cpp | 2 +- Code/Sandbox/Editor/CryEditDoc.h | 1 - Code/Sandbox/Editor/Export/ExportManager.cpp | 34 +++++++++---------- Code/Sandbox/Editor/Export/ExportManager.h | 8 ++--- Code/Sandbox/Editor/FBXExporterDialog.cpp | 6 ++-- Code/Sandbox/Editor/FBXExporterDialog.h | 4 +-- Code/Sandbox/Editor/FBXExporterDialog.ui | 4 +-- Code/Sandbox/Editor/Lib/Tests/IEditorMock.h | 2 +- .../SceneCore/Export/MtlMaterialExporter.cpp | 2 +- .../SceneUI/SceneWidgets/SceneGraphWidget.h | 2 +- .../Code/Source/AssetMemoryAnalyzer.cpp | 2 +- 14 files changed, 55 insertions(+), 56 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTracking.cpp b/Code/Framework/AzCore/AzCore/Debug/AssetTracking.cpp index 787dcff22d..f238b8a74a 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTracking.cpp +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTracking.cpp @@ -63,13 +63,13 @@ namespace AZ static AssetTrackingImpl* GetSharedInstance(); static ThreadData& GetSharedThreadData(); - using MasterAssets = AZStd::unordered_map<AssetTrackingId, AssetMasterInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>; + using PrimaryAssets = AZStd::unordered_map<AssetTrackingId, AssetPrimaryInfo, AZStd::hash<AssetTrackingId>, AZStd::equal_to<AssetTrackingId>, AZStdAssetTrackingAllocator>; using ThreadData = ThreadData; using mutex_type = AZStd::mutex; using lock_type = AZStd::lock_guard<mutex_type>; mutex_type m_mutex; - MasterAssets m_masterAssets; + PrimaryAssets m_primaryAssets; AssetTreeNodeBase* m_assetRoot = nullptr; AssetAllocationTableBase* m_allocationTable = nullptr; bool m_performingAnalysis = false; @@ -118,7 +118,7 @@ namespace AZ auto& threadData = GetSharedThreadData(); AssetTreeNodeBase* parentAsset = threadData.m_currentAssetStack.empty() ? nullptr : threadData.m_currentAssetStack.back(); AssetTreeNodeBase* childAsset; - AssetMasterInfo* assetMasterInfo; + AssetPrimaryInfo* assetPrimaryInfo; if (!parentAsset) { @@ -128,22 +128,22 @@ namespace AZ { lock_type lock(m_mutex); - // Locate or create the master record for this asset - auto masterItr = m_masterAssets.find(assetId); + // Locate or create the primary record for this asset + auto primaryItr = m_primaryAssets.find(assetId); - if (masterItr != m_masterAssets.end()) + if (primaryItr != m_primaryAssets.end()) { - assetMasterInfo = &masterItr->second; + assetPrimaryInfo = &primaryItr->second; } else { - auto insertResult = m_masterAssets.emplace(assetId, AssetMasterInfo()); - assetMasterInfo = &insertResult.first->second; - assetMasterInfo->m_id = &insertResult.first->first; + auto insertResult = m_primaryAssets.emplace(assetId, AssetPrimaryInfo()); + assetPrimaryInfo = &insertResult.first->second; + assetPrimaryInfo->m_id = &insertResult.first->first; } // Add this asset to the stack for this thread's context - childAsset = parentAsset->FindOrAddChild(assetId, assetMasterInfo); + childAsset = parentAsset->FindOrAddChild(assetId, assetPrimaryInfo); } threadData.m_currentAssetStack.push_back(childAsset); @@ -304,7 +304,7 @@ namespace AZ char* pos = buffer; for (auto itr = assetStack.rbegin(); itr != assetStack.rend(); ++itr) { - pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetMasterInfo()->m_id->m_id.c_str()); + pos += azsnprintf(pos, BUFFER_SIZE - (pos - buffer), "%s\n", (*itr)->GetAssetPrimaryInfo()->m_id->m_id.c_str()); if (pos >= buffer + BUFFER_SIZE) { diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h index e5be75c7d3..00b82d09ef 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypes.h @@ -79,9 +79,9 @@ namespace AZ AssetTrackingString m_id; }; - // Master information about an asset. + // Primary information about an asset. // Currently just contains the ID of the asset, but in the future may carry additional information about that asset (such as where in code it was initialized). - struct AssetMasterInfo + struct AssetPrimaryInfo { const AssetTrackingId* m_id; }; @@ -90,8 +90,8 @@ namespace AZ class AssetTreeNodeBase { public: - virtual const AssetMasterInfo* GetAssetMasterInfo() const = 0; - virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) = 0; + virtual const AssetPrimaryInfo* GetAssetPrimaryInfo() const = 0; + virtual AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) = 0; }; // Base class for an asset tree. Implemented by the template AssetTree<>. diff --git a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h index 91f0a0ef21..711c0cf4eb 100644 --- a/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h +++ b/Code/Framework/AzCore/AzCore/Debug/AssetTrackingTypesImpl.h @@ -29,18 +29,18 @@ namespace AZ class AssetTreeNode : public AssetTreeNodeBase { public: - AssetTreeNode(const AssetMasterInfo* masterInfo = nullptr, AssetTreeNode* parent = nullptr) : - m_masterInfo(masterInfo), + AssetTreeNode(const AssetPrimaryInfo* primaryInfo = nullptr, AssetTreeNode* parent = nullptr) : + m_primaryinfo(primaryInfo), m_parent(parent) { } - const AssetMasterInfo* GetAssetMasterInfo() const override + const AssetPrimaryInfo* GetAssetPrimaryInfo() const override { - return m_masterInfo; + return m_primaryinfo; } - AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetMasterInfo* info) override + AssetTreeNodeBase* FindOrAddChild(const AssetTrackingId& id, const AssetPrimaryInfo* info) override { AssetTreeNodeBase* result = nullptr; auto childItr = m_children.find(id); @@ -61,7 +61,7 @@ namespace AZ using AssetMap = AssetTrackingMap<AssetTrackingId, AssetTreeNode>; - const AssetMasterInfo* m_masterInfo; + const AssetPrimaryInfo* m_primaryinfo; AssetTreeNode* m_parent; AssetMap m_children; AssetDataT m_data; diff --git a/Code/Framework/AzCore/Tests/Debug/AssetTracking.cpp b/Code/Framework/AzCore/Tests/Debug/AssetTracking.cpp index a4a152a4f6..92d02a2706 100644 --- a/Code/Framework/AzCore/Tests/Debug/AssetTracking.cpp +++ b/Code/Framework/AzCore/Tests/Debug/AssetTracking.cpp @@ -105,7 +105,7 @@ namespace UnitTest EXPECT_EQ(&rootAsset, &m_env->m_tree.GetRoot()); ASSERT_NE(itr, rootAsset.m_children.end()); - EXPECT_EQ(itr->second.m_masterInfo->m_id->m_id, "TestScopedAllocation.1"); + EXPECT_EQ(itr->second.m_primaryinfo->m_id->m_id, "TestScopedAllocation.1"); EXPECT_EQ(&itr->second, m_env->m_table.FindAllocation(TEST_POINTER)); diff --git a/Code/Sandbox/Editor/CryEditDoc.h b/Code/Sandbox/Editor/CryEditDoc.h index 9f954f31d8..481e9fa046 100644 --- a/Code/Sandbox/Editor/CryEditDoc.h +++ b/Code/Sandbox/Editor/CryEditDoc.h @@ -216,7 +216,6 @@ protected: void OnSliceInstantiationFailed(const AZ::Data::AssetId& sliceAssetId, const AzFramework::SliceInstantiationTicket& /*ticket*/) override; ////////////////////////////////////////////////////////////////////////// - QString m_strMasterCDFolder; bool m_bLoadFailed; QColor m_waterColor; XmlNodeRef m_fogTemplate; diff --git a/Code/Sandbox/Editor/Export/ExportManager.cpp b/Code/Sandbox/Editor/Export/ExportManager.cpp index bf5c3aa469..b41872595a 100644 --- a/Code/Sandbox/Editor/Export/ExportManager.cpp +++ b/Code/Sandbox/Editor/Export/ExportManager.cpp @@ -65,7 +65,7 @@ namespace const float kTangentDelta = 0.01f; const float kAspectRatio = 1.777778f; const int kReserveCount = 7; // x,y,z,rot_x,rot_y,rot_z,fov - const QString kMasterCameraName = "MasterCamera"; + const QString kPrimaryCameraName = "PrimaryCamera"; } // namespace @@ -169,10 +169,10 @@ CExportManager::CExportManager() , m_numberOfExportFrames(0) , m_pivotEntityObject(0) , m_bBakedKeysSequenceExport(true) - , m_animTimeExportMasterSequenceCurrentTime(0.0f) + , m_animTimeExportPrimarySequenceCurrentTime(0.0f) , m_animKeyTimeExport(true) , m_soundKeyTimeExport(true) - , m_bExportOnlyMasterCamera(false) + , m_bExportOnlyPrimaryCamera(false) { RegisterExporter(new COBJExporter()); RegisterExporter(new COCMExporter()); @@ -773,14 +773,14 @@ bool CExportManager::ShowFBXExportDialog() return false; } - SetFBXExportSettings(fpsDialog.GetExportCoordsLocalToTheSelectedObject(), fpsDialog.GetExportOnlyMasterCamera(), fpsDialog.GetFPS()); + SetFBXExportSettings(fpsDialog.GetExportCoordsLocalToTheSelectedObject(), fpsDialog.GetExportOnlyPrimaryCamera(), fpsDialog.GetFPS()); return true; } bool CExportManager::ProcessObjectsForExport() { - Export::CObject* pObj = new Export::CObject(kMasterCameraName.toUtf8().data()); + Export::CObject* pObj = new Export::CObject(kPrimaryCameraName.toUtf8().data()); pObj->entityType = Export::eCamera; m_data.m_objects.push_back(pObj); @@ -808,13 +808,13 @@ bool CExportManager::ProcessObjectsForExport() Export::CObject* pObj2 = m_data.m_objects[objectID]; CBaseObject* pObject = 0; - if (QString::compare(pObj2->name, kMasterCameraName) == 0) + if (QString::compare(pObj2->name, kPrimaryCameraName) == 0) { pObject = GetIEditor()->GetObjectManager()->FindObject(GetIEditor()->GetViewManager()->GetCameraObjectId()); } else { - if (m_bExportOnlyMasterCamera && pObj2->entityType != Export::eCameraTarget) + if (m_bExportOnlyPrimaryCamera && pObj2->entityType != Export::eCameraTarget) { continue; } @@ -952,7 +952,7 @@ void CExportManager::FillAnimTimeNode(XmlNodeRef writeNode, CTrackViewAnimNode* if (numAllTracks > 0) { XmlNodeRef objNode = writeNode->createNode(CleanXMLText(pObjectNode->GetName()).toUtf8().data()); - writeNode->setAttr("time", m_animTimeExportMasterSequenceCurrentTime); + writeNode->setAttr("time", m_animTimeExportPrimarySequenceCurrentTime); for (unsigned int trackID = 0; trackID < numAllTracks; ++trackID) { @@ -1020,7 +1020,7 @@ void CExportManager::FillAnimTimeNode(XmlNodeRef writeNode, CTrackViewAnimNode* XmlNodeRef keyNode = subNode->createNode(keyContentName.toUtf8().data()); - float keyGlobalTime = m_animTimeExportMasterSequenceCurrentTime + keyTime; + float keyGlobalTime = m_animTimeExportPrimarySequenceCurrentTime + keyTime; keyNode->setAttr("keyTime", keyGlobalTime); if (keyStartTime > 0) @@ -1123,13 +1123,13 @@ bool CExportManager::AddObjectsFromSequence(CTrackViewSequence* pSequence, XmlNo const QString sequenceName = pSubSequence->GetName(); XmlNodeRef subSeqNode2 = seqNode->createNode(sequenceName.toUtf8().data()); - if (sequenceName == m_animTimeExportMasterSequenceName) + if (sequenceName == m_animTimeExportPrimarySequenceName) { - m_animTimeExportMasterSequenceCurrentTime = sequenceKey.time; + m_animTimeExportPrimarySequenceCurrentTime = sequenceKey.time; } else { - m_animTimeExportMasterSequenceCurrentTime += sequenceKey.time; + m_animTimeExportPrimarySequenceCurrentTime += sequenceKey.time; } AddObjectsFromSequence(pSubSequence, subSeqNode2); @@ -1336,7 +1336,7 @@ bool CExportManager::Export(const char* defaultName, const char* defaultExt, con { m_numberOfExportFrames = pSequence->GetTimeRange().end * m_FBXBakedExportFPS; - if (!m_bExportOnlyMasterCamera) + if (!m_bExportOnlyPrimaryCamera) { AddObjectsFromSequence(pSequence); } @@ -1365,10 +1365,10 @@ bool CExportManager::Export(const char* defaultName, const char* defaultExt, con return returnRes; } -void CExportManager::SetFBXExportSettings(bool bLocalCoordsToSelectedObject, bool bExportOnlyMasterCamera, const float fps) +void CExportManager::SetFBXExportSettings(bool bLocalCoordsToSelectedObject, bool bExportOnlyPrimaryCamera, const float fps) { m_bExportLocalCoords = bLocalCoordsToSelectedObject; - m_bExportOnlyMasterCamera = bExportOnlyMasterCamera; + m_bExportOnlyPrimaryCamera = bExportOnlyPrimaryCamera; m_FBXBakedExportFPS = fps; } @@ -1439,10 +1439,10 @@ void CExportManager::SaveNodeKeysTimeToXML() if (dlg.exec()) { m_animTimeNode = XmlHelpers::CreateXmlNode(pSequence->GetName()); - m_animTimeExportMasterSequenceName = pSequence->GetName(); + m_animTimeExportPrimarySequenceName = pSequence->GetName(); m_data.Clear(); - m_animTimeExportMasterSequenceCurrentTime = 0.0; + m_animTimeExportPrimarySequenceCurrentTime = 0.0; AddObjectsFromSequence(pSequence, m_animTimeNode); diff --git a/Code/Sandbox/Editor/Export/ExportManager.h b/Code/Sandbox/Editor/Export/ExportManager.h index d8edf1d3b1..8904ef08ed 100644 --- a/Code/Sandbox/Editor/Export/ExportManager.h +++ b/Code/Sandbox/Editor/Export/ExportManager.h @@ -171,7 +171,7 @@ private: bool AddObjectsFromSequence(CTrackViewSequence* pSequence, XmlNodeRef seqNode = 0); bool IsDuplicateObjectBeingAdded(const QString& newObject); - void SetFBXExportSettings(bool bLocalCoordsToSelectedObject, bool bExportOnlyMasterCamera, const float fps); + void SetFBXExportSettings(bool bLocalCoordsToSelectedObject, bool bExportOnlyPrimaryCamera, const float fps); bool ProcessObjectsForExport(); bool ShowFBXExportDialog(); @@ -193,13 +193,13 @@ private: float m_FBXBakedExportFPS; bool m_bExportLocalCoords; - bool m_bExportOnlyMasterCamera; + bool m_bExportOnlyPrimaryCamera; int m_numberOfExportFrames; CEntityObject* m_pivotEntityObject; bool m_bBakedKeysSequenceExport; - QString m_animTimeExportMasterSequenceName; - float m_animTimeExportMasterSequenceCurrentTime; + QString m_animTimeExportPrimarySequenceName; + float m_animTimeExportPrimarySequenceCurrentTime; XmlNodeRef m_animTimeNode; bool m_animKeyTimeExport; diff --git a/Code/Sandbox/Editor/FBXExporterDialog.cpp b/Code/Sandbox/Editor/FBXExporterDialog.cpp index 7638680b10..677e6dcfe7 100644 --- a/Code/Sandbox/Editor/FBXExporterDialog.cpp +++ b/Code/Sandbox/Editor/FBXExporterDialog.cpp @@ -55,9 +55,9 @@ bool CFBXExporterDialog::GetExportCoordsLocalToTheSelectedObject() const return m_ui->m_exportLocalCoordsCheckbox->isChecked(); } -bool CFBXExporterDialog::GetExportOnlyMasterCamera() const +bool CFBXExporterDialog::GetExportOnlyPrimaryCamera() const { - return m_ui->m_exportOnlyMasterCameraCheckBox->isChecked(); + return m_ui->m_exportOnlyPrimaryCameraCheckBox->isChecked(); } void CFBXExporterDialog::SetExportLocalCoordsCheckBoxEnable(bool checked) @@ -100,7 +100,7 @@ int CFBXExporterDialog::exec() if (m_bDisplayOnlyFPSSetting) { m_ui->m_exportLocalCoordsCheckbox->setEnabled(false); - m_ui->m_exportOnlyMasterCameraCheckBox->setEnabled(false); + m_ui->m_exportOnlyPrimaryCameraCheckBox->setEnabled(false); } m_ui->m_fpsCombo->addItem("24"); diff --git a/Code/Sandbox/Editor/FBXExporterDialog.h b/Code/Sandbox/Editor/FBXExporterDialog.h index 9978cb4aca..ffa249ca5b 100644 --- a/Code/Sandbox/Editor/FBXExporterDialog.h +++ b/Code/Sandbox/Editor/FBXExporterDialog.h @@ -36,7 +36,7 @@ public: float GetFPS() const; bool GetExportCoordsLocalToTheSelectedObject() const; - bool GetExportOnlyMasterCamera() const; + bool GetExportOnlyPrimaryCamera() const; void SetExportLocalCoordsCheckBoxEnable(bool checked); int exec() override; @@ -44,7 +44,7 @@ public: protected: void OnFPSChange(); void SetExportLocalToTheSelectedObjectCheckBox(); - void SetExportOnlyMasterCameraCheckBox(); + void SetExportOnlyPrimaryCameraCheckBox(); void accept() override; diff --git a/Code/Sandbox/Editor/FBXExporterDialog.ui b/Code/Sandbox/Editor/FBXExporterDialog.ui index 8c02ce1ca9..6b7b93c342 100644 --- a/Code/Sandbox/Editor/FBXExporterDialog.ui +++ b/Code/Sandbox/Editor/FBXExporterDialog.ui @@ -49,9 +49,9 @@ </layout> </item> <item> - <widget class="QCheckBox" name="m_exportOnlyMasterCameraCheckBox"> + <widget class="QCheckBox" name="m_exportOnlyPrimaryCameraCheckBox"> <property name="text"> - <string>Export Only Master Camera</string> + <string>Export Only Primary Camera</string> </property> </widget> </item> diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index a309a1a5f5..7372de523f 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -20,7 +20,7 @@ class CEditorMock : public IEditor { public: - // GMock does not work with a variadic function (https://github.com/google/googlemock/blob/master/googlemock/docs/FrequentlyAskedQuestions.md) + // GMock does not work with a variadic function void ExecuteCommand(const char* sCommand, ...) override { va_list args; diff --git a/Code/Tools/SceneAPI/SceneCore/Export/MtlMaterialExporter.cpp b/Code/Tools/SceneAPI/SceneCore/Export/MtlMaterialExporter.cpp index f364167173..261b7be33f 100644 --- a/Code/Tools/SceneAPI/SceneCore/Export/MtlMaterialExporter.cpp +++ b/Code/Tools/SceneAPI/SceneCore/Export/MtlMaterialExporter.cpp @@ -86,7 +86,7 @@ namespace AZ if (sourceFileExists && !updateMaterial) { - // Don't write to the cache if there's a source material as this will be the master material. + // Don't write to the cache if there's a source material as this will be the primary material. continue; } diff --git a/Code/Tools/SceneAPI/SceneUI/SceneWidgets/SceneGraphWidget.h b/Code/Tools/SceneAPI/SceneUI/SceneWidgets/SceneGraphWidget.h index 4f2406206f..ce01889a63 100644 --- a/Code/Tools/SceneAPI/SceneUI/SceneWidgets/SceneGraphWidget.h +++ b/Code/Tools/SceneAPI/SceneUI/SceneWidgets/SceneGraphWidget.h @@ -84,7 +84,7 @@ namespace AZ NoneCheckable, // No nodes can be checked. OnlyFilterTypesCheckable // Only nodes in the filter type list can be checked. }; - // Updates the tree to include/exclude check boxes and the master selection. Call "BuildTree()" to rebuild the tree. + // Updates the tree to include/exclude check boxes and the primary selection. Call "BuildTree()" to rebuild the tree. virtual void MakeCheckable(CheckableOption option); // Add a type to filter for. Filter types are used to determine if a check box is added and/or to be shown if // the type is an end point. See "IncludeEndPoints" and "MakeCheckable" for more details. diff --git a/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp b/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp index 1083ec876a..ac3ab0dd04 100644 --- a/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp +++ b/Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer.cpp @@ -308,7 +308,7 @@ namespace AssetMemoryAnalyzer AZStd::function<void(AssetInfo*, AssetTreeNode*, int)> recurse; recurse = [&recurse](AssetInfo* outAsset, AssetTreeNode* inAsset, int depth) { - outAsset->m_id = inAsset->m_masterInfo ? inAsset->m_masterInfo->m_id->m_id.c_str() : nullptr; + outAsset->m_id = inAsset->m_primaryinfo ? inAsset->m_primaryinfo->m_id->m_id.c_str() : nullptr; // For every code point in this asset node, record its allocations for (auto& codePointInfo : inAsset->m_data.m_codePointsToAllocations) From 08bd4ee740c995d49b995be338db36a540b50f52 Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Thu, 22 Apr 2021 14:28:42 -0500 Subject: [PATCH 83/96] [LYN-3160] Removed IEditor::Get/SetEditMode and some additional unused (related) content in the InfoBar. --- .../EditorUtilityCommands_legacy_test_case.py | 18 - .../EditorUtilityCommands_test.py | 2 - .../EditorUtilityCommands_test_case.py | 16 - .../Editor/Core/LevelEditorMenuHandler.cpp | 20 - Code/Sandbox/Editor/CryEdit.cpp | 270 ++-------- Code/Sandbox/Editor/CryEdit.h | 18 - Code/Sandbox/Editor/CryEditDoc.cpp | 2 - Code/Sandbox/Editor/IEditor.h | 14 - Code/Sandbox/Editor/IEditorImpl.cpp | 113 +---- Code/Sandbox/Editor/IEditorImpl.h | 14 - Code/Sandbox/Editor/InfoBar.cpp | 467 +----------------- Code/Sandbox/Editor/InfoBar.h | 20 - Code/Sandbox/Editor/InfoBar.ui | 105 ---- Code/Sandbox/Editor/Lib/Tests/IEditorMock.h | 2 - .../Lib/Tests/test_EditorPythonBindings.cpp | 2 - .../Editor/Lib/Tests/test_SetVectorDlg.cpp | 92 ---- Code/Sandbox/Editor/MainWindow.cpp | 140 ------ Code/Sandbox/Editor/MainWindow.h | 15 - Code/Sandbox/Editor/Objects/AxisGizmo.cpp | 209 +------- Code/Sandbox/Editor/PythonEditorEventsBus.h | 10 - Code/Sandbox/Editor/PythonEditorFuncs.cpp | 77 --- Code/Sandbox/Editor/PythonEditorFuncs.h | 4 - Code/Sandbox/Editor/RenderViewport.cpp | 75 --- Code/Sandbox/Editor/Resource.h | 11 - Code/Sandbox/Editor/SetVectorDlg.cpp | 257 ---------- Code/Sandbox/Editor/SetVectorDlg.h | 61 --- Code/Sandbox/Editor/SetVectorDlg.ui | 55 --- Code/Sandbox/Editor/ToolbarManager.cpp | 14 - Code/Sandbox/Editor/editor_lib_files.cmake | 3 - .../Editor/editor_lib_test_files.cmake | 1 - 30 files changed, 34 insertions(+), 2073 deletions(-) delete mode 100644 Code/Sandbox/Editor/Lib/Tests/test_SetVectorDlg.cpp delete mode 100644 Code/Sandbox/Editor/SetVectorDlg.cpp delete mode 100644 Code/Sandbox/Editor/SetVectorDlg.h delete mode 100644 Code/Sandbox/Editor/SetVectorDlg.ui diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_legacy_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_legacy_test_case.py index 9bb9ba5337..9160530ba4 100755 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_legacy_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_legacy_test_case.py @@ -27,15 +27,6 @@ def testing_cvar(setMethod, methodName, label, value, compare): print('{} failed'.format(methodName)) -def testing_edit_mode(mode): - general.set_edit_mode(mode) - - if (general.get_edit_mode(mode)): - return True - - return False - - def testing_axis_constraints(constraint): general.set_axis_constraint(constraint) @@ -58,15 +49,6 @@ compare = lambda lhs, rhs: rhs == int(lhs) testing_cvar(general.set_cvar_integer, 'set_cvar_integer', 'sys_LocalMemoryGeometryLimit', 33, compare) -# ----- Test Edit Mode - -if (testing_edit_mode("SELECT") and testing_edit_mode('SELECTAREA') and - testing_edit_mode("MOVE") and testing_edit_mode("ROTATE") and - testing_edit_mode("SCALE") and testing_edit_mode("TOOL")): - - print("edit mode works") - - # ----- Test Axis Constraints if (testing_axis_constraints("X") and testing_axis_constraints("Y") and diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test.py index 6261312814..bc258cce3f 100755 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test.py @@ -33,7 +33,6 @@ class TestEditorAutomation(object): "SetCVarFromFloat worked", "SetCVarFromString worked", "SetCVarFromInteger worked", - "edit mode works", "axis constraint works", "end of editor utility tests" ] @@ -48,7 +47,6 @@ class TestEditorAutomation(object): "set_cvar_float worked", "set_cvar_string worked", "set_cvar_integer worked", - "edit mode works", "axis constraint works", "end of editor utility tests" ] diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test_case.py b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test_case.py index bae7da19b0..91dd883a10 100755 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonBindings/EditorUtilityCommands_test_case.py @@ -28,15 +28,6 @@ def testing_cvar(setMethod, methodName, label, value, compare): print('{} failed'.format(methodName)) -def testing_edit_mode(mode): - python_editor_funcs.PythonEditorBus(bus.Broadcast, 'SetEditMode', mode) - - if mode == python_editor_funcs.PythonEditorBus(bus.Broadcast, 'GetEditMode'): - return True - - return False - - def testing_axis_constraints(constraint): python_editor_funcs.PythonEditorBus(bus.Broadcast, 'SetAxisConstraint', constraint) @@ -57,13 +48,6 @@ testing_cvar('SetCVarFromString', 'SetCVarFromString', 'e_ScreenShotFileFormat', compare = lambda lhs, rhs: rhs == int(lhs) testing_cvar('SetCVarFromInteger', 'SetCVarFromInteger', 'sys_LocalMemoryGeometryLimit', 33, compare) -# ----- Test Edit Mode - -if (testing_edit_mode("SELECT") and testing_edit_mode('SELECTAREA') and - testing_edit_mode("MOVE") and testing_edit_mode("ROTATE") and - testing_edit_mode("SCALE") and testing_edit_mode("TOOL")): - print("edit mode works") - # ----- Test Axis Constraints if (testing_axis_constraints("X") and testing_axis_constraints("Y") and diff --git a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp index 0863e1627f..aed53d6e8b 100644 --- a/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Sandbox/Editor/Core/LevelEditorMenuHandler.cpp @@ -577,16 +577,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe modifyMenu.AddAction(ID_MODIFY_LINK); modifyMenu.AddAction(ID_MODIFY_UNLINK); modifyMenu.AddSeparator(); - - auto alignMenu = modifyMenu.AddMenu(tr("Align")); - alignMenu.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID); - - auto constrainMenu = modifyMenu.AddMenu(tr("Constrain")); - constrainMenu.AddAction(ID_SELECT_AXIS_X); - constrainMenu.AddAction(ID_SELECT_AXIS_Y); - constrainMenu.AddAction(ID_SELECT_AXIS_Z); - constrainMenu.AddAction(ID_SELECT_AXIS_XY); - constrainMenu.AddAction(ID_SELECT_AXIS_TERRAIN); } auto snapMenu = modifyMenu.AddMenu(tr("Snap")); @@ -608,20 +598,10 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe } auto transformModeMenu = modifyMenu.AddMenu(tr("Transform Mode")); - if (!newViewportInteractionModelEnabled) - { - transformModeMenu.AddAction(ID_EDITMODE_SELECT); - } - transformModeMenu.AddAction(ID_EDITMODE_MOVE); transformModeMenu.AddAction(ID_EDITMODE_ROTATE); transformModeMenu.AddAction(ID_EDITMODE_SCALE); - if (!newViewportInteractionModelEnabled) - { - transformModeMenu.AddAction(ID_EDITMODE_SELECTAREA); - } - editMenu.AddSeparator(); // Lock Selection diff --git a/Code/Sandbox/Editor/CryEdit.cpp b/Code/Sandbox/Editor/CryEdit.cpp index b373ef0009..a474706910 100644 --- a/Code/Sandbox/Editor/CryEdit.cpp +++ b/Code/Sandbox/Editor/CryEdit.cpp @@ -125,7 +125,6 @@ AZ_POP_DISABLE_WARNING #include "AnimationContext.h" #include "GotoPositionDlg.h" -#include "SetVectorDlg.h" #include "ConsoleDialog.h" #include "Controls/ConsoleSCB.h" @@ -395,29 +394,20 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_EDITMODE_MOVE, OnEditmodeMove) ON_COMMAND(ID_EDITMODE_ROTATE, OnEditmodeRotate) ON_COMMAND(ID_EDITMODE_SCALE, OnEditmodeScale) - ON_COMMAND(ID_EDITMODE_SELECT, OnEditmodeSelect) ON_COMMAND(ID_OBJECTMODIFY_SETAREA, OnObjectSetArea) ON_COMMAND(ID_OBJECTMODIFY_SETHEIGHT, OnObjectSetHeight) ON_COMMAND(ID_OBJECTMODIFY_FREEZE, OnObjectmodifyFreeze) ON_COMMAND(ID_OBJECTMODIFY_UNFREEZE, OnObjectmodifyUnfreeze) - ON_COMMAND(ID_EDITMODE_SELECTAREA, OnEditmodeSelectarea) - ON_COMMAND(ID_SELECT_AXIS_X, OnSelectAxisX) - ON_COMMAND(ID_SELECT_AXIS_Y, OnSelectAxisY) - ON_COMMAND(ID_SELECT_AXIS_Z, OnSelectAxisZ) - ON_COMMAND(ID_SELECT_AXIS_XY, OnSelectAxisXy) ON_COMMAND(ID_UNDO, OnUndo) ON_COMMAND(ID_TOOLBAR_WIDGET_REDO, OnUndo) // Can't use the same ID, because for the menu we can't have a QWidgetAction, while for the toolbar we want one ON_COMMAND(ID_SELECTION_SAVE, OnSelectionSave) ON_COMMAND(ID_IMPORT_ASSET, OnOpenAssetImporter) ON_COMMAND(ID_SELECTION_LOAD, OnSelectionLoad) - ON_COMMAND(ID_OBJECTMODIFY_ALIGNTOGRID, OnAlignToGrid) ON_COMMAND(ID_LOCK_SELECTION, OnLockSelection) ON_COMMAND(ID_EDIT_LEVELDATA, OnEditLevelData) ON_COMMAND(ID_FILE_EDITLOGFILE, OnFileEditLogFile) ON_COMMAND(ID_FILE_RESAVESLICES, OnFileResaveSlices) ON_COMMAND(ID_FILE_EDITEDITORINI, OnFileEditEditorini) - ON_COMMAND(ID_SELECT_AXIS_TERRAIN, OnSelectAxisTerrain) - ON_COMMAND(ID_SELECT_AXIS_SNAPTOALL, OnSelectAxisSnapToAll) ON_COMMAND(ID_PREFERENCES, OnPreferences) ON_COMMAND(ID_RELOAD_GEOMETRY, OnReloadGeometry) ON_COMMAND(ID_REDO, OnRedo) @@ -484,7 +474,6 @@ void CCryEditApp::RegisterActionHandlers() ON_COMMAND(ID_VIEW_CYCLE2DVIEWPORT, OnViewCycle2dviewport) #endif ON_COMMAND(ID_DISPLAY_GOTOPOSITION, OnDisplayGotoPosition) - ON_COMMAND(ID_DISPLAY_SETVECTOR, OnDisplaySetVector) ON_COMMAND(ID_SNAPANGLE, OnSnapangle) ON_COMMAND(ID_RULER, OnRuler) ON_COMMAND(ID_ROTATESELECTION_XAXIS, OnRotateselectionXaxis) @@ -2755,85 +2744,31 @@ void CCryEditApp::OnSetHeight() ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnEditmodeMove() { - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - using namespace AzToolsFramework; - EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), - &EditorTransformComponentSelectionRequests::SetTransformMode, - EditorTransformComponentSelectionRequests::Mode::Translation); - } - else - { - GetIEditor()->SetEditMode(eEditModeMove); - } + using namespace AzToolsFramework; + EditorTransformComponentSelectionRequestBus::Event( + GetEntityContextId(), + &EditorTransformComponentSelectionRequests::SetTransformMode, + EditorTransformComponentSelectionRequests::Mode::Translation); } ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnEditmodeRotate() { - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - using namespace AzToolsFramework; - EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), - &EditorTransformComponentSelectionRequests::SetTransformMode, - EditorTransformComponentSelectionRequests::Mode::Rotation); - } - else - { - GetIEditor()->SetEditMode(eEditModeRotate); - } + using namespace AzToolsFramework; + EditorTransformComponentSelectionRequestBus::Event( + GetEntityContextId(), + &EditorTransformComponentSelectionRequests::SetTransformMode, + EditorTransformComponentSelectionRequests::Mode::Rotation); } ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnEditmodeScale() { - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - using namespace AzToolsFramework; - EditorTransformComponentSelectionRequestBus::Event( - GetEntityContextId(), - &EditorTransformComponentSelectionRequests::SetTransformMode, - EditorTransformComponentSelectionRequests::Mode::Scale); - } - else - { - GetIEditor()->SetEditMode(eEditModeScale); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnEditmodeSelect() -{ - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - GetIEditor()->SetEditMode(eEditModeSelect); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnEditmodeSelectarea() -{ - // TODO: Add your command handler code here - GetIEditor()->SetEditMode(eEditModeSelectArea); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateEditmodeSelectarea(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetEditMode() == eEditModeSelectArea); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateEditmodeSelect(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - action->setChecked(GetIEditor()->GetEditMode() == eEditModeSelect); - } + using namespace AzToolsFramework; + EditorTransformComponentSelectionRequestBus::Event( + GetEntityContextId(), + &EditorTransformComponentSelectionRequests::SetTransformMode, + EditorTransformComponentSelectionRequests::Mode::Scale); } ////////////////////////////////////////////////////////////////////////// @@ -2841,19 +2776,12 @@ void CCryEditApp::OnUpdateEditmodeMove(QAction* action) { Q_ASSERT(action->isCheckable()); - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; - AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( - mode, AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); + AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; + AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( + mode, AzToolsFramework::GetEntityContextId(), + &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); - action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Translation); - } - else - { - action->setChecked(GetIEditor()->GetEditMode() == eEditModeMove); - } + action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Translation); } ////////////////////////////////////////////////////////////////////////// @@ -2861,20 +2789,12 @@ void CCryEditApp::OnUpdateEditmodeRotate(QAction* action) { Q_ASSERT(action->isCheckable()); - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; - AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( - mode, AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); + AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; + AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( + mode, AzToolsFramework::GetEntityContextId(), + &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); - action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Rotation); - } - else - { - action->setChecked(GetIEditor()->GetEditMode() == eEditModeRotate); - action->setEnabled(true); - } + action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Rotation); } ////////////////////////////////////////////////////////////////////////// @@ -2882,20 +2802,12 @@ void CCryEditApp::OnUpdateEditmodeScale(QAction* action) { Q_ASSERT(action->isCheckable()); - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; - AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( - mode, AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); + AzToolsFramework::EditorTransformComponentSelectionRequests::Mode mode; + AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( + mode, AzToolsFramework::GetEntityContextId(), + &AzToolsFramework::EditorTransformComponentSelectionRequests::GetTransformMode); - action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Scale); - } - else - { - action->setChecked(GetIEditor()->GetEditMode() == eEditModeScale); - action->setEnabled(true); - } + action->setChecked(mode == AzToolsFramework::EditorTransformComponentSelectionRequests::Mode::Scale); } ////////////////////////////////////////////////////////////////////////// @@ -3076,101 +2988,6 @@ void CCryEditApp::OnViewSwitchToGame() GetIEditor()->SetInGameMode(inGame); } -void CCryEditApp::OnSelectAxisX() -{ - AxisConstrains axis = (GetIEditor()->GetAxisConstrains() != AXIS_X) ? AXIS_X : AXIS_NONE; - GetIEditor()->SetAxisConstraints(axis); -} - -void CCryEditApp::OnSelectAxisY() -{ - AxisConstrains axis = (GetIEditor()->GetAxisConstrains() != AXIS_Y) ? AXIS_Y : AXIS_NONE; - GetIEditor()->SetAxisConstraints(axis); -} - -void CCryEditApp::OnSelectAxisZ() -{ - AxisConstrains axis = (GetIEditor()->GetAxisConstrains() != AXIS_Z) ? AXIS_Z : AXIS_NONE; - GetIEditor()->SetAxisConstraints(axis); -} - -void CCryEditApp::OnSelectAxisXy() -{ - AxisConstrains axis = (GetIEditor()->GetAxisConstrains() != AXIS_XY) ? AXIS_XY : AXIS_NONE; - GetIEditor()->SetAxisConstraints(axis); -} - -void CCryEditApp::OnUpdateSelectAxisX(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_X); -} - -void CCryEditApp::OnUpdateSelectAxisXy(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_XY); -} - -void CCryEditApp::OnUpdateSelectAxisY(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_Y); -} - -void CCryEditApp::OnUpdateSelectAxisZ(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_Z); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnSelectAxisTerrain() -{ - IEditor* editor = GetIEditor(); - bool isAlreadyEnabled = (editor->GetAxisConstrains() == AXIS_TERRAIN) && (editor->IsTerrainAxisIgnoreObjects()); - if (!isAlreadyEnabled) - { - editor->SetAxisConstraints(AXIS_TERRAIN); - editor->SetTerrainAxisIgnoreObjects(true); - } - else - { - // behave like a toggle button - click on the same thing again to disable. - editor->SetAxisConstraints(AXIS_NONE); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnSelectAxisSnapToAll() -{ - IEditor* editor = GetIEditor(); - bool isAlreadyEnabled = (editor->GetAxisConstrains() == AXIS_TERRAIN) && (!editor->IsTerrainAxisIgnoreObjects()); - if (!isAlreadyEnabled) - { - editor->SetAxisConstraints(AXIS_TERRAIN); - editor->SetTerrainAxisIgnoreObjects(false); - } - else - { - // behave like a toggle button - click on the same thing again to disable. - editor->SetAxisConstraints(AXIS_NONE); - } -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateSelectAxisTerrain(QAction* action) -{ - Q_ASSERT(action->isCheckable()); - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_TERRAIN && GetIEditor()->IsTerrainAxisIgnoreObjects()); -} - -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnUpdateSelectAxisSnapToAll(QAction* action) -{ - action->setChecked(GetIEditor()->GetAxisConstrains() == AXIS_TERRAIN && !GetIEditor()->IsTerrainAxisIgnoreObjects()); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnExportSelectedObjects() { @@ -3351,26 +3168,6 @@ void CCryEditApp::OnUpdateSelected(QAction* action) action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty()); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnAlignToGrid() -{ - CSelectionGroup* sel = GetIEditor()->GetSelection(); - if (!sel->IsEmpty()) - { - CUndo undo("Align To Grid"); - Matrix34 tm; - for (int i = 0; i < sel->GetCount(); i++) - { - CBaseObject* obj = sel->GetObject(i); - tm = obj->GetWorldTM(); - Vec3 snaped = gSettings.pGrid->Snap(tm.GetTranslation()); - tm.SetTranslation(snaped); - obj->SetWorldTM(tm, eObjectUpdateFlags_UserInput); - obj->OnEvent(EVENT_ALIGN_TOGRID); - } - } -} - void CCryEditApp::OnShowHelpers() { GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()); @@ -4530,13 +4327,6 @@ void CCryEditApp::OnDisplayGotoPosition() dlg.exec(); } -////////////////////////////////////////////////////////////////////////// -void CCryEditApp::OnDisplaySetVector() -{ - CSetVectorDlg dlg; - dlg.exec(); -} - ////////////////////////////////////////////////////////////////////////// void CCryEditApp::OnSnapangle() { diff --git a/Code/Sandbox/Editor/CryEdit.h b/Code/Sandbox/Editor/CryEdit.h index 7c77a03bb4..dc18dbcfda 100644 --- a/Code/Sandbox/Editor/CryEdit.h +++ b/Code/Sandbox/Editor/CryEdit.h @@ -224,40 +224,23 @@ public: void OnEditmodeMove(); void OnEditmodeRotate(); void OnEditmodeScale(); - void OnEditmodeSelect(); void OnObjectSetArea(); void OnObjectSetHeight(); - void OnUpdateEditmodeSelect(QAction* action); void OnUpdateEditmodeMove(QAction* action); void OnUpdateEditmodeRotate(QAction* action); void OnUpdateEditmodeScale(QAction* action); void OnObjectmodifyFreeze(); void OnObjectmodifyUnfreeze(); - void OnEditmodeSelectarea(); - void OnUpdateEditmodeSelectarea(QAction* action); - void OnSelectAxisX(); - void OnSelectAxisY(); - void OnSelectAxisZ(); - void OnSelectAxisXy(); - void OnUpdateSelectAxisX(QAction* action); - void OnUpdateSelectAxisXy(QAction* action); - void OnUpdateSelectAxisY(QAction* action); - void OnUpdateSelectAxisZ(QAction* action); void OnUndo(); void OnSelectionSave(); void OnOpenAssetImporter(); void OnSelectionLoad(); void OnUpdateSelected(QAction* action); - void OnAlignToGrid(); void OnLockSelection(); void OnEditLevelData(); void OnFileEditLogFile(); void OnFileResaveSlices(); void OnFileEditEditorini(); - void OnSelectAxisTerrain(); - void OnSelectAxisSnapToAll(); - void OnUpdateSelectAxisTerrain(QAction* action); - void OnUpdateSelectAxisSnapToAll(QAction* action); void OnPreferences(); void OnReloadTextures(); void OnReloadGeometry(); @@ -448,7 +431,6 @@ private: void OnToolsScriptHelp(); void OnViewCycle2dviewport(); void OnDisplayGotoPosition(); - void OnDisplaySetVector(); void OnSnapangle(); void OnUpdateSnapangle(QAction* action); void OnRuler(); diff --git a/Code/Sandbox/Editor/CryEditDoc.cpp b/Code/Sandbox/Editor/CryEditDoc.cpp index a94d588516..916317b6bb 100644 --- a/Code/Sandbox/Editor/CryEditDoc.cpp +++ b/Code/Sandbox/Editor/CryEditDoc.cpp @@ -279,8 +279,6 @@ void CCryEditDoc::DeleteContents() // [LY-90904] move this to the EditorVegetationManager component InstanceStatObjEventBus::Broadcast(&InstanceStatObjEventBus::Events::ReleaseData); - GetIEditor()->SetEditMode(eEditModeSelect); - ////////////////////////////////////////////////////////////////////////// // Clear all undo info. ////////////////////////////////////////////////////////////////////////// diff --git a/Code/Sandbox/Editor/IEditor.h b/Code/Sandbox/Editor/IEditor.h index 83a0029d9f..90fb8823e7 100644 --- a/Code/Sandbox/Editor/IEditor.h +++ b/Code/Sandbox/Editor/IEditor.h @@ -318,17 +318,6 @@ enum EOperationMode eModellingMode // Geometry modeling mode }; -enum EEditMode -{ - eEditModeSelect, - eEditModeSelectArea, - eEditModeMove, - eEditModeRotate, - eEditModeScale, - eEditModeTool, - eEditModeRotateCircle, -}; - //! Mouse events that viewport can send enum EMouseEvent { @@ -619,9 +608,6 @@ struct IEditor virtual void SetOperationMode(EOperationMode mode) = 0; virtual EOperationMode GetOperationMode() = 0; - //! editMode - EEditMode - virtual void SetEditMode(int editMode) = 0; - virtual int GetEditMode() = 0; //! Shows/Hides transformation manipulator. //! if bShow is true also returns a valid ITransformManipulator pointer. virtual ITransformManipulator* ShowTransformManipulator(bool bShow) = 0; diff --git a/Code/Sandbox/Editor/IEditorImpl.cpp b/Code/Sandbox/Editor/IEditorImpl.cpp index d4fd86312e..561953d729 100644 --- a/Code/Sandbox/Editor/IEditorImpl.cpp +++ b/Code/Sandbox/Editor/IEditorImpl.cpp @@ -144,8 +144,7 @@ namespace const char* CEditorImpl::m_crashLogFileName = "SessionStatus/editor_statuses.json"; CEditorImpl::CEditorImpl() - : m_currEditMode(eEditModeSelect) - , m_operationMode(eOperationModeNone) + : m_operationMode(eOperationModeNone) , m_pSystem(nullptr) , m_pFileUtil(nullptr) , m_pClassFactory(nullptr) @@ -236,18 +235,6 @@ CEditorImpl::CEditorImpl() m_pRuler = new CRuler; m_selectedRegion.min = Vec3(0, 0, 0); m_selectedRegion.max = Vec3(0, 0, 0); - ZeroStruct(m_lastAxis); - m_lastAxis[eEditModeSelect] = AXIS_TERRAIN; - m_lastAxis[eEditModeSelectArea] = AXIS_TERRAIN; - m_lastAxis[eEditModeMove] = AXIS_TERRAIN; - m_lastAxis[eEditModeRotate] = AXIS_Z; - m_lastAxis[eEditModeScale] = AXIS_XY; - ZeroStruct(m_lastCoordSys); - m_lastCoordSys[eEditModeSelect] = COORDS_LOCAL; - m_lastCoordSys[eEditModeSelectArea] = COORDS_LOCAL; - m_lastCoordSys[eEditModeMove] = COORDS_WORLD; - m_lastCoordSys[eEditModeRotate] = COORDS_WORLD; - m_lastCoordSys[eEditModeScale] = COORDS_WORLD; DetectVersion(); RegisterTools(); @@ -257,8 +244,6 @@ CEditorImpl::CEditorImpl() m_pAssetBrowserRequestHandler = nullptr; m_assetEditorRequestsHandler = nullptr; - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); - AZ::IO::SystemFile::CreateDir("SessionStatus"); QFile::setPermissions(m_crashLogFileName, QFileDevice::ReadOther | QFileDevice::WriteOther); } @@ -282,8 +267,6 @@ void CEditorImpl::Initialize() // Activate QT immediately so that its available as soon as CEditorImpl is (and thus GetIEditor()) InitializeEditorCommon(GetIEditor()); - - LoadSettings(); } //The only purpose of that function is to be called at the very begining of the shutdown sequence so that we can instrument and track @@ -298,8 +281,6 @@ void CEditorImpl::OnEarlyExitShutdownSequence() void CEditorImpl::Uninitialize() { - SaveSettings(); - if (m_pSystem) { UninitializeEditorCommonISystem(m_pSystem); @@ -360,8 +341,6 @@ void CEditorImpl::LoadPlugins() CEditorImpl::~CEditorImpl() { - AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusDisconnect(); - gSettings.Save(); m_bExiting = true; // Can't save level after this point (while Crash) SAFE_RELEASE(m_pSourceControl); @@ -650,40 +629,6 @@ IMainStatusBar* CEditorImpl::GetMainStatusBar() return MainWindow::instance()->StatusBar(); } -int CEditorImpl::GetEditMode() -{ - return m_currEditMode; -} - -void CEditorImpl::SetEditMode(int editMode) -{ - bool isEditorInGameMode = false; - EBUS_EVENT_RESULT(isEditorInGameMode, AzToolsFramework::EditorEntityContextRequestBus, IsEditorRunningGame); - - if (isEditorInGameMode) - { - if (editMode != eEditModeSelect) - { - if (SelectionContainsComponentEntities()) - { - return; - } - } - } - - EEditMode newEditMode = (EEditMode)editMode; - if (m_currEditMode == newEditMode) - { - return; - } - - m_currEditMode = newEditMode; - AABB box(Vec3(0, 0, 0), Vec3(0, 0, 0)); - SetSelectedRegion(box); - - Notify(eNotify_OnEditModeChange); -} - void CEditorImpl::SetOperationMode(EOperationMode mode) { m_operationMode = mode; @@ -728,7 +673,6 @@ ITransformManipulator* CEditorImpl::GetTransformManipulator() void CEditorImpl::SetAxisConstraints(AxisConstrains axisFlags) { m_selectedAxis = axisFlags; - m_lastAxis[m_currEditMode] = m_selectedAxis; m_pViewManager->SetAxisConstrain(axisFlags); SetTerrainAxisIgnoreObjects(false); @@ -754,7 +698,6 @@ bool CEditorImpl::IsTerrainAxisIgnoreObjects() void CEditorImpl::SetReferenceCoordSys(RefCoordSys refCoords) { m_refCoordsSys = refCoords; - m_lastCoordSys[m_currEditMode] = m_refCoordsSys; // Update all views. UpdateViews(eUpdateObjects, NULL); @@ -1884,60 +1827,6 @@ bool CEditorImpl::IsNewViewportInteractionModelEnabled() const return m_isNewViewportInteractionModelEnabled; } -void CEditorImpl::OnStartPlayInEditor() -{ - if (SelectionContainsComponentEntities()) - { - SetEditMode(eEditModeSelect); - } -} - -namespace -{ - const std::vector<std::pair<EEditMode, QString>> s_editModeNames = { - { eEditModeSelect, QStringLiteral("Select") }, - { eEditModeSelectArea, QStringLiteral("SelectArea") }, - { eEditModeMove, QStringLiteral("Move") }, - { eEditModeRotate, QStringLiteral("Rotate") }, - { eEditModeScale, QStringLiteral("Scale") } - }; -} - -void CEditorImpl::LoadSettings() -{ - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); - - settings.beginGroup(QStringLiteral("Editor")); - settings.beginGroup(QStringLiteral("CoordSys")); - - for (const auto& editMode : s_editModeNames) - { - if (settings.contains(editMode.second)) - { - m_lastCoordSys[editMode.first] = static_cast<RefCoordSys>(settings.value(editMode.second).toInt()); - } - } - - settings.endGroup(); // CoordSys - settings.endGroup(); // Editor -} - -void CEditorImpl::SaveSettings() const -{ - QSettings settings(QStringLiteral("Amazon"), QStringLiteral("O3DE")); - - settings.beginGroup(QStringLiteral("Editor")); - settings.beginGroup(QStringLiteral("CoordSys")); - - for (const auto& editMode : s_editModeNames) - { - settings.setValue(editMode.second, static_cast<int>(m_lastCoordSys[editMode.first])); - } - - settings.endGroup(); // CoordSys - settings.endGroup(); // Editor -} - IEditorPanelUtils* CEditorImpl::GetEditorPanelUtils() { return m_panelEditorUtils; diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index 7bb864aaa3..db391b7678 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -23,7 +23,6 @@ #include <memory> // for shared_ptr #include <QMap> #include <QApplication> -#include <AzToolsFramework/Entity/EditorEntityContextBus.h> #include <AzToolsFramework/Thumbnails/ThumbnailerBus.h> #include <AzCore/std/string/string.h> @@ -86,7 +85,6 @@ namespace AssetDatabase class CEditorImpl : public IEditor - , protected AzToolsFramework::EditorEntityContextNotificationBus::Handler { Q_DECLARE_TR_FUNCTIONS(CEditorImpl) @@ -226,8 +224,6 @@ public: void SetDataModified(); void SetOperationMode(EOperationMode mode); EOperationMode GetOperationMode(); - void SetEditMode(int editMode); - int GetEditMode(); ITransformManipulator* ShowTransformManipulator(bool bShow); ITransformManipulator* GetTransformManipulator(); @@ -348,23 +344,15 @@ public: protected: - ////////////////////////////////////////////////////////////////////////// - // EditorEntityContextNotificationBus implementation - void OnStartPlayInEditor() override; - ////////////////////////////////////////////////////////////////////////// AZStd::string LoadProjectIdFromProjectData(); void DetectVersion(); void RegisterTools(); void SetPrimaryCDFolder(); - void LoadSettings(); - void SaveSettings() const; - //! List of all notify listeners. std::list<IEditorNotifyListener*> m_listeners; - EEditMode m_currEditMode; EOperationMode m_operationMode; ISystem* m_pSystem; IFileUtil* m_pFileUtil; @@ -378,8 +366,6 @@ protected: AABB m_selectedRegion; AxisConstrains m_selectedAxis; RefCoordSys m_refCoordsSys; - AxisConstrains m_lastAxis[16]; - RefCoordSys m_lastCoordSys[16]; bool m_bAxisVectorLock; bool m_bUpdates; bool m_bTerrainAxisIgnoreObjects; diff --git a/Code/Sandbox/Editor/InfoBar.cpp b/Code/Sandbox/Editor/InfoBar.cpp index 9e50e4ed3e..a1a1f7b055 100644 --- a/Code/Sandbox/Editor/InfoBar.cpp +++ b/Code/Sandbox/Editor/InfoBar.cpp @@ -30,6 +30,8 @@ AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING #include <ui_InfoBar.h> AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING +#include <QLineEdit> + #include <AzQtComponents/Components/Style.h> #include "CryPhysicsDeprecation.h" @@ -52,10 +54,6 @@ CInfoBar::CInfoBar(QWidget* parent) { ui->setupUi(this); - m_enabledVector = false; - m_bVectorLock = false; - m_prevEditMode = 0; - m_bSelectionLocked = false; m_bSelectionChanged = false; m_bDragMode = false; m_prevMoveSpeed = 0; @@ -70,25 +68,14 @@ CInfoBar::CInfoBar(QWidget* parent) OnInitDialog(); - connect(ui->m_vectorLock, &QToolButton::clicked, this, &CInfoBar::OnVectorLock); - connect(ui->m_lockSelection, &QToolButton::clicked, this, &CInfoBar::OnLockSelection); - auto comboBoxTextChanged = static_cast<void(QComboBox::*)(const QString&)>(&QComboBox::currentTextChanged); connect(ui->m_moveSpeed, comboBoxTextChanged, this, &CInfoBar::OnUpdateMoveSpeedText); connect(ui->m_moveSpeed->lineEdit(), &QLineEdit::returnPressed, this, &CInfoBar::OnSpeedComboBoxEnter); - connect(ui->m_posCtrl, &AzQtComponents::VectorInput::valueChanged, this, &CInfoBar::OnVectorChanged); - // Hide some buttons from the expander menu - AzQtComponents::Style::addClass(ui->m_posCtrl, "expanderMenu_hide"); AzQtComponents::Style::addClass(ui->m_physDoStepBtn, "expanderMenu_hide"); AzQtComponents::Style::addClass(ui->m_physSingleStepBtn, "expanderMenu_hide"); - // posCtrl is a VectorInput initialized via UI; as such, we can't construct it to have only 3 elements. - // We can just hide the W element as it is unused. - ui->m_posCtrl->getElements()[3]->setVisible(false); - - connect(ui->m_setVector, &QToolButton::clicked, this, &CInfoBar::OnBnClickedSetVector); connect(ui->m_physicsBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedPhysics); connect(ui->m_physSingleStepBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedSingleStepPhys); connect(ui->m_physDoStepBtn, &QToolButton::clicked, this, &CInfoBar::OnBnClickedDoStepPhys); @@ -99,12 +86,6 @@ CInfoBar::CInfoBar(QWidget* parent) connect(this, &CInfoBar::ActionTriggered, MainWindow::instance()->GetActionManager(), &ActionManager::ActionTriggered); - connect(ui->m_lockSelection, &QAbstractButton::toggled, ui->m_lockSelection, [this](bool checked) { - ui->m_lockSelection->setToolTip(checked ? tr("Unlock Object Selection") : tr("Lock Object Selection")); - }); - connect(ui->m_vectorLock, &QAbstractButton::toggled, ui->m_vectorLock, [this](bool checked) { - ui->m_vectorLock->setToolTip(checked ? tr("Unlock Axis Vectors") : tr("Lock Axis Vectors")); - }); connect(ui->m_physicsBtn, &QAbstractButton::toggled, ui->m_physicsBtn, [this](bool checked) { ui->m_physicsBtn->setToolTip(checked ? tr("Stop Simulation (Ctrl+P)") : tr("Simulate (Ctrl+P)")); }); @@ -121,27 +102,6 @@ CInfoBar::CInfoBar(QWidget* parent) ui->m_vrBtn->setToolTip(checked ? tr("Disable VR Preview") : tr("Enable VR Preview")); }); - // hide old ui elements that are not valid with the new viewport interaction model - if (GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - ui->m_lockSelection->setVisible(false); - AzQtComponents::Style::addClass(ui->m_lockSelection, "expanderMenu_hide"); - ui->m_posCtrl->setVisible(false); - AzQtComponents::Style::addClass(ui->m_posCtrl, "expanderMenu_hide"); - ui->m_setVector->setVisible(false); - AzQtComponents::Style::addClass(ui->m_setVector, "expanderMenu_hide"); - ui->m_vectorLock->setVisible(false); - AzQtComponents::Style::addClass(ui->m_vectorLock, "expanderMenu_hide"); - - // As we're hiding some of the icons, we have an extra spacer to deal with. - // We cannot set the visibility of separators, so we'll have to take it out. - int separatorIndex = layout()->indexOf(ui->verticalSpacer_2); - QLayoutItem* separator = layout()->takeAt(separatorIndex); - - // takeAt() removes the item from the layout; delete to avoid memory leaks. - delete separator; - } - ui->m_moveSpeed->setValidator(new QDoubleValidator(m_minSpeed, m_maxSpeed, m_numDecimals, ui->m_moveSpeed)); // Save off the move speed here since setting up the combo box can cause it to update values in the background. @@ -207,150 +167,6 @@ void CInfoBar::OnEditorNotifyEvent(EEditorNotifyEvent event) { m_bSelectionChanged = true; } - else if (event == eNotify_OnEditModeChange) - { - int emode = GetIEditor()->GetEditMode(); - switch (emode) - { - case eEditModeMove: - ui->m_setVector->setToolTip(tr("Set Position of Selected Objects")); - break; - case eEditModeRotate: - ui->m_setVector->setToolTip(tr("Set Rotation of Selected Objects")); - break; - case eEditModeScale: - ui->m_setVector->setToolTip(tr("Set Scale of Selected Objects")); - break; - default: - ui->m_setVector->setToolTip(tr("Set Position/Rotation/Scale of Selected Objects (None Selected)")); - break; - } - } -} - -////////////////////////////////////////////////////////////////////////// - -void CInfoBar::OnVectorChanged() -{ - SetVector(GetVector()); - OnVectorUpdate(false); -} - -void CInfoBar::OnVectorUpdate(bool followTerrain) -{ - int emode = GetIEditor()->GetEditMode(); - if (emode != eEditModeMove && emode != eEditModeRotate && emode != eEditModeScale) - { - return; - } - - Vec3 v = GetVector(); - - ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); - if (pManipulator) - { - return; - } - - CSelectionGroup* selection = GetIEditor()->GetObjectManager()->GetSelection(); - if (selection->IsEmpty()) - { - return; - } - - GetIEditor()->RestoreUndo(); - - int referenceCoordSys = GetIEditor()->GetReferenceCoordSys(); - - CBaseObject* obj = GetIEditor()->GetSelectedObject(); - - Matrix34 tm; - AffineParts ap; - if (obj) - { - tm = obj->GetWorldTM(); - ap.SpectralDecompose(tm); - } - - if (emode == eEditModeMove) - { - if (obj) - { - if (referenceCoordSys == COORDS_WORLD) - { - tm.SetTranslation(v); - obj->SetWorldTM(tm); - } - else - { - obj->SetPos(v); - } - } - else - { - GetIEditor()->GetSelection()->MoveTo(v, followTerrain ? CSelectionGroup::eMS_FollowTerrain : CSelectionGroup::eMS_None, referenceCoordSys); - } - } - if (emode == eEditModeRotate) - { - if (obj) - { - AZ::Vector3 av = LYVec3ToAZVec3(v); - AZ::Transform tr = AZ::ConvertEulerDegreesToTransform(av); - Matrix34 lyTransform = AZTransformToLYTransform(tr); - - AffineParts newap; - newap.SpectralDecompose(lyTransform); - - if (referenceCoordSys == COORDS_WORLD) - { - tm = Matrix34::Create(ap.scale, newap.rot, ap.pos); - obj->SetWorldTM(tm); - } - else - { - obj->SetRotation(newap.rot); - } - } - else - { - CBaseObject *refObj; - CSelectionGroup* pGroup = GetIEditor()->GetSelection(); - if (pGroup && pGroup->GetCount() > 0) - { - refObj = pGroup->GetObject(0); - AffineParts ap2; - ap2.SpectralDecompose(refObj->GetWorldTM()); - Vec3 oldEulerRotation = AZVec3ToLYVec3(AZ::ConvertQuaternionToEulerDegrees(LYQuaternionToAZQuaternion(ap2.rot))); - Vec3 diff = v - oldEulerRotation; - GetIEditor()->GetSelection()->Rotate((Ang3)diff, referenceCoordSys); - } - } - } - if (emode == eEditModeScale) - { - if (v.x == 0 || v.y == 0 || v.z == 0) - { - return; - } - - if (obj) - { - if (referenceCoordSys == COORDS_WORLD) - { - tm = Matrix34::Create(v, ap.rot, ap.pos); - obj->SetWorldTM(tm); - } - else - { - obj->SetScale(v); - } - } - else - { - GetIEditor()->GetSelection()->SetScale(v, referenceCoordSys); - } - } } void CInfoBar::IdleUpdate() @@ -375,21 +191,6 @@ void CInfoBar::IdleUpdate() Vec3 marker = GetIEditor()->GetMarkerPosition(); - /* - // Get active viewport. - int hx = marker.x / 2; - int hy = marker.y / 2; - if (m_heightMapX != hx || m_heightMapY != hy) - { - m_heightMapX = hx; - m_heightMapY = hy; - updateUI = true; - } - */ - - RefCoordSys coordSys = GetIEditor()->GetReferenceCoordSys(); - bool bWorldSpace = GetIEditor()->GetReferenceCoordSys() == COORDS_WORLD; - CSelectionGroup* selection = GetIEditor()->GetSelection(); if (selection->GetCount() != m_numSelected) { @@ -447,198 +248,11 @@ void CInfoBar::IdleUpdate() } } - bool bSelLocked = GetIEditor()->IsSelectionLocked(); - if (bSelLocked != m_bSelectionLocked) - { - m_bSelectionLocked = bSelLocked; - ui->m_lockSelection->setChecked(m_bSelectionLocked); - } - - - if (GetIEditor()->GetSelection()->IsEmpty()) - { - if (ui->m_lockSelection->isEnabled()) - { - ui->m_lockSelection->setEnabled(false); - } - } - else - { - if (!ui->m_lockSelection->isEnabled()) - { - ui->m_lockSelection->setEnabled(true); - } - } - - ////////////////////////////////////////////////////////////////////////// - // Update vector. - ////////////////////////////////////////////////////////////////////////// - Vec3 v(0, 0, 0); - bool enable = false; - float min = 0, max = 10000; - - int emode = GetIEditor()->GetEditMode(); - ITransformManipulator* pManipulator = GetIEditor()->GetTransformManipulator(); - - if (pManipulator) - { - AffineParts ap; - ap.SpectralDecompose(pManipulator->GetTransformation(coordSys)); - - if (emode == eEditModeMove) - { - v = ap.pos; - enable = true; - - min = -64000; - max = 64000; - } - if (emode == eEditModeRotate) - { - v = Vec3(RAD2DEG(Ang3::GetAnglesXYZ(Matrix33(ap.rot)))); - enable = true; - min = -10000; - max = 10000; - } - if (emode == eEditModeScale) - { - v = ap.scale; - enable = true; - min = -10000; - max = 10000; - } - } - else - { - if (selection->IsEmpty()) - { - // Show marker position. - EnableVector(false); - SetVector(marker); - SetVectorRange(-100000, 100000); - return; - } - - CBaseObject* obj = GetIEditor()->GetSelectedObject(); - if (!obj) - { - CSelectionGroup* pGroup = GetIEditor()->GetSelection(); - if (pGroup && pGroup->GetCount() > 0) - { - obj = pGroup->GetObject(0); - } - } - - if (obj) - { - v = obj->GetWorldPos(); - } - - if (emode == eEditModeMove) - { - if (obj) - { - if (bWorldSpace) - { - v = obj->GetWorldTM().GetTranslation(); - } - else - { - v = obj->GetPos(); - } - } - enable = true; - min = -64000; - max = 64000; - } - if (emode == eEditModeRotate) - { - if (obj) - { - Quat objRot; - if (bWorldSpace) - { - AffineParts ap; - ap.SpectralDecompose(obj->GetWorldTM()); - objRot = ap.rot; - } - else - { - objRot = obj->GetRotation(); - } - - // Always convert objRot to v in order to ensure that the inspector and info bar are always in sync - v = AZVec3ToLYVec3(AZ::ConvertQuaternionToEulerDegrees(LYQuaternionToAZQuaternion(objRot))); - } - enable = true; - min = -10000; - max = 10000; - } - if (emode == eEditModeScale) - { - if (obj) - { - if (bWorldSpace) - { - AffineParts ap; - ap.SpectralDecompose(obj->GetWorldTM()); - v = ap.scale; - } - else - { - v = obj->GetScale(); - } - } - enable = true; - min = -10000; - max = 10000; - } - } - - bool updateDisplayVector = (m_currValue != v); - - // If Edit mode changed. - if (m_prevEditMode != emode) - { - // Scale mode enables vector lock. - SetVectorLock(emode == eEditModeScale); - - // Change undo strings. - QString undoString("Modify Object(s)"); - int mode = GetIEditor()->GetEditMode(); - switch (mode) - { - case eEditModeMove: - undoString = QStringLiteral("Move Object(s)"); - break; - case eEditModeRotate: - undoString = QStringLiteral("Rotate Object(s)"); - break; - case eEditModeScale: - undoString = QStringLiteral("Scale Object(s)"); - break; - } - - // edit mode changed, we must update the number values - updateDisplayVector = true; - } - - SetVectorRange(min, max); - EnableVector(enable); - // if our selection changed, or if our display values are out of date if (m_bSelectionChanged) { - updateDisplayVector = true; m_bSelectionChanged = false; } - - if (updateDisplayVector) - { - SetVector(v); - } - - m_prevEditMode = emode; } inline double Round(double fVal, double fStep) @@ -650,71 +264,6 @@ inline double Round(double fVal, double fStep) return fVal; } -void CInfoBar::SetVector(const Vec3& v) -{ - if (!m_bDragMode) - { - m_lastValue = m_currValue; - } - - if (m_currValue != v) - { - ui->m_posCtrl->setValuebyIndex(v.x, 0); - ui->m_posCtrl->setValuebyIndex(v.y, 1); - ui->m_posCtrl->setValuebyIndex(v.z, 2); - m_currValue = v; - } -} - -Vec3 CInfoBar::GetVector() -{ - Vec3 v; - v.x = ui->m_posCtrl->getElements()[0]->getValue(); - v.y = ui->m_posCtrl->getElements()[1]->getValue(); - v.z = ui->m_posCtrl->getElements()[2]->getValue(); - m_currValue = v; - return v; -} - -void CInfoBar::EnableVector(bool enable) -{ - if (m_enabledVector != enable) - { - m_enabledVector = enable; - ui->m_posCtrl->setEnabled(enable); - ui->m_vectorLock->setEnabled(enable); - ui->m_setVector->setEnabled(enable); - } -} - -void CInfoBar::SetVectorLock(bool bVectorLock) -{ - m_bVectorLock = bVectorLock; - ui->m_vectorLock->setChecked(bVectorLock); - GetIEditor()->SetAxisVectorLock(bVectorLock); -} - -void CInfoBar::SetVectorRange(float min, float max) -{ - // Worth noting that this gets called every IdleUpdate, so it is necessary to make sure - // setting the min/max doesn't result in the Qt event queue being pumped - ui->m_posCtrl->setMinimum(min); - ui->m_posCtrl->setMaximum(max); -} - -void CInfoBar::OnVectorLock() -{ - SetVectorLock(!m_bVectorLock); -} - -void CInfoBar::OnLockSelection() -{ - bool newLockSelectionValue = !m_bSelectionLocked; - m_bSelectionLocked = newLockSelectionValue; - ui->m_lockSelection->setChecked(newLockSelectionValue); - GetIEditor()->LockSelection(newLockSelectionValue); -} - void CInfoBar::OnUpdateMoveSpeedText(const QString& text) { gSettings.cameraMoveSpeed = aznumeric_cast<float>(Round(text.toDouble(), m_speedStep)); @@ -730,12 +279,6 @@ void CInfoBar::OnInitDialog() QFontMetrics metrics({}); int width = metrics.boundingRect("-9999.99").width() * m_fieldWidthMultiplier; - ui->m_posCtrl->setEnabled(false); - ui->m_posCtrl->getElements()[0]->setFixedWidth(width); - ui->m_posCtrl->getElements()[1]->setFixedWidth(width); - ui->m_posCtrl->getElements()[2]->setFixedWidth(width); - ui->m_setVector->setEnabled(false); - ui->m_moveSpeed->setFixedWidth(width); ui->m_physicsBtn->setEnabled(false); @@ -809,12 +352,6 @@ void CInfoBar::OnBnClickedGotoPosition() emit ActionTriggered(ID_DISPLAY_GOTOPOSITION); } -////////////////////////////////////////////////////////////////////////// -void CInfoBar::OnBnClickedSetVector() -{ - emit ActionTriggered(ID_DISPLAY_SETVECTOR); -} - ////////////////////////////////////////////////////////////////////////// void CInfoBar::OnBnClickedMuteAudio() { diff --git a/Code/Sandbox/Editor/InfoBar.h b/Code/Sandbox/Editor/InfoBar.h index aa0d0628a2..6e547d46c6 100644 --- a/Code/Sandbox/Editor/InfoBar.h +++ b/Code/Sandbox/Editor/InfoBar.h @@ -59,24 +59,9 @@ protected: virtual void OnOK() {}; virtual void OnCancel() {}; - void OnVectorUpdate(bool followTerrain); - - // this gets called by stepper or text edit changes - void OnVectorChanged(); - - void SetVector(const Vec3& v); - void SetVectorRange(float min, float max); - Vec3 GetVector(); - void EnableVector(bool enable); - - void SetVectorLock(bool bVectorLock); - void OnBnClickedSyncplayer(); void OnBnClickedGotoPosition(); - void OnVectorLock(); - void OnLockSelection(); - void OnBnClickedSetVector(); void OnSpeedComboBoxEnter(); void OnUpdateMoveSpeedText(const QString&); void OnBnClickedTerrainCollision(); @@ -98,13 +83,10 @@ protected: void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override; void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override; - bool m_enabledVector; - float m_width, m_height; //int m_heightMapX,m_heightMapY; double m_fieldWidthMultiplier = 1.8; - int m_prevEditMode; int m_numSelected; float m_prevMoveSpeed; @@ -117,8 +99,6 @@ protected: // Speed presets float m_speedPresetValues[3] = { 0.1f, 1.0f, 10.0f }; - bool m_bVectorLock; - bool m_bSelectionLocked; bool m_bSelectionChanged; bool m_bDragMode; diff --git a/Code/Sandbox/Editor/InfoBar.ui b/Code/Sandbox/Editor/InfoBar.ui index e6d135da4b..84207629df 100644 --- a/Code/Sandbox/Editor/InfoBar.ui +++ b/Code/Sandbox/Editor/InfoBar.ui @@ -57,42 +57,6 @@ </property> </widget> </item> - <item> - <widget class="AzQtComponents::VectorInput" name="m_posCtrl" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Position</string> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="m_setVector"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>XYZ</string> - </property> - <property name="icon"> - <iconset resource="InfoBar.qrc"> - <normaloff>:/InfoBar/XYZ-default.svg</normaloff>:/InfoBar/XYZ-default.svg</iconset> - </property> - <property name="iconSize"> - <size> - <width>22</width> - <height>18</height> - </size> - </property> - </widget> - </item> <item> <widget class="QToolButton" name="m_gotoPos"> <property name="sizePolicy"> @@ -135,68 +99,6 @@ </property> </spacer> </item> - <item> - <widget class="QToolButton" name="m_lockSelection"> - <property name="toolTip"> - <string>Lock Object Selection</string> - </property> - <property name="text"> - <string>Lock Selection</string> - </property> - <property name="icon"> - <iconset resource="InfoBar.qrc"> - <normaloff>:/InfoBar/LockSelection-default.svg</normaloff>:/InfoBar/LockSelection-default.svg</iconset> - </property> - <property name="iconSize"> - <size> - <width>18</width> - <height>18</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="m_vectorLock"> - <property name="toolTip"> - <string>Lock Scale Axis Vectors</string> - </property> - <property name="text"> - <string>Lock Scale</string> - </property> - <property name="icon"> - <iconset resource="InfoBar.qrc"> - <normaloff>:/InfoBar/LockScale-default.svg</normaloff>:/InfoBar/LockScale-default.svg</iconset> - </property> - <property name="iconSize"> - <size> - <width>18</width> - <height>18</height> - </size> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>1</width> - <height>18</height> - </size> - </property> - </spacer> - </item> <item> <widget class="QLabel" name="label_5"> <property name="text"> @@ -424,13 +326,6 @@ </item> </layout> </widget> - <customwidgets> - <customwidget> - <class>AzQtComponents::VectorInput</class> - <extends>QWidget</extends> - <header location="global">AzQtComponents/Components/Widgets/VectorInput.h</header> - </customwidget> - </customwidgets> <resources> <include location="InfoBar.qrc"/> </resources> diff --git a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h index a309a1a5f5..c111aa836b 100644 --- a/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h +++ b/Code/Sandbox/Editor/Lib/Tests/IEditorMock.h @@ -123,8 +123,6 @@ public: MOCK_METHOD0(GetRuler, CRuler* ()); MOCK_METHOD1(SetOperationMode, void(EOperationMode )); MOCK_METHOD0(GetOperationMode, EOperationMode()); - MOCK_METHOD1(SetEditMode, void(int )); - MOCK_METHOD0(GetEditMode, int()); MOCK_METHOD1(ShowTransformManipulator, ITransformManipulator* (bool)); MOCK_METHOD0(GetTransformManipulator, ITransformManipulator* ()); MOCK_METHOD1(SetAxisConstraints, void(AxisConstrains )); diff --git a/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp b/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp index 3bb33d623b..39e8266cf6 100644 --- a/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp +++ b/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp @@ -200,8 +200,6 @@ namespace EditorPythonBindingsUnitTests EXPECT_TRUE(behaviorBus->m_events.find("OpenFileBox") != behaviorBus->m_events.end()); EXPECT_TRUE(behaviorBus->m_events.find("GetAxisConstraint") != behaviorBus->m_events.end()); EXPECT_TRUE(behaviorBus->m_events.find("SetAxisConstraint") != behaviorBus->m_events.end()); - EXPECT_TRUE(behaviorBus->m_events.find("GetEditMode") != behaviorBus->m_events.end()); - EXPECT_TRUE(behaviorBus->m_events.find("SetEditMode") != behaviorBus->m_events.end()); EXPECT_TRUE(behaviorBus->m_events.find("GetPakFromFile") != behaviorBus->m_events.end()); EXPECT_TRUE(behaviorBus->m_events.find("Log") != behaviorBus->m_events.end()); EXPECT_TRUE(behaviorBus->m_events.find("Undo") != behaviorBus->m_events.end()); diff --git a/Code/Sandbox/Editor/Lib/Tests/test_SetVectorDlg.cpp b/Code/Sandbox/Editor/Lib/Tests/test_SetVectorDlg.cpp deleted file mode 100644 index 18faf6deba..0000000000 --- a/Code/Sandbox/Editor/Lib/Tests/test_SetVectorDlg.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ - -#include "EditorDefs.h" -#include <AzTest/AzTest.h> -#include <AzCore/UnitTest/TestTypes.h> - -#include <SetVectorDlg.h> - -using namespace AZ; -using namespace ::testing; - -namespace UnitTest -{ - class TestSetVectorDlg - : public ::testing::Test - { - public: - - }; - - const float SetVectorDlgNearTolerance = 0.0001f; - - TEST_F(TestSetVectorDlg, GetVectorFromString_ThreeParams_Success) - { - QString testStr{ "1,2,3" }; - Vec3 result{ 0, 0, 0 }; - - result = CSetVectorDlg::GetVectorFromString(testStr); - - EXPECT_NEAR(result[0], 1.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[1], 2.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[2], 3.0f, SetVectorDlgNearTolerance); - } - - TEST_F(TestSetVectorDlg, GetVectorFromString_FourParams_ThreeParsed) - { - QString testStr{ "1,2,3,4" }; - Vec3 result{ 0, 0, 0 }; - - result = CSetVectorDlg::GetVectorFromString(testStr); - - EXPECT_NEAR(result[0], 1.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[1], 2.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[2], 3.0f, SetVectorDlgNearTolerance); - } - - TEST_F(TestSetVectorDlg, GetVectorFromString_TwoParams_ThirdZero) - { - QString testStr{ "1,2" }; - Vec3 result{ 0, 0, 0 }; - - result = CSetVectorDlg::GetVectorFromString(testStr); - - EXPECT_NEAR(result[0], 1.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[1], 2.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[2], 0.0f, SetVectorDlgNearTolerance); - } - - TEST_F(TestSetVectorDlg, GetVectorFromString_NoParams_AllZero) - { - QString testStr; - Vec3 result{ 0, 0, 0 }; - - result = CSetVectorDlg::GetVectorFromString(testStr); - - EXPECT_NEAR(result[0], 0.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[1], 0.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[2], 0.0f, SetVectorDlgNearTolerance); - } - - TEST_F(TestSetVectorDlg, GetVectorFromString_BadStrings_AllZero) - { - QString testStr{ "some,illegal,strings" }; - Vec3 resultExpected{ 0, 1, 0 }; - - auto result = CSetVectorDlg::GetVectorFromString(testStr); - - EXPECT_NEAR(result[0], 0.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[1], 0.0f, SetVectorDlgNearTolerance); - EXPECT_NEAR(result[2], 0.0f, SetVectorDlgNearTolerance); - } -} // namespace UnitTest diff --git a/Code/Sandbox/Editor/MainWindow.cpp b/Code/Sandbox/Editor/MainWindow.cpp index d7659c2512..902b04f266 100644 --- a/Code/Sandbox/Editor/MainWindow.cpp +++ b/Code/Sandbox/Editor/MainWindow.cpp @@ -750,11 +750,6 @@ void MainWindow::InitActions() am->AddAction(ID_TOOLBAR_SEPARATOR, QString()); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - am->AddAction(ID_TOOLBAR_WIDGET_REF_COORD, QString()); - } - am->AddAction(ID_TOOLBAR_WIDGET_UNDO, QString()); am->AddAction(ID_TOOLBAR_WIDGET_REDO, QString()); am->AddAction(ID_TOOLBAR_WIDGET_SNAP_ANGLE, QString()); @@ -995,18 +990,6 @@ void MainWindow::InitActions() am->AddAction(ID_EDIT_RENAMEOBJECT, tr("Rename Object(s)...")) .SetStatusTip(tr("Rename Object")); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - am->AddAction(ID_EDITMODE_SELECT, tr("Select mode")) - .SetIcon(Style::icon("Select")) - .SetApplyHoverEffect() - .SetShortcut(tr("1")) - .SetToolTip(tr("Select mode (1)")) - .SetCheckable(true) - .SetStatusTip(tr("Select object(s)")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateEditmodeSelect); - } - am->AddAction(ID_EDITMODE_MOVE, tr("Move")) .SetIcon(Style::icon("Move")) .SetApplyHoverEffect() @@ -1032,69 +1015,6 @@ void MainWindow::InitActions() .SetStatusTip(tr("Select and scale selected object(s)")) .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateEditmodeScale); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - am->AddAction(ID_EDITMODE_SELECTAREA, tr("Select terrain")) - .SetIcon(Style::icon("Select_terrain")) - .SetApplyHoverEffect() - .SetShortcut(tr("5")) - .SetToolTip(tr("Select terrain (5)")) - .SetCheckable(true) - .SetStatusTip(tr("Switch to terrain selection mode")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateEditmodeSelectarea); - am->AddAction(ID_SELECT_AXIS_X, tr("Constrain to X axis")) - .SetIcon(Style::icon("X_axis")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+1")) - .SetToolTip(tr("Constrain to X axis (Ctrl+1)")) - .SetCheckable(true) - .SetStatusTip(tr("Lock movement on X axis")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisX); - am->AddAction(ID_SELECT_AXIS_Y, tr("Constrain to Y axis")) - .SetIcon(Style::icon("Y_axis")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+2")) - .SetToolTip(tr("Constrain to Y axis (Ctrl+2)")) - .SetCheckable(true) - .SetStatusTip(tr("Lock movement on Y axis")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisY); - am->AddAction(ID_SELECT_AXIS_Z, tr("Constrain to Z axis")) - .SetIcon(Style::icon("Z_axis")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+3")) - .SetToolTip(tr("Constrain to Z axis (Ctrl+3)")) - .SetCheckable(true) - .SetStatusTip(tr("Lock movement on Z axis")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisZ); - am->AddAction(ID_SELECT_AXIS_XY, tr("Constrain to XY plane")) - .SetIcon(Style::icon("XY2_copy")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+4")) - .SetToolTip(tr("Constrain to XY plane (Ctrl+4)")) - .SetCheckable(true) - .SetStatusTip(tr("Lock movement on XY plane")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisXy); - am->AddAction(ID_SELECT_AXIS_TERRAIN, tr("Constrain to terrain/geometry")) - .SetIcon(Style::icon("Object_follow_terrain")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+5")) - .SetToolTip(tr("Constrain to terrain/geometry (Ctrl+5)")) - .SetCheckable(true) - .SetStatusTip(tr("Lock object movement to follow terrain")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisTerrain); - am->AddAction(ID_SELECT_AXIS_SNAPTOALL, tr("Follow terrain and snap to objects")) - .SetIcon(Style::icon("Follow_terrain")) - .SetApplyHoverEffect() - .SetShortcut(tr("Ctrl+6")) - .SetToolTip(tr("Follow terrain and snap to objects (Ctrl+6)")) - .SetCheckable(true) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelectAxisSnapToAll); - am->AddAction(ID_OBJECTMODIFY_ALIGNTOGRID, tr("Align to grid")) - .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateSelected) - .SetIcon(Style::icon("Align_to_grid")) - .SetApplyHoverEffect(); - } - am->AddAction(ID_SNAP_TO_GRID, tr("Snap to grid")) .SetIcon(Style::icon("Grid")) .SetApplyHoverEffect() @@ -1153,7 +1073,6 @@ void MainWindow::InitActions() am->AddAction(ID_CHANGEMOVESPEED_CHANGESTEP, tr("Change Step")) .SetStatusTip(tr("Change Flycam Movement Step")); am->AddAction(ID_DISPLAY_GOTOPOSITION, tr("Go to Position...")); - am->AddAction(ID_DISPLAY_SETVECTOR, tr("Display Set Vector")); am->AddAction(ID_MODIFY_GOTO_SELECTION, tr("Center on Selection")) .SetShortcut(tr("Z")) .SetToolTip(tr("Center on Selection (Z)")) @@ -1500,62 +1419,6 @@ void MainWindow::InitToolBars() AdjustToolBarIconSize(static_cast<AzQtComponents::ToolBar::ToolBarIconSize>(gSettings.gui.nToolbarIconSize)); } -QComboBox* MainWindow::CreateRefCoordComboBox() -{ - // ID_REF_COORDS_SYS; - auto coordSysCombo = new RefCoordComboBox(this); - - connect(this, &MainWindow::ToggleRefCoordSys, coordSysCombo, &RefCoordComboBox::ToggleRefCoordSys); - connect(this, &MainWindow::UpdateRefCoordSys, coordSysCombo, &RefCoordComboBox::UpdateRefCoordSys); - - return coordSysCombo; -} - -RefCoordComboBox::RefCoordComboBox(QWidget* parent) - : QComboBox(parent) -{ - addItems(coordSysList()); - setCurrentIndex(0); - - connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [](int index) - { - if (index >= 0 && index < LAST_COORD_SYSTEM) - { - RefCoordSys coordSys = (RefCoordSys)index; - if (GetIEditor()->GetReferenceCoordSys() != index) - { - GetIEditor()->SetReferenceCoordSys(coordSys); - } - } - }); - - UpdateRefCoordSys(); -} - -QStringList RefCoordComboBox::coordSysList() const -{ - static QStringList list = { tr("View"), tr("Local"), tr("Parent"), tr("World"), tr("Custom") }; - return list; -} - -void RefCoordComboBox::UpdateRefCoordSys() -{ - RefCoordSys coordSys = GetIEditor()->GetReferenceCoordSys(); - if (coordSys >= 0 && coordSys < LAST_COORD_SYSTEM) - { - setCurrentIndex(coordSys); - } -} - -void RefCoordComboBox::ToggleRefCoordSys() -{ - QStringList coordSys = coordSysList(); - const int localIndex = coordSys.indexOf(tr("Local")); - const int worldIndex = coordSys.indexOf(tr("World")); - const int newIndex = currentIndex() == localIndex ? worldIndex : localIndex; - setCurrentIndex(newIndex); -} - QToolButton* MainWindow::CreateUndoRedoButton(int command) { // We do either undo or redo below, sort that out here @@ -2520,9 +2383,6 @@ QWidget* MainWindow::CreateToolbarWidget(int actionId) case ID_TOOLBAR_WIDGET_REDO: w = CreateUndoRedoButton(ID_REDO); break; - case ID_TOOLBAR_WIDGET_REF_COORD: - w = CreateRefCoordComboBox(); - break; case ID_TOOLBAR_WIDGET_SNAP_GRID: w = CreateSnapToGridWidget(); break; diff --git a/Code/Sandbox/Editor/MainWindow.h b/Code/Sandbox/Editor/MainWindow.h index c40d732cee..3e652888fe 100644 --- a/Code/Sandbox/Editor/MainWindow.h +++ b/Code/Sandbox/Editor/MainWindow.h @@ -77,19 +77,6 @@ namespace AzToolsFramework // Subclassing so we can add slots to our toolbar widgets // Using lambdas is crashy since the lamdba doesn't know when the widget is deleted. -class RefCoordComboBox - : public QComboBox -{ - Q_OBJECT -public: - explicit RefCoordComboBox(QWidget* parent); -public Q_SLOTS: - void ToggleRefCoordSys(); - void UpdateRefCoordSys(); -private: - QStringList coordSysList() const; -}; - class UndoRedoToolButton : public QToolButton { @@ -229,8 +216,6 @@ private: QWidget* CreateSnapToGridWidget(); QWidget* CreateSnapToAngleWidget(); - QComboBox* CreateRefCoordComboBox(); - QToolButton* CreateUndoRedoButton(int command); QToolButton* CreateEnvironmentModeButton(); diff --git a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp index 44138b290d..40970838c1 100644 --- a/Code/Sandbox/Editor/Objects/AxisGizmo.cpp +++ b/Code/Sandbox/Editor/Objects/AxisGizmo.cpp @@ -137,36 +137,6 @@ void CAxisGizmo::GetWorldBounds(AABB& bbox) void CAxisGizmo::DrawAxis(DisplayContext& dc) { m_pAxisHelper->SetHighlightAxis(m_highlightAxis); - // Only enable axis planes when editor is in Move mode. - int nEditMode = GetIEditor()->GetEditMode(); - int nModeFlags = 0; - switch (nEditMode) - { - case eEditModeMove: - nModeFlags |= CAxisHelper::MOVE_MODE; - break; - case eEditModeRotate: - nModeFlags |= CAxisHelper::ROTATE_MODE; - nModeFlags &= ~(CAxisHelper::ROTATE_CIRCLE_MODE); - break; - case eEditModeRotateCircle: - nModeFlags |= CAxisHelper::ROTATE_CIRCLE_MODE; - nModeFlags &= ~(CAxisHelper::ROTATE_MODE); - break; - case eEditModeScale: - nModeFlags |= CAxisHelper::SCALE_MODE; - break; - case eEditModeSelect: - nModeFlags |= CAxisHelper::SELECT_MODE; - break; - case eEditModeSelectArea: - nModeFlags |= CAxisHelper::SELECT_MODE; - break; - } - - //nModeFlags |= CAxisHelper::MOVE_MODE | CAxisHelper::ROTATE_MODE | CAxisHelper::SCALE_MODE; - - m_pAxisHelper->SetMode(nModeFlags); Matrix34 tm = GetTransformation(m_bAlwaysUseLocal ? COORDS_LOCAL : GetIEditor()->GetReferenceCoordSys(), dc.view); m_pAxisHelper->DrawAxis(tm, GetIEditor()->GetGlobalGizmoParameters(), dc); @@ -177,21 +147,6 @@ void CAxisGizmo::DrawAxis(DisplayContext& dc) m_pAxisHelper->DrawDome(tm, GetIEditor()->GetGlobalGizmoParameters(), dc, objectBox); } - ////////////////////////////////////////////////////////////////////////// - // Draw extended infinite-axis gizmo - ////////////////////////////////////////////////////////////////////////// - if (!(dc.flags & DISPLAY_2D) && - (nModeFlags == CAxisHelper::MOVE_MODE || - nModeFlags == CAxisHelper::ROTATE_MODE)) - { - bool bClickedShift = CheckVirtualKey(Qt::Key_Shift); - if (bClickedShift && (m_axisGizmoCount == 1 || m_highlightAxis || (m_axisGizmoCount == 2 && m_object && m_object->IsSkipSelectionHelper()))) - { - bool bClickedAlt = CheckVirtualKey(Qt::Key_Menu); - bool bUsePhysicalProxy = !bClickedAlt; - m_pAxisHelperExtended->DrawAxes(dc, tm, bUsePhysicalProxy); - } - } } ////////////////////////////////////////////////////////////////////////// @@ -324,7 +279,7 @@ Matrix34 CAxisGizmo::GetTransformation(RefCoordSys coordSys, IDisplayViewport* v } ////////////////////////////////////////////////////////////////////////// -bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, int nFlags) +bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point, [[maybe_unused]] int nFlags) { AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Editor); @@ -364,22 +319,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point m_cMouseDownPos = point; m_initPos = GetTransformation(COORDS_WORLD).GetTranslation(); - switch (hc.manipulatorMode) - { - case 1: - view->SetCurrentCursor(STD_CURSOR_MOVE); - GetIEditor()->SetEditMode(eEditModeMove); - break; - case 2: - view->SetCurrentCursor(STD_CURSOR_ROTATE); - GetIEditor()->SetEditMode(eEditModeRotate); - break; - case 3: - view->SetCurrentCursor(STD_CURSOR_SCALE); - GetIEditor()->SetEditMode(eEditModeScale); - break; - } - return true; } } @@ -387,152 +326,6 @@ bool CAxisGizmo::MouseCallback(CViewport* view, EMouseEvent event, QPoint& point { if (m_bDragging) { - bool bCallBack = true; - Vec3 vDragValue(0, 0, 0); - // Dragging transform manipulator. - switch (GetIEditor()->GetEditMode()) - { - case eEditModeMove: - { - view->SetCurrentCursor(STD_CURSOR_MOVE); - - if (view->GetAxisConstrain() == AXIS_TERRAIN) - { - if (nFlags & MK_CONTROL) - { - bool bCollideWithTerrain; - Vec3 posOnTerrain = view->ViewToWorld(point, &bCollideWithTerrain, true); - if (!bCollideWithTerrain) - { - return true; - } - vDragValue = posOnTerrain - m_initPos; - } - else - { - Vec3 p1 = view->SnapToGrid(view->ViewToWorld(m_cMouseDownPos)); - Vec3 p2 = view->SnapToGrid(view->ViewToWorld(point)); - vDragValue = p2 - p1; - vDragValue.z = 0; - } - } - else - { - Vec3 p1 = view->MapViewToCP(m_cMouseDownPos); - Vec3 p2 = view->MapViewToCP(point); - if (p1.IsZero() || p2.IsZero()) - { - return true; - } - vDragValue = view->GetCPVector(p1, p2); - } - } - break; - case eEditModeRotate: - { - view->SetCurrentCursor(STD_CURSOR_ROTATE); - - Ang3 ang(0, 0, 0); - float ax = (point.x() - m_cMouseDownPos.x()); - float ay = (point.y() - m_cMouseDownPos.y()); - switch (view->GetAxisConstrain()) - { - case AXIS_X: - ang.x = ay; - break; - case AXIS_Y: - ang.y = ay; - break; - case AXIS_Z: - ang.z = ay; - break; - case AXIS_XY: - ang(ax, ay, 0); - break; - case AXIS_XZ: - ang(ax, 0, ay); - break; - case AXIS_YZ: - ang(0, ay, ax); - break; - case AXIS_TERRAIN: - ang(ax, ay, 0); - break; - } - ; - ang = gSettings.pGrid->SnapAngle(ang); - vDragValue = Vec3(DEG2RAD(ang)); - } - break; - case eEditModeScale: - { - Vec3 scl(0, 0, 0); - float ay = 1.0f - 0.01f * (point.y() - m_cMouseDownPos.y()); - if (ay < 0.01f) - { - ay = 0.01f; - } - scl(ay, ay, ay); - switch (view->GetAxisConstrain()) - { - case AXIS_X: - scl(ay, 1, 1); - break; - case AXIS_Y: - scl(1, ay, 1); - break; - case AXIS_Z: - scl(1, 1, ay); - break; - case AXIS_XY: - scl(ay, ay, ay); - break; - case AXIS_XZ: - scl(ay, ay, ay); - break; - case AXIS_YZ: - scl(ay, ay, ay); - break; - case AXIS_XYZ: - scl(ay, ay, ay); - break; - case AXIS_TERRAIN: - scl(ay, ay, ay); - break; - } - ; - view->SetCurrentCursor(STD_CURSOR_SCALE); - vDragValue = scl; - } - break; - case eEditModeRotateCircle: - { - Matrix34 tm = GetTransformation(m_bAlwaysUseLocal ? COORDS_LOCAL : GetIEditor()->GetReferenceCoordSys()); - Vec3 v0, v1; - Vec3 vHitNormal; - if (m_pAxisHelper->HitTestForRotationCircle(tm, view, m_cMouseDownPos, 0.05f, &v0, &vHitNormal) && m_pAxisHelper->HitTestForRotationCircle(tm, view, point, 2.0f, &v1, &vHitNormal)) - { - Vec3 vDir0 = (v0 - tm.GetTranslation()).GetNormalized(); - Vec3 vDir1 = (v1 - tm.GetTranslation()).GetNormalized(); - - Vec3 vCurlDir = vDir0.Cross(vDir1).GetNormalized(); - if (vHitNormal.Dot(vCurlDir) > 0) - { - vDragValue = Vec3(std::acos(vDir0.Dot(vDir1)), 0, 0); - } - else - { - vDragValue = Vec3(-std::acos(vDir0.Dot(vDir1)), 0, 0); - } - } - else - { - bCallBack = false; - } - } - break; - } - return true; } else diff --git a/Code/Sandbox/Editor/PythonEditorEventsBus.h b/Code/Sandbox/Editor/PythonEditorEventsBus.h index f4b2971a17..69ef2671a1 100644 --- a/Code/Sandbox/Editor/PythonEditorEventsBus.h +++ b/Code/Sandbox/Editor/PythonEditorEventsBus.h @@ -139,16 +139,6 @@ namespace AzToolsFramework */ virtual void SetAxisConstraint(AZStd::string_view pConstrain) = 0; - /* - * Gets edit mode. - */ - virtual const char* GetEditMode() = 0; - - /* - * Sets edit mode. - */ - virtual void SetEditMode(AZStd::string_view pEditMode) = 0; - /* * Finds a pak file name for a given file. */ diff --git a/Code/Sandbox/Editor/PythonEditorFuncs.cpp b/Code/Sandbox/Editor/PythonEditorFuncs.cpp index f5de22387c..8f735706fd 100644 --- a/Code/Sandbox/Editor/PythonEditorFuncs.cpp +++ b/Code/Sandbox/Editor/PythonEditorFuncs.cpp @@ -688,68 +688,6 @@ namespace } } - ////////////////////////////////////////////////////////////////////////// - // Edit Mode - ////////////////////////////////////////////////////////////////////////// - const char* PyGetEditMode() - { - int actualEditMode = GetIEditor()->GetEditMode(); - switch (actualEditMode) - { - case eEditModeSelect: - return "SELECT"; - case eEditModeSelectArea: - return "SELECTAREA"; - case eEditModeMove: - return "MOVE"; - case eEditModeRotate: - return "ROTATE"; - case eEditModeScale: - return "SCALE"; - case eEditModeTool: - return "TOOL"; - default: - throw std::logic_error("Invalid edit mode."); - } - } - - void PySetEditMode(AZStd::string_view pEditMode) - { - if (pEditMode == "MOVE") - { - GetIEditor()->SetEditMode(eEditModeMove); - } - else if (pEditMode == "ROTATE") - { - GetIEditor()->SetEditMode(eEditModeRotate); - } - else if (pEditMode == "SCALE") - { - GetIEditor()->SetEditMode(eEditModeScale); - } - else if (pEditMode == "SELECT") - { - GetIEditor()->SetEditMode(eEditModeSelect); - } - else if (pEditMode == "SELECTAREA") - { - GetIEditor()->SetEditMode(eEditModeSelectArea); - } - else if (pEditMode == "TOOL") - { - GetIEditor()->SetEditMode(eEditModeTool); - } - else if (pEditMode == "RULER") - { - CRuler* pRuler = GetIEditor()->GetRuler(); - pRuler->SetActive(!pRuler->IsActive()); - } - else - { - throw std::logic_error("Invalid edit mode."); - } - } - ////////////////////////////////////////////////////////////////////////// const char* PyGetPakFromFile(const char* filename) { @@ -1031,8 +969,6 @@ namespace AzToolsFramework ->Event("OpenFileBox", &EditorLayerPythonRequestBus::Events::OpenFileBox) ->Event("GetAxisConstraint", &EditorLayerPythonRequestBus::Events::GetAxisConstraint) ->Event("SetAxisConstraint", &EditorLayerPythonRequestBus::Events::SetAxisConstraint) - ->Event("GetEditMode", &EditorLayerPythonRequestBus::Events::GetEditMode) - ->Event("SetEditMode", &EditorLayerPythonRequestBus::Events::SetEditMode) ->Event("GetPakFromFile", &EditorLayerPythonRequestBus::Events::GetPakFromFile) ->Event("Log", &EditorLayerPythonRequestBus::Events::Log) ->Event("Undo", &EditorLayerPythonRequestBus::Events::Undo) @@ -1168,16 +1104,6 @@ namespace AzToolsFramework return PySetAxisConstraint(pConstrain); } - const char* PythonEditorComponent::GetEditMode() - { - return PyGetEditMode(); - } - - void PythonEditorComponent::SetEditMode(AZStd::string_view pEditMode) - { - return PySetEditMode(pEditMode); - } - const char* PythonEditorComponent::GetPakFromFile(const char* filename) { return PyGetPakFromFile(filename); @@ -1252,9 +1178,6 @@ namespace AzToolsFramework addLegacyGeneral(behaviorContext->Method("get_axis_constraint", PyGetAxisConstraint, nullptr, "Gets axis.")); addLegacyGeneral(behaviorContext->Method("set_axis_constraint", PySetAxisConstraint, nullptr, "Sets axis.")); - addLegacyGeneral(behaviorContext->Method("get_edit_mode", PyGetEditMode, nullptr, "Gets edit mode.")); - addLegacyGeneral(behaviorContext->Method("set_edit_mode", PySetEditMode, nullptr, "Sets edit mode.")); - addLegacyGeneral(behaviorContext->Method("get_pak_from_file", PyGetPakFromFile, nullptr, "Finds a pak file name for a given file.")); addLegacyGeneral(behaviorContext->Method("log", PyLog, nullptr, "Prints the message to the editor console window.")); diff --git a/Code/Sandbox/Editor/PythonEditorFuncs.h b/Code/Sandbox/Editor/PythonEditorFuncs.h index 37cb6bd551..471f0d581f 100644 --- a/Code/Sandbox/Editor/PythonEditorFuncs.h +++ b/Code/Sandbox/Editor/PythonEditorFuncs.h @@ -95,10 +95,6 @@ namespace AzToolsFramework void SetAxisConstraint(AZStd::string_view pConstrain) override; - const char* GetEditMode() override; - - void SetEditMode(AZStd::string_view pEditMode) override; - const char* GetPakFromFile(const char* filename) override; void Log(const char* pMessage) override; diff --git a/Code/Sandbox/Editor/RenderViewport.cpp b/Code/Sandbox/Editor/RenderViewport.cpp index 53355f4dd9..af4cbd46bc 100644 --- a/Code/Sandbox/Editor/RenderViewport.cpp +++ b/Code/Sandbox/Editor/RenderViewport.cpp @@ -4301,11 +4301,6 @@ void CRenderViewport::RenderSnappingGrid() { return; } - if (GetIEditor()->GetEditMode() != eEditModeMove - && GetIEditor()->GetEditMode() != eEditModeRotate) - { - return; - } CGrid* pGrid = GetViewManager()->GetGrid(); if (pGrid->IsEnabled() == false && pGrid->IsAngleSnapEnabled() == false) { @@ -4317,76 +4312,6 @@ void CRenderViewport::RenderSnappingGrid() int prevState = dc.GetState(); dc.DepthWriteOff(); - Vec3 p = pSelGroup->GetObject(0)->GetWorldPos(); - - AABB bbox; - pSelGroup->GetObject(0)->GetBoundBox(bbox); - float size = 2 * bbox.GetRadius(); - float alphaMax = 1.0f, alphaMin = 0.2f; - dc.SetLineWidth(3); - - if (GetIEditor()->GetEditMode() == eEditModeMove && pGrid->IsEnabled()) - // Draw the translation grid. - { - Vec3 u = m_constructionPlaneAxisX; - Vec3 v = m_constructionPlaneAxisY; - float step = pGrid->scale * pGrid->size; - const int MIN_STEP_COUNT = 5; - const int MAX_STEP_COUNT = 300; - int nSteps = std::min(std::max(FloatToIntRet(size / step), MIN_STEP_COUNT), MAX_STEP_COUNT); - size = nSteps * step; - for (int i = -nSteps; i <= nSteps; ++i) - { - // Draw u lines. - float alphaCur = alphaMax - fabsf(float(i) / float(nSteps)) * (alphaMax - alphaMin); - dc.DrawLine(p + v * (step * i), p + u * size + v * (step * i), - ColorF(0, 0, 0, alphaCur), ColorF(0, 0, 0, alphaMin)); - dc.DrawLine(p + v * (step * i), p - u * size + v * (step * i), - ColorF(0, 0, 0, alphaCur), ColorF(0, 0, 0, alphaMin)); - // Draw v lines. - dc.DrawLine(p + u * (step * i), p + v * size + u * (step * i), - ColorF(0, 0, 0, alphaCur), ColorF(0, 0, 0, alphaMin)); - dc.DrawLine(p + u * (step * i), p - v * size + u * (step * i), - ColorF(0, 0, 0, alphaCur), ColorF(0, 0, 0, alphaMin)); - } - } - else if (GetIEditor()->GetEditMode() == eEditModeRotate && pGrid->IsAngleSnapEnabled()) - // Draw the rotation grid. - { - int nAxis(GetAxisConstrain()); - if (nAxis == AXIS_X || nAxis == AXIS_Y || nAxis == AXIS_Z) - { - RefCoordSys coordSys = GetIEditor()->GetReferenceCoordSys(); - Vec3 xAxis(1, 0, 0); - Vec3 yAxis(0, 1, 0); - Vec3 zAxis(0, 0, 1); - Vec3 rotAxis; - if (nAxis == AXIS_X) - { - rotAxis = m_constructionMatrix[coordSys].TransformVector(xAxis); - } - else if (nAxis == AXIS_Y) - { - rotAxis = m_constructionMatrix[coordSys].TransformVector(yAxis); - } - else if (nAxis == AXIS_Z) - { - rotAxis = m_constructionMatrix[coordSys].TransformVector(zAxis); - } - Vec3 anotherAxis = m_constructionPlane.n * size; - float step = pGrid->angleSnap; - int nSteps = FloatToIntRet(180.0f / step); - for (int i = 0; i < nSteps; ++i) - { - AngleAxis rot(i* step* gf_PI / 180.0, rotAxis); - Vec3 dir = rot * anotherAxis; - dc.DrawLine(p, p + dir, - ColorF(0, 0, 0, alphaMax), ColorF(0, 0, 0, alphaMin)); - dc.DrawLine(p, p - dir, - ColorF(0, 0, 0, alphaMax), ColorF(0, 0, 0, alphaMin)); - } - } - } dc.SetState(prevState); } diff --git a/Code/Sandbox/Editor/Resource.h b/Code/Sandbox/Editor/Resource.h index d72c2d76d4..8c4b09ae67 100644 --- a/Code/Sandbox/Editor/Resource.h +++ b/Code/Sandbox/Editor/Resource.h @@ -141,18 +141,12 @@ #define ID_EDITMODE_ROTATE 33506 #define ID_EDITMODE_SCALE 33507 #define ID_EDITMODE_MOVE 33508 -#define ID_EDITMODE_SELECT 33509 -#define ID_EDITMODE_SELECTAREA 33510 #define ID_SELECTION_DELETE 33512 #define ID_EDIT_ESCAPE 33513 #define ID_OBJECTMODIFY_SETAREA 33514 #define ID_OBJECTMODIFY_SETHEIGHT 33515 #define ID_OBJECTMODIFY_FREEZE 33517 #define ID_OBJECTMODIFY_UNFREEZE 33518 -#define ID_SELECT_AXIS_XY 33520 -#define ID_SELECT_AXIS_X 33521 -#define ID_SELECT_AXIS_Y 33522 -#define ID_SELECT_AXIS_Z 33523 #define ID_UNDO 33524 #define ID_EDIT_CLONE 33525 #define ID_SELECTION_SAVE 33527 @@ -161,7 +155,6 @@ #define ID_EDIT_LEVELDATA 33542 #define ID_FILE_EDITEDITORINI 33543 #define ID_FILE_EDITLOGFILE 33544 -#define ID_SELECT_AXIS_TERRAIN 33545 #define ID_PREFERENCES 33546 #define ID_RELOAD_GEOMETRY 33549 #define ID_REDO 33550 @@ -213,7 +206,6 @@ #define ID_TV_NEXTKEY 33603 #define ID_PLAY_LOOP 33607 #define ID_TERRAIN 33611 -#define ID_OBJECTMODIFY_ALIGNTOGRID 33619 #define ID_PANEL_VEG_EXPORT 33672 #define ID_PANEL_VEG_IMPORT 33673 #define ID_PANEL_VEG_DISTRIBUTE 33674 @@ -226,7 +218,6 @@ #define ID_PANEL_VEG_ADDCATEGORY 33682 #define ID_PANEL_VEG_RENAMECATEGORY 33683 #define ID_PANEL_VEG_REMOVECATEGORY 33684 -#define ID_SELECT_AXIS_SNAPTOALL 33685 #define ID_TOOLS_PREFERENCES 33691 #define ID_EDIT_INVERTSELECTION 33692 #define ID_TOOLTERRAINMODIFY_SMOOTH 33695 @@ -279,7 +270,6 @@ #define ID_DISPLAY_GOTOPOSITION 34004 #define ID_PHYSICS_SIMULATEOBJECTS 34007 #define ID_TERRAIN_TEXTURE_EXPORT 34008 -#define ID_DISPLAY_SETVECTOR 34010 #define ID_TV_SEQUENCE_NEW 34049 #define ID_TV_MODE_DOPESHEET 34052 #define ID_VIEW_LAYOUTS 34053 @@ -403,7 +393,6 @@ #define ID_TOOLBAR_WIDGET_FIRST 50003 #define ID_TOOLBAR_WIDGET_UNDO 50003 #define ID_TOOLBAR_WIDGET_REDO 50004 -#define ID_TOOLBAR_WIDGET_REF_COORD 50006 #define ID_TOOLBAR_WIDGET_SNAP_ANGLE 50007 #define ID_TOOLBAR_WIDGET_SNAP_GRID 50008 #define ID_TOOLBAR_WIDGET_ENVIRONMENT_MODE 50011 diff --git a/Code/Sandbox/Editor/SetVectorDlg.cpp b/Code/Sandbox/Editor/SetVectorDlg.cpp deleted file mode 100644 index 583f5ff4af..0000000000 --- a/Code/Sandbox/Editor/SetVectorDlg.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#include "EditorDefs.h" - -#include "SetVectorDlg.h" - -// Editor -#include "MainWindow.h" -#include "MathConversion.h" -#include "ActionManager.h" -#include "Objects/BaseObject.h" -#include "Objects/SelectionGroup.h" - -AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING -#include "ui_SetVectorDlg.h" -AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -///////////////////////////////////////////////////////////////////////////// -// CSetVectorDlg dialog - - -CSetVectorDlg::CSetVectorDlg(QWidget* pParent /*=NULL*/) - : QDialog(pParent) - , m_ui(new Ui::SetVectorDlg) -{ - m_ui->setupUi(this); - - OnInitDialog(); - - connect(m_ui->buttonOk, &QPushButton::clicked, this, &CSetVectorDlg::accept); - connect(m_ui->buttonCancel, &QPushButton::clicked, this, &CSetVectorDlg::reject); -} - -CSetVectorDlg::~CSetVectorDlg() -{ -} - -///////////////////////////////////////////////////////////////////////////// -// CSetVectorDlg message handlers - - -void CSetVectorDlg::OnInitDialog() -{ - QString editModeString; - int emode = GetIEditor()->GetEditMode(); - - if (emode == eEditModeMove) - { - editModeString = tr("Position"); - } - else if (emode == eEditModeRotate) - { - editModeString = tr("Rotation"); - } - else if (emode == eEditModeScale) - { - editModeString = tr("Scale"); - } - - m_ui->label->setText(tr("Enter %1 here:").arg(editModeString)); - - currentVec = GetVectorFromEditor(); - m_ui->edit->setText(QStringLiteral("%1, %2, %3").arg(currentVec.x, 2, 'f', 2).arg(currentVec.y, 2, 'f', 2).arg(currentVec.z, 2, 'f', 2)); -} - -void CSetVectorDlg::accept() -{ - Vec3 newVec = GetVectorFromText(); - SetVector(newVec); - - if (GetIEditor()->GetEditMode() == eEditModeMove && currentVec.GetDistance(newVec) > 10.0f) - { - MainWindow::instance()->GetActionManager()->GetAction(ID_GOTO_SELECTED)->trigger(); - } - QDialog::accept(); -} - -Vec3 CSetVectorDlg::GetVectorFromEditor() -{ - Vec3 v; - int emode = GetIEditor()->GetEditMode(); - CBaseObject* obj = GetIEditor()->GetSelectedObject(); - bool bWorldSpace = GetIEditor()->GetReferenceCoordSys() == COORDS_WORLD; - - if (obj) - { - v = obj->GetWorldPos(); - } - - if (emode == eEditModeMove) - { - if (obj) - { - if (bWorldSpace) - { - v = obj->GetWorldTM().GetTranslation(); - } - else - { - v = obj->GetPos(); - } - } - } - if (emode == eEditModeRotate) - { - if (obj) - { - Quat qrot; - if (bWorldSpace) - { - AffineParts ap; - ap.SpectralDecompose(obj->GetWorldTM()); - qrot = ap.rot; - } - else - { - qrot = obj->GetRotation(); - } - - v = AZVec3ToLYVec3(AZ::ConvertQuaternionToEulerDegrees(LYQuaternionToAZQuaternion(qrot))); - } - } - if (emode == eEditModeScale) - { - if (obj) - { - if (bWorldSpace) - { - AffineParts ap; - ap.SpectralDecompose(obj->GetWorldTM()); - v = ap.scale; - } - else - { - v = obj->GetScale(); - } - } - } - return v; -} - -Vec3 CSetVectorDlg::GetVectorFromText() -{ - return GetVectorFromString(m_ui->edit->text()); -} - -Vec3 CSetVectorDlg::GetVectorFromString(const QString& vecString) -{ - const int maxCoordinates = 3; - float vec[maxCoordinates] = { 0, 0, 0 }; - - const QStringList parts = vecString.split(QRegularExpression("[\\s,;\\t]"), Qt::SkipEmptyParts); - const int checkCoords = AZStd::GetMin(parts.count(), maxCoordinates); - for (int k = 0; k < checkCoords; ++k) - { - vec[k] = parts[k].toDouble(); - } - - return Vec3(vec[0], vec[1], vec[2]); -} - -void CSetVectorDlg::SetVector(const Vec3& v) -{ - int emode = GetIEditor()->GetEditMode(); - if (emode != eEditModeMove && emode != eEditModeRotate && emode != eEditModeScale) - { - return; - } - - int referenceCoordSys = GetIEditor()->GetReferenceCoordSys(); - - CBaseObject* obj = GetIEditor()->GetSelectedObject(); - - Matrix34 tm; - AffineParts ap; - if (obj) - { - tm = obj->GetWorldTM(); - ap.SpectralDecompose(tm); - } - - if (emode == eEditModeMove) - { - if (obj) - { - CUndo undo("Set Position"); - if (referenceCoordSys == COORDS_WORLD) - { - tm.SetTranslation(v); - obj->SetWorldTM(tm, eObjectUpdateFlags_UserInput); - } - else - { - obj->SetPos(v, eObjectUpdateFlags_UserInput); - } - } - } - if (emode == eEditModeRotate) - { - CUndo undo("Set Rotation"); - if (obj) - { - Quat qrot = AZQuaternionToLYQuaternion(AZ::ConvertEulerDegreesToQuaternion(LYVec3ToAZVec3(v))); - if (referenceCoordSys == COORDS_WORLD) - { - tm = Matrix34::Create(ap.scale, qrot, ap.pos); - obj->SetWorldTM(tm, eObjectUpdateFlags_UserInput); - } - else - { - obj->SetRotation(qrot, eObjectUpdateFlags_UserInput); - } - } - else - { - GetIEditor()->GetSelection()->Rotate((Ang3)v, referenceCoordSys); - } - } - if (emode == eEditModeScale) - { - if (v.x == 0 || v.y == 0 || v.z == 0) - { - return; - } - - CUndo undo("Set Scale"); - if (obj) - { - if (referenceCoordSys == COORDS_WORLD) - { - tm = Matrix34::Create(v, ap.rot, ap.pos); - obj->SetWorldTM(tm, eObjectUpdateFlags_UserInput); - } - else - { - obj->SetScale(v, eObjectUpdateFlags_UserInput); - } - } - else - { - GetIEditor()->GetSelection()->Scale(v, referenceCoordSys); - } - } -} - -#include <moc_SetVectorDlg.cpp> diff --git a/Code/Sandbox/Editor/SetVectorDlg.h b/Code/Sandbox/Editor/SetVectorDlg.h deleted file mode 100644 index e9fd8115e5..0000000000 --- a/Code/Sandbox/Editor/SetVectorDlg.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or -* its licensors. -* -* For complete copyright and license terms please see the LICENSE at the root of this -* distribution (the "License"). All use of this software is governed by the License, -* or, if provided, by the license below or the license accompanying this file. Do not -* remove or modify any license notices. This file is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* -*/ -// Original file Copyright Crytek GMBH or its affiliates, used under license. - -#ifndef CRYINCLUDE_EDITOR_SETVECTORDLG_H -#define CRYINCLUDE_EDITOR_SETVECTORDLG_H - -#pragma once -// GotoPositionDlg.h : header file -// - -#if !defined(Q_MOC_RUN) -#include <QDialog> -#endif - -namespace Ui -{ - class SetVectorDlg; -} - -///////////////////////////////////////////////////////////////////////////// -// CSetVectorDlg dialog - -class SANDBOX_API CSetVectorDlg - : public QDialog -{ - Q_OBJECT - // Construction -public: - CSetVectorDlg(QWidget* pParent = NULL); // standard constructor - ~CSetVectorDlg(); - - static Vec3 GetVectorFromString(const QString& vecString); - - // Implementation -protected: - void OnInitDialog(); - void accept() override; - void SetVector(const Vec3& v); - Vec3 GetVectorFromText(); - Vec3 GetVectorFromEditor(); - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - Vec3 currentVec; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING - -private: - AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING - QScopedPointer<Ui::SetVectorDlg> m_ui; - AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING -}; - -#endif // CRYINCLUDE_EDITOR_SETVECTORDLG_H diff --git a/Code/Sandbox/Editor/SetVectorDlg.ui b/Code/Sandbox/Editor/SetVectorDlg.ui deleted file mode 100644 index a8ed3cb282..0000000000 --- a/Code/Sandbox/Editor/SetVectorDlg.ui +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>SetVectorDlg</class> - <widget class="QDialog" name="SetVectorDlg"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>270</width> - <height>99</height> - </rect> - </property> - <property name="windowTitle"> - <string>Set Vector</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <property name="horizontalSpacing"> - <number>29</number> - </property> - <item row="0" column="0" colspan="2"> - <widget class="QLabel" name="label"> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> - </property> - </widget> - </item> - <item row="1" column="0" colspan="2"> - <widget class="QLineEdit" name="edit"> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QPushButton" name="buttonCancel"> - <property name="text"> - <string>Cancel</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="buttonOk"> - <property name="text"> - <string>Set</string> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/Code/Sandbox/Editor/ToolbarManager.cpp b/Code/Sandbox/Editor/ToolbarManager.cpp index 12fd9b1a03..6977121933 100644 --- a/Code/Sandbox/Editor/ToolbarManager.cpp +++ b/Code/Sandbox/Editor/ToolbarManager.cpp @@ -587,26 +587,13 @@ AmazonToolbar ToolbarManager::GetEditModeToolbar() const t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); - if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) - { - t.AddAction(ID_EDITMODE_SELECT, ORIGINAL_TOOLBAR_VERSION); - } - t.AddAction(ID_EDITMODE_MOVE, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_EDITMODE_ROTATE, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_EDITMODE_SCALE, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_EDITMODE_SELECTAREA, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_VIEW_SWITCHTOGAME, TOOLBARS_WITH_PLAY_GAME); t.AddAction(ID_TOOLBAR_SEPARATOR, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_TOOLBAR_WIDGET_REF_COORD, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_X, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_Y, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_Z, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_XY, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_TERRAIN, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_SELECT_AXIS_SNAPTOALL, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_TOOLBAR_WIDGET_SNAP_GRID, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_TOOLBAR_WIDGET_SNAP_ANGLE, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_RULER, ORIGINAL_TOOLBAR_VERSION); @@ -623,7 +610,6 @@ AmazonToolbar ToolbarManager::GetObjectToolbar() const AmazonToolbar t = AmazonToolbar("Object", QObject::tr("Object Toolbar")); t.SetMainToolbar(true); t.AddAction(ID_GOTO_SELECTED, ORIGINAL_TOOLBAR_VERSION); - t.AddAction(ID_OBJECTMODIFY_ALIGNTOGRID, ORIGINAL_TOOLBAR_VERSION); t.AddAction(ID_OBJECTMODIFY_SETHEIGHT, ORIGINAL_TOOLBAR_VERSION); if (!GetIEditor()->IsNewViewportInteractionModelEnabled()) diff --git a/Code/Sandbox/Editor/editor_lib_files.cmake b/Code/Sandbox/Editor/editor_lib_files.cmake index da32d6d062..4adf501d45 100644 --- a/Code/Sandbox/Editor/editor_lib_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_files.cmake @@ -484,9 +484,6 @@ set(FILES SelectLightAnimationDialog.h SelectSequenceDialog.cpp SelectSequenceDialog.h - SetVectorDlg.cpp - SetVectorDlg.h - SetVectorDlg.ui ShadersDialog.cpp ShadersDialog.h ShadersDialog.ui diff --git a/Code/Sandbox/Editor/editor_lib_test_files.cmake b/Code/Sandbox/Editor/editor_lib_test_files.cmake index 27713f4d30..f537169136 100644 --- a/Code/Sandbox/Editor/editor_lib_test_files.cmake +++ b/Code/Sandbox/Editor/editor_lib_test_files.cmake @@ -20,7 +20,6 @@ set(FILES Lib/Tests/test_MainWindowPythonBindings.cpp Lib/Tests/test_MaterialPythonFuncs.cpp Lib/Tests/test_ObjectManagerPythonBindings.cpp - Lib/Tests/test_SetVectorDlg.cpp Lib/Tests/test_TrackViewPythonBindings.cpp Lib/Tests/test_ViewPanePythonBindings.cpp Lib/Tests/test_ViewportTitleDlgPythonBindings.cpp From 957d1360da152ad3012209241cf40f6cdde56cd7 Mon Sep 17 00:00:00 2001 From: sharmajs-amzn <82233357+sharmajs-amzn@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:54:36 -0700 Subject: [PATCH 84/96] Custom UV Stream Names in assimp (#210) (#243) * Custom UV Stream Names in assimp https://jira.agscollab.com/browse/LYN-2506 --- .../FbxSceneBuilder/Importers/AssImpUvMapImporter.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpUvMapImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpUvMapImporter.cpp index 6d9189c1de..65e7c00d74 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpUvMapImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/Importers/AssImpUvMapImporter.cpp @@ -32,7 +32,7 @@ namespace AZ { namespace FbxSceneBuilder { - const char* AssImpUvMapImporter::m_defaultNodeName = "UVMap"; + const char* AssImpUvMapImporter::m_defaultNodeName = "UV"; AssImpUvMapImporter::AssImpUvMapImporter() { @@ -44,7 +44,7 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context); if (serializeContext) { - serializeContext->Class<AssImpUvMapImporter, SceneCore::LoadingComponent>()->Version(2); // LYN-2576 + serializeContext->Class<AssImpUvMapImporter, SceneCore::LoadingComponent>()->Version(3); // LYN-2506 } } @@ -84,7 +84,13 @@ namespace AZ AZStd::shared_ptr<SceneData::GraphData::MeshVertexUVData> uvMap = AZStd::make_shared<AZ::SceneData::GraphData::MeshVertexUVData>(); uvMap->ReserveContainerSpace(vertexCount); + AZStd::string name(AZStd::string::format("%s%d", m_defaultNodeName, texCoordIndex)); + if (mesh->mTextureCoordsNames[texCoordIndex].length) + { + name = mesh->mTextureCoordsNames[texCoordIndex].C_Str(); + } + uvMap->SetCustomName(name.c_str()); for (int v = 0; v < mesh->mNumVertices; ++v) From 607f78668772190d796f4c71957946ad54d0f24f Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Thu, 22 Apr 2021 15:00:50 -0500 Subject: [PATCH 85/96] [LYN-3160] Fixed virtual destructor compile issue on linux. --- Code/Sandbox/Editor/IEditorImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Sandbox/Editor/IEditorImpl.h b/Code/Sandbox/Editor/IEditorImpl.h index db391b7678..a99fa234b9 100644 --- a/Code/Sandbox/Editor/IEditorImpl.h +++ b/Code/Sandbox/Editor/IEditorImpl.h @@ -90,7 +90,7 @@ class CEditorImpl public: CEditorImpl(); - ~CEditorImpl(); + virtual ~CEditorImpl(); void Initialize(); void OnBeginShutdownSequence(); From 8e1eb32de71a63f9ab394a38b7c20a2e868ccb94 Mon Sep 17 00:00:00 2001 From: Chris Galvan <chgalvan@amazon.com> Date: Thu, 22 Apr 2021 15:22:44 -0500 Subject: [PATCH 86/96] [LYN-3160] Fixed python bindings unit test that was still looking for get/set_edit_mode functions. --- Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp b/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp index 39e8266cf6..6456b95c00 100644 --- a/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp +++ b/Code/Sandbox/Editor/Lib/Tests/test_EditorPythonBindings.cpp @@ -151,9 +151,6 @@ namespace EditorPythonBindingsUnitTests EXPECT_TRUE(behaviorContext->m_methods.find("get_axis_constraint") != behaviorContext->m_methods.end()); EXPECT_TRUE(behaviorContext->m_methods.find("set_axis_constraint") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("get_edit_mode") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("set_edit_mode") != behaviorContext->m_methods.end()); - EXPECT_TRUE(behaviorContext->m_methods.find("get_pak_from_file") != behaviorContext->m_methods.end()); EXPECT_TRUE(behaviorContext->m_methods.find("log") != behaviorContext->m_methods.end()); From 8c29ebe72841931593c7e3062664bfe5d976feb9 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Thu, 22 Apr 2021 13:30:11 -0700 Subject: [PATCH 87/96] chaging name from Lumberyard to od3e --- AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py index f253ac98fb..20f4911bab 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/setup.py @@ -30,7 +30,7 @@ if __name__ == '__main__': setup( name="editor_python_test_tools", version="1.0.0", - description='Lumberyard editor Python bindings test tools', + description='O3DE editor Python bindings test tools', long_description=long_description, packages=find_packages(where='Tools', exclude=['tests']), install_requires=[ From 17dbe55189ff586df47d66ed3b6404b6850988ac Mon Sep 17 00:00:00 2001 From: srikappa <srikappa@amazon.com> Date: Thu, 22 Apr 2021 13:57:08 -0700 Subject: [PATCH 88/96] Added undo and redo support for nested prefab creation --- .../PrefabEditorEntityOwnershipService.cpp | 4 +- .../Prefab/Instance/Instance.cpp | 9 +++- .../Prefab/Instance/Instance.h | 1 + .../Prefab/PrefabPublicHandler.cpp | 48 +++++++------------ .../Prefab/PrefabSystemComponent.cpp | 29 ++++++----- .../Prefab/PrefabSystemComponent.h | 10 ++-- .../Prefab/PrefabSystemComponentInterface.h | 4 +- 7 files changed, 54 insertions(+), 51 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index 2424658ecf..363e01f889 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -277,7 +277,7 @@ namespace AzToolsFramework AZ::IO::PathView filePath, Prefab::InstanceOptionalReference instanceToParentUnder) { AZStd::unique_ptr<Prefab::Instance> createdPrefabInstance = - m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath); + m_prefabSystemComponent->CreatePrefab(entities, AZStd::move(nestedPrefabInstances), filePath, nullptr, false); if (createdPrefabInstance) { @@ -296,7 +296,7 @@ namespace AzToolsFramework Prefab::PrefabDom serializedInstance; if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance)) { - m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance); + m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance, false); } return addedInstance; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp index 0a5b43482e..8e7dbe36f6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.cpp @@ -317,7 +317,6 @@ namespace AzToolsFramework removedNestedInstance = AZStd::move(nestedInstanceIterator->second); removedNestedInstance->m_parent = nullptr; - removedNestedInstance->m_alias = InstanceAlias(); m_nestedInstances.erase(instanceAlias); } @@ -392,6 +391,14 @@ namespace AzToolsFramework } } + void Instance::GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback) + { + for (auto& [instanceAlias, instance] : m_nestedInstances) + { + callback(instance); + } + } + void Instance::GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback) { for (auto& [entityAlias, entity] : m_entities) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h index d1c7a4d853..a91faec5bd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/Instance/Instance.h @@ -113,6 +113,7 @@ namespace AzToolsFramework void GetConstEntities(const AZStd::function<bool(const AZ::Entity&)>& callback); void GetNestedEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback); void GetEntities(const AZStd::function<bool(AZStd::unique_ptr<AZ::Entity>&)>& callback); + void GetNestedInstances(const AZStd::function<void(AZStd::unique_ptr<Instance>&)>& callback); /** * Gets the alias for a given EnitityId in the Instance DOM. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 46bd924f30..85da969f6c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -101,6 +101,10 @@ namespace AzToolsFramework nestedInstance->GetInstanceAlias(), nestedInstance->GetLinkId(), undoBatch.GetUndoBatch()); } + PrefabUndoHelpers::UpdatePrefabInstance( + commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate, + undoBatch.GetUndoBatch()); + auto prefabEditorEntityOwnershipInterface = AZ::Interface<PrefabEditorEntityOwnershipInterface>::Get(); if (!prefabEditorEntityOwnershipInterface) { @@ -118,13 +122,21 @@ namespace AzToolsFramework "(A null instance is returned).")); } - PrefabUndoHelpers::UpdatePrefabInstance( - commonRootEntityOwningInstance->get(), "Update prefab instance", commonRootInstanceDomBeforeCreate, undoBatch.GetUndoBatch()); + AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId(); + + instanceToCreate->get().GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) { + AZ_Assert(nestedInstance, "Invalid nested instance found in the new prefab created."); + EntityOptionalReference nestedInstanceContainerEntity = nestedInstance->GetContainerEntity(); + AZ_Assert( + nestedInstanceContainerEntity, "Invalid container entity found for the nested instance used in prefab creation."); + CreateLink( + {&nestedInstanceContainerEntity->get()}, *nestedInstance, instanceToCreate->get().GetTemplateId(), + undoBatch.GetUndoBatch(), containerEntityId); + }); CreateLink( topLevelEntities, instanceToCreate->get(), commonRootEntityOwningInstance->get().GetTemplateId(), undoBatch.GetUndoBatch(), commonRootEntityId); - AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId(); // Change top level entities to be parented to the container entity // Mark them as dirty so this change is correctly applied to the template @@ -225,19 +237,7 @@ namespace AzToolsFramework PrefabOperationResult PrefabPublicHandler::SavePrefab(AZ::IO::Path filePath) { - auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get(); - if (!prefabSystemComponentInterface) - { - AZ_Assert( - false, - "Prefab - PrefabPublicHandler - " - "Prefab System Component Interface could not be found. " - "Check that it is being correctly initialized."); - return AZ::Failure( - AZStd::string("SavePrefab - Internal error (Prefab System Component Interface could not be found).")); - } - - auto templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str()); + auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(filePath.c_str()); if (templateId == InvalidTemplateId) { @@ -438,26 +438,14 @@ namespace AzToolsFramework PrefabRequestResult PrefabPublicHandler::HasUnsavedChanges(AZ::IO::Path prefabFilePath) const { - auto prefabSystemComponentInterface = AZ::Interface<PrefabSystemComponentInterface>::Get(); - if (!prefabSystemComponentInterface) - { - AZ_Assert( - false, - "Prefab - PrefabPublicHandler - " - "Prefab System Component Interface could not be found. " - "Check that it is being correctly initialized."); - return AZ::Failure( - AZStd::string("HasUnsavedChanges - Internal error (Prefab System Component Interface could not be found).")); - } - - auto templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(prefabFilePath.c_str()); + auto templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(prefabFilePath.c_str()); if (templateId == InvalidTemplateId) { return AZ::Failure(AZStd::string("HasUnsavedChanges - Path error. Path could be invalid, or the prefab may not be loaded in this level.")); } - return AZ::Success(prefabSystemComponentInterface->IsTemplateDirty(templateId)); + return AZ::Success(m_prefabSystemComponentInterface->IsTemplateDirty(templateId)); } PrefabOperationResult PrefabPublicHandler::DeleteEntitiesInInstance(const EntityIdList& entityIds) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 9070630e56..4b25c80fd3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -91,8 +91,9 @@ namespace AzToolsFramework m_instanceUpdateExecutor.UpdateTemplateInstancesInQueue(); } - AZStd::unique_ptr<Instance> PrefabSystemComponent::CreatePrefab(const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, - AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity) + AZStd::unique_ptr<Instance> PrefabSystemComponent::CreatePrefab( + const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, + AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity, bool shouldCreateLinks) { AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath); if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId) @@ -122,7 +123,7 @@ namespace AzToolsFramework newInstance->SetTemplateSourcePath(relativeFilePath); - TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance); + TemplateId newTemplateId = CreateTemplateFromInstance(*newInstance, shouldCreateLinks); if (newTemplateId == InvalidTemplateId) { AZ_Error("Prefab", false, @@ -157,7 +158,7 @@ namespace AzToolsFramework } } - void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) + void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges) { auto templateToUpdate = FindTemplate(templateId); if (templateToUpdate) @@ -167,7 +168,10 @@ namespace AzToolsFramework { templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); templateToUpdate->get().MarkAsDirty(true); - PropagateTemplateChanges(templateId); + if (shouldPropagateTemplateChanges) + { + PropagateTemplateChanges(templateId); + } } } } @@ -288,7 +292,7 @@ namespace AzToolsFramework return newInstance; } - TemplateId PrefabSystemComponent::CreateTemplateFromInstance(Instance& instance) + TemplateId PrefabSystemComponent::CreateTemplateFromInstance(Instance& instance, bool shouldCreateLinks) { // We will register the template to match the path the instance has const AZ::IO::Path& templateSourcePath = instance.GetTemplateSourcePath(); @@ -322,14 +326,15 @@ namespace AzToolsFramework return InvalidTemplateId; } - if (!GenerateLinksForNewTemplate(newTemplateId, instance)) + if (shouldCreateLinks) { - // Clear new template and any links associated with it - RemoveTemplate(newTemplateId); - - return InvalidTemplateId; + if (!GenerateLinksForNewTemplate(newTemplateId, instance)) + { + // Clear new template and any links associated with it + RemoveTemplate(newTemplateId); + return InvalidTemplateId; + } } - return newTemplateId; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index 40780b9775..d04b760aae 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -190,8 +190,10 @@ namespace AzToolsFramework * @param filePath the path to associate the template of the new instance to * @return A pointer to the newly created instance. nullptr on failure */ - AZStd::unique_ptr<Instance> CreatePrefab(const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, - AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr) override; + AZStd::unique_ptr<Instance> CreatePrefab( + const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, + AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr, + bool ShouldCreateLinks = true) override; PrefabDom& FindTemplateDom(TemplateId templateId) override; @@ -201,7 +203,7 @@ namespace AzToolsFramework * @param templateId The id of the template to update. * @param updatedDom The DOM to update the template with. */ - void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override; + void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges = true) override; void PropagateTemplateChanges(TemplateId templateId) override; @@ -262,7 +264,7 @@ namespace AzToolsFramework * along with any new Prefab Links representing any of the nested instances present * @param instance The instance used to generate the new Template */ - TemplateId CreateTemplateFromInstance(Instance& instance); + TemplateId CreateTemplateFromInstance(Instance& instance, bool shouldCreateLinks); /** * Connect two templates with given link, and a nested instance value iterator diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index 8b94935cc1..d957a14b61 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -55,13 +55,13 @@ namespace AzToolsFramework virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; - virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; + virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges = true) = 0; virtual void PropagateTemplateChanges(TemplateId templateId) = 0; virtual AZStd::unique_ptr<Instance> InstantiatePrefab(const TemplateId& templateId) = 0; virtual AZStd::unique_ptr<Instance> CreatePrefab(const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume, AZ::IO::PathView filePath, - AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr) = 0; + AZStd::unique_ptr<AZ::Entity> containerEntity = nullptr, bool ShouldCreateLinks = true) = 0; }; From f44f06c9f0a5cc26c67f8aadc7ced73782d0b45d Mon Sep 17 00:00:00 2001 From: AMZN-stankowi <stankowi@amazon.com> Date: Thu, 22 Apr 2021 14:09:44 -0700 Subject: [PATCH 89/96] AssImp set to be the default FBX processor (#78) (#136) * AssImp set to be the default FBX processor (#78) If you encounter issues, reach out to the Helios team with details, and then switch back to FBX SDK locally by changing FBXImporter.h * Merge pull request #219 from aws-lumberyard-dev/sceneapi_scripting LYN-3030: Fix to export_chunks_builder.py to match the AssImp node paths * Hide some automated test folders from the asset processor for automatedtesting. This is necessary because these assets should only be processed when running the test, and not any time AP is launched for this project. * Putting these test assets back to visible to Asset Processor. These tests need to be updated at some point to handle that, but they won't work with this change for now. Note that until this is addressed, these tests may randomly time out if they're the first tests run on a clean asset processor, and these tests launch AP without using a unique port, so the test can also fail if an Asset Processor executable is hanging open. Grabbed the change I missed from the 1.0 branch merge, no idea how this got lost. * Moved from main to periodic. Allen and Fuzzy were already on board, and I think with the potential flakiness in this test, we don't want this in main. Co-authored-by: jackalbe <23512001+jackalbe@users.noreply.github.com> --- .../PythonAssetBuilder/AssetBuilder_test.py | 17 ++++++++-------- .../AssetBuilder_test_case.py | 19 +++++++++--------- .../export_chunks_builder.py | 20 ++++++------------- .../SceneAPI/FbxSceneBuilder/FbxImporter.cpp | 2 +- .../SceneAPI/FbxSceneBuilder/FbxImporter.h | 2 +- Gems/Blast/Editor/Scripts/bootstrap.py | 2 +- 6 files changed, 27 insertions(+), 35 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py index e914182542..818dc23079 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test.py @@ -22,7 +22,7 @@ import ly_test_tools.environment.file_system as file_system import ly_test_tools.log.log_monitor import ly_test_tools.environment.waiter as waiter -@pytest.mark.SUITE_sandbox +@pytest.mark.SUITE_periodic @pytest.mark.parametrize('launcher_platform', ['windows_editor']) @pytest.mark.parametrize('project', ['AutomatedTesting']) @pytest.mark.parametrize('level', ['auto_test']) @@ -31,14 +31,13 @@ class TestPythonAssetProcessing(object): unexpected_lines = [] expected_lines = [ 'Mock asset exists', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found', - 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel) found' + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel) found', + 'Expected subId for asset (gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel) found' ] timeout = 180 halt_on_unexpected = False diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py index 54857c2067..cd9adfdbcf 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/AssetBuilder_test_case.py @@ -26,8 +26,9 @@ assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdB if (assetId.is_valid() is False): raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead') -if (assetId.to_string().endswith(':54c06b89') is False): - raise_and_stop(f'Mock AssetId has unexpected sub-id for {mockAssetPath}!') +assetIdString = assetId.to_string() +if (assetIdString.endswith(':528cca58') is False): + raise_and_stop(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!') print ('Mock asset exists') @@ -41,12 +42,12 @@ def test_azmodel_product(generatedModelAssetPath, expectedSubId): else: print(f'Expected subId for asset ({generatedModelAssetPath}) found') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center.azmodel', '10412075') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_positive.azmodel', '10d16e68') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_X_negative.azmodel', '10a71973') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_positive.azmodel', '10130556') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Y_negative.azmodel', '1065724d') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_positive.azmodel', '1024be55') -test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_Z_negative.azmodel', '1052c94e') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel', '10315ae0') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel', '10661093') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel', '10af8810') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel', '10f8c263') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel', '100ac47f') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel', '105d8e0c') +test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel', '1002d464') azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt') diff --git a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py index ad68a486b1..7e1f108c28 100644 --- a/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py +++ b/AutomatedTesting/Gem/PythonTests/PythonAssetBuilder/export_chunks_builder.py @@ -1,7 +1,6 @@ """ All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or its licensors. - For complete copyright and license terms please see the LICENSE at the root of this distribution (the "License"). All use of this software is governed by the License, or, if provided, by the license below or the license accompanying this file. Do not @@ -27,7 +26,10 @@ def get_mesh_node_names(sceneGraph): nodeContent = sceneGraph.get_node_content(node) if nodeContent is not None and nodeContent.CastWithTypeName('MeshData'): if sceneGraph.is_node_end_point(node) is False: - meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node))) + nodeName = sceneData.SceneGraphName(sceneGraph.get_node_name(node)) + nodePath = nodeName.get_path() + if (len(nodeName.get_path())): + meshDataList.append(sceneData.SceneGraphName(sceneGraph.get_node_name(node))) # advance to next node if sceneGraph.has_node_sibling(node): @@ -54,17 +56,7 @@ def update_manifest(scene): meshGroup['id'] = '{' + str(uuid.uuid5(uuid.NAMESPACE_DNS, sourceFilenameOnly + chunkPath)) + '}' sceneManifest.mesh_group_add_comment(meshGroup, 'auto generated by scene manifest') sceneManifest.mesh_group_add_advanced_coordinate_system(meshGroup, None, None, None, 1.0) - - # create selection node list - pathSet = set() - for meshIndex in range(len(meshNameList)): - targetPath = meshNameList[meshIndex].get_path() - if (activeMeshIndex == meshIndex): - sceneManifest.mesh_group_select_node(meshGroup, targetPath) - else: - if targetPath not in pathSet: - pathSet.update(targetPath) - sceneManifest.mesh_group_unselect_node(meshGroup, targetPath) + sceneManifest.mesh_group_select_node(meshGroup, chunkPath) return sceneManifest.export() @@ -85,4 +77,4 @@ def main(): mySceneJobHandler.add_callback('OnUpdateManifest', on_update_manifest) if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.cpp b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.cpp index 8bbe62c913..650eb4c935 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.cpp +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.cpp @@ -73,7 +73,7 @@ namespace AZ SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context); if (serializeContext) { - serializeContext->Class<FbxImporter, SceneCore::LoadingComponent>()->Version(1); + serializeContext->Class<FbxImporter, SceneCore::LoadingComponent>()->Version(2); // SPEC-5776 } } diff --git a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.h b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.h index 7aa43ca389..5bf9ab84c9 100644 --- a/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.h +++ b/Code/Tools/SceneAPI/FbxSceneBuilder/FbxImporter.h @@ -51,7 +51,7 @@ namespace AZ AZStd::unique_ptr<SDKScene::SceneWrapperBase> m_sceneWrapper; AZStd::shared_ptr<FbxSceneSystem> m_sceneSystem; - bool m_useAssetImporterSDK = false; + bool m_useAssetImporterSDK = true; }; } // namespace FbxSceneBuilder } // namespace SceneAPI diff --git a/Gems/Blast/Editor/Scripts/bootstrap.py b/Gems/Blast/Editor/Scripts/bootstrap.py index 8614cb7d1d..3837383a89 100755 --- a/Gems/Blast/Editor/Scripts/bootstrap.py +++ b/Gems/Blast/Editor/Scripts/bootstrap.py @@ -9,5 +9,5 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. """ -# LYN-652 to re-enable the next line +# LYN-652 to re-enable once the Blast gem tests are stable # import asset_builder_blast From 8f76dd0f26652f4fb2207c6f10113a7137efcae3 Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Thu, 22 Apr 2021 14:30:15 -0700 Subject: [PATCH 90/96] Fixing string interpolation security risk in test metrics --- scripts/build/Jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 4352cb1e6a..8c0c46e7c6 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -361,7 +361,7 @@ def TestMetrics(Map options, String workspace, String branchName, String repoNam ] withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " + - "-e jenkins.creds.user ${username} -e jenkins.creds.pass ${apitoken} " + + '-e jenkins.creds.user $username -e jenkins.creds.pass $apitoken ' + "-e jenkins.base_url ${env.JENKINS_URL} " + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " bat label: "Publishing ${buildJobName} Test Metrics", From ea965dc78aa2a0922e2594cf9a84cbab5740f9c4 Mon Sep 17 00:00:00 2001 From: bosnichd <bosnichd@amazon.com> Date: Thu, 22 Apr 2021 16:07:20 -0600 Subject: [PATCH 91/96] Fix for "GameLauncher crashes silently after any interaction within it" Fix for "GameLauncher crashes silently after any interaction within it" --- Gems/Gestures/Code/CMakeLists.txt | 3 +++ .../Include/Gestures/IGestureRecognizer.h | 27 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Gems/Gestures/Code/CMakeLists.txt b/Gems/Gestures/Code/CMakeLists.txt index fe0fd9d98b..c05b39b72c 100644 --- a/Gems/Gestures/Code/CMakeLists.txt +++ b/Gems/Gestures/Code/CMakeLists.txt @@ -20,6 +20,9 @@ ly_add_target( PUBLIC Include BUILD_DEPENDENCIES + PUBLIC + Gem::Atom_RPI.Public + AZ::AtomCore PRIVATE Legacy::CryCommon ) diff --git a/Gems/Gestures/Code/Include/Gestures/IGestureRecognizer.h b/Gems/Gestures/Code/Include/Gestures/IGestureRecognizer.h index 3f71cd4b62..4b5b7726d8 100644 --- a/Gems/Gestures/Code/Include/Gestures/IGestureRecognizer.h +++ b/Gems/Gestures/Code/Include/Gestures/IGestureRecognizer.h @@ -19,6 +19,9 @@ #include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h> #include <AzFramework/Input/Devices/Touch/InputDeviceTouch.h> +#include <Atom/RPI.Public/ViewportContext.h> +#include <Atom/RPI.Public/ViewportContextBus.h> + //////////////////////////////////////////////////////////////////////////////////////////////////// namespace Gestures { @@ -184,8 +187,16 @@ namespace Gestures return; } - const AZ::Vector2 eventScreenPositionPixels = positionData2D->ConvertToScreenSpaceCoordinates(static_cast<float>(gEnv->pRenderer->GetWidth()), - static_cast<float>(gEnv->pRenderer->GetHeight())); + auto atomViewportRequests = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get(); + AZ::RPI::ViewportContextPtr viewportContext = atomViewportRequests->GetDefaultViewportContext(); + if (viewportContext == nullptr) + { + return; + } + + AzFramework::WindowSize windowSize = viewportContext->GetViewportSize(); + const AZ::Vector2 eventScreenPositionPixels = positionData2D->ConvertToScreenSpaceCoordinates(static_cast<float>(windowSize.m_width), + static_cast<float>(windowSize.m_height)); if (inputChannel.IsStateBegan()) { o_hasBeenConsumed = OnPressedEvent(eventScreenPositionPixels, pointerIndex); @@ -225,8 +236,16 @@ namespace Gestures //////////////////////////////////////////////////////////////////////////////////////////////// inline void IRecognizer::UpdateNormalizedPositionAndDeltaFromScreenPosition(const AZ::Vector2& screenPositionPixels) { - const AZ::Vector2 normalizedPosition(screenPositionPixels.GetX() / static_cast<float>(gEnv->pRenderer->GetWidth()), - screenPositionPixels.GetY() / static_cast<float>(gEnv->pRenderer->GetHeight())); + auto atomViewportRequests = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get(); + AZ::RPI::ViewportContextPtr viewportContext = atomViewportRequests->GetDefaultViewportContext(); + if (viewportContext == nullptr) + { + return; + } + + AzFramework::WindowSize windowSize = viewportContext->GetViewportSize(); + const AZ::Vector2 normalizedPosition(screenPositionPixels.GetX() / static_cast<float>(windowSize.m_width), + screenPositionPixels.GetY() / static_cast<float>(windowSize.m_height)); AzFramework::InputChannel::PositionData2D::UpdateNormalizedPositionAndDelta(normalizedPosition); } } From 9ca7408929c15ffb9c30a4f1940e0c31c107a639 Mon Sep 17 00:00:00 2001 From: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> Date: Thu, 22 Apr 2021 15:56:24 -0700 Subject: [PATCH 92/96] SPEC-6499 Timeout in pipes expire due to logs being in a sub-step --- scripts/build/Jenkins/Jenkinsfile | 78 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 4352cb1e6a..fe60d9236c 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -337,14 +337,16 @@ def PreBuildCommonSteps(Map pipelineConfig, String repositoryName, String projec } def Build(Map options, String platform, String type, String workspace) { - def command = "${options.BUILD_ENTRY_POINT} --platform ${platform} --type ${type}" - dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { - if (env.IS_UNIX) { - sh label: "Running ${platform} ${type}", - script: "${options.PYTHON_DIR}/python.sh -u ${command}" - } else { - bat label: "Running ${platform} ${type}", - script: "${options.PYTHON_DIR}/python.cmd -u ${command}".replace('/','\\') + timeout(time: env.TIMEOUT, unit: 'MINUTES', activity: true) { + def command = "${options.BUILD_ENTRY_POINT} --platform ${platform} --type ${type}" + dir("${workspace}/${ENGINE_REPOSITORY_NAME}") { + if (env.IS_UNIX) { + sh label: "Running ${platform} ${type}", + script: "${options.PYTHON_DIR}/python.sh -u ${command}" + } else { + bat label: "Running ${platform} ${type}", + script: "${options.PYTHON_DIR}/python.cmd -u ${command}".replace('/','\\') + } } } } @@ -502,43 +504,41 @@ try { envVars['IS_UNIX'] = 1 } withEnv(GetEnvStringList(envVars)) { - timeout(time: envVars['TIMEOUT'], unit: 'MINUTES', activity: true) { - try { - def build_job_name = build_job.key - - CreateSetupStage(pipelineConfig, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() - - if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages - build_job.value.steps.each { build_step -> - build_job_name = build_step - CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() - } - } else { - CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() - } + try { + def build_job_name = build_job.key + + CreateSetupStage(pipelineConfig, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars).call() - if (env.MARS_REPO && platform.key == 'Windows' && build_job_name.startsWith('test')) { - def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY - def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION - CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() + if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages + build_job.value.steps.each { build_step -> + build_job_name = build_step + CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() } + } else { + CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() } - catch(Exception e) { - // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java - // {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED} - def currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' - if (currentResult == 'FAILURE') { - currentBuild.result = 'FAILURE' - error "FAILURE: ${e}" - } else if (currentResult == 'UNSTABLE') { - currentBuild.result = 'UNSTABLE' - unstable(message: "UNSTABLE: ${e}") - } + + if (env.MARS_REPO && platform.key == 'Windows' && build_job_name.startsWith('test')) { + def output_directory = platform.value.build_types[build_job_name].PARAMETERS.OUTPUT_DIRECTORY + def configuration = platform.value.build_types[build_job_name].PARAMETERS.CONFIGURATION + CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() } - finally { - CreateTeardownStage(envVars).call() + } + catch(Exception e) { + // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java + // {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED} + def currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' + if (currentResult == 'FAILURE') { + currentBuild.result = 'FAILURE' + error "FAILURE: ${e}" + } else if (currentResult == 'UNSTABLE') { + currentBuild.result = 'UNSTABLE' + unstable(message: "UNSTABLE: ${e}") } } + finally { + CreateTeardownStage(envVars).call() + } } } } From cb7a26ce5e11938709d27aa161909e064c98fc98 Mon Sep 17 00:00:00 2001 From: chcurran <chcurran@amazon.com> Date: Thu, 22 Apr 2021 16:13:24 -0700 Subject: [PATCH 93/96] Editor for stability and overloaded nodes. LYN-2904, LYN-3059, LYN-3234, LYN-2888 --- .../Code/Editor/Nodes/NodeDisplayUtils.cpp | 3 +- .../Widgets/NodePalette/NodePaletteModel.cpp | 2 +- .../Grammar/AbstractCodeModel.cpp | 32 +++++++---- .../ScriptCanvas/Grammar/Primitives.cpp | 15 ++++- .../Grammar/PrimitivesExecution.cpp | 5 +- .../ScriptCanvas/Libraries/Core/Method.cpp | 55 ++++++++++++++++--- .../ScriptCanvas/Libraries/Core/Method.h | 4 +- 7 files changed, 87 insertions(+), 29 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Nodes/NodeDisplayUtils.cpp b/Gems/ScriptCanvas/Code/Editor/Nodes/NodeDisplayUtils.cpp index c6ecac00f1..a903c9f885 100644 --- a/Gems/ScriptCanvas/Code/Editor/Nodes/NodeDisplayUtils.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Nodes/NodeDisplayUtils.cpp @@ -332,7 +332,8 @@ namespace ScriptCanvasEditor::Nodes contextGroup = TranslationContextGroup::ClassMethod; break; default: - AZ_Assert(false, "Invalid node type"); + AZ_Error("ScriptCanvas", false, "Invalid method node type, node creation failed. This node nodes to be deleted."); + break; } graphCanvasEntity->Init(); diff --git a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp index 2edc950e6f..6028b284fa 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Widgets/NodePalette/NodePaletteModel.cpp @@ -136,7 +136,7 @@ namespace return; } - if (behaviorClass) + if (behaviorClass && !isOverloaded) { auto excludeMethodAttributeData = azdynamic_cast<const AZ::Edit::AttributeData<AZ::Script::Attributes::ExcludeFlags>*>(AZ::FindAttribute(AZ::Script::Attributes::ExcludeFrom, method.m_attributes)); if (ShouldExcludeFromNodeList(excludeMethodAttributeData, behaviorClass->m_azRtti ? behaviorClass->m_azRtti->GetTypeId() : behaviorClass->m_typeId)) diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp index 958e37f82c..3bc105d1dd 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/AbstractCodeModel.cpp @@ -146,7 +146,10 @@ namespace ScriptCanvas for (auto iter : m_functions) { - AZStd::const_pointer_cast<ExecutionTree>(iter)->Clear(); + if (auto mutableIter = AZStd::const_pointer_cast<ExecutionTree>(iter)) + { + mutableIter->Clear(); + } } m_functions.clear(); @@ -155,24 +158,36 @@ namespace ScriptCanvas for (auto iter : m_ebusHandlingByNode) { - iter.second->Clear(); + if (iter.second) + { + iter.second->Clear(); + } } m_ebusHandlingByNode.clear(); for (auto iter : m_eventHandlingByNode) { - iter.second->Clear(); + if (iter.second) + { + iter.second->Clear(); + } } for (auto iter : m_nodeablesByNode) { - AZStd::const_pointer_cast<NodeableParse>(iter.second)->Clear(); + if (auto mutableIter = AZStd::const_pointer_cast<NodeableParse>(iter.second)) + { + mutableIter->Clear(); + } } m_nodeablesByNode.clear(); for (auto iter : m_variableWriteHandlingBySlot) { - AZStd::const_pointer_cast<VariableWriteHandling>(iter.second)->Clear(); + if (auto mutableIter = AZStd::const_pointer_cast<VariableWriteHandling>(iter.second)) + { + mutableIter->Clear(); + } } m_variableWriteHandlingBySlot.clear(); m_variableWriteHandlingByVariable.clear(); @@ -795,13 +810,6 @@ namespace ScriptCanvas } } - AZ_Assert(variables.size() == constructionNodeables.size() + constructionInputVariables.size() + entityIds.size() - , "ctor var size: %zu, nodeables: %zu, inputs: %zu, entity ids: %zu" - , variables.size() - , constructionNodeables.size() - , constructionInputVariables.size() - , entityIds.size()); - return variables; } diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp index bbde312ef3..672375f29b 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/Primitives.cpp @@ -82,7 +82,10 @@ namespace ScriptCanvas { for (auto& iter : m_events) { - AZStd::const_pointer_cast<ExecutionTree>(iter.second)->Clear(); + if (auto event = AZStd::const_pointer_cast<ExecutionTree>(iter.second)) + { + event->Clear(); + } } } @@ -90,7 +93,10 @@ namespace ScriptCanvas { m_eventNode = nullptr; m_eventSlot = nullptr; - AZStd::const_pointer_cast<ExecutionTree>(m_eventHandlerFunction)->Clear(); + if (auto function = AZStd::const_pointer_cast<ExecutionTree>(m_eventHandlerFunction)) + { + function->Clear(); + } } void FunctionPrototype::Clear() @@ -152,7 +158,10 @@ namespace ScriptCanvas for (auto& iter : m_latents) { - AZStd::const_pointer_cast<ExecutionTree>(iter.second)->Clear(); + if (auto latent = AZStd::const_pointer_cast<ExecutionTree>(iter.second)) + { + latent->Clear(); + } } m_latents.clear(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp index c6e7925a31..ed61d7e838 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Grammar/PrimitivesExecution.cpp @@ -72,7 +72,10 @@ namespace ScriptCanvas for (auto returnValue : m_returnValues) { - AZStd::const_pointer_cast<ReturnValue>(returnValue.second)->Clear(); + if (auto returnValuePtr = AZStd::const_pointer_cast<ReturnValue>(returnValue.second)) + { + returnValuePtr->Clear(); + } } m_returnValues.clear(); diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp index 1a69dbb25e..0e0467fdcc 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.cpp @@ -249,20 +249,46 @@ namespace ScriptCanvas return; } - if (className.empty()) + if (!InitializeOverloaded(namespaces, className, methodName)) { - InitializeFree(namespaces, methodName); + if (className.empty()) + { + InitializeFree(namespaces, methodName); + } + else if (auto ebusIterator = behaviorContext->m_ebuses.find(className); ebusIterator == behaviorContext->m_ebuses.end()) + { + InitializeClass(namespaces, className, methodName); + } + else + { + InitializeEvent(namespaces, className, methodName); + } } - else if (auto ebusIterator = behaviorContext->m_ebuses.find(className); ebusIterator == behaviorContext->m_ebuses.end()) + + PopulateNodeType(); + } + + bool Method::InitializeOverloaded([[maybe_unused]] const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName) + { + const AZ::BehaviorMethod* method{}; + const AZ::BehaviorClass* bcClass{}; + AZStd::string prettyClassName; + + if (IsMethodOverloaded() && BehaviorContextUtils::FindExplicitOverload(method, bcClass, className, methodName, &prettyClassName)) { - InitializeClass(namespaces, className, methodName); + MethodConfiguration config(*method, method->IsMember() ? MethodType::Member : MethodType::Free); + config.m_class = bcClass; + config.m_namespaces = &m_namespaces; + config.m_className = &className; + config.m_lookupName = &methodName; + config.m_prettyClassName = prettyClassName; + InitializeMethod(config); + return true; } else { - InitializeEvent(namespaces, className, methodName); + return false; } - - PopulateNodeType(); } void Method::InitializeClass(const NamespacePath&, AZStd::string_view className, AZStd::string_view methodName) @@ -273,8 +299,7 @@ namespace ScriptCanvas const AZ::BehaviorClass* bcClass{}; AZStd::string prettyClassName; - if ((IsMethodOverloaded() && BehaviorContextUtils::FindExplicitOverload(method, bcClass, className, methodName, &prettyClassName)) - || BehaviorContextUtils::FindClass(method, bcClass, className, methodName, &prettyClassName)) + if (BehaviorContextUtils::FindClass(method, bcClass, className, methodName, &prettyClassName)) { MethodConfiguration config(*method, MethodType::Member); config.m_class = bcClass; @@ -308,6 +333,7 @@ namespace ScriptCanvas AZStd::lock_guard<AZStd::recursive_mutex> lock(m_mutex); const AZ::BehaviorMethod* method{}; + if (BehaviorContextUtils::FindFree(method, methodName)) { MethodConfiguration config(*method, MethodType::Free); @@ -525,6 +551,17 @@ namespace ScriptCanvas m_method = &method; m_class = bcClass; + AZ::BehaviorContext* behaviorContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext); + + if (bcClass && behaviorContext) + { + if (auto prettyNameAttribute = AZ::FindAttribute(AZ::ScriptCanvasAttributes::PrettyName, bcClass->m_attributes)) + { + AZ::AttributeReader operatorAttrReader(nullptr, prettyNameAttribute); + operatorAttrReader.Read<AZStd::string>(m_classNamePretty, *behaviorContext); + } + } if (m_classNamePretty.empty()) { diff --git a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h index 7af2c15e82..b03e3aefd8 100644 --- a/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h +++ b/Gems/ScriptCanvas/Code/Include/ScriptCanvas/Libraries/Core/Method.h @@ -86,8 +86,6 @@ namespace ScriptCanvas bool IsObjectClass(AZStd::string_view objectClass) const { return objectClass.compare(m_className) == 0; } - - //! Attempts to initialize node with a BehaviorContext BehaviorMethod //! If the className is empty, then the methodName is searched on the BehaviorContext //! If className is not empty the className is used to look for a registered BehaviorEBus in the BehaviorContext @@ -102,6 +100,8 @@ namespace ScriptCanvas void InitializeFree(const NamespacePath& namespaces, AZStd::string_view methodName); + bool InitializeOverloaded(const NamespacePath& namespaces, AZStd::string_view className, AZStd::string_view methodName); + AZ_INLINE bool IsValid() const { return m_method != nullptr; } bool HasBusID() const { return (m_method == nullptr) ? false : m_method->HasBusId(); } From ad7e7d829e8e5dfc7af58567cd0f659d19b4a01e Mon Sep 17 00:00:00 2001 From: evanchia <evanchia@amazon.com> Date: Thu, 22 Apr 2021 16:42:52 -0700 Subject: [PATCH 94/96] changed variable formatting method --- scripts/build/Jenkins/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 8c0c46e7c6..0d2315f1de 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -361,7 +361,7 @@ def TestMetrics(Map options, String workspace, String branchName, String repoNam ] withCredentials([usernamePassword(credentialsId: "${env.SERVICE_USER}", passwordVariable: 'apitoken', usernameVariable: 'username')]) { def command = "${options.PYTHON_DIR}/python.cmd -u mars/scripts/python/ctest_test_metric_scraper.py " + - '-e jenkins.creds.user $username -e jenkins.creds.pass $apitoken ' + + '-e jenkins.creds.user %username% -e jenkins.creds.pass %apitoken% ' + "-e jenkins.base_url ${env.JENKINS_URL} " + "${cmakeBuildDir} ${branchName} %BUILD_NUMBER% AR ${configuration} ${repoName} " bat label: "Publishing ${buildJobName} Test Metrics", From a9af90be5ab54ce5f370fef6f6a49120e456b81e Mon Sep 17 00:00:00 2001 From: srikappa <srikappa@amazon.com> Date: Thu, 22 Apr 2021 17:01:29 -0700 Subject: [PATCH 95/96] Removed the shouldPropagateTemplateChanges flag to revisit optimization later and fixed some function comments --- .../Entity/PrefabEditorEntityOwnershipService.cpp | 2 +- .../Prefab/PrefabSystemComponent.cpp | 7 ++----- .../AzToolsFramework/Prefab/PrefabSystemComponent.h | 13 +++++++++---- .../Prefab/PrefabSystemComponentInterface.h | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp index dd1fdec74d..07be2a6644 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/PrefabEditorEntityOwnershipService.cpp @@ -298,7 +298,7 @@ namespace AzToolsFramework Prefab::PrefabDom serializedInstance; if (Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(addedInstance, serializedInstance)) { - m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance, false); + m_prefabSystemComponent->UpdatePrefabTemplate(addedInstance.GetTemplateId(), serializedInstance); } return addedInstance; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 53652933a4..d89a388e91 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -159,7 +159,7 @@ namespace AzToolsFramework } } - void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges) + void PrefabSystemComponent::UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) { auto templateToUpdate = FindTemplate(templateId); if (templateToUpdate) @@ -169,10 +169,7 @@ namespace AzToolsFramework { templateDomToUpdate.CopyFrom(updatedDom, templateDomToUpdate.GetAllocator()); templateToUpdate->get().MarkAsDirty(true); - if (shouldPropagateTemplateChanges) - { - PropagateTemplateChanges(templateId); - } + PropagateTemplateChanges(templateId); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index d04b760aae..d4499d1e2d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -187,7 +187,10 @@ namespace AzToolsFramework * @param entities A vector of entities that will be used in the new instance. May be empty * @param instances A vector of Prefab Instances that will be nested in the new instance, will be consumed and moved. * May be empty - * @param filePath the path to associate the template of the new instance to + * @param filePath the path to associate the template of the new instance to. + * @param containerEntity The container entity for the prefab to be created. It will be created if a nullptr is provided. + * @param shouldCreateLinks The flag indicating if links should be created between the templates of the instance + * and its nested instances. * @return A pointer to the newly created instance. nullptr on failure */ AZStd::unique_ptr<Instance> CreatePrefab( @@ -199,11 +202,11 @@ namespace AzToolsFramework /** * Updates a template with the given updated DOM. - * + * * @param templateId The id of the template to update. * @param updatedDom The DOM to update the template with. */ - void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges = true) override; + void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override; void PropagateTemplateChanges(TemplateId templateId) override; @@ -262,7 +265,9 @@ namespace AzToolsFramework /** * Takes a prefab instance and generates a new Prefab Template * along with any new Prefab Links representing any of the nested instances present - * @param instance The instance used to generate the new Template + * @param instance The instance used to generate the new Template. + * @param shouldCreateLinks The flag indicating if links should be created between the templates of the instance + * and its nested instances. */ TemplateId CreateTemplateFromInstance(Instance& instance, bool shouldCreateLinks); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h index d957a14b61..f0ea99f3dd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponentInterface.h @@ -55,7 +55,7 @@ namespace AzToolsFramework virtual void SetTemplateDirtyFlag(const TemplateId& templateId, bool dirty) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; - virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom, bool shouldPropagateTemplateChanges = true) = 0; + virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void PropagateTemplateChanges(TemplateId templateId) = 0; virtual AZStd::unique_ptr<Instance> InstantiatePrefab(const TemplateId& templateId) = 0; From bac334a2449441cb2d2ad695ce7d92e6675e7808 Mon Sep 17 00:00:00 2001 From: chiyenteng <82238204+chiyenteng@users.noreply.github.com> Date: Thu, 22 Apr 2021 17:42:06 -0700 Subject: [PATCH 96/96] Fix serialization issues related to sequence node/track (#214) (#247) * Fix serialization issues related to sequence node/track --- Code/CryEngine/CryCommon/IMovieSystem.h | 24 ++- .../Source/Cinematics/AnimAZEntityNode.cpp | 11 +- .../Code/Source/Cinematics/AnimAZEntityNode.h | 2 +- .../Source/Cinematics/AnimComponentNode.cpp | 13 +- .../Source/Cinematics/AnimComponentNode.h | 2 +- .../Source/Cinematics/AnimEnvironmentNode.cpp | 9 +- .../Source/Cinematics/AnimEnvironmentNode.h | 2 +- .../Code/Source/Cinematics/AnimNode.cpp | 35 +++- .../Maestro/Code/Source/Cinematics/AnimNode.h | 2 +- .../Code/Source/Cinematics/AnimNodeGroup.cpp | 9 +- .../Code/Source/Cinematics/AnimNodeGroup.h | 4 +- .../Code/Source/Cinematics/AnimPostFXNode.cpp | 9 +- .../Code/Source/Cinematics/AnimPostFXNode.h | 2 +- .../Source/Cinematics/AnimScreenFaderNode.cpp | 9 +- .../Source/Cinematics/AnimScreenFaderNode.h | 2 +- .../Code/Source/Cinematics/AnimSequence.cpp | 4 +- .../Code/Source/Cinematics/AnimSerializer.cpp | 195 +++++++++--------- .../Code/Source/Cinematics/AnimSerializer.h | 4 +- .../Code/Source/Cinematics/AnimSplineTrack.h | 2 +- .../AnimSplineTrack_Vec2Specialization.h | 84 ++++---- .../Code/Source/Cinematics/AnimTrack.h | 2 +- .../Source/Cinematics/AssetBlendTrack.cpp | 42 ++-- .../Code/Source/Cinematics/AssetBlendTrack.h | 2 +- .../Code/Source/Cinematics/BoolTrack.cpp | 46 +++-- .../Code/Source/Cinematics/BoolTrack.h | 2 +- .../Code/Source/Cinematics/CVarNode.cpp | 9 +- .../Maestro/Code/Source/Cinematics/CVarNode.h | 2 +- .../Code/Source/Cinematics/CaptureTrack.cpp | 42 ++-- .../Code/Source/Cinematics/CaptureTrack.h | 2 +- .../Code/Source/Cinematics/CharacterTrack.cpp | 44 ++-- .../Code/Source/Cinematics/CharacterTrack.h | 2 +- .../Code/Source/Cinematics/CommentNode.cpp | 9 +- .../Code/Source/Cinematics/CommentNode.h | 2 +- .../Code/Source/Cinematics/CommentTrack.cpp | 42 ++-- .../Code/Source/Cinematics/CommentTrack.h | 2 +- .../Source/Cinematics/CompoundSplineTrack.cpp | 39 ++-- .../Source/Cinematics/CompoundSplineTrack.h | 2 +- .../Code/Source/Cinematics/ConsoleTrack.cpp | 42 ++-- .../Code/Source/Cinematics/ConsoleTrack.h | 2 +- .../Code/Source/Cinematics/EventNode.cpp | 11 +- .../Code/Source/Cinematics/EventNode.h | 2 +- .../Code/Source/Cinematics/EventTrack.cpp | 11 +- .../Code/Source/Cinematics/EventTrack.h | 2 +- .../Code/Source/Cinematics/GotoTrack.cpp | 44 ++-- .../Code/Source/Cinematics/GotoTrack.h | 2 +- .../Code/Source/Cinematics/LayerNode.cpp | 9 +- .../Code/Source/Cinematics/LayerNode.h | 2 +- .../Code/Source/Cinematics/LookAtTrack.cpp | 46 +++-- .../Code/Source/Cinematics/LookAtTrack.h | 2 +- .../Code/Source/Cinematics/MaterialNode.cpp | 9 +- .../Code/Source/Cinematics/MaterialNode.h | 2 +- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 13 +- Gems/Maestro/Code/Source/Cinematics/Movie.h | 2 +- .../Code/Source/Cinematics/SceneNode.cpp | 9 +- .../Code/Source/Cinematics/SceneNode.h | 2 +- .../Source/Cinematics/ScreenFaderTrack.cpp | 44 ++-- .../Code/Source/Cinematics/ScreenFaderTrack.h | 2 +- .../Code/Source/Cinematics/ScriptVarNode.cpp | 9 +- .../Code/Source/Cinematics/ScriptVarNode.h | 2 +- .../Code/Source/Cinematics/SelectTrack.cpp | 44 ++-- .../Code/Source/Cinematics/SelectTrack.h | 2 +- .../Code/Source/Cinematics/SequenceTrack.cpp | 44 ++-- .../Code/Source/Cinematics/SequenceTrack.h | 2 +- .../Source/Cinematics/ShadowsSetupNode.cpp | 11 +- .../Code/Source/Cinematics/ShadowsSetupNode.h | 2 +- .../Code/Source/Cinematics/SoundTrack.cpp | 42 ++-- .../Code/Source/Cinematics/SoundTrack.h | 2 +- .../Source/Cinematics/TimeRangesTrack.cpp | 42 ++-- .../Code/Source/Cinematics/TimeRangesTrack.h | 3 +- .../Source/Cinematics/TrackEventTrack.cpp | 42 ++-- .../Code/Source/Cinematics/TrackEventTrack.h | 2 +- .../Source/Components/SequenceComponent.cpp | 19 +- .../Source/Components/SequenceComponent.h | 2 +- 73 files changed, 801 insertions(+), 442 deletions(-) diff --git a/Code/CryEngine/CryCommon/IMovieSystem.h b/Code/CryEngine/CryCommon/IMovieSystem.h index 7a1125ae2b..c22394e1b3 100644 --- a/Code/CryEngine/CryCommon/IMovieSystem.h +++ b/Code/CryEngine/CryCommon/IMovieSystem.h @@ -327,7 +327,16 @@ struct IMovieCallback */ struct IAnimTrack { - AZ_RTTI(IAnimTrack, "{AA0D5170-FB28-426F-BA13-7EFF6BB3AC67}") + AZ_RTTI(IAnimTrack, "{AA0D5170-FB28-426F-BA13-7EFF6BB3AC67}"); + AZ_CLASS_ALLOCATOR(IAnimTrack, AZ::SystemAllocator, 0); + + static void Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<IAnimTrack>(); + } + } //! Flags that can be set on animation track. enum EAnimTrackFlags @@ -594,7 +603,16 @@ struct IAnimNodeOwner struct IAnimNode { public: - AZ_RTTI(IAnimNode, "{0A096354-7F26-4B18-B8C0-8F10A3E0440A}") + AZ_RTTI(IAnimNode, "{0A096354-7F26-4B18-B8C0-8F10A3E0440A}"); + AZ_CLASS_ALLOCATOR(IAnimNode, AZ::SystemAllocator, 0); + + static void Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<IAnimNode>(); + } + } ////////////////////////////////////////////////////////////////////////// // Supported params. @@ -922,7 +940,7 @@ struct IAnimSequence static void Reflect(AZ::ReflectContext* context) { - if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr) + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { serializeContext->Class<IAnimSequence>(); } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.cpp index 0fdcca5e2d..b0ebb10b0e 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.cpp @@ -88,11 +88,14 @@ void CAnimAzEntityNode::SetSkipInterpolatedCameraNode(const bool skipNodeCameraA } ////////////////////////////////////////////////////////////////////////// -void CAnimAzEntityNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimAzEntityNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimAzEntityNode, CAnimNode>() - ->Version(1) - ->Field("Entity", &CAnimAzEntityNode::m_entityId); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimAzEntityNode, CAnimNode>() + ->Version(1) + ->Field("Entity", &CAnimAzEntityNode::m_entityId); + } } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h index 2a3264f381..863d0e927f 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimAZEntityNode.h @@ -74,7 +74,7 @@ public: // will be animating these components during interpolation. void SetSkipInterpolatedCameraNode(const bool skipNodeCameraAnimation) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.cpp index d66d0f266f..ea7322014c 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.cpp @@ -651,12 +651,15 @@ void CAnimComponentNode::AddPropertyToParamInfoMap(const CAnimParamType& paramTy } ////////////////////////////////////////////////////////////////////////// -void CAnimComponentNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimComponentNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimComponentNode, CAnimNode>() - ->Version(1) - ->Field("ComponentID", &CAnimComponentNode::m_componentId) - ->Field("ComponentTypeID", &CAnimComponentNode::m_componentTypeId); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimComponentNode, CAnimNode>() + ->Version(1) + ->Field("ComponentID", &CAnimComponentNode::m_componentId) + ->Field("ComponentTypeID", &CAnimComponentNode::m_componentTypeId); + } } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h index d519a9ba96..5d83f7ba0d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimComponentNode.h @@ -102,7 +102,7 @@ public: m_skipComponentAnimationUpdates = skipAnimationUpdates; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: // functions involved in the process to parse and store component behavior context animated properties diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.cpp index 8ee5f605aa..7996cc8c65 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.cpp @@ -67,10 +67,13 @@ void CAnimEnvironmentNode::Initialize() } } ////////////////////////////////////////////////////////////////////////// -void CAnimEnvironmentNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimEnvironmentNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimEnvironmentNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimEnvironmentNode, CAnimNode>() + ->Version(1); + } } void CAnimEnvironmentNode::Animate(SAnimContext& ac) diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.h index 1a92e4d30d..9287ce4cdd 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimEnvironmentNode.h @@ -40,7 +40,7 @@ public: virtual unsigned int GetParamCount() const; virtual CAnimParamType GetParamType(unsigned int nIndex) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimNode.cpp index 25215e348d..ef346bd230 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimNode.cpp @@ -272,17 +272,32 @@ bool CAnimNode::RemoveTrack(IAnimTrack* pTrack) } ////////////////////////////////////////////////////////////////////////// -void CAnimNode::Reflect(AZ::SerializeContext* serializeContext) +static bool AnimNodeVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) { - serializeContext->Class<CAnimNode>() - ->Version(2) - ->Field("ID", &CAnimNode::m_id) - ->Field("Name", &CAnimNode::m_name) - ->Field("Flags", &CAnimNode::m_flags) - ->Field("Tracks", &CAnimNode::m_tracks) - ->Field("Parent", &CAnimNode::m_parentNodeId) - ->Field("Type", &CAnimNode::m_nodeType) - ->Field("Expanded", &CAnimNode::m_expanded); + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimNode>()); + } + + return true; +} + +void CAnimNode::Reflect(AZ::ReflectContext* context) +{ + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimNode, IAnimNode>() + ->Version(3, &AnimNodeVersionConverter) + ->Field("ID", &CAnimNode::m_id) + ->Field("Name", &CAnimNode::m_name) + ->Field("Flags", &CAnimNode::m_flags) + ->Field("Tracks", &CAnimNode::m_tracks) + ->Field("Parent", &CAnimNode::m_parentNodeId) + ->Field("Type", &CAnimNode::m_nodeType) + ->Field("Expanded", &CAnimNode::m_expanded); + } } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimNode.h index 4df5e692d0..0c52ac5a48 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimNode.h @@ -162,7 +162,7 @@ public: void SetExpanded(bool expanded) override; bool GetExpanded() const override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual void UpdateDynamicParamsInternal() {}; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.cpp index 05ba8309b1..1a177b6dc0 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.cpp @@ -36,8 +36,11 @@ CAnimParamType CAnimNodeGroup::GetParamType([[maybe_unused]] unsigned int nIndex } ////////////////////////////////////////////////////////////////////////// -void CAnimNodeGroup::Reflect(AZ::SerializeContext* serializeContext) +void CAnimNodeGroup::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimNodeGroup, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimNodeGroup, CAnimNode>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.h b/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.h index 66ffeea570..fcb18c448a 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimNodeGroup.h @@ -34,7 +34,7 @@ public: virtual CAnimParamType GetParamType(unsigned int nIndex) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; -#endif // CRYINCLUDE_CRYMOVIE_ANIMNODEGROUP_H \ No newline at end of file +#endif // CRYINCLUDE_CRYMOVIE_ANIMNODEGROUP_H diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp index d42a5d948e..f94022af89 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp @@ -453,8 +453,11 @@ void CAnimPostFXNode::OnReset() } ////////////////////////////////////////////////////////////////////////// -void CAnimPostFXNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimPostFXNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimPostFXNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimPostFXNode, CAnimNode>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h index 38bcffd20b..2f332aa7c2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.h @@ -63,7 +63,7 @@ public: void InitPostLoad(IAnimSequence* sequence) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.cpp index bc5f0597a7..ba30c3de39 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.cpp @@ -291,10 +291,13 @@ void CAnimScreenFaderNode::Serialize } ////////////////////////////////////////////////////////////////////////// -void CAnimScreenFaderNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimScreenFaderNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimScreenFaderNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimScreenFaderNode, CAnimNode>() + ->Version(1); + } } //----------------------------------------------------------------------------- diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h index c67febe983..eb77385ba3 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimScreenFaderNode.h @@ -56,7 +56,7 @@ public: bool IsAnyTextureVisible() const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp index ffbdce8ed6..9145b18380 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSequence.cpp @@ -837,9 +837,7 @@ static bool AnimSequenceVersionConverter( void CAnimSequence::Reflect(AZ::ReflectContext* context) { - IAnimSequence::Reflect(context); - - if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr) + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { serializeContext->Class<CAnimSequence, IAnimSequence>() ->Version(IAnimSequence::kSequenceVersion, &AnimSequenceVersionConverter) diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.cpp index 1c60c23b51..81281b27df 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.cpp @@ -17,101 +17,104 @@ #include "AnimSerializer.h" -void AnimSerializer::ReflectAnimTypes(AZ::SerializeContext* context) +void AnimSerializer::ReflectAnimTypes(AZ::ReflectContext* context) { - // Reflection for Maestro's AZ_TYPE_INFO'ed classes - context->Class<CAnimParamType>() - ->Version(1) - ->Field("Type", &CAnimParamType::m_type) - ->Field("Name", &CAnimParamType::m_name); - - context->Class<Range>() - ->Field("Start", &Range::start) - ->Field("End", &Range::end); - - // Curve Key classes - context->Class<IKey>() - ->Field("Time", &IKey::time) - ->Field("Flags", &IKey::flags); - - context->Class<AZ::IAssetBlendKey, ITimeRangeKey>() - ->Field("AssetId", &AZ::IAssetBlendKey::m_assetId) - ->Field("Description", &AZ::IAssetBlendKey::m_description) - ->Field("BlendInTime", &AZ::IAssetBlendKey::m_blendInTime) - ->Field("BlendOutTime", &AZ::IAssetBlendKey::m_blendOutTime); - - context->Class<IBoolKey, IKey>(); - - context->Class<ICaptureKey, IKey>() - ->Field("Duration", &ICaptureKey::duration) - ->Field("TimeStep", &ICaptureKey::timeStep) - ->Field("Folder", &ICaptureKey::folder) - ->Field("Once", &ICaptureKey::once) - ->Field("FilePrefix", &ICaptureKey::prefix); - - context->Class<ICharacterKey, ITimeRangeKey>() - ->Field("Animation", &ICharacterKey::m_animation) - ->Field("BlendGap", &ICharacterKey::m_bBlendGap) - ->Field("PlayInPlace", &ICharacterKey::m_bInPlace); - - context->Class<ICommentKey, IKey>() - ->Field("Comment", &ICommentKey::m_strComment) - ->Field("Duration", &ICommentKey::m_duration) - ->Field("Font", &ICommentKey::m_strFont) - ->Field("Color", &ICommentKey::m_color) - ->Field("Size", &ICommentKey::m_size) - ->Field("Align", &ICommentKey::m_align); - - context->Class<IConsoleKey, IKey>() - ->Field("Command", &IConsoleKey::command); - - context->Class<IDiscreteFloatKey, IKey>() - ->Field("Value", &IDiscreteFloatKey::m_fValue); - - context->Class<IEventKey, IKey>() - ->Field("Event", &IEventKey::event) - ->Field("EventValue", &IEventKey::eventValue) - ->Field("Anim", &IEventKey::animation) - ->Field("Target", &IEventKey::target) - ->Field("Length", &IEventKey::duration); - - context->Class<ILookAtKey, IKey>() - ->Field("LookAtNodeName", &ILookAtKey::szSelection) - ->Field("LookPose", &ILookAtKey::lookPose) - ->Field("Duration", &ILookAtKey::fDuration) - ->Field("SmoothTime", &ILookAtKey::smoothTime); - - context->Class<IScreenFaderKey, IKey>() - ->Field("FadeTime", &IScreenFaderKey::m_fadeTime) - ->Field("FadeColor", &IScreenFaderKey::m_fadeColor) - ->Field("FadeType", &IScreenFaderKey::m_fadeType) - ->Field("FadeChangeType", &IScreenFaderKey::m_fadeChangeType) - ->Field("Texture", &IScreenFaderKey::m_strTexture) - ->Field("useCurColor", &IScreenFaderKey::m_bUseCurColor); - - context->Class<ISelectKey, IKey>() - ->Field("SelectedName", &ISelectKey::szSelection) - ->Field("SelectedEntityId", &ISelectKey::cameraAzEntityId) - ->Field("Duration", &ISelectKey::fDuration) - ->Field("BlendTime", &ISelectKey::fBlendTime); - - context->Class<ISequenceKey, IKey>() - ->Field("Node", &ISequenceKey::szSelection) - ->Field("SequenceEntityId", &ISequenceKey::sequenceEntityId) - ->Field("OverrideTimes", &ISequenceKey::bOverrideTimes) - ->Field("StartTime", &ISequenceKey::fStartTime) - ->Field("EndTime", &ISequenceKey::fEndTime); - - context->Class<ISoundKey, IKey>() - ->Field("StartTrigger", &ISoundKey::sStartTrigger) - ->Field("StopTrigger", &ISoundKey::sStopTrigger) - ->Field("Duration", &ISoundKey::fDuration) - ->Field("Color", &ISoundKey::customColor); - - context->Class<ITimeRangeKey, IKey>() - ->Field("Duration", &ITimeRangeKey::m_duration) - ->Field("Start", &ITimeRangeKey::m_startTime) - ->Field("End", &ITimeRangeKey::m_endTime) - ->Field("Speed", &ITimeRangeKey::m_speed) - ->Field("Loop", &ITimeRangeKey::m_bLoop); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext != nullptr) + { + // Reflection for Maestro's AZ_TYPE_INFO'ed classes + serializeContext->Class<CAnimParamType>() + ->Version(1) + ->Field("Type", &CAnimParamType::m_type) + ->Field("Name", &CAnimParamType::m_name); + + serializeContext->Class<Range>() + ->Field("Start", &Range::start) + ->Field("End", &Range::end); + + // Curve Key classes + serializeContext->Class<IKey>() + ->Field("Time", &IKey::time) + ->Field("Flags", &IKey::flags); + + serializeContext->Class<AZ::IAssetBlendKey, ITimeRangeKey>() + ->Field("AssetId", &AZ::IAssetBlendKey::m_assetId) + ->Field("Description", &AZ::IAssetBlendKey::m_description) + ->Field("BlendInTime", &AZ::IAssetBlendKey::m_blendInTime) + ->Field("BlendOutTime", &AZ::IAssetBlendKey::m_blendOutTime); + + serializeContext->Class<IBoolKey, IKey>(); + + serializeContext->Class<ICaptureKey, IKey>() + ->Field("Duration", &ICaptureKey::duration) + ->Field("TimeStep", &ICaptureKey::timeStep) + ->Field("Folder", &ICaptureKey::folder) + ->Field("Once", &ICaptureKey::once) + ->Field("FilePrefix", &ICaptureKey::prefix); + + serializeContext->Class<ICharacterKey, ITimeRangeKey>() + ->Field("Animation", &ICharacterKey::m_animation) + ->Field("BlendGap", &ICharacterKey::m_bBlendGap) + ->Field("PlayInPlace", &ICharacterKey::m_bInPlace); + + serializeContext->Class<ICommentKey, IKey>() + ->Field("Comment", &ICommentKey::m_strComment) + ->Field("Duration", &ICommentKey::m_duration) + ->Field("Font", &ICommentKey::m_strFont) + ->Field("Color", &ICommentKey::m_color) + ->Field("Size", &ICommentKey::m_size) + ->Field("Align", &ICommentKey::m_align); + + serializeContext->Class<IConsoleKey, IKey>() + ->Field("Command", &IConsoleKey::command); + + serializeContext->Class<IDiscreteFloatKey, IKey>() + ->Field("Value", &IDiscreteFloatKey::m_fValue); + + serializeContext->Class<IEventKey, IKey>() + ->Field("Event", &IEventKey::event) + ->Field("EventValue", &IEventKey::eventValue) + ->Field("Anim", &IEventKey::animation) + ->Field("Target", &IEventKey::target) + ->Field("Length", &IEventKey::duration); + + serializeContext->Class<ILookAtKey, IKey>() + ->Field("LookAtNodeName", &ILookAtKey::szSelection) + ->Field("LookPose", &ILookAtKey::lookPose) + ->Field("Duration", &ILookAtKey::fDuration) + ->Field("SmoothTime", &ILookAtKey::smoothTime); + + serializeContext->Class<IScreenFaderKey, IKey>() + ->Field("FadeTime", &IScreenFaderKey::m_fadeTime) + ->Field("FadeColor", &IScreenFaderKey::m_fadeColor) + ->Field("FadeType", &IScreenFaderKey::m_fadeType) + ->Field("FadeChangeType", &IScreenFaderKey::m_fadeChangeType) + ->Field("Texture", &IScreenFaderKey::m_strTexture) + ->Field("useCurColor", &IScreenFaderKey::m_bUseCurColor); + + serializeContext->Class<ISelectKey, IKey>() + ->Field("SelectedName", &ISelectKey::szSelection) + ->Field("SelectedEntityId", &ISelectKey::cameraAzEntityId) + ->Field("Duration", &ISelectKey::fDuration) + ->Field("BlendTime", &ISelectKey::fBlendTime); + + serializeContext->Class<ISequenceKey, IKey>() + ->Field("Node", &ISequenceKey::szSelection) + ->Field("SequenceEntityId", &ISequenceKey::sequenceEntityId) + ->Field("OverrideTimes", &ISequenceKey::bOverrideTimes) + ->Field("StartTime", &ISequenceKey::fStartTime) + ->Field("EndTime", &ISequenceKey::fEndTime); + + serializeContext->Class<ISoundKey, IKey>() + ->Field("StartTrigger", &ISoundKey::sStartTrigger) + ->Field("StopTrigger", &ISoundKey::sStopTrigger) + ->Field("Duration", &ISoundKey::fDuration) + ->Field("Color", &ISoundKey::customColor); + + serializeContext->Class<ITimeRangeKey, IKey>() + ->Field("Duration", &ITimeRangeKey::m_duration) + ->Field("Start", &ITimeRangeKey::m_startTime) + ->Field("End", &ITimeRangeKey::m_endTime) + ->Field("Speed", &ITimeRangeKey::m_speed) + ->Field("Loop", &ITimeRangeKey::m_bLoop); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.h b/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.h index bc9b2269ee..3242970cad 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSerializer.h @@ -11,11 +11,11 @@ */ #pragma once -#include <AzCore/Serialization/SerializeContext.h> +#include <AzCore/RTTI/ReflectContext.h> class AnimSerializer { public: //! Reflection for Maestro's AZ_TYPE_INFO'ed classes - static void ReflectAnimTypes(AZ::SerializeContext* context); + static void ReflectAnimTypes(AZ::ReflectContext* context); }; diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h index 0bd2f24ad8..02ed7aa55a 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack.h @@ -370,7 +370,7 @@ public: m_id = id; } - static void Reflect(AZ::SerializeContext* serializeContext) {} + static void Reflect([[maybe_unused]] AZ::ReflectContext* context) {} protected: diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack_Vec2Specialization.h b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack_Vec2Specialization.h index 83ba4b00c3..bc85c6b6f4 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack_Vec2Specialization.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimSplineTrack_Vec2Specialization.h @@ -404,34 +404,39 @@ inline bool TAnimSplineTrack<Vec2>::VersionConverter(AZ::SerializeContext& conte AZ::SerializeContext::DataElementNode& classElement) { bool result = true; - if (classElement.GetVersion() == 1) + if (classElement.GetVersion() < 5) { - bool converted = false; + classElement.AddElement(context, "BaseClass1", azrtti_typeid<IAnimTrack>()); - int splineElementIdx = classElement.FindElement(AZ_CRC("Spline", 0x35f655e9)); - if (splineElementIdx != -1) + if (classElement.GetVersion() == 1) { - // Find & copy the raw pointer node - AZ::SerializeContext::DataElementNode& splinePtrNodeRef = classElement.GetSubElement(splineElementIdx); - AZ::SerializeContext::DataElementNode splinePtrNodeCopy = splinePtrNodeRef; + bool converted = false; - // Reset the node, then convert it to an intrusive pointer - splinePtrNodeRef = AZ::SerializeContext::DataElementNode(); - if (splinePtrNodeRef.Convert<AZStd::intrusive_ptr<spline::TrackSplineInterpolator<Vec2>>>(context, "Spline")) + int splineElementIdx = classElement.FindElement(AZ_CRC("Spline", 0x35f655e9)); + if (splineElementIdx != -1) { - // Use the standard name used with the smart pointers serialization - // (smart pointers are serialized as containers with one element); - // Set the intrusive pointer to the raw pointer value - splinePtrNodeCopy.SetName(AZ::SerializeContext::IDataContainer::GetDefaultElementName()); - splinePtrNodeRef.AddElement(splinePtrNodeCopy); + // Find & copy the raw pointer node + AZ::SerializeContext::DataElementNode& splinePtrNodeRef = classElement.GetSubElement(splineElementIdx); + AZ::SerializeContext::DataElementNode splinePtrNodeCopy = splinePtrNodeRef; - converted = true; + // Reset the node, then convert it to an intrusive pointer + splinePtrNodeRef = AZ::SerializeContext::DataElementNode(); + if (splinePtrNodeRef.Convert<AZStd::intrusive_ptr<spline::TrackSplineInterpolator<Vec2>>>(context, "Spline")) + { + // Use the standard name used with the smart pointers serialization + // (smart pointers are serialized as containers with one element); + // Set the intrusive pointer to the raw pointer value + splinePtrNodeCopy.SetName(AZ::SerializeContext::IDataContainer::GetDefaultElementName()); + splinePtrNodeRef.AddElement(splinePtrNodeCopy); + + converted = true; + } } - } - // Did not convert. Discard unknown versions if failed to convert, and hope for the best - AZ_Assert(converted, "Failed to convert TUiAnimSplineTrack<Vec2> version %d to the current version", classElement.GetVersion()); - result = converted; + // Did not convert. Discard unknown versions if failed to convert, and hope for the best + AZ_Assert(converted, "Failed to convert TUiAnimSplineTrack<Vec2> version %d to the current version", classElement.GetVersion()); + result = converted; + } } return result; @@ -439,31 +444,34 @@ inline bool TAnimSplineTrack<Vec2>::VersionConverter(AZ::SerializeContext& conte ////////////////////////////////////////////////////////////////////////// template<> -inline void TAnimSplineTrack<Vec2>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimSplineTrack<Vec2>::Reflect(AZ::ReflectContext* context) { - spline::SplineKey<Vec2>::Reflect(serializeContext); - spline::SplineKeyEx<Vec2>::Reflect(serializeContext); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + spline::SplineKey<Vec2>::Reflect(serializeContext); + spline::SplineKeyEx<Vec2>::Reflect(serializeContext); - spline::TrackSplineInterpolator<Vec2>::Reflect(serializeContext); - BezierSplineVec2::Reflect(serializeContext); + spline::TrackSplineInterpolator<Vec2>::Reflect(serializeContext); + BezierSplineVec2::Reflect(serializeContext); - serializeContext->Class<TAnimSplineTrack<Vec2> >() - ->Version(4, &TAnimSplineTrack<Vec2>::VersionConverter) - ->Field("Flags", &TAnimSplineTrack<Vec2>::m_flags) - ->Field("DefaultValue", &TAnimSplineTrack<Vec2>::m_defaultValue) - ->Field("ParamType", &TAnimSplineTrack<Vec2>::m_nParamType) - ->Field("Spline", &TAnimSplineTrack<Vec2>::m_spline) - ->Field("Id", &TAnimSplineTrack<Vec2>::m_id); + serializeContext->Class<TAnimSplineTrack<Vec2>, IAnimTrack>() + ->Version(5, &TAnimSplineTrack<Vec2>::VersionConverter) + ->Field("Flags", &TAnimSplineTrack<Vec2>::m_flags) + ->Field("DefaultValue", &TAnimSplineTrack<Vec2>::m_defaultValue) + ->Field("ParamType", &TAnimSplineTrack<Vec2>::m_nParamType) + ->Field("Spline", &TAnimSplineTrack<Vec2>::m_spline) + ->Field("Id", &TAnimSplineTrack<Vec2>::m_id); - AZ::EditContext* ec = serializeContext->GetEditContext(); + AZ::EditContext* ec = serializeContext->GetEditContext(); - // Preventing the default value from being pushed to slice to keep it from dirtying the slice when updated internally - if (ec) - { - ec->Class<TAnimSplineTrack<Vec2>>("TAnimSplineTrack Vec2", "Specialization track for Vec2 AnimSpline")-> - DataElement(AZ::Edit::UIHandlers::Vector2, &TAnimSplineTrack<Vec2>::m_defaultValue, "DefaultValue", "")-> + // Preventing the default value from being pushed to slice to keep it from dirtying the slice when updated internally + if (ec) + { + ec->Class<TAnimSplineTrack<Vec2>>("TAnimSplineTrack Vec2", "Specialization track for Vec2 AnimSpline")-> + DataElement(AZ::Edit::UIHandlers::Vector2, &TAnimSplineTrack<Vec2>::m_defaultValue, "DefaultValue", "")-> Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Hide)-> Attribute(AZ::Edit::Attributes::SliceFlags, AZ::Edit::SliceFlags::NotPushable); + } } } #endif // CRYINCLUDE_CRYMOVIE_ANIMSPLINETRACK_VEC2SPECIALIZATION_H diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h b/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h index d8a644e671..24c78f5a1b 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AnimTrack.h @@ -249,7 +249,7 @@ public: m_id = id; } - static void Reflect([[maybe_unused]] AZ::SerializeContext* serializeContext) {} + static void Reflect([[maybe_unused]] AZ::ReflectContext* context) {} protected: void CheckValid() diff --git a/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.cpp index b619d3877f..ee3b6a64c2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.cpp @@ -163,16 +163,31 @@ float CAssetBlendTrack::GetKeyDuration(int key) const } ////////////////////////////////////////////////////////////////////////// +static bool AssetBlendTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<AZ::IAssetBlendKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<AZ::IAssetBlendKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<AZ::IAssetBlendKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<AZ::IAssetBlendKey>::m_flags) - ->Field("Range", &TAnimTrack<AZ::IAssetBlendKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<AZ::IAssetBlendKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<AZ::IAssetBlendKey>::m_keys) - ->Field("Id", &TAnimTrack<AZ::IAssetBlendKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<AZ::IAssetBlendKey>, IAnimTrack>() + ->Version(3, &AssetBlendTrackVersionConverter) + ->Field("Flags", &TAnimTrack<AZ::IAssetBlendKey>::m_flags) + ->Field("Range", &TAnimTrack<AZ::IAssetBlendKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<AZ::IAssetBlendKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<AZ::IAssetBlendKey>::m_keys) + ->Field("Id", &TAnimTrack<AZ::IAssetBlendKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// @@ -277,10 +292,13 @@ float CAssetBlendTrack::GetEndTime() const } ////////////////////////////////////////////////////////////////////////// -void CAssetBlendTrack::Reflect(AZ::SerializeContext* serializeContext) +void CAssetBlendTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<AZ::IAssetBlendKey>::Reflect(serializeContext); + TAnimTrack<AZ::IAssetBlendKey>::Reflect(context); - serializeContext->Class<CAssetBlendTrack, TAnimTrack<AZ::IAssetBlendKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAssetBlendTrack, TAnimTrack<AZ::IAssetBlendKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.h b/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.h index a14e66463e..e676fdf05b 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/AssetBlendTrack.h @@ -47,7 +47,7 @@ public: float GetEndTime() const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: diff --git a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.cpp index adfbba312d..e485d022b2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.cpp @@ -98,24 +98,42 @@ bool CBoolTrack::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTr } ////////////////////////////////////////////////////////////////////////// +static bool BoolTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<IBoolKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<IBoolKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<IBoolKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<IBoolKey>::m_flags) - ->Field("Range", &TAnimTrack<IBoolKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<IBoolKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<IBoolKey>::m_keys) - ->Field("Id", &TAnimTrack<IBoolKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<IBoolKey>, IAnimTrack>() + ->Version(3, &BoolTrackVersionConverter) + ->Field("Flags", &TAnimTrack<IBoolKey>::m_flags) + ->Field("Range", &TAnimTrack<IBoolKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<IBoolKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<IBoolKey>::m_keys) + ->Field("Id", &TAnimTrack<IBoolKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CBoolTrack::Reflect(AZ::SerializeContext* serializeContext) +void CBoolTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IBoolKey>::Reflect(serializeContext); + TAnimTrack<IBoolKey>::Reflect(context); - serializeContext->Class<CBoolTrack, TAnimTrack<IBoolKey> >() - ->Version(1) - ->Field("DefaultValue", &CBoolTrack::m_bDefaultValue); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CBoolTrack, TAnimTrack<IBoolKey>>() + ->Version(1) + ->Field("DefaultValue", &CBoolTrack::m_bDefaultValue); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h index 5a69706967..d374aad5db 100644 --- a/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/BoolTrack.h @@ -45,7 +45,7 @@ public: bool Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks = true) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: bool m_bDefaultValue; diff --git a/Gems/Maestro/Code/Source/Cinematics/CVarNode.cpp b/Gems/Maestro/Code/Source/Cinematics/CVarNode.cpp index 20b0bae527..2d27feec95 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CVarNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CVarNode.cpp @@ -151,8 +151,11 @@ void CAnimCVarNode::Animate(SAnimContext& ec) } ////////////////////////////////////////////////////////////////////////// -void CAnimCVarNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimCVarNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimCVarNode,CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimCVarNode, CAnimNode>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/CVarNode.h b/Gems/Maestro/Code/Source/Cinematics/CVarNode.h index 63b1fb46f8..7a1b578238 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CVarNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/CVarNode.h @@ -41,7 +41,7 @@ public: int GetDefaultKeyTangentFlags() const override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp index 1a9df2baa7..c627343914 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.cpp @@ -71,23 +71,41 @@ void CCaptureTrack::GetKeyInfo(int key, const char*& description, float& duratio } ////////////////////////////////////////////////////////////////////////// +static bool CaptureTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ICaptureKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ICaptureKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ICaptureKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ICaptureKey>::m_flags) - ->Field("Range", &TAnimTrack<ICaptureKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ICaptureKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ICaptureKey>::m_keys) - ->Field("Id", &TAnimTrack<ICaptureKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ICaptureKey>, IAnimTrack>() + ->Version(3, &CaptureTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ICaptureKey>::m_flags) + ->Field("Range", &TAnimTrack<ICaptureKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ICaptureKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ICaptureKey>::m_keys) + ->Field("Id", &TAnimTrack<ICaptureKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CCaptureTrack::Reflect(AZ::SerializeContext* serializeContext) +void CCaptureTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ICaptureKey>::Reflect(serializeContext); + TAnimTrack<ICaptureKey>::Reflect(context); - serializeContext->Class<CCaptureTrack, TAnimTrack<ICaptureKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CCaptureTrack, TAnimTrack<ICaptureKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.h b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.h index c4f15f65ae..cee5f5137d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/CaptureTrack.h @@ -33,7 +33,7 @@ public: void SerializeKey(ICaptureKey& key, XmlNodeRef& keyNode, bool bLoading); void GetKeyInfo(int key, const char*& description, float& duration); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_CAPTURETRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.cpp index 9c54069d4c..4ad6cbb24a 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.cpp @@ -150,16 +150,31 @@ float CCharacterTrack::GetKeyDuration(int key) const } ////////////////////////////////////////////////////////////////////////// +static bool CharacterTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ICharacterKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ICharacterKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ICharacterKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ICharacterKey>::m_flags) - ->Field("Range", &TAnimTrack<ICharacterKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ICharacterKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ICharacterKey>::m_keys) - ->Field("Id", &TAnimTrack<ICharacterKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ICharacterKey>, IAnimTrack>() + ->Version(3, &CharacterTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ICharacterKey>::m_flags) + ->Field("Range", &TAnimTrack<ICharacterKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ICharacterKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ICharacterKey>::m_keys) + ->Field("Id", &TAnimTrack<ICharacterKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// @@ -169,11 +184,14 @@ AnimValueType CCharacterTrack::GetValueType() } ////////////////////////////////////////////////////////////////////////// -void CCharacterTrack::Reflect(AZ::SerializeContext* serializeContext) +void CCharacterTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ICharacterKey>::Reflect(serializeContext); + TAnimTrack<ICharacterKey>::Reflect(context); - serializeContext->Class<CCharacterTrack, TAnimTrack<ICharacterKey> >() - ->Version(1) - ->Field("AnimationLayer", &CCharacterTrack::m_iAnimationLayer); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CCharacterTrack, TAnimTrack<ICharacterKey>>() + ->Version(1) + ->Field("AnimationLayer", &CCharacterTrack::m_iAnimationLayer); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.h b/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.h index d95d648318..ccfb2f87c2 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/CharacterTrack.h @@ -51,7 +51,7 @@ public: float GetEndTime() const { return m_timeRange.end; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: int m_iAnimationLayer; diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentNode.cpp b/Gems/Maestro/Code/Source/Cinematics/CommentNode.cpp index c052d7dd04..a519de18f7 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CommentNode.cpp @@ -107,10 +107,13 @@ void CCommentNode::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmpty } ////////////////////////////////////////////////////////////////////////// -void CCommentNode::Reflect(AZ::SerializeContext* serializeContext) +void CCommentNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CCommentNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CCommentNode, CAnimNode>() + ->Version(1); + } } //----------------------------------------------------------------------------- diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentNode.h b/Gems/Maestro/Code/Source/Cinematics/CommentNode.h index a0d62903f6..1fc46817ff 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/CommentNode.h @@ -49,7 +49,7 @@ public: virtual unsigned int GetParamCount() const; virtual CAnimParamType GetParamType(unsigned int nIndex) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp index 981b98de01..3f64433dbb 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.cpp @@ -78,23 +78,41 @@ void CCommentTrack::SerializeKey(ICommentKey& key, XmlNodeRef& keyNode, bool bLo ////////////////////////////////////////////////////////////////////////// +static bool CommentTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ICommentKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ICommentKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ICommentKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ICommentKey>::m_flags) - ->Field("Range", &TAnimTrack<ICommentKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ICommentKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ICommentKey>::m_keys) - ->Field("Id", &TAnimTrack<ICommentKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ICommentKey>, IAnimTrack>() + ->Version(3, &CommentTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ICommentKey>::m_flags) + ->Field("Range", &TAnimTrack<ICommentKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ICommentKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ICommentKey>::m_keys) + ->Field("Id", &TAnimTrack<ICommentKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CCommentTrack::Reflect(AZ::SerializeContext* serializeContext) +void CCommentTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ICommentKey>::Reflect(serializeContext); + TAnimTrack<ICommentKey>::Reflect(context); - serializeContext->Class<CCommentTrack, TAnimTrack<ICommentKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CCommentTrack, TAnimTrack<ICommentKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.h b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.h index 9ae370e58d..2db786b72d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CommentTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/CommentTrack.h @@ -40,7 +40,7 @@ public: //! void ValidateKeyOrder() { CheckValid(); } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_COMMENTTRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp index 002a370c61..c1aab0060f 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.cpp @@ -604,16 +604,31 @@ void CCompoundSplineTrack::SetId(unsigned int id) } ////////////////////////////////////////////////////////////////////////// -void CCompoundSplineTrack::Reflect(AZ::SerializeContext* serializeContext) -{ - serializeContext->Class<CCompoundSplineTrack>() - ->Version(3) - ->Field("Flags", &CCompoundSplineTrack::m_flags) - ->Field("ParamType", &CCompoundSplineTrack::m_nParamType) - ->Field("NumSubTracks", &CCompoundSplineTrack::m_nDimensions) - ->Field("SubTracks", &CCompoundSplineTrack::m_subTracks) - ->Field("SubTrackNames", &CCompoundSplineTrack::m_subTrackNames) - ->Field("ValueType", &CCompoundSplineTrack::m_valueType) - ->Field("Expanded", &CCompoundSplineTrack::m_expanded) - ->Field("Id", &CCompoundSplineTrack::m_id); +static bool CompoundSplineTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 4) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + +void CCompoundSplineTrack::Reflect(AZ::ReflectContext* context) +{ + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CCompoundSplineTrack, IAnimTrack>() + ->Version(4, &CompoundSplineTrackVersionConverter) + ->Field("Flags", &CCompoundSplineTrack::m_flags) + ->Field("ParamType", &CCompoundSplineTrack::m_nParamType) + ->Field("NumSubTracks", &CCompoundSplineTrack::m_nDimensions) + ->Field("SubTracks", &CCompoundSplineTrack::m_subTracks) + ->Field("SubTrackNames", &CCompoundSplineTrack::m_subTrackNames) + ->Field("ValueType", &CCompoundSplineTrack::m_valueType) + ->Field("Expanded", &CCompoundSplineTrack::m_expanded) + ->Field("Id", &CCompoundSplineTrack::m_id); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h index 642d9fa4e0..63b76631ab 100644 --- a/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/CompoundSplineTrack.h @@ -157,7 +157,7 @@ public: unsigned int GetId() const override; void SetId(unsigned int id) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: int m_refCount; diff --git a/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.cpp index fce49f0bd4..03c3eef634 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.cpp @@ -47,23 +47,41 @@ void CConsoleTrack::GetKeyInfo(int key, const char*& description, float& duratio } ////////////////////////////////////////////////////////////////////////// +static bool ConsoleTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<IConsoleKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<IConsoleKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<IConsoleKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<IConsoleKey>::m_flags) - ->Field("Range", &TAnimTrack<IConsoleKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<IConsoleKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<IConsoleKey>::m_keys) - ->Field("Id", &TAnimTrack<IConsoleKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<IConsoleKey>, IAnimTrack>() + ->Version(3, &ConsoleTrackVersionConverter) + ->Field("Flags", &TAnimTrack<IConsoleKey>::m_flags) + ->Field("Range", &TAnimTrack<IConsoleKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<IConsoleKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<IConsoleKey>::m_keys) + ->Field("Id", &TAnimTrack<IConsoleKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CConsoleTrack::Reflect(AZ::SerializeContext* serializeContext) +void CConsoleTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IConsoleKey>::Reflect(serializeContext); + TAnimTrack<IConsoleKey>::Reflect(context); - serializeContext->Class<CConsoleTrack, TAnimTrack<IConsoleKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CConsoleTrack, TAnimTrack<IConsoleKey> >() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.h b/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.h index c9ef0e3c4e..854ebacbaa 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/ConsoleTrack.h @@ -35,7 +35,7 @@ public: void GetKeyInfo(int key, const char*& description, float& duration); void SerializeKey(IConsoleKey& key, XmlNodeRef& keyNode, bool bLoading); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_CONSOLETRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/EventNode.cpp b/Gems/Maestro/Code/Source/Cinematics/EventNode.cpp index 9ce35c4dbe..7a3f1361cf 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/EventNode.cpp @@ -112,8 +112,11 @@ void CAnimEventNode::OnReset() } ////////////////////////////////////////////////////////////////////////// -void CAnimEventNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimEventNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimEventNode, CAnimNode>() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimEventNode, CAnimNode>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/EventNode.h b/Gems/Maestro/Code/Source/Cinematics/EventNode.h index d54fe73d80..78b3cd53ae 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/EventNode.h @@ -42,7 +42,7 @@ public: virtual CAnimParamType GetParamType(unsigned int nIndex) const; virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: //! Last animated key in track. diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp index 02977ef377..a90a1dad83 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.cpp @@ -103,10 +103,13 @@ void CEventTrack::InitPostLoad(IAnimSequence* sequence) } ////////////////////////////////////////////////////////////////////////// -void CEventTrack::Reflect(AZ::SerializeContext* serializeContext) +void CEventTrack::Reflect(AZ::ReflectContext* context) { // Note the template base class TAnimTrack<IEventKey>::Reflect() is reflected by CTrackEventTrack::Reflect() - serializeContext->Class<CEventTrack, TAnimTrack<IEventKey> >() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CEventTrack, TAnimTrack<IEventKey>>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/EventTrack.h b/Gems/Maestro/Code/Source/Cinematics/EventTrack.h index 58c9153014..b03f7d8e9f 100644 --- a/Gems/Maestro/Code/Source/Cinematics/EventTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/EventTrack.h @@ -42,7 +42,7 @@ public: void SetKey(int index, IKey* key); void InitPostLoad(IAnimSequence* sequence) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: AZStd::intrusive_ptr<IAnimStringTable> m_pStrings; diff --git a/Gems/Maestro/Code/Source/Cinematics/GotoTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/GotoTrack.cpp index 77662592cd..facd1e80fa 100644 --- a/Gems/Maestro/Code/Source/Cinematics/GotoTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/GotoTrack.cpp @@ -156,23 +156,41 @@ void CGotoTrack::SetKeyAtTime(float time, IKey* key) } ////////////////////////////////////////////////////////////////////////// +static bool GotoTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<IDiscreteFloatKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<IDiscreteFloatKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<IDiscreteFloatKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<IDiscreteFloatKey>::m_flags) - ->Field("Range", &TAnimTrack<IDiscreteFloatKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<IDiscreteFloatKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<IDiscreteFloatKey>::m_keys) - ->Field("Id", &TAnimTrack<IDiscreteFloatKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<IDiscreteFloatKey>, IAnimTrack>() + ->Version(3, &GotoTrackVersionConverter) + ->Field("Flags", &TAnimTrack<IDiscreteFloatKey>::m_flags) + ->Field("Range", &TAnimTrack<IDiscreteFloatKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<IDiscreteFloatKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<IDiscreteFloatKey>::m_keys) + ->Field("Id", &TAnimTrack<IDiscreteFloatKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CGotoTrack::Reflect(AZ::SerializeContext* serializeContext) +void CGotoTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IDiscreteFloatKey>::Reflect(serializeContext); + TAnimTrack<IDiscreteFloatKey>::Reflect(context); - serializeContext->Class<CGotoTrack, TAnimTrack<IDiscreteFloatKey> >() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CGotoTrack, TAnimTrack<IDiscreteFloatKey>>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/GotoTrack.h b/Gems/Maestro/Code/Source/Cinematics/GotoTrack.h index 1a38817204..aff269c56a 100644 --- a/Gems/Maestro/Code/Source/Cinematics/GotoTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/GotoTrack.h @@ -40,7 +40,7 @@ public: void SerializeKey(IDiscreteFloatKey& key, XmlNodeRef& keyNode, bool bLoading); void GetKeyInfo(int key, const char*& description, float& duration); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: void SetKeyAtTime(float time, IKey* key); diff --git a/Gems/Maestro/Code/Source/Cinematics/LayerNode.cpp b/Gems/Maestro/Code/Source/Cinematics/LayerNode.cpp index 1e2b6d401e..a7f0984069 100644 --- a/Gems/Maestro/Code/Source/Cinematics/LayerNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/LayerNode.cpp @@ -172,8 +172,11 @@ bool CLayerNode::GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& } ////////////////////////////////////////////////////////////////////////// -void CLayerNode::Reflect(AZ::SerializeContext* serializeContext) +void CLayerNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CLayerNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CLayerNode, CAnimNode>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/LayerNode.h b/Gems/Maestro/Code/Source/Cinematics/LayerNode.h index 7660c544b4..0ca977df2d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/LayerNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/LayerNode.h @@ -52,7 +52,7 @@ public: virtual unsigned int GetParamCount() const; virtual CAnimParamType GetParamType(unsigned int nIndex) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.cpp index 164b15b809..745dc5a8a4 100644 --- a/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.cpp @@ -79,24 +79,42 @@ void CLookAtTrack::GetKeyInfo(int key, const char*& description, float& duration ////////////////////////////////////////////////////////////////////////// +static bool LookAtTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ILookAtKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ILookAtKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ILookAtKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ILookAtKey>::m_flags) - ->Field("Range", &TAnimTrack<ILookAtKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ILookAtKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ILookAtKey>::m_keys) - ->Field("Id", &TAnimTrack<ILookAtKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ILookAtKey>, IAnimTrack>() + ->Version(3, &LookAtTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ILookAtKey>::m_flags) + ->Field("Range", &TAnimTrack<ILookAtKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ILookAtKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ILookAtKey>::m_keys) + ->Field("Id", &TAnimTrack<ILookAtKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CLookAtTrack::Reflect(AZ::SerializeContext* serializeContext) +void CLookAtTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ILookAtKey>::Reflect(serializeContext); + TAnimTrack<ILookAtKey>::Reflect(context); - serializeContext->Class<CLookAtTrack, TAnimTrack<ILookAtKey> >() - ->Version(1) - ->Field("AnimationLayer", &CLookAtTrack::m_iAnimationLayer); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CLookAtTrack, TAnimTrack<ILookAtKey>>() + ->Version(1) + ->Field("AnimationLayer", &CLookAtTrack::m_iAnimationLayer); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.h b/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.h index c3479b04b8..c45df95046 100644 --- a/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/LookAtTrack.h @@ -41,7 +41,7 @@ public: int GetAnimationLayerIndex() const { return m_iAnimationLayer; } void SetAnimationLayerIndex(int index) { m_iAnimationLayer = index; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: int m_iAnimationLayer; }; diff --git a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.cpp b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.cpp index a54737953e..abf1e5dc52 100644 --- a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.cpp @@ -432,10 +432,13 @@ void CAnimMaterialNode::AddTrack(IAnimTrack* track) } ////////////////////////////////////////////////////////////////////////// -void CAnimMaterialNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimMaterialNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimMaterialNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimMaterialNode, CAnimNode>() + ->Version(1); + } } #undef s_nodeParamsInitialized diff --git a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h index 39b917b15c..9d6ff6b6e0 100644 --- a/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/MaterialNode.h @@ -49,7 +49,7 @@ public: virtual void InitializeTrack(IAnimTrack* pTrack, const CAnimParamType& paramType); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index ee7a443964..f68ddb2b49 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -1196,13 +1196,16 @@ void CMovieSystem::Callback(IMovieCallback::ECallbackReason reason, IAnimNode* p } ////////////////////////////////////////////////////////////////////////// -/*static*/ void CMovieSystem::Reflect(AZ::SerializeContext* serializeContext) +void CMovieSystem::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CMovieSystem>() - ->Version(1) - ->Field("Sequences", &CMovieSystem::m_sequences); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CMovieSystem>() + ->Version(1) + ->Field("Sequences", &CMovieSystem::m_sequences); + } - AnimSerializer::ReflectAnimTypes(serializeContext); + AnimSerializer::ReflectAnimTypes(context); } ////////////////////////////////////////////////////////////////////////// diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.h b/Gems/Maestro/Code/Source/Cinematics/Movie.h index 1749d3b491..2150a72304 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.h +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.h @@ -204,7 +204,7 @@ public: void OnSequenceActivated(IAnimSequence* sequence) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp index 652a144513..0b971dc7da 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.cpp @@ -1026,10 +1026,13 @@ void CAnimSceneNode::Serialize(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmp SetFlags(GetFlags() | eAnimNodeFlags_CanChangeName); } -void CAnimSceneNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimSceneNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimSceneNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimSceneNode, CAnimNode>() + ->Version(1); + } } void CAnimSceneNode::PrecacheStatic(float startTime) diff --git a/Gems/Maestro/Code/Source/Cinematics/SceneNode.h b/Gems/Maestro/Code/Source/Cinematics/SceneNode.h index f5e2a92005..81166ab6b1 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SceneNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/SceneNode.h @@ -90,7 +90,7 @@ public: virtual void PrecacheStatic(float startTime) override; virtual void PrecacheDynamic(float time) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); // Utility function to find the sequence associated with an ISequenceKey static IAnimSequence* GetSequenceFromSequenceKey(const ISequenceKey& sequenceKey); diff --git a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp index aae6f7d01b..8b2e615c26 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.cpp @@ -179,23 +179,41 @@ bool CScreenFaderTrack::SetActiveTexture(int index) } ////////////////////////////////////////////////////////////////////////// +static bool ScreenFaderTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<IScreenFaderKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<IScreenFaderKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<IScreenFaderKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<IScreenFaderKey>::m_flags) - ->Field("Range", &TAnimTrack<IScreenFaderKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<IScreenFaderKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<IScreenFaderKey>::m_keys) - ->Field("Id", &TAnimTrack<IScreenFaderKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<IScreenFaderKey>, IAnimTrack>() + ->Version(3, &ScreenFaderTrackVersionConverter) + ->Field("Flags", &TAnimTrack<IScreenFaderKey>::m_flags) + ->Field("Range", &TAnimTrack<IScreenFaderKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<IScreenFaderKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<IScreenFaderKey>::m_keys) + ->Field("Id", &TAnimTrack<IScreenFaderKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CScreenFaderTrack::Reflect(AZ::SerializeContext* serializeContext) +void CScreenFaderTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IScreenFaderKey>::Reflect(serializeContext); + TAnimTrack<IScreenFaderKey>::Reflect(context); - serializeContext->Class<CScreenFaderTrack, TAnimTrack<IScreenFaderKey> >() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CScreenFaderTrack, TAnimTrack<IScreenFaderKey>>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h index 335e22038c..0c8faa890f 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/ScreenFaderTrack.h @@ -50,7 +50,7 @@ public: void SetLastTextureID(int nTextureID){ m_lastTextureID = nTextureID; }; bool SetActiveTexture(int index); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: void ReleasePreloadedTextures(); diff --git a/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.cpp b/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.cpp index fc6a57a521..e1ecdc77f5 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.cpp @@ -107,8 +107,11 @@ void CAnimScriptVarNode::Animate(SAnimContext& ec) } } -void CAnimScriptVarNode::Reflect(AZ::SerializeContext* serializeContext) +void CAnimScriptVarNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CAnimScriptVarNode, CAnimNode>() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CAnimScriptVarNode, CAnimNode>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.h b/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.h index 10e0c83063..6355961117 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/ScriptVarNode.h @@ -40,7 +40,7 @@ public: virtual CAnimParamType GetParamType(unsigned int nIndex) const; virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: float m_value; diff --git a/Gems/Maestro/Code/Source/Cinematics/SelectTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/SelectTrack.cpp index cc23a86ecd..53489bb454 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SelectTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SelectTrack.cpp @@ -63,23 +63,41 @@ void CSelectTrack::GetKeyInfo(int key, const char*& description, float& duration } ////////////////////////////////////////////////////////////////////////// +static bool SelectTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ISelectKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ISelectKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ISelectKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ISelectKey>::m_flags) - ->Field("Range", &TAnimTrack<ISelectKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ISelectKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ISelectKey>::m_keys) - ->Field("Id", &TAnimTrack<ISelectKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ISelectKey>, IAnimTrack>() + ->Version(3, &SelectTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ISelectKey>::m_flags) + ->Field("Range", &TAnimTrack<ISelectKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ISelectKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ISelectKey>::m_keys) + ->Field("Id", &TAnimTrack<ISelectKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CSelectTrack::Reflect(AZ::SerializeContext* serializeContext) +void CSelectTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ISelectKey>::Reflect(serializeContext); + TAnimTrack<ISelectKey>::Reflect(context); - serializeContext->Class<CSelectTrack, TAnimTrack<ISelectKey> >() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CSelectTrack, TAnimTrack<ISelectKey>>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/SelectTrack.h b/Gems/Maestro/Code/Source/Cinematics/SelectTrack.h index a146f656ad..6e581bd507 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SelectTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/SelectTrack.h @@ -35,7 +35,7 @@ public: void GetKeyInfo(int key, const char*& description, float& duration); void SerializeKey(ISelectKey& key, XmlNodeRef& keyNode, bool bLoading); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_SELECTTRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.cpp index 25b8e9b421..b230dacf91 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.cpp @@ -83,23 +83,41 @@ void CSequenceTrack::GetKeyInfo(int key, const char*& description, float& durati } ////////////////////////////////////////////////////////////////////////// +static bool SequencTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ISequenceKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ISequenceKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ISequenceKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ISequenceKey>::m_flags) - ->Field("Range", &TAnimTrack<ISequenceKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ISequenceKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ISequenceKey>::m_keys) - ->Field("Id", &TAnimTrack<ISequenceKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ISequenceKey>, IAnimTrack>() + ->Version(3, &SequencTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ISequenceKey>::m_flags) + ->Field("Range", &TAnimTrack<ISequenceKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ISequenceKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ISequenceKey>::m_keys) + ->Field("Id", &TAnimTrack<ISequenceKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CSequenceTrack::Reflect(AZ::SerializeContext* serializeContext) +void CSequenceTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ISequenceKey>::Reflect(serializeContext); + TAnimTrack<ISequenceKey>::Reflect(context); - serializeContext->Class<CSequenceTrack, TAnimTrack<ISequenceKey> >() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CSequenceTrack, TAnimTrack<ISequenceKey> >() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.h b/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.h index 816b011e39..d4bfa65985 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/SequenceTrack.h @@ -29,7 +29,7 @@ public: void GetKeyInfo(int key, const char*& description, float& duration); void SerializeKey(ISequenceKey& key, XmlNodeRef& keyNode, bool bLoading); - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_SEQUENCETRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.cpp b/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.cpp index 317791fe7c..5cc8409b2d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.cpp @@ -117,8 +117,11 @@ bool CShadowsSetupNode::GetParamInfoFromType(const CAnimParamType& paramId, SPar } ////////////////////////////////////////////////////////////////////////// -void CShadowsSetupNode::Reflect(AZ::SerializeContext* serializeContext) +void CShadowsSetupNode::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<CShadowsSetupNode, CAnimNode>() - ->Version(1); -} \ No newline at end of file + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CShadowsSetupNode, CAnimNode>() + ->Version(1); + } +} diff --git a/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.h b/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.h index 8cdf908168..85a44ace69 100644 --- a/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.h +++ b/Gems/Maestro/Code/Source/Cinematics/ShadowsSetupNode.h @@ -45,7 +45,7 @@ public: virtual unsigned int GetParamCount() const; virtual CAnimParamType GetParamType(unsigned int nIndex) const; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); protected: virtual bool GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const; diff --git a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.cpp index 2378cceb2d..c7bf492e54 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.cpp @@ -60,23 +60,41 @@ void CSoundTrack::GetKeyInfo(int key, const char*& description, float& duration) } ////////////////////////////////////////////////////////////////////////// +static bool SoundTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ISoundKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ISoundKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ISoundKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ISoundKey>::m_flags) - ->Field("Range", &TAnimTrack<ISoundKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ISoundKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ISoundKey>::m_keys) - ->Field("Id", &TAnimTrack<ISoundKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ISoundKey>, IAnimTrack>() + ->Version(3, &SoundTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ISoundKey>::m_flags) + ->Field("Range", &TAnimTrack<ISoundKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ISoundKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ISoundKey>::m_keys) + ->Field("Id", &TAnimTrack<ISoundKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CSoundTrack::Reflect(AZ::SerializeContext* serializeContext) +void CSoundTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<ISoundKey>::Reflect(serializeContext); + TAnimTrack<ISoundKey>::Reflect(context); - serializeContext->Class<CSoundTrack, TAnimTrack<ISoundKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CSoundTrack, TAnimTrack<ISoundKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h index 8f76f09e79..83706ea9ba 100644 --- a/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/SoundTrack.h @@ -55,7 +55,7 @@ public: bool UsesMute() const override { return true; } - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_SOUNDTRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.cpp index e2b18bdac1..334c5bdd6b 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.cpp @@ -100,23 +100,41 @@ int CTimeRangesTrack::GetActiveKeyIndexForTime(const float time) } ////////////////////////////////////////////////////////////////////////// +static bool TimeRangesTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<ITimeRangeKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<ITimeRangeKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<ITimeRangeKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<ITimeRangeKey>::m_flags) - ->Field("Range", &TAnimTrack<ITimeRangeKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<ITimeRangeKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<ITimeRangeKey>::m_keys) - ->Field("Id", &TAnimTrack<ITimeRangeKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<ITimeRangeKey>, IAnimTrack>() + ->Version(3, &TimeRangesTrackVersionConverter) + ->Field("Flags", &TAnimTrack<ITimeRangeKey>::m_flags) + ->Field("Range", &TAnimTrack<ITimeRangeKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<ITimeRangeKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<ITimeRangeKey>::m_keys) + ->Field("Id", &TAnimTrack<ITimeRangeKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CTimeRangesTrack::Reflect(AZ::SerializeContext* serializeContext) +void CTimeRangesTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IBoolKey>::Reflect(serializeContext); + TAnimTrack<ITimeRangeKey>::Reflect(context); - serializeContext->Class<CTimeRangesTrack, TAnimTrack<ITimeRangeKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CTimeRangesTrack, TAnimTrack<ITimeRangeKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.h b/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.h index e8861e53a4..dd07e6d8e4 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/TimeRangesTrack.h @@ -39,8 +39,7 @@ public: int GetActiveKeyIndexForTime(const float time); - static void Reflect(AZ::SerializeContext* serializeContext); - + static void Reflect(AZ::ReflectContext* context); }; #endif // CRYINCLUDE_CRYMOVIE_TIMERANGESTRACK_H diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp index 9d690e1afb..41c17ce6f3 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.cpp @@ -159,23 +159,41 @@ void CTrackEventTrack::GetKeyInfo(int key, const char*& description, float& dura } ////////////////////////////////////////////////////////////////////////// +static bool EventTrackVersionConverter( + AZ::SerializeContext& serializeContext, + AZ::SerializeContext::DataElementNode& rootElement) +{ + if (rootElement.GetVersion() < 3) + { + rootElement.AddElement(serializeContext, "BaseClass1", azrtti_typeid<IAnimTrack>()); + } + + return true; +} + template<> -inline void TAnimTrack<IEventKey>::Reflect(AZ::SerializeContext* serializeContext) +inline void TAnimTrack<IEventKey>::Reflect(AZ::ReflectContext* context) { - serializeContext->Class<TAnimTrack<IEventKey> >() - ->Version(2) - ->Field("Flags", &TAnimTrack<IEventKey>::m_flags) - ->Field("Range", &TAnimTrack<IEventKey>::m_timeRange) - ->Field("ParamType", &TAnimTrack<IEventKey>::m_nParamType) - ->Field("Keys", &TAnimTrack<IEventKey>::m_keys) - ->Field("Id", &TAnimTrack<IEventKey>::m_id); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<TAnimTrack<IEventKey>, IAnimTrack>() + ->Version(3, &EventTrackVersionConverter) + ->Field("Flags", &TAnimTrack<IEventKey>::m_flags) + ->Field("Range", &TAnimTrack<IEventKey>::m_timeRange) + ->Field("ParamType", &TAnimTrack<IEventKey>::m_nParamType) + ->Field("Keys", &TAnimTrack<IEventKey>::m_keys) + ->Field("Id", &TAnimTrack<IEventKey>::m_id); + } } ////////////////////////////////////////////////////////////////////////// -void CTrackEventTrack::Reflect(AZ::SerializeContext* serializeContext) +void CTrackEventTrack::Reflect(AZ::ReflectContext* context) { - TAnimTrack<IEventKey>::Reflect(serializeContext); + TAnimTrack<IEventKey>::Reflect(context); - serializeContext->Class<CTrackEventTrack, TAnimTrack<IEventKey> >() - ->Version(1); + if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) + { + serializeContext->Class<CTrackEventTrack, TAnimTrack<IEventKey>>() + ->Version(1); + } } diff --git a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h index 86043110c3..1095a7736d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h +++ b/Gems/Maestro/Code/Source/Cinematics/TrackEventTrack.h @@ -78,7 +78,7 @@ public: void SetKey(int index, IKey* key); void InitPostLoad(IAnimSequence* sequence) override; - static void Reflect(AZ::SerializeContext* serializeContext); + static void Reflect(AZ::ReflectContext* context); private: AZStd::intrusive_ptr< IAnimStringTable> m_pStrings; diff --git a/Gems/Maestro/Code/Source/Components/SequenceComponent.cpp b/Gems/Maestro/Code/Source/Components/SequenceComponent.cpp index 62261d1427..491e9287b8 100644 --- a/Gems/Maestro/Code/Source/Components/SequenceComponent.cpp +++ b/Gems/Maestro/Code/Source/Components/SequenceComponent.cpp @@ -34,6 +34,7 @@ #include <Cinematics/SelectTrack.h> #include <Cinematics/SequenceTrack.h> #include <Cinematics/SoundTrack.h> +#include <Cinematics/TimeRangesTrack.h> #include <Cinematics/TrackEventTrack.h> #include <Cinematics/AnimSequence.h> @@ -105,18 +106,16 @@ namespace Maestro { } - /*static*/ void SequenceComponent::Reflect(AZ::ReflectContext* context) + void SequenceComponent::Reflect(AZ::ReflectContext* context) { - AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context); - - if (serializeContext) + // Reflect the Cinematics library + ReflectCinematicsLib(context); + + if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) { serializeContext->Class<SequenceComponent, AZ::Component>() ->Version(2) ->Field("Sequence", &SequenceComponent::m_sequence); - - // Reflect the Cinematics library - ReflectCinematicsLib(serializeContext); } if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) @@ -141,12 +140,13 @@ namespace Maestro } } - /*static*/ void SequenceComponent::ReflectCinematicsLib(AZ::SerializeContext* context) + void SequenceComponent::ReflectCinematicsLib(AZ::ReflectContext* context) { // The Movie System itself CMovieSystem::Reflect(context); // Tracks + IAnimTrack::Reflect(context); TAnimSplineTrack<Vec2>::Reflect(context); CBoolTrack::Reflect(context); CCaptureTrack::Reflect(context); @@ -163,10 +163,13 @@ namespace Maestro CSoundTrack::Reflect(context); CTrackEventTrack::Reflect(context); CAssetBlendTrack::Reflect(context); + CTimeRangesTrack::Reflect(context); // Nodes + IAnimSequence::Reflect(context); CAnimSequence::Reflect(context); CAnimSceneNode::Reflect(context); + IAnimNode::Reflect(context); CAnimNode::Reflect(context); CAnimAzEntityNode::Reflect(context); CAnimComponentNode::Reflect(context); diff --git a/Gems/Maestro/Code/Source/Components/SequenceComponent.h b/Gems/Maestro/Code/Source/Components/SequenceComponent.h index eab484903d..20e7d22fe3 100644 --- a/Gems/Maestro/Code/Source/Components/SequenceComponent.h +++ b/Gems/Maestro/Code/Source/Components/SequenceComponent.h @@ -104,7 +104,7 @@ namespace Maestro AZStd::intrusive_ptr<IAnimSequence> m_sequence; // Reflects the entire CryMovie library - static void ReflectCinematicsLib(AZ::SerializeContext* context); + static void ReflectCinematicsLib(AZ::ReflectContext* context); }; } // namespace Maestro