diff --git a/.gitignore b/.gitignore index e842a1b9..9309668d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ /assets/shaders/output/ /build_release/ /active_project +/test/assets/assets.db +/test/products/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 041c2b75..32fc99bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,17 +23,8 @@ if (SKY_BUILD_TEST) add_subdirectory(test) endif() -add_subdirectory(framework) -add_subdirectory(core) -add_subdirectory(engine) -add_subdirectory(render) -add_subdirectory(sample) -add_subdirectory(Launcher) - -set(ACTIVE_PROJECT_PATH ${CMAKE_SOURCE_DIR}/active_project/native) -if (EXISTS ${ACTIVE_PROJECT_PATH}) - add_subdirectory(${ACTIVE_PROJECT_PATH}) -endif () +add_subdirectory(runtime) +add_subdirectory(launcher) if (SKY_BUILD_EDITOR) add_subdirectory(editor) diff --git a/asset.json b/asset.json deleted file mode 100644 index 1b537300..00000000 --- a/asset.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "asset_folders": - [ - "shaders" - ], - "builders": - [ - "ShaderBuilder" - ] -} \ No newline at end of file diff --git a/assets/fonts/OpenSans-Bold.ttf b/assets/fonts/OpenSans-Bold.ttf new file mode 100644 index 00000000..b7fadfa4 Binary files /dev/null and b/assets/fonts/OpenSans-Bold.ttf differ diff --git a/assets/fonts/OpenSans-BoldItalic.ttf b/assets/fonts/OpenSans-BoldItalic.ttf new file mode 100644 index 00000000..136a4b4c Binary files /dev/null and b/assets/fonts/OpenSans-BoldItalic.ttf differ diff --git a/assets/fonts/OpenSans-Italic.ttf b/assets/fonts/OpenSans-Italic.ttf new file mode 100644 index 00000000..e99cb92d Binary files /dev/null and b/assets/fonts/OpenSans-Italic.ttf differ diff --git a/assets/fonts/OpenSans-Regular.ttf b/assets/fonts/OpenSans-Regular.ttf new file mode 100644 index 00000000..8529c432 Binary files /dev/null and b/assets/fonts/OpenSans-Regular.ttf differ diff --git a/assets/images/test.png b/assets/images/test.png deleted file mode 100644 index 8896fc51..00000000 Binary files a/assets/images/test.png and /dev/null differ diff --git a/assets/materials/standard_pbr.mat b/assets/materials/standard_pbr.mat index ad61e66c..ce2b42fb 100644 --- a/assets/materials/standard_pbr.mat +++ b/assets/materials/standard_pbr.mat @@ -1,5 +1,6 @@ { "techniques": [ - "techniques/standard_forward.tech" + "techniques/standard_forward.tech", + "techniques/depth.tech" ] } \ No newline at end of file diff --git a/assets/shaders/common/random.hlsl b/assets/shaders/common/random.hlsl index 16583d0b..49e16bd0 100644 --- a/assets/shaders/common/random.hlsl +++ b/assets/shaders/common/random.hlsl @@ -1,9 +1,9 @@ float Random(float2 co) { - float a = 12.9898; - float b = 78.233; - float c = 43758.5453; - float dt= dot(co.xy ,float2(a,b)); - float sn= fmod(dt,3.14); - return frac(sin(sn) * c); + float a = 12.9898; + float b = 78.233; + float c = 43758.5453; + float dt= dot(co.xy ,float2(a,b)); + float sn= fmod(dt,3.14); + return frac(sin(sn) * c); } \ No newline at end of file diff --git a/assets/shaders/debug.hlsl b/assets/shaders/debug.hlsl new file mode 100644 index 00000000..7b14e108 --- /dev/null +++ b/assets/shaders/debug.hlsl @@ -0,0 +1,36 @@ +struct VSInput +{ + float4 Pos : POSITION; + float4 Color : COLOR; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; + float4 Color : COLOR; +}; + +#include "shaders/layout/default_pass.hlsl" +#include "shaders/layout/default_local.hlsl" + +#if VIEW_COUNT > 1 +#define VIEW_INFO View[ViewIndex] +#else +#define VIEW_INFO View +#endif + +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + + float4 WorldPos = mul(World, input.Pos); + output.Pos = mul(VIEW_INFO.ViewProj, float4(WorldPos.xyz, 1.0)); + + output.COLOR = input.Color; + return output; +} + +float4 FSMain(VSOutput input) : SV_TARGET +{ + return input.Color; +} \ No newline at end of file diff --git a/assets/shaders/depth_only.hlsl b/assets/shaders/depth_only.hlsl new file mode 100644 index 00000000..0eb1b45e --- /dev/null +++ b/assets/shaders/depth_only.hlsl @@ -0,0 +1,24 @@ +#include "shaders/vertex/position_only.hlsl" + +#include "shaders/layout/default_pass.hlsl" +#include "shaders/layout/default_local.hlsl" + +#if VIEW_COUNT > 1 +#define VIEW_INFO View[ViewIndex] +#else +#define VIEW_INFO View +#endif + +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + + float4 WorldPos = mul(World, input.Pos); + output.Pos = mul(VIEW_INFO.ViewProj, float4(WorldPos.xyz, 1.0)); + return output; +} + +float4 FSMain() : SV_TARGET +{ + return float4(0.0, 0.0, 0.0, 0.0); +} \ No newline at end of file diff --git a/assets/shaders/error.hlsl b/assets/shaders/error.hlsl new file mode 100644 index 00000000..c3edd2bb --- /dev/null +++ b/assets/shaders/error.hlsl @@ -0,0 +1,24 @@ +#include "shaders/vertex/position_only.hlsl" + +#include "shaders/layout/default_pass.hlsl" +#include "shaders/layout/default_local.hlsl" + +#if VIEW_COUNT > 1 +#define VIEW_INFO View[ViewIndex] +#else +#define VIEW_INFO View +#endif + +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + + float4 WorldPos = mul(World, input.Pos); + output.Pos = mul(VIEW_INFO.ViewProj, float4(WorldPos.xyz, 1.0)); + return output; +} + +float4 FSMain() : SV_TARGET +{ + return float4(245.0 / 255.0, 66.0 / 255.0, 206.0 / 255.0, 1.0); +} \ No newline at end of file diff --git a/assets/shaders/layout/default_local.hlsl b/assets/shaders/layout/default_local.hlsl index 3ee67c10..d78157dd 100644 --- a/assets/shaders/layout/default_local.hlsl +++ b/assets/shaders/layout/default_local.hlsl @@ -2,4 +2,14 @@ { float4x4 World; float4x4 InverseTrans; -} \ No newline at end of file +} + +#ifdef ENABLE_SKIN + +#define MAX_BONE_NUM (80) +[[vk::binding(1, 2)]] cbuffer skin : register(b1, space2) +{ + float4x4 Bones[MAX_BONE_NUM]; +} + +#endif \ No newline at end of file diff --git a/assets/shaders/layout/default_pass.hlsl b/assets/shaders/layout/default_pass.hlsl index 6f2ed0b3..3dbfc170 100644 --- a/assets/shaders/layout/default_pass.hlsl +++ b/assets/shaders/layout/default_pass.hlsl @@ -1,13 +1,13 @@ struct ViewInfo { - float4x4 ViewToWorld; - float4x4 ViewToClip; - float4x4 WorldToView; - float4x4 WorldToClip; + float4x4 World; + float4x4 View; + float4x4 Project; + float4x4 ViewProj; }; -#define VIEW_COUNT 1 [[vk::binding(0, 0)]] cbuffer global : register(b0, space0) { + float4x4 LightMatrix; float4 Viewport; } @@ -21,4 +21,7 @@ struct ViewInfo { { ViewInfo View; } -#endif \ No newline at end of file +#endif + +// [[vk::binding(2, 0)]] Texture2D ShadowMap : register(t1, space0); +// [[vk::binding(3, 0)]] SamplerState ShadowMapSampler : register(t1, space0); \ No newline at end of file diff --git a/assets/shaders/lighting/brdf_lut.hlsl b/assets/shaders/lighting/brdf_lut.hlsl index 5ecee96b..1aee4ec6 100644 --- a/assets/shaders/lighting/brdf_lut.hlsl +++ b/assets/shaders/lighting/brdf_lut.hlsl @@ -1,34 +1,49 @@ #include "shaders/vertex/full_screen.hlsl" +struct VSOutput +{ + float4 Pos : SV_POSITION; + float2 UV : TEXCOORD; +}; + +VSOutput VSMain(uint vid : SV_VertexID) +{ + VSOutput res; + + res.Pos = float4(FT_POSITIONS[vid], 0.0, 1.0); + res.UV = FT_UVS[vid]; + return res; +} + #include "shaders/lighting/pbr.hlsl" float2 BRDF_SAMPLE(float NoV, float roughness) { const uint NUM_SAMPLES = 1024; - // Normal always points along z-axis for the 2D lookup - const float3 N = float3(0.0, 0.0, 1.0); - float3 V = float3(sqrt(1.0 - NoV * NoV), 0.0, NoV); - - float2 LUT = float2(0.0, 0.0); - for(uint i = 0u; i < NUM_SAMPLES; i++) { - float2 Xi = Hammersley2d(i, NUM_SAMPLES); - float3 H = ImportanceSample_GGX(Xi, roughness, N); - float3 L = 2.0 * dot(V, H) * H - V; - - float dotNL = max(dot(N, L), 0.0); - float dotNV = max(dot(N, V), 0.0); - float dotVH = max(dot(V, H), 0.0); - float dotNH = max(dot(H, N), 0.0); - - if (dotNL > 0.0) { - float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); - float G_Vis = (G * dotVH) / (dotNH * dotNV); - float Fc = pow(1.0 - dotVH, 5.0); - LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); - } - } - return LUT / float(NUM_SAMPLES); + // Normal always points along z-axis for the 2D lookup + const float3 N = float3(0.0, 0.0, 1.0); + float3 V = float3(sqrt(1.0 - NoV * NoV), 0.0, NoV); + + float2 LUT = float2(0.0, 0.0); + for(uint i = 0u; i < NUM_SAMPLES; i++) { + float2 Xi = Hammersley2d(i, NUM_SAMPLES); + float3 H = ImportanceSample_GGX(Xi, roughness, N); + float3 L = 2.0 * dot(V, H) * H - V; + + float dotNL = max(dot(N, L), 0.0); + float dotNV = max(dot(N, V), 0.0); + float dotVH = max(dot(V, H), 0.0); + float dotNH = max(dot(H, N), 0.0); + + if (dotNL > 0.0) { + float G = G_SchlickSmithGGX(dotNL, dotNV, roughness); + float G_Vis = (G * dotVH) / (dotNH * dotNV); + float Fc = pow(1.0 - dotVH, 5.0); + LUT += float2((1.0 - Fc) * G_Vis, Fc * G_Vis); + } + } + return LUT / float(NUM_SAMPLES); } float4 FSMain(VSOutput input) : SV_TARGET diff --git a/assets/shaders/lighting/light.hlsl b/assets/shaders/lighting/light.hlsl index d1390262..4390afdb 100644 --- a/assets/shaders/lighting/light.hlsl +++ b/assets/shaders/lighting/light.hlsl @@ -1,10 +1,4 @@ struct LightInfo { float4 Direction; // xyz: dir float4 Color; // xyz: rgb w: intensity -}; - -struct StandardPBR { - float Metallic; - float Roughness; - float3 Albedo; }; \ No newline at end of file diff --git a/assets/shaders/lighting/pbr.hlsl b/assets/shaders/lighting/pbr.hlsl index 465ca2d3..6480eaeb 100644 --- a/assets/shaders/lighting/pbr.hlsl +++ b/assets/shaders/lighting/pbr.hlsl @@ -3,81 +3,100 @@ float2 Hammersley2d(uint i, uint N) { - // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html - uint bits = (i << 16u) | (i >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - float rdi = float(bits) * 2.3283064365386963e-10; - return float2(float(i) /float(N), rdi); + // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html + uint bits = (i << 16u) | (i >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + float rdi = float(bits) * 2.3283064365386963e-10; + return float2(float(i) /float(N), rdi); } // Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf float3 ImportanceSample_GGX(float2 Xi, float roughness, float3 normal) { - // Maps a 2D point to a hemisphere with spread based on roughness - float alpha = roughness * roughness; - float phi = 2.0 * PI * Xi.x + Random(normal.xz) * 0.1; - float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); - float sinTheta = sqrt(1.0 - cosTheta * cosTheta); - float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); - - // Tangent space - float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); - float3 tangentX = normalize(cross(up, normal)); - float3 tangentY = normalize(cross(normal, tangentX)); - - // Convert to world Space - return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); + // Maps a 2D point to a hemisphere with spread based on roughness + float alpha = roughness * roughness; + float phi = 2.0 * PI * Xi.x + Random(normal.xz) * 0.1; + float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y)); + float sinTheta = sqrt(1.0 - cosTheta * cosTheta); + float3 H = float3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta); + + // Tangent space + float3 up = abs(normal.z) < 0.999 ? float3(0.0, 0.0, 1.0) : float3(1.0, 0.0, 0.0); + float3 tangentX = normalize(cross(up, normal)); + float3 tangentY = normalize(cross(normal, tangentX)); + + // Convert to world Space + return normalize(tangentX * H.x + tangentY * H.y + normal * H.z); +} + +#include "shaders/lighting/light.hlsl" + +float3 DiffuseBRDF(float3 albedo) +{ + return (1 / PI) * albedo; +} + +float3 F_Schlick(float dotVH, float3 f0) +{ + return f0 + (1.0 - f0) * pow(1.0 - dotVH, 5.0); } float D_GGX(float dotNH, float roughness) { - float alpha = roughness * roughness; - float alpha2 = alpha * alpha; - float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; - return (alpha2)/(PI * denom * denom); + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2) / (PI * denom * denom); } -float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) +float G_SchlickGGX(float dotNV, float roughness) { - float r = (roughness + 1.0); - float k = (r*r) / 8.0; - float GL = dotNL / (dotNL * (1.0 - k) + k); - float GV = dotNV / (dotNV * (1.0 - k) + k); - return GL * GV; + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float num = dotNV; + float denom = dotNV * (1.0 - k) + k; + return num / denom; } -float3 F_Schlick(float cosTheta, float metallic, float3 elbedo) +float G_SchlickSmithGGX(float dotNL, float dotNV, float roughness) { - float3 F0 = lerp(float3(0.04, 0.04, 0.04), elbedo, metallic); - float3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); - return F; + float ggx1 = G_SchlickGGX(dotNL, roughness); + float ggx2 = G_SchlickGGX(dotNV, roughness); + return ggx1 * ggx2; } -#include "shaders/lighting/light.hlsl" +struct StandardPBR { + float Metallic; + float Roughness; + float3 Albedo; + float AO; + float4 Emissive; +}; float3 BRDF(float3 V, float3 N, LightInfo light, StandardPBR param) { - float3 L = -light.Direction.xyz; + float3 L = normalize(-light.Direction.xyz); float3 H = normalize(V + L); - float dotNV = clamp(dot(N, V), 0.0, 1.0); - float dotNL = clamp(dot(N, L), 0.0, 1.0); - float dotLH = clamp(dot(L, H), 0.0, 1.0); - float dotNH = clamp(dot(N, H), 0.0, 1.0); - - float3 color = float3(0.0, 0.0, 0.0); - if (dotNL > 0.0) - { - float rroughness = max(0.05, param.Roughness); - float D = D_GGX(dotNH, param.Roughness); - float G = G_SchlicksmithGGX(dotNL, dotNV, rroughness); - float3 F = F_Schlick(dotNV, param.Metallic, param.Albedo); - - float3 spec = D * F * G / (4.0 * dotNL * dotNV); - color += spec * dotNL * light.Color.rgb * light.Direction.w; - } - - return color; + float dotNV = max(dot(N, V), 0); + float dotNL = max(dot(N, L), 0); + float dotVH = max(dot(V, H), 0); + float dotNH = max(dot(N, H), 0); + + float3 L0 = float3(0.0, 0.0, 0.0); + + float3 F0 = lerp(0.04, param.Albedo, param.Metallic); + + float3 F = F_Schlick(dotVH, F0); + float D = D_GGX(dotNH, param.Roughness); + float G = G_SchlickSmithGGX(dotNL, dotNV, param.Roughness); + + float3 specular = D * F * G / 4 * dotNV * dotNL; + + float3 kD = lerp(param.Albedo, 0, param.Metallic); + L0 += ((1 - F) * kD / PI + specular) * light.Direction.w * param.AO + param.Emissive; + return L0; } \ No newline at end of file diff --git a/assets/shaders/post_processing/final.hlsl b/assets/shaders/post_processing/final.hlsl index 854ebc5d..f59b1f2a 100644 --- a/assets/shaders/post_processing/final.hlsl +++ b/assets/shaders/post_processing/final.hlsl @@ -1,7 +1,21 @@ #include "shaders/vertex/full_screen.hlsl" -#include "shaders/color/color_common.hlsl" +struct VSOutput +{ + float4 Pos : SV_POSITION; + float2 UV : TEXCOORD; +}; + +VSOutput VSMain(uint vid : SV_VertexID) +{ + VSOutput res; + + res.Pos = float4(FT_POSITIONS[vid], 0.0, 1.0); + res.UV = FT_UVS[vid]; + return res; +} +#include "shaders/color/color_common.hlsl" [[vk::binding(0, 0)]] Texture2D InColor : register(t0, space0); [[vk::binding(1, 0)]] SamplerState InColorSampler : register(s0, space0); diff --git a/assets/shaders/standard_pbr.hlsl b/assets/shaders/standard_pbr.hlsl index e60fc4ef..22d411cb 100644 --- a/assets/shaders/standard_pbr.hlsl +++ b/assets/shaders/standard_pbr.hlsl @@ -9,28 +9,91 @@ #define VIEW_INFO View #endif -VSOutput VSMain(VSInput input) +VSOutput VSMain(VSInput input +#if VIEW_COUNT > 1 + , uint ViewIndex : SV_ViewID +#endif +) { VSOutput output = (VSOutput)0; - output.WorldPos = mul(World, input.Pos).xyz; - output.Normal = mul((float3x3)InverseTrans, input.Normal.xyz); - output.Tangent = float4(mul((float3x3)InverseTrans, input.Tangent.xyz), input.Tangent.w); + float4x4 worldMatrix = World; +#if ENABLE_SKIN + float4x4 skinMat = + mul(Bones[input.joints.x], input.weights.x) + + mul(Bones[input.joints.y], input.weights.y) + + mul(Bones[input.joints.z], input.weights.z) + + mul(Bones[input.joints.w], input.weights.w); + worldMatrix = mul(worldMatrix, skinMat); +#endif + + output.WorldPos = mul(worldMatrix, input.Pos).xyz; + output.Normal = mul((float3x3)worldMatrix, input.Normal.xyz); + output.Tangent = float4(mul((float3x3)worldMatrix, input.Tangent.xyz), input.Tangent.w); output.Color = input.Color; output.UV = input.UV; - output.Pos = mul(VIEW_INFO.WorldToClip, float4(output.WorldPos, 1.0)); + output.Pos = mul(VIEW_INFO.ViewProj, float4(output.WorldPos, 1.0)); + +#if VIEW_COUNT > 1 + output.ViewIndex = input.ViewIndex; +#endif return output; } #include "shaders/layout/standard_shading.hlsl" #include "shaders/lighting/pbr.hlsl" +// static const float4x4 biasMat = float4x4( +// 0.5, 0.0, 0.0, 0.5, +// 0.0, 0.5, 0.0, 0.5, +// 0.0, 0.0, 1.0, 0.0, +// 0.0, 0.0, 0.0, 1.0 ); +// +// float textureProj(float4 shadowCoord, float2 off) +// { +// float shadow = 1.0; +// float bias = 0.001; +// if ( shadowCoord.z > -1.0 && shadowCoord.z < 1.0 ) +// { +// float dist = ShadowMap.Sample( ShadowMapSampler, shadowCoord.xy + off ).r; +// if ( shadowCoord.w > 0.0 && dist + bias < shadowCoord.z ) +// { +// shadow = 0.05; +// } +// } +// return shadow; +// } +// +// float filterPCF(float4 sc) +// { +// int2 texDim; +// ShadowMap.GetDimensions(texDim.x, texDim.y); +// float scale = 1.5; +// float dx = scale * 1.0 / float(texDim.x); +// float dy = scale * 1.0 / float(texDim.y); +// +// float shadowFactor = 0.0; +// int count = 0; +// int range = 3; +// +// for (int x = -range; x <= range; x++) +// { +// for (int y = -range; y <= range; y++) +// { +// shadowFactor += textureProj(sc, float2(dx*x, dy*y)); +// count++; +// } +// +// } +// return shadowFactor / count; +// } + float4 FSMain(VSOutput input) : SV_TARGET { LightInfo light; light.Color = float4(1.0, 1.0, 1.0, 1.0); - light.Direction = float4(normalize(float3(-1, -1, -1)), 1.0); + light.Direction = float4(float3(-1, -1, 0), 2.5); float3 tNormal = NormalMap.Sample(NormalSampler, input.UV.xy).xyz * 2.0 - 1.0; float3 N = normalize(input.Normal); @@ -40,8 +103,8 @@ float4 FSMain(VSOutput input) : SV_TARGET N = normalize(mul(TBN, tNormal)); - float3 viewPos = float3(VIEW_INFO.ViewToWorld[0][3], VIEW_INFO.ViewToWorld[1][3], VIEW_INFO.ViewToWorld[2][3]); - float3 L = -light.Direction.xyz; + float3 viewPos = float3(VIEW_INFO.World[3][0], VIEW_INFO.World[3][1], VIEW_INFO.World[3][2]); + float3 L = normalize(-light.Direction.xyz); float3 V = normalize(viewPos - input.WorldPos); float4 texAlbedo = AlbedoMap.Sample(AlbedoSampler, input.UV.xy); @@ -53,10 +116,22 @@ float4 FSMain(VSOutput input) : SV_TARGET float4 mr = MetallicRoughnessMap.Sample(MetallicRoughnessSampler, input.UV.xy); pbrParam.Metallic = mr.b; pbrParam.Roughness = mr.g; + pbrParam.AO = 1.0; + pbrParam.Emissive = float4(0, 0, 0, 0); - float4 ao = AoMap.Sample(AoSampler, input.UV.xy); - float4 emissive = EmissiveMap.Sample(EmissiveSampler, input.UV.xy); +#ifdef ENABLE_AO_MAP + pbrParam.AO = AoMap.Sample(AoSampler, input.UV.xy).x; +#endif + +#ifdef ENABLE_EMISSIVE_MAP + pbrParam.Emissive = EmissiveMap.Sample(EmissiveSampler, input.UV.xy); +#endif - float3 e0 = BRDF(V, N, light, pbrParam) + emissive.xyz; - return float4(e0, albedo.a) ; + float shadow = 1.0; +// float4 fragPosLightSpace = mul(biasMat, mul(LightMatrix, float4(input.WorldPos, 1.0))); +// float4 shadowCoord = fragPosLightSpace / fragPosLightSpace.w; +// float shadow = filterPCF(shadowCoord); +// shadow = max(shadow, 1.0); + float3 e0 = BRDF(V, N, light, pbrParam) * shadow; + return float4(e0, albedo.a); } \ No newline at end of file diff --git a/assets/shaders/ui/gui.hlsl b/assets/shaders/ui/gui.hlsl new file mode 100644 index 00000000..466ee344 --- /dev/null +++ b/assets/shaders/ui/gui.hlsl @@ -0,0 +1,40 @@ +struct VSInput +{ + float2 Pos : POSITION; + float2 UV : UV; + float4 Color : COLOR; +}; + + +struct VSOutput +{ + float4 Pos : SV_POSITION; + + float2 UV : UV; + float4 Color : COLOR; +}; + +[[vk::binding(0, 1)]] cbuffer Constants : register(b0, space1) +{ + float2 Scale; + float2 Translate; +} + +[[vk::binding(1, 1)]] Texture2D FontTexture : register(t0, space1); +[[vk::binding(2, 1)]] SamplerState FontSampler : register(s0, space1); + +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + + output.Color = input.Color; + output.UV = input.UV; + + output.Pos = float4(input.Pos * Scale + Translate, 0, 1); + return output; +} + +float4 FSMain(VSOutput input) : SV_TARGET +{ + return input.Color * FontTexture.Sample(FontSampler, input.UV); +} \ No newline at end of file diff --git a/assets/shaders/ui/text.hlsl b/assets/shaders/ui/text.hlsl new file mode 100644 index 00000000..1bce987d --- /dev/null +++ b/assets/shaders/ui/text.hlsl @@ -0,0 +1,41 @@ +struct VSInput +{ + float2 Pos : POSITION; + float2 UV : UV; + float4 Color : COLOR; +}; + + +struct VSOutput +{ + float4 Pos : SV_POSITION; + + float2 UV : UV; + float4 Color : COLOR; +}; + +[[vk::binding(0, 1)]] cbuffer Constants : register(b0, space1) +{ + float2 Scale; + float2 Translate; +} + +[[vk::binding(1, 1)]] Texture2D FontTexture : register(t0, space1); +[[vk::binding(2, 1)]] SamplerState FontSampler : register(s0, space1); + +VSOutput VSMain(VSInput input) +{ + VSOutput output = (VSOutput)0; + + output.Color = input.Color; + output.UV = input.UV; + + output.Pos = float4(input.Pos * Scale + Translate, 0, 1); + return output; +} + +float4 FSMain(VSOutput input) : SV_TARGET +{ + float texColor = FontTexture.Sample(FontSampler, input.UV).x; + return float4(input.Color.xyz, input.Color.w * texColor); +} \ No newline at end of file diff --git a/assets/shaders/vertex/full_screen.hlsl b/assets/shaders/vertex/full_screen.hlsl index 79c451f2..929e2357 100644 --- a/assets/shaders/vertex/full_screen.hlsl +++ b/assets/shaders/vertex/full_screen.hlsl @@ -1,27 +1,11 @@ -struct VSOutput -{ - float4 Pos : SV_POSITION; - - [[vk::location(0)]] float2 UV : TEXCOORD; +const float2 FT_POSITIONS[3] = { + float2(-1.0, 3.0), + float2(-1.0, -1.0), + float2( 3.0, -1.0) }; -VSOutput VSMain(uint vid : SV_VertexID) -{ - const float2 FT_POSITIONS[3] = { - float2(-1.0, 3.0), - float2(-1.0, -1.0), - float2( 3.0, -1.0) - }; - - const float2 FT_UVS[3] = { - float2(0.0, 2.0), - float2(0.0, 0.0), - float2(2.0, 0.0) - }; - - VSOutput res; - - res.Pos = float4(FT_POSITIONS[vid], 0.0, 1.0); - res.UV = FT_UVS[vid]; - return res; -} \ No newline at end of file +const float2 FT_UVS[3] = { + float2(0.0, 2.0), + float2(0.0, 0.0), + float2(2.0, 0.0) +}; \ No newline at end of file diff --git a/assets/shaders/vertex/position_only.hlsl b/assets/shaders/vertex/position_only.hlsl index cf0866a5..beda0dd3 100644 --- a/assets/shaders/vertex/position_only.hlsl +++ b/assets/shaders/vertex/position_only.hlsl @@ -1,4 +1,9 @@ struct VSInput { - [[vk::location(0)]] float4 Pos : POSITION; + float4 Pos : POSITION; +}; + +struct VSOutput +{ + float4 Pos : SV_POSITION; }; \ No newline at end of file diff --git a/assets/shaders/vertex/standard.hlsl b/assets/shaders/vertex/standard.hlsl index 6582ddc8..1cd3d0e8 100644 --- a/assets/shaders/vertex/standard.hlsl +++ b/assets/shaders/vertex/standard.hlsl @@ -1,20 +1,29 @@ +#define VIEW_COUNT 1 + struct VSInput { - [[vk::location(0)]] float4 Pos : POSITION; - [[vk::location(1)]] float4 Normal : NORMAL; - [[vk::location(2)]] float4 Tangent : TANGENT; - [[vk::location(3)]] float4 Color : COLOR; - [[vk::location(4)]] float4 UV : TEXCOORD; -}; + float4 Pos : POSITION; + float4 UV : UV; + float4 Normal : NORMAL; + float4 Tangent : TANGENT; + float4 Color : COLOR; +#if ENABLE_SKIN + uint4 joints : JOINTS; + float4 weights : WEIGHTS; +#endif +}; struct VSOutput { float4 Pos : SV_POSITION; + float4 UV : UV; + float3 WorldPos : POSITION; + float3 Normal : NORMAL; + float4 Tangent : TANGENT; + float4 Color : COLOR; - [[vk::location(0)]] float3 WorldPos : POSITION0; - [[vk::location(1)]] float3 Normal : NORMAL0; - [[vk::location(2)]] float4 Tangent : TANGENT; - [[vk::location(3)]] float4 Color : COLOR; - [[vk::location(4)]] float4 UV : TEXCOORD; +#if VIEW_COUNT > 1 + nointerpolation uint ViewIndex : VIEWINDEX; +#endif }; \ No newline at end of file diff --git a/assets/splash/splash.jpg b/assets/splash/splash.jpg new file mode 100644 index 00000000..9bf76db4 Binary files /dev/null and b/assets/splash/splash.jpg differ diff --git a/assets/techniques/debug.tech b/assets/techniques/debug.tech new file mode 100644 index 00000000..2312ea9f --- /dev/null +++ b/assets/techniques/debug.tech @@ -0,0 +1,18 @@ +{ + "type": "graphics", + "shader": { + "path": "shaders/debug.hlsl", + "vertex": "VSMain", + "fragment": "FSMain" + }, + "pass": { + "tag": "ForwardColor" + }, + "depth_stencil": { + "depthTestEnable": true, + "depthWriteEnable": false + }, + "raster_state": { + "cullMode": "NONE" + } +} diff --git a/assets/techniques/depth.tech b/assets/techniques/depth.tech new file mode 100644 index 00000000..3877f4cb --- /dev/null +++ b/assets/techniques/depth.tech @@ -0,0 +1,19 @@ +{ + "type": "graphics", + "shader": { + "path": "shaders/depth_only.hlsl", + "vertex": "VSMain", + "fragment": "FSMain" + }, + "pass": { + "tag": "DepthOnly" + }, + "depth_stencil": { + "depthTestEnable": true, + "depthWriteEnable": true + }, + "raster_state": { + "cullMode": "BACK" + }, + "vertex": "position_only" +} diff --git a/assets/techniques/gui.tech b/assets/techniques/gui.tech index 91b5c3a7..87bcc2d1 100644 --- a/assets/techniques/gui.tech +++ b/assets/techniques/gui.tech @@ -1,8 +1,9 @@ { "type": "graphics", - "shaders": { - "vert": "shaderlibs/glsl/gui/gui.vert", - "frag": "shaderlibs/glsl/gui/gui.frag" + "shader": { + "path": "shaders/ui/gui.hlsl", + "vertex": "VSMain", + "fragment": "FSMain" }, "pass": { "tag": "ui" @@ -16,8 +17,11 @@ "dstAlpha": "ONE_MINUS_SRC_ALPHA" } ], + "depth_stencil": { + "depthTestEnable": true, + "depthWriteEnable": false + }, "raster_state": { "cullMode": "NONE" - }, - "vertex": "gui" + } } diff --git a/assets/techniques/standard_forward.tech b/assets/techniques/standard_forward.tech index 56d8865e..9a21fa7c 100644 --- a/assets/techniques/standard_forward.tech +++ b/assets/techniques/standard_forward.tech @@ -15,5 +15,15 @@ "raster_state": { "cullMode": "BACK" }, - "vertex": "standard" + "pre_defines": [ + ], + "vertex_options": { + "SKIN": "ENABLE_SKIN", + "INSTANCE": "ENABLE_INSTANCE" + }, + "common_options": { + "ENABLE_EMISSIVE_MAP": false, + "ENABLE_AO_MAP": false, + "ENABLE_ALPHA_MASK": false + } } diff --git a/assets/techniques/text.tech b/assets/techniques/text.tech new file mode 100644 index 00000000..b1f8c9c4 --- /dev/null +++ b/assets/techniques/text.tech @@ -0,0 +1,23 @@ +{ + "type": "graphics", + "shader": { + "path": "shaders/ui/text.hlsl", + "vertex": "VSMain", + "fragment": "FSMain" + }, + "pass": { + "tag": "ui" + }, + "blend_state": [ + { + "blendEnable": true, + "srcColor": "SRC_ALPHA", + "dstColor": "ONE_MINUS_SRC_ALPHA", + "srcAlpha": "ONE", + "dstAlpha": "ONE_MINUS_SRC_ALPHA" + } + ], + "raster_state": { + "cullMode": "NONE" + } +} diff --git a/assets/vertex/vertex_library.vtxlib b/assets/vertex/vertex_library.vtxlib index 7ad9badb..710bfd52 100644 --- a/assets/vertex/vertex_library.vtxlib +++ b/assets/vertex/vertex_library.vtxlib @@ -96,6 +96,64 @@ } ] }, + "standard_skinned": { + "attributes": [ + { + "location": 0, + "binding": 0, + "offset": 0, + "format": "F_RGBA32" + }, + { + "location": 1, + "binding": 1, + "offset": 0, + "format": "F_RGBA32" + }, + { + "location": 2, + "binding": 1, + "offset": 16, + "format": "F_RGBA32" + }, + { + "location": 3, + "binding": 1, + "offset": 32, + "format": "F_RGBA32" + }, + { + "location": 4, + "binding": 1, + "offset": 48, + "format": "F_RGBA32" + }, + { + "location": 5, + "binding": 2, + "offset": 0, + "format": "U_RGBA8" + }, + { + "location": 6, + "binding": 2, + "offset": 32, + "format": "F_RGBA32" + } + ], + "bindings": [ + { + "binding": 0, + "stride": 16, + "rate": "PER_VERTEX" + }, + { + "binding": 1, + "stride": 64, + "rate": "PER_VERTEX" + } + ] + }, "geometry": { "attributes": [ { diff --git a/build_scripts/Project.py b/build_scripts/Project.py deleted file mode 100644 index b192f2aa..00000000 --- a/build_scripts/Project.py +++ /dev/null @@ -1,37 +0,0 @@ -import argparse -import os.path - -parser = argparse.ArgumentParser() -parser.add_argument('--init', action='store_true', help='Init Project') -parser.add_argument('--config', action='store_true', help='Config Project') -parser.add_argument('--project', help='project path') -parser.add_argument('--engine', help='engine path') - - -def main(): - args = parser.parse_args() - project_path = os.path.abspath(args.project) - engine_path = os.path.abspath(args.engine) - print("Init Project... \nProject Path: %s\nEngine Path: %s" % (project_path, engine_path)) - - if args.init: - # check project path exists - assert os.path.exists(project_path) - - project_link = os.path.join(engine_path, "active_project") - engine_asset_path = os.path.join(engine_path, "assets") - engine_asset_link = os.path.join(project_path, "engine_assets") - - # create project link - if os.path.exists(project_link): - os.rmdir(project_link) - os.symlink(project_path, project_link, True) - - # engine asset dir link - if os.path.exists(engine_asset_link): - os.rmdir(engine_asset_link) - os.symlink(engine_asset_path, engine_asset_link) - - -if __name__ == '__main__': - main() diff --git a/build_scripts/build_android.txt b/build_scripts/build_android.txt deleted file mode 100644 index 7031d59b..00000000 --- a/build_scripts/build_android.txt +++ /dev/null @@ -1,5 +0,0 @@ -## glslang -cmake -S . -B build -G "Ninja" -DCMAKE_INSTALL_PREFIX=build/install -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Debug -DANDROID_STL=c++_static -DCMAKE_SYSTEM_VERSION=31 -DANDROID_PLATFORM=android-31 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM=C:\\Users\\blues\\AppData\\Local\\Android\\Sdk\\cmake\\3.22.1\\bin\\ninja.exe -DCMAKE_TOOLCHAIN_FILE=C:\\Users\\blues\\AppData\\Local\\Android\\Sdk\\ndk\\25.0.8775105\\build\\cmake\\android.toolchain.cmake -DANDROID_NDK=C:\\Users\\blues\\AppData\\Local\\Android\\Sdk\\ndk\\25.0.8775105 -DCMAKE_ANDROID_NDK=C:\\Users\\blues\\AppData\\Local\\Android\\Sdk\\ndk\\25.0.8775105 - -pip install setuptools -python update_glslang_sources.py \ No newline at end of file diff --git a/cmake/configuration.cmake b/cmake/configuration.cmake index ef5455e5..99a6d582 100644 --- a/cmake/configuration.cmake +++ b/cmake/configuration.cmake @@ -11,7 +11,7 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") "-framework GameController" "-framework IOKit" "-framework Metal") - set(PLATFORM_BUNDLE MACOSX_BUNDLE) +# set(PLATFORM_BUNDLE MACOSX_BUNDLE) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "iOS") set(PLATFORM_BUNDLE MACOSX_BUNDLE) elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Android") diff --git a/cmake/options.cmake b/cmake/options.cmake index d6f9e5f2..e5611e36 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -3,5 +3,9 @@ SET(3RD_PATH "" CACHE STRING "SkyEngine 3rd path") option(SKY_BUILD_EDITOR "build editor" OFF) option(SKY_BUILD_GLES "build gles" OFF) option(SKY_BUILD_TEST "build test" OFF) -option(SKY_BUILD_DXC "build dxcompiler" OFF) -option(SKY_EDITOR "editor mode" OFF) \ No newline at end of file +option(SKY_EDITOR "editor mode" OFF) +option(SKY_USE_TRACY "use tracy profiler" OFF) + +# todo: controlled by project config json. +option(SKY_BUILD_XR "xr plugin" OFF) +option(SKY_BUILD_PYTHON "python plugin" OFF) \ No newline at end of file diff --git a/cmake/template/CMakeLists_native.txt b/cmake/template/CMakeLists_native.txt new file mode 100644 index 00000000..e4441d86 --- /dev/null +++ b/cmake/template/CMakeLists_native.txt @@ -0,0 +1,4 @@ +add_subdirectory(runtime) +add_subdirectory(launcher) + +sky_set_dependency(TARGET Launcher) \ No newline at end of file diff --git a/cmake/template/CMakeLists_project.txt b/cmake/template/CMakeLists_project.txt new file mode 100644 index 00000000..5709e535 --- /dev/null +++ b/cmake/template/CMakeLists_project.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.19.0) + +PROJECT(@PROJECT_NAME@) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +SET(ENGINE_ROOT "" CACHE STRING "SkyEngine path") +SET(3RD_PATH "" CACHE STRING "SkyEngine 3rd path") + +include(${ENGINE_ROOT}/cmake/functions.cmake) +include(${ENGINE_ROOT}/cmake/options.cmake) +include(${ENGINE_ROOT}/cmake/configuration.cmake) +include(${ENGINE_ROOT}/cmake/thirdparty.cmake) + +add_subdirectory(native) \ No newline at end of file diff --git a/cmake/thirdparty.cmake b/cmake/thirdparty.cmake index 086b1da9..02b2c339 100644 --- a/cmake/thirdparty.cmake +++ b/cmake/thirdparty.cmake @@ -1,4 +1,4 @@ -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/thirdparty) +set(CMAKE_MODULE_PATH ${ENGINE_ROOT}/cmake/thirdparty) function(sky_find_3rd) cmake_parse_arguments(TMP @@ -38,6 +38,7 @@ if(EXISTS ${3RD_PATH}) sky_find_3rd(TARGET sfmt DIR sfmt) sky_find_3rd(TARGET boost DIR boost) sky_find_3rd(TARGET taskflow DIR taskflow) + sky_find_3rd(TARGET mimalloc DIR mimalloc) # framework sky_find_3rd(TARGET rapidjson DIR rapidjson) @@ -48,24 +49,44 @@ if(EXISTS ${3RD_PATH}) sky_find_3rd(TARGET volk DIR volk) sky_find_3rd(TARGET vma DIR VulkanMemoryAllocator) - # tmp + # imgui sky_find_3rd(TARGET imgui DIR imgui) + sky_find_3rd(TARGET implot DIR implot) + sky_find_3rd(TARGET ImGuizmo DIR ImGuizmo) + + # temp + sky_find_3rd(TARGET cxxopts DIR cxxopts) # shader sky_find_3rd(TARGET glslang DIR glslang) sky_find_3rd(TARGET SPIRVCross DIR SPIRV-Cross) - sky_find_3rd(TARGET cxxopts DIR cxxopts) + if (WIN32) + sky_find_3rd(TARGET dxcompiler DIR dxcompiler) + endif () # test sky_find_3rd(TARGET googletest DIR googletest) - if (SKY_BUILD_DXC) - sky_find_3rd(TARGET dxcompiler DIR dxcompiler) + # script + sky_find_3rd(TARGET cpython DIR cpython) + + # text + if (SKY_BUILD_FREETYPE) + sky_find_3rd(TARGET freetype DIR freetype) endif () - if (SKY_BUILD_PERF_TOOL) - sky_find_3rd(TARGET implot DIR implot) - endif() + if (SKY_USE_TRACY) + sky_find_3rd(TARGET tracy DIR tracy) + add_definitions(-DTRACY_ENABLE) + endif () + + if (SKY_BUILD_BULLET) + sky_find_3rd(TARGET bullet3 DIR bullet3) + endif () + + if (SKY_BUILD_RECAST) + sky_find_3rd(TARGET recast DIR recast) + endif () if (SKY_BUILD_TOOL) sky_find_3rd(TARGET assimp DIR assimp) @@ -74,11 +95,16 @@ if(EXISTS ${3RD_PATH}) sky_find_3rd(TARGET PerlinNoise DIR PerlinNoise) sky_find_3rd(TARGET ktx DIR ktx) sky_find_3rd(TARGET ispc_texcomp DIR ispc_texcomp) + sky_find_3rd(TARGET pmp DIR pmp) endif () if (WIN32 OR ANDROID) sky_find_3rd(TARGET gles DIR gles) endif() + + if (SKY_BUILD_XR) + sky_find_3rd(TARGET OpenXR DIR OpenXR_SDK) + endif () else() message(FATAL_ERROR "3rdParty folder: ${3RD_PATH} does not exist, call cmake defining a valid 3RD_PATH") -endif() +endif() \ No newline at end of file diff --git a/cmake/thirdparty/FindImGuizmo.cmake b/cmake/thirdparty/FindImGuizmo.cmake new file mode 100644 index 00000000..a9a1f62c --- /dev/null +++ b/cmake/thirdparty/FindImGuizmo.cmake @@ -0,0 +1,24 @@ +set(LIB_NAME "ImGuizmo") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +if (TARGET ${TARGET_WITH_NAMESPACE}) + return() +endif() + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}ImGuizmo${CMAKE_STATIC_LIBRARY_SUFFIX}) + +set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}ImGuizmo${CMAKE_STATIC_LIBRARY_SUFFIX}) + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/FindOpenXR.cmake b/cmake/thirdparty/FindOpenXR.cmake new file mode 100644 index 00000000..1dca73c4 --- /dev/null +++ b/cmake/thirdparty/FindOpenXR.cmake @@ -0,0 +1,32 @@ +set(LIB_NAME "OpenXR") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +if (TARGET ${TARGET_WITH_NAMESPACE}) + return() +endif() + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +if (MSVC) + set(DEBUG_SUFFIX "d") +endif() + +if (ANDROID) + set(${LIB_NAME}_DYNAMIC_LIBRARY ${${LIB_NAME}_PATH}/libopenxr_loader.so) +else () + set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}openxr_loader${DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) + + set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}openxr_loader${CMAKE_STATIC_LIBRARY_SUFFIX}) + + set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") +endif () + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findbullet3.cmake b/cmake/thirdparty/Findbullet3.cmake new file mode 100644 index 00000000..a4706006 --- /dev/null +++ b/cmake/thirdparty/Findbullet3.cmake @@ -0,0 +1,36 @@ +set(LIB_NAME "bullet3") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include/bullet) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +set(LIB_SUFFIX "d") + +set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Collision${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Common${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Dynamics${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Geometry${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}BulletCollision${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}BulletDynamics${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}LinearMath${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Collision${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Common${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Dynamics${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Bullet3Geometry${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}BulletCollision${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}BulletDynamics${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}LinearMath${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findcpython.cmake b/cmake/thirdparty/Findcpython.cmake new file mode 100644 index 00000000..cbff5fe6 --- /dev/null +++ b/cmake/thirdparty/Findcpython.cmake @@ -0,0 +1,26 @@ +set(LIB_NAME "cpython") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +if (MSVC) + set(${LIB_NAME}_DYNAMIC_LIBRARY ${${LIB_NAME}_PATH}/bin/Release/python313.dll) + set(${LIB_NAME}_LIBRARY_DEBUG ${${LIB_NAME}_LIBS_DIR}/Debug/python313_d.lib) + set(${LIB_NAME}_LIBRARY_RELEASE ${${LIB_NAME}_LIBS_DIR}/Release/python313.lib) +elseif (APPLE) + set(${LIB_NAME}_DYNAMIC_LIBRARY ${${LIB_NAME}_PATH}/python313.dylib) +else() + set(${LIB_NAME}_DYNAMIC_LIBRARY ${${LIB_NAME}_PATH}/python313.so) +endif() + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) +set_target_properties(${TARGET_WITH_NAMESPACE} PROPERTIES INTERFACE_DYN_LIBS ${${LIB_NAME}_DYNAMIC_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findglslang.cmake b/cmake/thirdparty/Findglslang.cmake index fd2f8c09..4e75b58a 100644 --- a/cmake/thirdparty/Findglslang.cmake +++ b/cmake/thirdparty/Findglslang.cmake @@ -10,7 +10,31 @@ set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) if (MSVC) set(LIB_DEBUG_SUFFIX d) endif () -set(${LIB_NAME}_LIBRARY_DEBUG + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}GenericCodeGen${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}glslang${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}glslang-default-resource-limits${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}MachineIndependent${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}OSDependent${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPVRemapper${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools-opt${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) + + set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}GenericCodeGen${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}glslang${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}glslang-default-resource-limits${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}MachineIndependent${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}OSDependent${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPVRemapper${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools-opt${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) +else () + set(${LIB_NAME}_LIBRARY_DEBUG ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}GenericCodeGen${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}glslang${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}glslang-default-resource-limits${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} @@ -23,7 +47,7 @@ set(${LIB_NAME}_LIBRARY_DEBUG ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools-opt${LIB_DEBUG_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}) -set(${LIB_NAME}_LIBRARY_RELEASE + set(${LIB_NAME}_LIBRARY_RELEASE ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}GenericCodeGen${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}glslang${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}glslang-default-resource-limits${CMAKE_STATIC_LIBRARY_SUFFIX} @@ -35,6 +59,9 @@ set(${LIB_NAME}_LIBRARY_RELEASE ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPVRemapper${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools${CMAKE_STATIC_LIBRARY_SUFFIX} ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}SPIRV-Tools-opt${CMAKE_STATIC_LIBRARY_SUFFIX}) +endif () + + set(${LIB_NAME}_LIBRARY "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" diff --git a/cmake/thirdparty/Findimgui.cmake b/cmake/thirdparty/Findimgui.cmake index 68eb7710..51c5635c 100644 --- a/cmake/thirdparty/Findimgui.cmake +++ b/cmake/thirdparty/Findimgui.cmake @@ -8,11 +8,11 @@ set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) set(${LIB_NAME}_LIBRARY_DEBUG - ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Imgui${CMAKE_STATIC_LIBRARY_SUFFIX}) + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}ImGui${CMAKE_STATIC_LIBRARY_SUFFIX}) set(${LIB_NAME}_LIBRARY_RELEASE - ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Imgui${CMAKE_STATIC_LIBRARY_SUFFIX}) - + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}ImGui${CMAKE_STATIC_LIBRARY_SUFFIX}) + set(${LIB_NAME}_LIBRARY "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") diff --git a/cmake/thirdparty/Findimplot.cmake b/cmake/thirdparty/Findimplot.cmake index a8f3a5a5..39f4ccb8 100644 --- a/cmake/thirdparty/Findimplot.cmake +++ b/cmake/thirdparty/Findimplot.cmake @@ -8,10 +8,10 @@ set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) set(${LIB_NAME}_LIBRARY_DEBUG - ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Implot${CMAKE_STATIC_LIBRARY_SUFFIX}) + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}ImPlot${CMAKE_STATIC_LIBRARY_SUFFIX}) set(${LIB_NAME}_LIBRARY_RELEASE - ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Implot${CMAKE_STATIC_LIBRARY_SUFFIX}) + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}ImPlot${CMAKE_STATIC_LIBRARY_SUFFIX}) set(${LIB_NAME}_LIBRARY "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" diff --git a/cmake/thirdparty/Findmimalloc.cmake b/cmake/thirdparty/Findmimalloc.cmake new file mode 100644 index 00000000..a3e88f5f --- /dev/null +++ b/cmake/thirdparty/Findmimalloc.cmake @@ -0,0 +1,24 @@ +set(LIB_NAME "mimalloc") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +if (TARGET ${TARGET_WITH_NAMESPACE}) + return() +endif() + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}mimalloc${CMAKE_STATIC_LIBRARY_SUFFIX}) + +set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}mimalloc${CMAKE_STATIC_LIBRARY_SUFFIX}) + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findpmp.cmake b/cmake/thirdparty/Findpmp.cmake new file mode 100644 index 00000000..69359158 --- /dev/null +++ b/cmake/thirdparty/Findpmp.cmake @@ -0,0 +1,19 @@ +set(LIB_NAME "pmp") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +if (TARGET ${TARGET_WITH_NAMESPACE}) + return() +endif() + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +set(${LIB_NAME}_LIBRARY + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}pmp${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}pmp_vis${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findrecast.cmake b/cmake/thirdparty/Findrecast.cmake new file mode 100644 index 00000000..3c9a5c1b --- /dev/null +++ b/cmake/thirdparty/Findrecast.cmake @@ -0,0 +1,32 @@ +set(LIB_NAME "recast") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include/recastnavigation) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) + +set(LIB_SUFFIX "-d") + +set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}DebugUtils${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}DetourCrowd${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Detour${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}DetourTileCache${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}Recast${LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}DebugUtils${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}DetourCrowd${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Detour${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}DetourTileCache${CMAKE_STATIC_LIBRARY_SUFFIX} + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}Recast${CMAKE_STATIC_LIBRARY_SUFFIX} +) + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/Findtracy.cmake b/cmake/thirdparty/Findtracy.cmake new file mode 100644 index 00000000..eda93b51 --- /dev/null +++ b/cmake/thirdparty/Findtracy.cmake @@ -0,0 +1,33 @@ +set(LIB_NAME "tracy") +set(TARGET_WITH_NAMESPACE "3rdParty::${LIB_NAME}") +if (TARGET ${TARGET_WITH_NAMESPACE}) + return() +endif() + +set(${LIB_NAME}_INCLUDE_DIR ${${LIB_NAME}_PATH}/include) +set(${LIB_NAME}_LIBS_DIR ${${LIB_NAME}_PATH}/lib) +set(${LIB_NAME}_BIN_DIR ${${LIB_NAME}_PATH}/bin) + +set(${LIB_NAME}_LIBRARY_DEBUG + ${${LIB_NAME}_LIBS_DIR}/Debug/${CMAKE_STATIC_LIBRARY_PREFIX}TracyClient${CMAKE_STATIC_LIBRARY_SUFFIX}) + +set(${LIB_NAME}_LIBRARY_RELEASE + ${${LIB_NAME}_LIBS_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}TracyClient${CMAKE_STATIC_LIBRARY_SUFFIX}) + +#set(${LIB_NAME}_DYN_LIBRARY_DEBUG +# ${${LIB_NAME}_BIN_DIR}/Debug/TracyClient.dll) + +set(${LIB_NAME}_DYN_LIBRARY_RELEASE + ${${LIB_NAME}_BIN_DIR}/Release/TracyClient.dll) + +set(${LIB_NAME}_LIBRARY + "$<$:${${LIB_NAME}_LIBRARY_RELEASE}>" + "$<$:${${LIB_NAME}_LIBRARY_DEBUG}>") + +add_library(${TARGET_WITH_NAMESPACE} INTERFACE IMPORTED GLOBAL) +target_include_directories(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_INCLUDE_DIR}) +target_link_libraries(${TARGET_WITH_NAMESPACE} INTERFACE ${${LIB_NAME}_LIBRARY}) + +set_target_properties(${TARGET_WITH_NAMESPACE} PROPERTIES INTERFACE_DYN_LIBS ${${LIB_NAME}_DYN_LIBRARY_RELEASE}) + +set(${LIB_NAME}_FOUND True) diff --git a/cmake/thirdparty/compile.txt b/cmake/thirdparty/compile.txt new file mode 100644 index 00000000..229247dc --- /dev/null +++ b/cmake/thirdparty/compile.txt @@ -0,0 +1,8 @@ +# bullet3 +-DBUILD_BULLET2_DEMOS=OFF -DBUILD_OPENGL3_DEMOS=OFF -DBUILD_CPU_DEMOS=OFF -DBUILD_UNIT_TESTS=OFF -DUSE_GRAPHICAL_BENCHMARK=OFF -DBUILD_EXTRAS=OFF -DINSTALL_LIBS=ON + +# recast +-DRECASTNAVIGATION_TESTS=OFF -DRECASTNAVIGATION_EXAMPLES=OFF -DRECASTNAVIGATION_DEMO=OFF + +# Polygon Mesh Processing +-DBUILD_SHARED_LIBS=OFF \ No newline at end of file diff --git a/core/include/core/archive/FileArchive.h b/core/include/core/archive/FileArchive.h deleted file mode 100644 index 9768013d..00000000 --- a/core/include/core/archive/FileArchive.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by blues on 2024/2/7. -// - -#pragma once - -#include -#include - -namespace sky { - - class IFileArchive : public IStreamArchive { - public: - explicit IFileArchive(const std::string &path); - ~IFileArchive() = default; - - bool IsOpen() const { return stream.is_open(); } - private: - std::fstream stream; - }; - - class OFileArchive : public OStreamArchive { - public: - explicit OFileArchive(const std::string &path); - ~OFileArchive() = default; - - private: - std::fstream stream; - }; - -} // namespace sky diff --git a/core/include/core/archive/MemoryArchive.h b/core/include/core/archive/MemoryArchive.h deleted file mode 100644 index ad673e08..00000000 --- a/core/include/core/archive/MemoryArchive.h +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by blues on 2024/1/14. -// - -#pragma once - -#include "ArchiveConcept.h" -#include - -namespace sky { - - class MemoryArchive { - public: - MemoryArchive() = default; - ~MemoryArchive() = default; - - bool Save(const char *data, size_t size); - - template - bool Save(const T &v) - { - auto size = v.size() * sizeof(typename T::value_type); - bool res = true; - res &= Save(static_cast(size)); - res &= Save(reinterpret_cast(v.data()), size); - return res; - } - - template - bool Save(const T &v) - { - return Save(reinterpret_cast(&v), sizeof(T)); - } - - template - MemoryArchive &operator<<(const T &v) - { - Save(v); - return *this; - } - - void Swap(std::vector &out) { return out.swap(storage); } - const std::vector &GetData() const { return storage; } - - private: - std::vector storage; - }; - -} // namespace sky \ No newline at end of file diff --git a/core/include/core/archive/StreamArchive.h b/core/include/core/archive/StreamArchive.h deleted file mode 100644 index 1caad567..00000000 --- a/core/include/core/archive/StreamArchive.h +++ /dev/null @@ -1,81 +0,0 @@ -// -// Created by bluesky on 2023/10/11. -// - -#pragma once - -#include -#include - -namespace sky { - - class IStreamArchive { - public: - explicit IStreamArchive(std::istream &s) : stream(s) {} - ~IStreamArchive() = default; - - bool Load(char *data, size_t size); - - template - bool Load(T &v) - { - uint32_t size = 0; - bool res = true; - res &= Load(size); - v.resize(size / sizeof(typename T::value_type)); - res &= Load(reinterpret_cast(v.data()), size); - return res; - } - - template - bool Load(T &val) - { - return Load(reinterpret_cast(&val), sizeof(T)); - } - - template - IStreamArchive &operator>>(T &v) - { - Load(v); - return *this; - } - - private: - std::istream &stream; - }; - - class OStreamArchive { - public: - explicit OStreamArchive(std::ostream &s) : stream(s) {} - ~OStreamArchive() = default; - - bool Save(const char *data, size_t size); - - template - bool Save(const T &v) - { - auto size = v.size() * sizeof(typename T::value_type); - bool res = true; - res &= Save(static_cast(size)); - res &= Save(reinterpret_cast(v.data()), size); - return res; - } - - template - bool Save(const T &v) - { - return Save(reinterpret_cast(&v), sizeof(T)); - } - - template - OStreamArchive &operator<<(const T &v) - { - Save(v); - return *this; - } - - private: - std::ostream &stream; - }; - -} // namespace sky \ No newline at end of file diff --git a/core/include/core/file/FileIO.h b/core/include/core/file/FileIO.h deleted file mode 100644 index 9178ba5e..00000000 --- a/core/include/core/file/FileIO.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zach Lee on 2022/1/16. -// - -#pragma once -#include -#include - -namespace sky { - - void WriteBin(const std::string &path, const char *data, size_t size); - void WriteString(const std::string &path, const std::string &out); - - bool ReadBin(const std::string &path, uint8_t *&out, uint32_t &size); - bool ReadBin(const std::string &path, std::vector &out); - bool ReadBin(const std::string &path, std::vector &out); - bool ReadString(const std::string &path, std::string &out); - -} // namespace sky \ No newline at end of file diff --git a/core/include/core/jobsystem/JobSystem.h b/core/include/core/jobsystem/JobSystem.h deleted file mode 100644 index ce0a6c77..00000000 --- a/core/include/core/jobsystem/JobSystem.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by Zach Lee on 2022/6/21. -// - -#pragma once - -#include "core/environment/Singleton.h" -#include "core/util/Macros.h" -#include - -namespace sky { - - class JobSystem : public Singleton { - public: - void RunAndWait(tf::Taskflow &flow) - { - executor.run(flow).wait(); - } - - auto Run(tf::Taskflow &flow) - { - return executor.run(flow); - } - - auto Run(tf::Taskflow &&flow) - { - return executor.run(std::forward(flow)); - } - - private: - friend class Singleton; - JobSystem() = default; - ~JobSystem() = default; - - tf::Executor executor; - }; - -} // namespace sky \ No newline at end of file diff --git a/core/include/core/math/Rect.h b/core/include/core/math/Rect.h deleted file mode 100644 index bf57ad5f..00000000 --- a/core/include/core/math/Rect.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by Zach Lee on 2021/11/14. -// - -#pragma once - -#include - -namespace sky { - - struct Rect { - int32_t xOffset; - int32_t yOffset; - uint32_t width; - uint32_t height; - }; - -} // namespace sky diff --git a/core/include/core/shapes/AABB.h b/core/include/core/shapes/AABB.h deleted file mode 100644 index 0c068888..00000000 --- a/core/include/core/shapes/AABB.h +++ /dev/null @@ -1,18 +0,0 @@ -// -// Created by Zach Lee on 2023/8/29. -// - -#pragma once - -#include - -namespace sky { - - struct AABB { - Vector3 min; - Vector3 max; - }; - - void Merge(const AABB &a, const AABB &b, AABB &out); - -} // namespace sky diff --git a/core/include/core/template/ReferenceObject.h b/core/include/core/template/ReferenceObject.h deleted file mode 100644 index 1f4e9bb5..00000000 --- a/core/include/core/template/ReferenceObject.h +++ /dev/null @@ -1,161 +0,0 @@ -// -// Created by Zach Lee on 2021/12/19. -// - -#pragma once - -#include -#include - -namespace sky { - - template - class RefObject { - public: - using ObjType = T; - - RefObject() : counter{} - { - } - - virtual ~RefObject() - { - } - - virtual void AddRef() - { - counter.fetch_add(1); - } - - virtual void RemoveRef() - { - auto prev = counter.fetch_sub(1); - SKY_ASSERT(prev >= 1); - if (prev == 1) { - OnExpire(); - } - } - - virtual void OnExpire() - { - } - - uint32_t GetRef() const - { - return counter.load(); - } - - private: - std::atomic_uint32_t counter; - }; - - template - class CounterPtrBase { - public: - CounterPtrBase(T *p) : ptr(p) - { - if (ptr != nullptr) { - ptr->AddRef(); - } - } - - virtual ~CounterPtrBase() - { - if (ptr != nullptr) { - ptr->RemoveRef(); - } - } - - CounterPtrBase(const CounterPtrBase &p) - { - UpdateRefs(p); - } - - CounterPtrBase &operator=(const CounterPtrBase &p) - { - UpdateRefs(p); - return *this; - } - - T *Get() - { - return ptr; - } - - const T *Get() const - { - return ptr; - } - - protected: - void UpdateRefs(const CounterPtrBase &p) - { - if (ptr != nullptr) { - ptr->RemoveRef(); - } - ptr = p.ptr; - if (ptr != nullptr) { - ptr->AddRef(); - } - } - - T *ptr = nullptr; - }; - - template - class CounterPtr : public CounterPtrBase { - public: - CounterPtr() : CounterPtrBase(nullptr) - { - } - - template - CounterPtr(U *p) : CounterPtrBase(p) - { - } - - template - CounterPtr(CounterPtr &u) : CounterPtrBase(u.Get()) - { - static_assert(std::is_base_of_v, "U must derived from T"); - } - - template - CounterPtr &operator=(const CounterPtr &u) - { - static_assert(std::is_base_of_v, "U must derived from T"); - CounterPtrBase::operator=(u); - return *this; - } - - ~CounterPtr() - { - } - - operator bool() - { - return CounterPtrBase::ptr != nullptr; - } - - T *Get() - { - return static_cast(CounterPtrBase::ptr); - } - - const T *Get() const - { - return static_cast(CounterPtrBase::ptr); - } - - T *operator->() - { - return Get(); - } - - const T *operator->() const - { - return Get(); - } - }; - -} // namespace sky \ No newline at end of file diff --git a/core/include/core/type/Rtti.h b/core/include/core/type/Rtti.h deleted file mode 100644 index 3b17bea1..00000000 --- a/core/include/core/type/Rtti.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// Created by Zach Lee on 2021/12/3. -// - -#pragma once - -#ifdef _MSC_VER - #define PRETTY_FUNC __FUNCSIG__ -#else - #define PRETTY_FUNC __PRETTY_FUNCTION__ -#endif - -#include -#include -#include - -namespace sky { - - template - constexpr std::string_view PrettyFunc() - { - return PRETTY_FUNC; - } - - template - struct TypeInfo { - - static constexpr std::string_view Name() - { - return PrettyFunc(); - } - - static constexpr uint32_t Hash() - { - return Fnv1a32(Name()); - } - - static constexpr T *Allocate() - { - return new T(); - } - - static constexpr void Free(T *ptr) - { - ptr->~T(); - } - }; - - using Destructor = void (*)(void *ptr); - using Constructor = void (*)(void *ptr); - using CopyFn = void (*)(const void *src, void *dst); - - struct TypeInfoRT { - std::string_view markedName; - const std::string_view signature; - const uint32_t typeId; - const size_t rank; - const size_t size; - const bool isFundamental; - const bool isVoid; - const bool isNullptr; - const bool isArithmetic; - const bool isFloatingPoint; - const bool isInteger; - const bool isCompound; - const bool isPointer; - const bool isMemberObjectPointer; - const bool isMemberFunctionPointer; - const bool isArray; - const bool isEnum; - const bool isUnion; - const bool isClass; - const bool isTrivial; - Constructor constructor = nullptr; - Destructor destructor = nullptr; - CopyFn copy = nullptr; - }; - - template - struct TypeAllocate { - static constexpr bool CTOR = std::is_default_constructible_v; - static constexpr bool DTOR = std::is_destructible_v; - static constexpr bool COPY = std::is_copy_constructible_v; - - static void Construct(void *ptr) - { - if constexpr (CTOR) { - new (ptr) T{}; - } - } - - static void Destruct(void *ptr) - { - if constexpr (DTOR) { - ((T *)ptr)->~T(); - } - } - - static void Copy(const void *src, void *dst) - { - if constexpr (COPY) { - new (dst) T{*((T *)src)}; - } - } - }; - -} // namespace sky diff --git a/core/include/core/type/Type.h b/core/include/core/type/Type.h deleted file mode 100644 index 4678cd0e..00000000 --- a/core/include/core/type/Type.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Created by Zach Lee on 2021/12/9. -// - -#pragma once -#include -#include - -namespace sky { - - template - class TypeInfoObj : public Singleton> { - public: - TypeInfoRT *RtInfo() - { - if (info == nullptr) { - std::lock_guard lock(mutex); - if (info == nullptr) { - info = new TypeInfoRT{ - "", // name - TypeInfo::Name(), // typeId - TypeInfo::Hash(), // hash - std::rank_v, // rank - sizeof(T), // size - std::is_fundamental_v, // isFundamental - std::is_void_v, // isVoid - std::is_null_pointer_v, // isNullptr - std::is_arithmetic_v, // isArithmetic - std::is_floating_point_v, // isFloatingPoint - std::is_integral_v, // isInteger - std::is_compound_v, // isCompound - std::is_pointer_v, // isPointer - std::is_member_pointer_v, // isMemberObjectPointer - std::is_member_function_pointer_v, // isMemberFunctionPointer - std::is_array_v, // isArray; - std::is_enum_v, // isEnum; - std::is_union_v, // isUnion; - std::is_class_v, // isClass; - std::is_trivial_v, // isTrivial; - TypeAllocate::CTOR ? &TypeAllocate::Construct : nullptr, - TypeAllocate::DTOR ? &TypeAllocate::Destruct : nullptr, - TypeAllocate::COPY ? &TypeAllocate::Copy : nullptr - }; - } - } - return info; - } - - private: - std::mutex mutex; - TypeInfoRT *info = nullptr; - }; - - template - struct FuncTraits; - - template - struct FuncTraits { - using CLASS_TYPE = Cls; - using RET_TYPE = Ret; - using ARGS_TYPE = std::tuple; - static constexpr bool CONST = false; - }; - - template - struct FuncTraits { - using CLASS_TYPE = Cls; - using RET_TYPE = Ret; - using ARGS_TYPE = std::tuple; - static constexpr bool CONST = true; - }; - - template - struct FuncTraits { - using RET_TYPE = Ret; - using ARGS_TYPE = std::tuple; - }; - -} // namespace sky diff --git a/core/src/archive/FileArchive.cpp b/core/src/archive/FileArchive.cpp deleted file mode 100644 index a676ab4f..00000000 --- a/core/src/archive/FileArchive.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by blues on 2024/2/7. -// - -#include - -namespace sky { - - IFileArchive::IFileArchive(const std::string &path) - : stream(path.c_str(), std::ios::binary | std::ios::in) - , IStreamArchive(stream) - { - } - - OFileArchive::OFileArchive(const std::string &path) - : stream(path.c_str(), std::ios::binary | std::ios::out) - , OStreamArchive(stream) - { - } - -} // namespace sky \ No newline at end of file diff --git a/core/src/archive/MemoryAchive.cpp b/core/src/archive/MemoryAchive.cpp deleted file mode 100644 index 398aa006..00000000 --- a/core/src/archive/MemoryAchive.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by blues on 2024/1/14. -// - -#include - -namespace sky { - - bool MemoryArchive::Save(const char *data, size_t size) - { - if (data != nullptr && size != 0) { - auto offset = storage.size(); - storage.resize(offset + size); - memcpy(&storage[offset], data, size); - } - return true; - } - -} // namespace sky \ No newline at end of file diff --git a/core/src/archive/StreamArchive.cpp b/core/src/archive/StreamArchive.cpp deleted file mode 100644 index dd382593..00000000 --- a/core/src/archive/StreamArchive.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by blues on 2023/10/11. -// - -#include "core/archive/StreamArchive.h" - -namespace sky { - - bool IStreamArchive::Load(char *data, size_t size) - { - return stream.rdbuf()->sgetn(data, static_cast(size)) == size; - } - - bool OStreamArchive::Save(const char *data, size_t size) - { - return stream.rdbuf()->sputn(data, static_cast(size)) == size; - } - -} // namespace sky \ No newline at end of file diff --git a/core/src/shapes/AABB.cpp b/core/src/shapes/AABB.cpp deleted file mode 100644 index a406eb72..00000000 --- a/core/src/shapes/AABB.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Created by Zach Lee on 2023/8/29. -// - -#include -#include - -namespace sky { - - void Merge(const AABB &a, const AABB &b, AABB &out) - { - out.min = Min(a.min, b.min); - out.max = Max(a.max, b.max); - } - -} // namespace sky diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index d7a4248d..fb488cae 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -19,8 +19,6 @@ if (Qt5_FOUND) INCS include LIBS - SkyEngine - SkyRenderAdaptor EditorFramework ) diff --git a/editor/framework/CMakeLists.txt b/editor/framework/CMakeLists.txt index ff321da4..5e4002a7 100644 --- a/editor/framework/CMakeLists.txt +++ b/editor/framework/CMakeLists.txt @@ -10,6 +10,8 @@ sky_add_library(TARGET EditorFramework STATIC PUBLIC_INC include LINK_LIBS - Core + Framework + RenderAdaptor + Physics ${QtLibs} ) diff --git a/editor/framework/include/editor/framework/AssetBrowserWidget.h b/editor/framework/include/editor/framework/AssetBrowserWidget.h new file mode 100644 index 00000000..80bc5780 --- /dev/null +++ b/editor/framework/include/editor/framework/AssetBrowserWidget.h @@ -0,0 +1,58 @@ +// +// Created by blues on 2024/7/12. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + class AssetFilterProxyModel : public QSortFilterProxyModel { + public: + explicit AssetFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent) {} + ~AssetFilterProxyModel() override = default; + + private: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; + }; + + class AssetListView : public QListView { + public: + explicit AssetListView(QWidget *parent) : QListView(parent) {} + ~AssetListView() override = default; + + void SetAssetBundle(SourceAssetBundle bundle) { assetBundle = bundle; } + SourceAssetBundle GetAssetBundle() const { return assetBundle; } + private: + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + + QPoint startPos = {}; + SourceAssetBundle assetBundle; + }; + + class AssetBrowserWidget : public QWidget { + public: + explicit AssetBrowserWidget(QWidget *parent); + ~AssetBrowserWidget() override = default; + + private: + void ResetView(); + void OnContentMenuClicked(const QPoint &pos); + + AssetListView* assetItemView = nullptr; + QLineEdit* filter = nullptr; + QComboBox* comboBox = nullptr; + }; + + +} // namespace sky::editor diff --git a/editor/framework/include/editor/framework/AssetEditorProxy.h b/editor/framework/include/editor/framework/AssetEditorProxy.h new file mode 100644 index 00000000..568a422f --- /dev/null +++ b/editor/framework/include/editor/framework/AssetEditorProxy.h @@ -0,0 +1,51 @@ +// +// Created by blues on 2024/7/12. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + class AssetItem : public QStandardItem { + public: + explicit AssetItem(const AssetSourcePtr &ptr); + ~AssetItem() override = default; + + private: + AssetSourcePtr source; + }; + + class AssetItemModel : public QStandardItemModel { + public: + explicit AssetItemModel(QObject *parent) : QStandardItemModel(parent) {} + ~AssetItemModel() override = default; + }; + + class AssetDataBaseProxy : public Singleton { + public: + AssetDataBaseProxy(); + ~AssetDataBaseProxy() override = default; + + AssetItemModel *GetModel() const { return model.get(); } + QFileSystemModel *GetProjectModel() const { return projectModel.get(); } + QFileSystemModel *GetEngineModel() const { return engineModel.get(); } + + const std::unordered_map& GetCategoryTable() const { return categoryLut; } + + private: + void Refresh(); + + std::unique_ptr model; + std::unique_ptr projectModel; + std::unique_ptr engineModel; + std::unordered_map categoryLut; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/include/editor/framework/EditorCamera.h b/editor/framework/include/editor/framework/EditorCamera.h new file mode 100644 index 00000000..6995db07 --- /dev/null +++ b/editor/framework/include/editor/framework/EditorCamera.h @@ -0,0 +1,35 @@ +// +// Created by blues on 2024/7/10. +// + +#pragma once + +#include +#include +#include + +namespace sky::editor { + + class EditorCamera { + public: + EditorCamera() = default; + ~EditorCamera() = default; + + void Init(RenderScene* scene, NativeWindow *window); + void Shutdown(); + void Tick(float time); + void UpdateAspect(uint32_t width, uint32_t height); + + private: + FirstPersonController controller; + SceneView *sceneView = nullptr; + RenderScene *renderScene = nullptr; + Transform transform = {}; + + float near = 0.1f; + float far = 10000.f; + float fov = 60.f; + float aspect = 1.f; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/include/editor/framework/ReflectedObjectWidget.h b/editor/framework/include/editor/framework/ReflectedObjectWidget.h new file mode 100644 index 00000000..2d305ab5 --- /dev/null +++ b/editor/framework/include/editor/framework/ReflectedObjectWidget.h @@ -0,0 +1,285 @@ +// +// Created by blues on 2024/7/7. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + class ReflectedMemberWidget; + + class ReflectedObjectWidget : public QWidget { + public: + ReflectedObjectWidget(void *obj, const TypeNode *node, QWidget *parent); + ~ReflectedObjectWidget() override = default; + + protected: + virtual void Refresh(); + + void *object; + const TypeNode *typeNode = nullptr; + + std::vector members; + }; + + class ReflectedMemberWidget : public QWidget { + public: + ReflectedMemberWidget(void *obj, const TypeMemberNode *node, QWidget *parent) + : QWidget(parent) + , object(obj) + , memberNode(node) + { + setLayout(new QHBoxLayout(this)); + layout()->setAlignment(Qt::AlignLeft); + layout()->setContentsMargins(0, 0, 0, 0); + } + ~ReflectedMemberWidget() override = default; + + protected: + void *object; + const TypeMemberNode* memberNode = nullptr; + }; + + template + class PropertyScalar : public ReflectedMemberWidget { + public: + explicit PropertyScalar(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + line = new QLineEdit(this); + layout()->addWidget(line); + + if constexpr (std::is_floating_point_v) { + line->setValidator(new QDoubleValidator(this)); + } else if constexpr (std::is_integral_v) { + line->setValidator(new QIntValidator(std::numeric_limits::min(), std::numeric_limits::max(), this)); + } + + connect(line, &QLineEdit::textEdited, this, [this](const QString &s) { + T value = 0; + if constexpr (std::is_floating_point_v) { + value = static_cast(s.toDouble()); + } else if constexpr (std::is_signed_v) { + value = static_cast(s.toInt()); + } else if constexpr (std::is_unsigned_v) { + value = static_cast(s.toUInt()); + } + memberNode->setterFn(object, &value); + RefreshValue(); + }); + + RefreshValue(); + } + + void RefreshValue() + { + auto anyVal = memberNode->getterConstFn(object); + auto *val = static_cast(anyVal.Data()); + line->setText(QString::number(*val)); + } + + ~PropertyScalar() override = default; + + private: + QLineEdit* line; + }; + + template + class PropertyVec : public ReflectedMemberWidget { + public: + explicit PropertyVec(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + auto *validator = new QDoubleValidator(this); + for (uint32_t i = 0; i < N; ++i) { + line[i] = new QLineEdit(this); + line[i]->setValidator(validator); + layout()->addWidget(line[i]); + connect(line[i], &QLineEdit::editingFinished, this, [i, this]() { + value[i] = static_cast(line[i]->text().toDouble()); + memberNode->setterFn(object, value); + RefreshValue(i); + }); + } + RefreshValue(); + } + + void RefreshValue() + { + auto anyVal = memberNode->getterConstFn(object); + auto *val = static_cast(anyVal.Data()); + for (uint32_t i = 0; i < N; ++i) { + value[i] = val[i]; + line[i]->setText(QString::number(val[i])); + } + } + + void RefreshValue(int i) + { + line[i]->setText(QString::number(value[i])); + } + + ~PropertyVec() override = default; + + private: + QLineEdit* line[N]; + float value[N] = {0}; + }; + + class PropertyColor : public ReflectedMemberWidget { + public: + PropertyColor(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + button = new QPushButton(this); + button->setFixedWidth(32); + layout()->addWidget(button); + + connect(button, &QPushButton::clicked, this, [this](bool v) { + QColorDialog dialog; + if (dialog.exec() != 0) { + auto qColor = dialog.selectedColor(); + auto color = Color(static_cast(qColor.redF()), + static_cast(qColor.greenF()), + static_cast(qColor.blueF()), + static_cast(qColor.alphaF()) + ); + memberNode->setterFn(object, &color); + + RefreshValue(qColor); + } + }); + RefreshValue(); + } + + void RefreshValue() + { + auto anyVal = memberNode->getterConstFn(object); + auto *color = anyVal.GetAs(); + QColor qColor; + qColor.setRedF(color->r); + qColor.setGreenF(color->g); + qColor.setBlueF(color->b); + qColor.setAlphaF(color->a); + RefreshValue(qColor); + } + + void RefreshValue(const QColor &qColor) + { + if(qColor.isValid()) { + QString qss = QString("background-color: %1").arg(qColor.name()); + button->setStyleSheet(qss); + } + } + + ~PropertyColor() override = default; + + private: + QPushButton *button = nullptr; + }; + + class AssetLineEditor : public QLineEdit { + public: + explicit AssetLineEditor(QWidget *parent) : QLineEdit(parent) {} + ~AssetLineEditor() override = default; + + private: + void dropEvent(QDropEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + }; + + class PropertyUuid : public ReflectedMemberWidget { + public: + PropertyUuid(void *obj, const TypeMemberNode *node, QWidget *parent); + ~PropertyUuid() override = default; + + void RefreshValue(); + + private: + QLineEdit* lineEdit = nullptr; + std::string_view assetType; + }; + + class PropertyBool : public ReflectedMemberWidget { + public: + PropertyBool(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + box = new QCheckBox(this); + layout()->addWidget(box); + + connect(box, &QCheckBox::stateChanged, this, [this](int v) { + bool val = (v == Qt::Checked); + memberNode->setterFn(object, &val); + }); + RefreshValue(); + } + + void RefreshValue() + { + auto any = memberNode->getterConstFn(object); + auto *pVal = any.GetAs(); + box->setCheckState(*pVal ? Qt::Checked : Qt::Unchecked); + } + + ~PropertyBool() override = default; + + private: + QCheckBox *box = nullptr; + }; + + class PropertyEnum : public ReflectedMemberWidget { + public: + PropertyEnum(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + box = new QComboBox(this); + layout()->addWidget(box); + + info = GetTypeNode(node->info); + for (const auto &[value, key] : info->enums) { + box->addItem(key.data()); + } +tatus + connect(box, qOverload(&QComboBox::activated), this, [this](int index) { + auto str = box->itemText(index); + for (const auto &[key, val] : info->enums) { + if (val == std::string_view(str.toStdString())) { + memberNode->setterFn(object, &key); + break; + } + } + + }); + RefreshValue(); + } + ~PropertyEnum() override = default; + + private: + void RefreshValue() + { + auto any = memberNode->getterConstFn(object); + auto *pVal = any.GetAs(); + + SKY_ASSERT(info->enums.count(*pVal)); + box->setCurrentText(info->enums.at(*pVal).data()); + } + + const TypeNode* info = nullptr; + QComboBox *box = nullptr; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/include/editor/framework/SThemeWidget.h b/editor/framework/include/editor/framework/SThemeWidget.h new file mode 100644 index 00000000..90ac9c0a --- /dev/null +++ b/editor/framework/include/editor/framework/SThemeWidget.h @@ -0,0 +1,19 @@ +// +// Created by blues on 2024/7/10. +// + +#pragma once + +#include + +namespace sky::editor { + + class SThemeWidget : public QWidget { + public: + explicit SThemeWidget(QWidget *parent) : QWidget(parent) + { + + } + }; + +} // namespace sky::editor diff --git a/editor/framework/include/editor/framework/ViewportWidget.h b/editor/framework/include/editor/framework/ViewportWidget.h new file mode 100644 index 00000000..63f8650f --- /dev/null +++ b/editor/framework/include/editor/framework/ViewportWidget.h @@ -0,0 +1,68 @@ +// +// Created by blues on 2024/7/10. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + class RenderWindow; +} // namespace sky + +namespace sky::editor { + + class ViewportWindow : public QWindow, public NativeWindow { + public: + explicit ViewportWindow(QWindow *parent = nullptr); + ~ViewportWindow() override = default; + + private: + bool event(QEvent *event) override; + }; + + class ViewportWidget : public QWidget, public IWindowEvent, public ITickEvent { + public: + explicit ViewportWidget(QWidget *parent); + ~ViewportWidget() override; + + void ResetWorld(const WorldPtr &world); + void UpdatePipeline(); + void ResetPipeline(); + + ViewportWindow* GetViewportWindow() const { return window; } + private: + void OnWindowResize(uint32_t width, uint32_t height) override; + void dropEvent(QDropEvent *event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragMoveEvent(QDragMoveEvent *event) override; + + void Tick(float time) override; + + ViewportWindow *window = nullptr; + RenderWindow *renderWindow = nullptr; + QWidget* windowContainer = nullptr; + QVBoxLayout* layout = nullptr; + WorldPtr world; + + RenderSceneProxy* sceneProxy = nullptr; + std::unique_ptr editorCamera; + std::unique_ptr gizmo; + + std::unique_ptr profiler; + EventBinder binder; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/include/editor/framework/WorldTreeView.h b/editor/framework/include/editor/framework/WorldTreeView.h new file mode 100644 index 00000000..e7a5cce7 --- /dev/null +++ b/editor/framework/include/editor/framework/WorldTreeView.h @@ -0,0 +1,47 @@ +// +// Created by blues on 2024/7/6. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky::editor { + + class WorldActorItem : public QStandardItem { + public: + explicit WorldActorItem(const ActorPtr& actor_) : QStandardItem(QString().fromStdString(actor_->GetName())), actor(actor_) {} + ~WorldActorItem() override = default; + + ActorPtr actor; + }; + + class WorldTreeView : public QWidget { + Q_OBJECT + public: + explicit WorldTreeView(QWidget *parent); + ~WorldTreeView() override = default; + + void BuildByWorld(const WorldPtr &world); + void RebuildTree(); + + Q_SIGNALS: + void WorldTreeSelectItemChanged(ActorPtr actor); // NOLINT + + private: + void GatherAllChildren(std::vector &actors, QStandardItem *item); + + void OnItemChanged(QStandardItem *item); + void OnContentMenuClicked(const QPoint &pos); + void OnSelectItemChanged(const QItemSelection &selected, const QItemSelection &deselected); + + QStandardItemModel *model = nullptr; + QTreeView *treeView = nullptr; + + WorldPtr attachedWorld; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/src/AssetBrowserWidget.cpp b/editor/framework/src/AssetBrowserWidget.cpp new file mode 100644 index 00000000..44145c6b --- /dev/null +++ b/editor/framework/src/AssetBrowserWidget.cpp @@ -0,0 +1,162 @@ +// +// Created by blues on 2024/7/12. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + bool AssetFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const + { + return true; + } + + AssetBrowserWidget::AssetBrowserWidget(QWidget *parent) : QWidget(parent) + { + setLayout(new QVBoxLayout(this)); + + auto *filterWidget = new QWidget(this); + filterWidget->setLayout(new QHBoxLayout(filterWidget)); + + filter = new QLineEdit(filterWidget); + filter->setClearButtonEnabled(true); + filter->setPlaceholderText("Search..."); + + auto *button = new QPushButton(this); + button->setFixedWidth(32); + button->setText("<<"); + connect(button, &QPushButton::clicked, this, &AssetBrowserWidget::ResetView); + + comboBox = new QComboBox(this); + comboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); + connect(comboBox, static_cast(&QComboBox::currentIndexChanged), this, + [this](int) { + ResetView(); + }); + comboBox->addItem("Project", static_cast(SourceAssetBundle::WORKSPACE)); + comboBox->addItem("Engine", static_cast(SourceAssetBundle::ENGINE)); + + filterWidget->layout()->addWidget(comboBox); + filterWidget->layout()->addWidget(button); + filterWidget->layout()->addWidget(filter); + + assetItemView = new AssetListView(this); + assetItemView->setWordWrap(true); + assetItemView->setViewMode(QListView::IconMode); + assetItemView->setIconSize(QSize(48, 48)); + assetItemView->setGridSize(QSize(128, 72)); + assetItemView->setUniformItemSizes(true); + assetItemView->setMovement(QListView::Static); + assetItemView->setResizeMode(QListView::Adjust); + assetItemView->setLayoutMode(QListView::Batched); + assetItemView->setBatchSize(10); + assetItemView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); + assetItemView->setContextMenuPolicy(Qt::CustomContextMenu); + + assetItemView->setDragEnabled(true); + assetItemView->setDragDropMode(QAbstractItemView::DragDropMode::DragDrop); + + auto *model = AssetDataBaseProxy::Get()->GetProjectModel(); + assetItemView->setModel(model); + assetItemView->setRootIndex(model->setRootPath(model->rootPath())); + assetItemView->SetAssetBundle(SourceAssetBundle::WORKSPACE); + + connect(assetItemView, &QAbstractItemView::activated, this, [this](const QModelIndex &index) { + auto *model = static_cast(assetItemView->model()); + auto path = model->filePath(index); + if (QFileInfo(path).isDir()) { + assetItemView->setRootIndex(model->index(path)); + } + }); + + layout()->addWidget(filterWidget); + layout()->addWidget(assetItemView); + + + connect(assetItemView, &QWidget::customContextMenuRequested, this, &AssetBrowserWidget::OnContentMenuClicked); + } + + void AssetBrowserWidget::OnContentMenuClicked(const QPoint &pos) + { + QMenu menu(tr("Asset Actions"), this); + + auto *buildAct = new QAction(tr("Build"), &menu); + connect(buildAct, &QAction::triggered, this, [this]() { + auto indices = assetItemView->selectionModel()->selectedIndexes(); + auto *fsModel = static_cast(assetItemView->model()); + QDir root = fsModel->rootPath(); + for (auto &index : indices) { + auto path = root.relativeFilePath(fsModel->filePath(index)); + + AssetSourcePath srcPath = {}; + srcPath.bundle = assetItemView->GetAssetBundle(); + srcPath.path = path.toStdString(); + AssetDataBase::Get()->RegisterAsset(srcPath); + } + }); + + menu.addAction(buildAct); + menu.exec(mapToGlobal(pos)); + } + + void AssetBrowserWidget::ResetView() + { + if (assetItemView == nullptr) { + return; + } + + auto str = comboBox->currentText(); + if (str == "Engine") { + auto *model = AssetDataBaseProxy::Get()->GetEngineModel(); + assetItemView->setModel(model); + assetItemView->setRootIndex(model->setRootPath(model->rootPath())); + assetItemView->SetAssetBundle(SourceAssetBundle::ENGINE); + } else if (str == "Project") { + auto *model = AssetDataBaseProxy::Get()->GetProjectModel(); + assetItemView->setModel(model); + assetItemView->setRootIndex(model->setRootPath(model->rootPath())); + assetItemView->SetAssetBundle(SourceAssetBundle::WORKSPACE); + } + } + + + void AssetListView::mousePressEvent(QMouseEvent *event) + { + if ((event->buttons() & Qt::LeftButton) != 0) { + startPos = event->pos(); + } + QListView::mousePressEvent(event); + } + + void AssetListView::mouseMoveEvent(QMouseEvent *event) + { + if ((event->buttons() & Qt::LeftButton) != 0 && + (event->pos() - startPos).manhattanLength() > QApplication::startDragDistance()) { + QModelIndex i = indexAt(event->pos()); + + auto *fsModel = static_cast(model()); + QDir root = fsModel->rootPath(); + auto path = root.relativeFilePath(fsModel->filePath(i)); + auto *drag = new QDrag(this); + auto *mimeData = new QMimeData(); + + QString sch = assetBundle == SourceAssetBundle::ENGINE ? "engine:" : "project:"; + + mimeData->setUrls({sch + path});; + drag->setMimeData(mimeData); + + drag->exec(Qt::CopyAction | Qt::MoveAction); + } + QListView::mouseMoveEvent(event); + } + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/src/AssetEditorProxy.cpp b/editor/framework/src/AssetEditorProxy.cpp new file mode 100644 index 00000000..b4d1c84e --- /dev/null +++ b/editor/framework/src/AssetEditorProxy.cpp @@ -0,0 +1,46 @@ +// +// Created by blues on 2024/7/12. +// + +#include + +namespace sky::editor { + + AssetItem::AssetItem(const AssetSourcePtr &ptr) + : QStandardItem(ptr->path.path.FileNameWithoutExt().c_str()), source(ptr) + { + setIcon(QIcon::fromTheme("folder")); + setDragEnabled(true); + } + + AssetDataBaseProxy::AssetDataBaseProxy() + { + model = std::make_unique(nullptr); + projectModel = std::make_unique(nullptr); + projectModel->setRootPath(AssetDataBase::Get()->GetWorkSpaceFs()->GetPath().GetStr().c_str()); + engineModel = std::make_unique(nullptr); + engineModel->setRootPath(AssetDataBase::Get()->GetEngineFs()->GetPath().GetStr().c_str()); + Refresh(); + } + + void AssetDataBaseProxy::Refresh() + { + auto *db = AssetDataBase::Get(); + const auto &sources = db->GetSources(); + + model->invisibleRootItem()->setText("Root"); + for (const auto &[id, source] : sources) { + auto iter = categoryLut.find(source->category); + if (iter == categoryLut.end()) { + auto *item = new QStandardItem(source->category.c_str()); + model->appendRow(item); + + iter = categoryLut.emplace(source->category, item->index()).first; + } + + auto *item = new AssetItem(source); + model->itemFromIndex(iter->second)->appendRow(item); + } + } + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/src/EditorCamera.cpp b/editor/framework/src/EditorCamera.cpp new file mode 100644 index 00000000..f0be45a4 --- /dev/null +++ b/editor/framework/src/EditorCamera.cpp @@ -0,0 +1,50 @@ +// +// Created by blues on 2024/7/10. +// + +#include +#include + +namespace sky::editor { + + void EditorCamera::Init(RenderScene* scene, NativeWindow *window) + { + controller.BindWindow(window); + renderScene = scene; + if (sceneView != nullptr) { + renderScene->RemoveSceneView(sceneView); + } + sceneView = renderScene->CreateSceneView(1); + + uint32_t width = window->GetWidth(); + uint32_t height = window->GetHeight(); + sceneView->SetMatrix(Matrix4::Identity()); + sceneView->SetPerspective(near, far, fov / 180.f * 3.14f, + static_cast(width) / static_cast(height)); + } + + void EditorCamera::Shutdown() + { + if (sceneView != nullptr) { + renderScene->RemoveSceneView(sceneView); + sceneView = nullptr; + } + } + + void EditorCamera::Tick(float time) + { + if (sceneView != nullptr) { + transform = controller.Resolve(time, transform); + sceneView->SetMatrix(transform.ToMatrix()); + } + } + + void EditorCamera::UpdateAspect(uint32_t width, uint32_t height) + { + if (sceneView != nullptr) { + sceneView->SetPerspective(near, far, fov / 180.f * 3.14f, + static_cast(width) / static_cast(height)); + } + } + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/src/ReflectedObjectWidget.cpp b/editor/framework/src/ReflectedObjectWidget.cpp new file mode 100644 index 00000000..c378987d --- /dev/null +++ b/editor/framework/src/ReflectedObjectWidget.cpp @@ -0,0 +1,177 @@ +// +// Created by blues on 2024/7/7. +// + +#include + +#include +#include + +#include +#include +#include + +namespace sky::editor { + + ReflectedObjectWidget::ReflectedObjectWidget(void *obj, const TypeNode *node, QWidget *parent) + : QWidget(parent) + , object(obj) + , typeNode(node) + { + auto *layout = new QFormLayout(this); + layout->setLabelAlignment(Qt::AlignLeft); + layout->setFormAlignment(Qt::AlignCenter); + setLayout(layout); + + for (const auto &[name, memberInfo] : typeNode->members) { + ReflectedMemberWidget *widget = nullptr; + if (memberInfo.info->staticInfo->isEnum) { + widget = new PropertyEnum(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyBool(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyScalar(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyVec<2>(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyVec<3>(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyVec<4>(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyColor(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + widget = new PropertyUuid(object, &memberInfo, this); + } else if (memberInfo.info->registeredId == TypeInfo::RegisteredId()) { + } + + if (widget != nullptr) { + layout->addRow(name.data(), widget); + } + } + } + + void ReflectedObjectWidget::Refresh() + { + } + + void AssetLineEditor::dragEnterEvent(QDragEnterEvent *event) + { + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } + } + + void AssetLineEditor::dragMoveEvent(QDragMoveEvent *event) + { + if (event->mimeData()->hasUrls()) { + event->acceptProposedAction(); + } + } + + void AssetLineEditor::dropEvent(QDropEvent *event) + { + std::set filterList = { + "project", + "engine" + }; + + const auto *mimeData = event->mimeData(); + if (mimeData->hasUrls()) { + auto sch = mimeData->urls()[0].scheme(); + if (auto iter = filterList.find(sch); iter == filterList.end()) { + return; + } + + auto path = mimeData->urls()[0].path(); + printf("drop sche: %s, path: %s\n", sch.toStdString().c_str(), path.toStdString().c_str()); + setText(path); + setModified(true); + emit editingFinished(); + event->accept(); + } else { + event->ignore(); + } + } + + PropertyUuid::PropertyUuid(void *obj, const TypeMemberNode *node, QWidget *parent) : ReflectedMemberWidget(obj, node, parent) + { + lineEdit = new AssetLineEditor(this); + lineEdit->setAcceptDrops(true); + lineEdit->setClearButtonEnabled(true); + + auto iter = node->properties.find(static_cast(CommonPropertyKey::ASSET_TYPE)); + SKY_ASSERT(iter != node->properties.end()); + assetType = *iter->second.GetAsConst(); + + auto *button = new QPushButton(this); + button->setText("..."); + button->setFixedWidth(32); + layout()->addWidget(lineEdit); + layout()->addWidget(button); + + connect(button, &QPushButton::clicked, this, [this]() { + }); + + connect(lineEdit, &QLineEdit::editingFinished, this, [this]() { + auto *edit = qobject_cast(sender()); + if (edit == nullptr || !edit->isModified()) + { + return; + } + + edit->setModified(false); + auto input = lineEdit->text(); + auto source = AssetDataBase::Get()->FindAsset(input.toStdString()); + if (input.isEmpty()) { + memberNode->setterFn(object, &Uuid::GetEmpty()); + } else if (source) { + if (source->category != assetType) { + QMessageBox(QMessageBox::Question, + "Error", + QString("%1\nrequested: %2\ncurrent: %3") + .arg("Invalid Asset Type!", assetType.data(), source->category.data()), + QMessageBox::Ok, QApplication::activeWindow()).exec(); + } else { + memberNode->setterFn(object, &source->uuid); + } + } else { + QMessageBox(QMessageBox::Warning, + "Warning", + "Asset Not Found.", + QMessageBox::Ok, QApplication::activeWindow()).exec(); + } + + RefreshValue(); + }); + + RefreshValue(); + } + + void PropertyUuid::RefreshValue() + { + auto any = memberNode->getterConstFn(object); + const auto *uuid = any.GetAsConst(); + SKY_ASSERT(uuid != nullptr); + auto source = AssetDataBase::Get()->FindAsset(*uuid); + lineEdit->setText(source ? source->path.path.GetStr().c_str() : ""); + } + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/framework/src/ViewportWidget.cpp b/editor/framework/src/ViewportWidget.cpp new file mode 100644 index 00000000..5ff59049 --- /dev/null +++ b/editor/framework/src/ViewportWidget.cpp @@ -0,0 +1,331 @@ +// +// Created by Zach Lee on 2021/12/12. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + std::unordered_map SCANCODE_MAP = { + {Qt::Key_A, ScanCode::KEY_A}, + {Qt::Key_B, ScanCode::KEY_B}, + {Qt::Key_C, ScanCode::KEY_C}, + {Qt::Key_D, ScanCode::KEY_D}, + {Qt::Key_E, ScanCode::KEY_E}, + {Qt::Key_F, ScanCode::KEY_F}, + {Qt::Key_G, ScanCode::KEY_G}, + {Qt::Key_H, ScanCode::KEY_H}, + {Qt::Key_I, ScanCode::KEY_I}, + {Qt::Key_J, ScanCode::KEY_J}, + {Qt::Key_K, ScanCode::KEY_K}, + {Qt::Key_L, ScanCode::KEY_L}, + {Qt::Key_M, ScanCode::KEY_M}, + {Qt::Key_N, ScanCode::KEY_N}, + {Qt::Key_O, ScanCode::KEY_O}, + {Qt::Key_P, ScanCode::KEY_P}, + {Qt::Key_Q, ScanCode::KEY_Q}, + {Qt::Key_R, ScanCode::KEY_R}, + {Qt::Key_S, ScanCode::KEY_S}, + {Qt::Key_T, ScanCode::KEY_T}, + {Qt::Key_U, ScanCode::KEY_U}, + {Qt::Key_V, ScanCode::KEY_V}, + {Qt::Key_W, ScanCode::KEY_W}, + {Qt::Key_X, ScanCode::KEY_X}, + {Qt::Key_Y, ScanCode::KEY_Y}, + {Qt::Key_Z, ScanCode::KEY_Z}, + {Qt::Key_1, ScanCode::KEY_1}, + {Qt::Key_2, ScanCode::KEY_2}, + {Qt::Key_3, ScanCode::KEY_3}, + {Qt::Key_4, ScanCode::KEY_4}, + {Qt::Key_5, ScanCode::KEY_5}, + {Qt::Key_6, ScanCode::KEY_6}, + {Qt::Key_7, ScanCode::KEY_7}, + {Qt::Key_8, ScanCode::KEY_8}, + {Qt::Key_9, ScanCode::KEY_9}, + {Qt::Key_0, ScanCode::KEY_0}, + {Qt::Key_Return, ScanCode::KEY_RETURN}, + {Qt::Key_Escape, ScanCode::KEY_ESCAPE}, + {Qt::Key_Backspace, ScanCode::KEY_BACKSPACE}, + {Qt::Key_Tab, ScanCode::KEY_TAB}, + {Qt::Key_Space, ScanCode::KEY_SPACE}, + {Qt::Key_Minus, ScanCode::KEY_MINUS}, + {Qt::Key_Equal, ScanCode::KEY_EQUALS}, +// {Qt::Key_, ScanCode::KEY_LEFTBRACKET}, +// {Qt::Key_, ScanCode::KEY_RIGHTBRACKET}, + {Qt::Key_Backslash, ScanCode::KEY_BACKSLASH}, +// {Qt::Key_, ScanCode::KEY_NONUSHASH}, + {Qt::Key_Semicolon, ScanCode::KEY_SEMICOLON}, + {Qt::Key_Apostrophe, ScanCode::KEY_APOSTROPHE}, +// {Qt::Key_, ScanCode::KEY_GRAVE}, + {Qt::Key_Comma, ScanCode::KEY_COMMA}, + {Qt::Key_Period, ScanCode::KEY_PERIOD}, + {Qt::Key_Slash, ScanCode::KEY_SLASH}, + {Qt::Key_CapsLock, ScanCode::KEY_CAPSLOCK}, + {Qt::Key_F1, ScanCode::KEY_F1}, + {Qt::Key_F2, ScanCode::KEY_F2}, + {Qt::Key_F3, ScanCode::KEY_F3}, + {Qt::Key_F4, ScanCode::KEY_F4}, + {Qt::Key_F5, ScanCode::KEY_F5}, + {Qt::Key_F6, ScanCode::KEY_F6}, + {Qt::Key_F7, ScanCode::KEY_F7}, + {Qt::Key_F8, ScanCode::KEY_F8}, + {Qt::Key_F9, ScanCode::KEY_F9}, + {Qt::Key_F10, ScanCode::KEY_F10}, + {Qt::Key_F11, ScanCode::KEY_F11}, + {Qt::Key_F12, ScanCode::KEY_F12}, + {Qt::Key_Print, ScanCode::KEY_PRINTSCREEN}, + {Qt::Key_ScrollLock, ScanCode::KEY_SCROLLLOCK}, + {Qt::Key_Pause, ScanCode::KEY_PAUSE}, + {Qt::Key_Insert, ScanCode::KEY_INSERT}, + {Qt::Key_Home, ScanCode::KEY_HOME}, + {Qt::Key_PageUp, ScanCode::KEY_PAGEUP}, + {Qt::Key_Delete, ScanCode::KEY_DELETE}, + {Qt::Key_End, ScanCode::KEY_END}, + {Qt::Key_PageDown, ScanCode::KEY_PAGEDOWN}, + {Qt::Key_Right, ScanCode::KEY_RIGHT}, + {Qt::Key_Left, ScanCode::KEY_LEFT}, + {Qt::Key_Down, ScanCode::KEY_DOWN}, + {Qt::Key_Up, ScanCode::KEY_UP}, + {Qt::Key_NumLock, ScanCode::KEY_NUMLOCKCLEAR}, + {Qt::Key_division, ScanCode::KEY_KP_DIVIDE}, + {Qt::Key_multiply, ScanCode::KEY_KP_MULTIPLY}, + {Qt::Key_Minus, ScanCode::KEY_KP_MINUS}, + {Qt::Key_Plus, ScanCode::KEY_KP_PLUS}, + {Qt::Key_Enter, ScanCode::KEY_KP_ENTER}, +// {Qt::Key_, ScanCode::KEY_KP_1}, +// {Qt::Key_, ScanCode::KEY_KP_2}, +// {Qt::Key_, ScanCode::KEY_KP_3}, +// {Qt::Key_, ScanCode::KEY_KP_4}, +// {Qt::Key_, ScanCode::KEY_KP_5}, +// {Qt::Key_, ScanCode::KEY_KP_6}, +// {Qt::Key_, ScanCode::KEY_KP_7}, +// {Qt::Key_, ScanCode::KEY_KP_8}, +// {Qt::Key_, ScanCode::KEY_KP_9}, +// {Qt::Key_, ScanCode::KEY_KP_0}, +// {Qt::Key_, ScanCode::KEY_KP_PERIOD}, + }; + + static KeyModFlags ConvertModifier(Qt::KeyboardModifiers modifier) + { + KeyModFlags flags = {}; + if ((modifier & Qt::SHIFT) != 0) { flags |= KeyMod::SHIFT; } + if ((modifier & Qt::CTRL) != 0) { flags |= KeyMod::CTRL; } + if ((modifier & Qt::ALT) != 0) { flags |= KeyMod::ALT; } + + return flags; + } + + ViewportWindow::ViewportWindow(QWindow *parent) : QWindow(parent) + { + setSurfaceType(SurfaceType::MetalSurface); + + winHandle = reinterpret_cast(winId()); + winID = winId(); + } + + ViewportWidget::~ViewportWidget() + { + ResetPipeline(); + } + + bool ViewportWindow::event(QEvent *event) + { + switch (event->type()) { + case QEvent::Resize: + descriptor.width = width(); + descriptor.height = height(); + Event::BroadCast(this, &IWindowEvent::OnWindowResize, descriptor.width, descriptor.height); + break; + case QEvent::MouseMove: { + auto* mouseEvent = static_cast(event); + auto pos = mouseEvent->pos(); + auto globalPos = mouseEvent->globalPos(); + MouseMotionEvent mEvent = {}; + mEvent.winID = winID; + mEvent.x = pos.x(); + mEvent.y = pos.y(); + mEvent.relX = globalPos.x(); + mEvent.relY = globalPos.y(); + Event::BroadCast(&IMouseEvent::OnMouseMotion, mEvent); + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: { + auto* mouseEvent = static_cast(event); + auto pressPos = mouseEvent->globalPos(); + auto button = mouseEvent->button(); + + MouseButtonEvent mEvent = {}; + mEvent.winID = winID; + mEvent.x = pressPos.x(); + mEvent.y = pressPos.y(); + if (button == Qt::LeftButton) { mEvent.button = MouseButtonType::LEFT; } + else if (button == Qt::RightButton) { mEvent.button = MouseButtonType::RIGHT; } + else if (button == Qt::MiddleButton) { mEvent.button = MouseButtonType::MIDDLE; } + + if (event->type() == QEvent::MouseButtonRelease) { + Event::BroadCast(&IMouseEvent::OnMouseButtonUp, mEvent); + } else { + Event::BroadCast(&IMouseEvent::OnMouseButtonDown, mEvent); + } + break; + } + case QEvent::Wheel: { + auto* wheelEvent = static_cast(event); + auto point = wheelEvent->angleDelta() / 20.f; + + MouseWheelEvent mEvent = {}; + mEvent.winID = winID; + mEvent.x = static_cast(point.x()); + mEvent.y = static_cast(point.y()); + Event::BroadCast(&IMouseEvent::OnMouseWheel, mEvent); + break; + } + case QEvent::KeyPress: + case QEvent::KeyRelease: { + auto* keyEvent = static_cast(event); + auto scanCode = static_cast(keyEvent->key()); + auto mod = ConvertModifier(keyEvent->modifiers()); + + auto iter = SCANCODE_MAP.find(scanCode); + if (iter == SCANCODE_MAP.end()) { + break; + } + + KeyboardEvent kEvent = {}; + kEvent.winID = winID; + kEvent.scanCode = iter->second; + kEvent.mod = mod; + if (event->type() == QEvent::KeyRelease) { + Event::BroadCast(&IKeyboardEvent::OnKeyUp, kEvent); + } else { + Event::BroadCast(&IKeyboardEvent::OnKeyDown, kEvent); + } + break; + } + case QEvent::Close: + break; + default: break; + } + return true; + } + + ViewportWidget::ViewportWidget(QWidget *parent) : QWidget(parent) + { + layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + + binder.Bind(this); + setAcceptDrops(true); + } + + void ViewportWidget::ResetWorld(const WorldPtr &world_) + { + if (windowContainer != nullptr) { + layout->removeWidget(windowContainer); + delete windowContainer; + windowContainer = nullptr; + } + + world = world_; + if (world != nullptr) { + window = new ViewportWindow(); + windowContainer = QWidget::createWindowContainer(window, this, Qt::Widget); + layout->addWidget(windowContainer); + Event::BroadCast(&ISystemEvent::OnMainWindowCreated, window); + + UpdatePipeline(); + } else { + + ResetPipeline(); + } + } + + void ViewportWidget::ResetPipeline() + { + if (editorCamera) { + editorCamera->Shutdown(); + } + Renderer::Get()->SetPipeline(nullptr); + profiler = nullptr; + gizmo = nullptr; + sceneProxy = nullptr; + Renderer::Get()->DestroyRenderWindow(renderWindow); + Event::DisConnect(this); + } + + void ViewportWidget::Tick(float time) + { + if (editorCamera) { + editorCamera->Tick(time); + } + } + + void ViewportWidget::OnWindowResize(uint32_t width, uint32_t height) + { + if (renderWindow != nullptr) { + renderWindow->Resize(width, height); + editorCamera->UpdateAspect(width, height); + } + + if (profiler) { + profiler->SetDisplaySize(window->GetWidth(), window->GetHeight()); + } + } + + void ViewportWidget::dropEvent(QDropEvent *event) + { + const auto *mimeData = event->mimeData(); + if (mimeData->hasUrls()) { + auto urls = mimeData->urls(); + } + } + + void ViewportWidget::dragEnterEvent(QDragEnterEvent *event) + { + } + + void ViewportWidget::dragMoveEvent(QDragMoveEvent *event) + { + } + + void ViewportWidget::UpdatePipeline() + { + renderWindow = Renderer::Get()->CreateRenderWindow(window->GetNativeHandle(), + window->GetWidth(), + window->GetHeight(), false); + +// auto *ppl = new DefaultForward(); + auto *ppl = new RenderPassPipeline(); + Renderer::Get()->SetPipeline(ppl); + + sceneProxy = static_cast(world->GetSubSystem("RenderScene")); + auto *scenePipeline = new DefaultForwardPipeline(sceneProxy->GetRenderScene()); + scenePipeline->SetOutput(renderWindow); + ppl->AddScenePass(scenePipeline); + + editorCamera = std::make_unique(); + editorCamera->Init(sceneProxy->GetRenderScene(), window); + + auto *gizmoFactory = Interface::Get()->GetApi(); + if (gizmoFactory != nullptr) { + gizmo.reset(gizmoFactory->CreateGizmo()); + gizmo->Init(*world, window); + } + + profiler = std::make_unique(sceneProxy->GetRenderScene()); + profiler->SetDisplaySize(window->GetWidth(), window->GetHeight()); + + Event::Connect(window, this); + } +} // namespace sky::editor diff --git a/editor/framework/src/WorldTreeView.cpp b/editor/framework/src/WorldTreeView.cpp new file mode 100644 index 00000000..37d6afd9 --- /dev/null +++ b/editor/framework/src/WorldTreeView.cpp @@ -0,0 +1,155 @@ + +// +// Created by blues on 2024/7/6. +// + +#include +#include +#include +#include +#include + +namespace sky::editor { + + WorldTreeView::WorldTreeView(QWidget *parent) : QWidget(parent) + { + treeView = new QTreeView(this); + treeView->setHeaderHidden(true); + treeView->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection); + treeView->setDragDropMode(QAbstractItemView::DragDropMode::DragDrop); + treeView->setDefaultDropAction(Qt::DropAction::MoveAction); + + auto *layout = new QVBoxLayout(this); + setLayout(layout); + layout->addWidget(treeView); + + setContextMenuPolicy(Qt::CustomContextMenu); + + model = new QStandardItemModel(this); + treeView->setModel(model); + connect(model, &QStandardItemModel::itemChanged, this, &WorldTreeView::OnItemChanged); + connect(treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &WorldTreeView::OnSelectItemChanged); + connect(this, &QWidget::customContextMenuRequested, this, &WorldTreeView::OnContentMenuClicked); + } + + void WorldTreeView::OnSelectItemChanged(const QItemSelection &selected, const QItemSelection &deselected) + { + auto indexes = selected.indexes(); + if (indexes.size() == 1) { + auto *item = dynamic_cast(model->itemFromIndex(indexes[0])); + emit WorldTreeSelectItemChanged(item != nullptr ? item->actor : nullptr); + SelectEvent::BroadCast(&ISelectEvent::OnActorSelected, item->actor.get()); + } else { + emit WorldTreeSelectItemChanged(nullptr); + SelectEvent::BroadCast(&ISelectEvent::OnActorSelected, nullptr); + } + } + + void WorldTreeView::BuildByWorld(const WorldPtr &world) + { + attachedWorld = world; + RebuildTree(); + } + + void WorldTreeView::RebuildTree() + { + model->clear(); + + std::unordered_map itemMap; + if (attachedWorld) { + const auto &actors = attachedWorld->GetActors(); + for (const auto &actor: actors) { + auto *item = new WorldActorItem(actor); + itemMap.emplace(actor->GetUuid(), item); + } + } + + for (auto &[id, item] : itemMap) { + auto *trans = item->actor->GetComponent(); + WorldActorItem *parent = nullptr; + if (auto *parentTrans = trans != nullptr ? trans->GetParent() : nullptr; parentTrans != nullptr) { + parent = itemMap.at(parentTrans->GetActor()->GetUuid()); + } + if (parent != nullptr) { + parent->appendRow(item); + } else { + model->appendRow(item); + } + } + } + + void WorldTreeView::GatherAllChildren(std::vector &actors, QStandardItem *item) // NOLINT + { + actors.emplace_back(static_cast(item)->actor); + int count = item->rowCount(); + for (int i = 0; i < count; ++i) { + GatherAllChildren(actors, item->child(i)); + } + } + + void WorldTreeView::OnContentMenuClicked(const QPoint &pos) + { + if (attachedWorld == nullptr) { + return; + } + + QMenu menu(tr("World Action"), this); + + auto *addAct = new QAction(tr("Add"), &menu); + connect(addAct, &QAction::triggered, this, [this]() { + auto indices = treeView->selectionModel()->selectedIndexes(); + + auto actor = attachedWorld->CreateActor("Actor"); + auto *item = new WorldActorItem(actor); + + auto *parent = indices.empty() ? model->invisibleRootItem() : model->itemFromIndex(indices[0]); + auto parentAct = indices.empty() ? ActorPtr{} : static_cast(parent)->actor; + parent->appendRow(item); + actor->SetParent(parentAct); + }); + + + auto *delAct = new QAction(tr("Delete"), &menu); + connect(delAct, &QAction::triggered, this, [this]() { + auto indices = treeView->selectionModel()->selectedIndexes(); + + for (auto &index : indices) { + std::vector actorsToDel; + GatherAllChildren(actorsToDel, model->itemFromIndex(index)); + model->removeRow(index.row(), index.parent()); + + for (auto &act : actorsToDel) { + attachedWorld->DetachFromWorld(act); + } + } + }); + + menu.addSeparator(); + auto *collapseAct = new QAction(tr("Collapse"), &menu); + connect(collapseAct, &QAction::triggered, this, [this]() { treeView->collapseAll(); }); + auto *expandAct = new QAction(tr("Expand"), &menu); + connect(expandAct, &QAction::triggered, this, [this]() { treeView->expandAll(); }); + + + menu.addAction(addAct); + menu.addAction(delAct); + menu.addAction(collapseAct); + menu.addAction(expandAct); + + menu.exec(mapToGlobal(pos)); + } + + void WorldTreeView::OnItemChanged(QStandardItem *item) + { + auto *aItem = dynamic_cast(item); + if (aItem != nullptr) { + aItem->actor->SetName(item->text().toStdString()); + + auto *parent = dynamic_cast(item->parent()); + if (parent != nullptr) { + aItem->actor->SetParent(parent->actor); + } + } + } + +} // namespace sky::editor \ No newline at end of file diff --git a/editor/include/editor/application/EditorApplication.h b/editor/include/editor/application/EditorApplication.h index aabefae3..15f0bc2a 100644 --- a/editor/include/editor/application/EditorApplication.h +++ b/editor/include/editor/application/EditorApplication.h @@ -4,25 +4,36 @@ #pragma once #include +#include +#include +#include #include #include - -namespace sky { - class SkyEngine; -} +#include namespace sky::editor { - class EditorApplication : public QObject, public Application { + class EditorApplication : public QApplication, public Application { Q_OBJECT public: - EditorApplication(); - ~EditorApplication(); + EditorApplication(int argc, char **argv); + ~EditorApplication() override; + + bool Init(int argc, char **argv) override; - bool Init(StartInfo &) override; + const NativeFileSystemPtr &GetWorkFs() const { return workFs; } + const NativeFileSystemPtr &GetEngineFs() const { return engineFs; } private: + void LoadConfigs() override; + void LoadFromJson(std::unordered_map &); + void SplashWindow(); + QTimer *timer = nullptr; - SkyEngine *engine = nullptr; + + NativeFileSystemPtr workFs; + NativeFileSystemPtr engineFs; + + std::unique_ptr mainWindow; }; } diff --git a/editor/include/editor/dockwidget/AssetWidget.h b/editor/include/editor/dockwidget/AssetWidget.h index 9459454f..2987b9f9 100644 --- a/editor/include/editor/dockwidget/AssetWidget.h +++ b/editor/include/editor/dockwidget/AssetWidget.h @@ -7,19 +7,30 @@ #include #include #include +#include +#include namespace sky::editor { - class AssetWidget : public QDockWidget { + class AssetDirBrowser : public QFrame { public: - AssetWidget(QWidget *parent); - ~AssetWidget() = default; - - void OnProjectChange(const QString &projectPath); + explicit AssetDirBrowser(QWidget *parent); + ~AssetDirBrowser() override = default; private: - QFileSystemModel *fsModel = nullptr; + void OnContentMenuClicked(const QPoint &pos); + + std::unordered_map models; + std::unordered_map modelRoot; QTreeView *treeView = nullptr; + + uint32_t currentModel = 0; + }; + + class AssetWidget : public QDockWidget { + public: + explicit AssetWidget(QWidget *parent); + ~AssetWidget() override = default; }; } diff --git a/editor/include/editor/dockwidget/DockManager.h b/editor/include/editor/dockwidget/DockManager.h index 423d23d8..31363134 100644 --- a/editor/include/editor/dockwidget/DockManager.h +++ b/editor/include/editor/dockwidget/DockManager.h @@ -26,7 +26,7 @@ namespace sky::editor { friend class Singleton; DockManager() = default; - ~DockManager() = default; + ~DockManager() override = default; std::unordered_map docks; }; diff --git a/editor/include/editor/inspector/InspectorWidget.h b/editor/include/editor/dockwidget/InspectorWidget.h similarity index 74% rename from editor/include/editor/inspector/InspectorWidget.h rename to editor/include/editor/dockwidget/InspectorWidget.h index 74b62636..5419ff3e 100644 --- a/editor/include/editor/inspector/InspectorWidget.h +++ b/editor/include/editor/dockwidget/InspectorWidget.h @@ -14,31 +14,34 @@ class QPushButton; namespace sky { class World; - class GameObject; - class Component; + class Actor; } namespace sky::editor { class InspectorWidget : public QDockWidget { + Q_OBJECT public: explicit InspectorWidget(QWidget* parent); ~InspectorWidget() override = default; - void SetWorldItem(WorldItem* item); - - void AddComponent(Component* comp); + void AddComponent(ComponentBase* comp); void Clear(); + public Q_SLOTS: + void OnSelectedItemChanged(ActorPtr actor); + private: void Refresh(); + void OnAddComponentClicked(); - WorldItem* selectedItem; QVBoxLayout* layout; QWidget* groupWidget; QPushButton *button; std::vector groups; + + ActorPtr actor = nullptr; }; } \ No newline at end of file diff --git a/editor/include/editor/dockwidget/WorldWidget.h b/editor/include/editor/dockwidget/WorldWidget.h index 3581f23d..29a28170 100644 --- a/editor/include/editor/dockwidget/WorldWidget.h +++ b/editor/include/editor/dockwidget/WorldWidget.h @@ -4,35 +4,25 @@ #pragma once #include -#include -#include #include #include +#include namespace sky::editor { - class WorldItem : public QTreeWidgetItem { - public: - explicit WorldItem(QTreeWidget *treeview, int type = Type) : QTreeWidgetItem(treeview, type) {} - explicit WorldItem(QTreeWidgetItem *parent, int type = Type) : QTreeWidgetItem(parent, type) {} - - GameObject* go = nullptr; - }; - class WorldWidget : public QDockWidget { public: explicit WorldWidget(QWidget* parent = nullptr); - ~WorldWidget() = default; + ~WorldWidget() override = default; void SetWorld(const WorldPtr& world); + WorldTreeView *GetWorldTreeView() const { return treeView; } + private: - void Refresh(); + QTimer* refreshTimer = nullptr; - WorldPtr world; - QTimer* refreshTimer; - QTreeWidget* worldTree; - WorldItem* rootItem; + WorldTreeView *treeView = nullptr; }; } \ No newline at end of file diff --git a/editor/include/editor/document/Constants.h b/editor/include/editor/document/Constants.h index 5d85819a..90e2339e 100644 --- a/editor/include/editor/document/Constants.h +++ b/editor/include/editor/document/Constants.h @@ -10,8 +10,9 @@ namespace sky::editor { enum class DocumentFlagBit : uint32_t { - PROJECT_OPEN = 1, - LEVEL_OPEN = 2, + NONE = 0, + ProjectOpen = 1, + WorldOpen = 2, MAX }; diff --git a/editor/include/editor/document/Document.h b/editor/include/editor/document/Document.h index 71aaab7a..896eb501 100644 --- a/editor/include/editor/document/Document.h +++ b/editor/include/editor/document/Document.h @@ -7,7 +7,8 @@ #include #include #include -#include +#include +#include namespace sky::editor { @@ -17,32 +18,29 @@ namespace sky::editor { class Document { public: - Document(const QString &path); + explicit Document(); ~Document(); static void Reflect(); - void Init(); - void Read(); - void Save(); + const WorldPtr &GetWorld() const { return world; } + WorldPtr OpenWorld(const QString &path); + void CloseWorld(); - void OpenLevel(const QString &path, bool newLevel); - void CloseLevel(); + void LoadWorld(); + void SaveWorld(); + bool NeedSave() const; void SetFlag(DocumentFlagBit bit); void ResetFlag(DocumentFlagBit bit); const DocFlagArray &GetFlag() const; - const WorldPtr &GetMainWorld() const; - private: DocFlagArray flags; - QString projectFullPath; - QString projectHome; - ProjectData projectData; - std::unique_ptr currentLevel; + QString filePath; + WorldPtr world; }; } // namespace sky::editor diff --git a/editor/include/editor/document/Level.h b/editor/include/editor/document/Level.h deleted file mode 100644 index 1a88c651..00000000 --- a/editor/include/editor/document/Level.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by Zach Lee on 2023/1/15. -// - -#pragma once -#include -#include -#include - -namespace sky::editor { - - class Level { - public: - Level() = default; - ~Level(); - - void New(const QString &level); - void Open(const QString &level); - - const WorldPtr &GetWorld() const; - - private: - void Save(); - void Load(); - void InitRenderScene(); - QString path; - WorldPtr world; - std::unique_ptr renderScene; - }; - -} // namespace sky::editor diff --git a/editor/include/editor/inspector/ComponentInspector.h b/editor/include/editor/inspector/ComponentInspector.h index ada65fdc..a420456b 100644 --- a/editor/include/editor/inspector/ComponentInspector.h +++ b/editor/include/editor/inspector/ComponentInspector.h @@ -5,10 +5,7 @@ #pragma once #include - -namespace sky { - class Component; -} // namespace sky +#include namespace sky::editor { @@ -17,10 +14,10 @@ namespace sky::editor { explicit ComponentInspector(QWidget* parent) : InspectorBase(parent) {} ~ComponentInspector() override = default; - void SetComponent(Component *comp); + void SetComponent(ComponentBase *comp); private: - Component *component = nullptr; + ComponentBase *component = nullptr; }; } // namespace sky::editor \ No newline at end of file diff --git a/editor/include/editor/inspector/PropertyColorWidget.h b/editor/include/editor/inspector/PropertyColorWidget.h deleted file mode 100644 index 8178f844..00000000 --- a/editor/include/editor/inspector/PropertyColorWidget.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by Zach Lee on 2023/8/23. -// - -#pragma once - -#include -#include - -namespace sky::editor { - - class PropertyColorWidget : public PropertyWidget { - public: - explicit PropertyColorWidget(void *inst, const TypeNode *node, QWidget* parent); - void Refresh() override; - - private: - QPushButton *button = nullptr; - }; - -} // namespace sky::editor \ No newline at end of file diff --git a/editor/include/editor/inspector/PropertyUtil.h b/editor/include/editor/inspector/PropertyUtil.h deleted file mode 100644 index a7308ff0..00000000 --- a/editor/include/editor/inspector/PropertyUtil.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#pragma once -#include -#include -#include - -namespace sky::editor::util { - - bool CheckProperty(const PropertyMap& properties, CommonPropertyKey key, bool dft = true); - -} // sky::editor::util diff --git a/editor/include/editor/inspector/PropertyVectorX.h b/editor/include/editor/inspector/PropertyVectorX.h deleted file mode 100644 index 54893a7a..00000000 --- a/editor/include/editor/inspector/PropertyVectorX.h +++ /dev/null @@ -1,119 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - struct TypeNode; -} // namespace sky - -namespace sky::editor { - - class PropertyBool : public PropertyWidget { - public: - explicit PropertyBool(void *inst, const TypeNode *node, QWidget* parent) : PropertyWidget(inst, node, parent) - { - layout->setSpacing(0); - layout->addWidget(label, 0, Qt::AlignLeft | Qt::AlignTop); - - box = new QCheckBox(this); - layout->addWidget(box, 0, Qt::AlignLeft | Qt::AlignTop); - - connect(box, &QCheckBox::stateChanged, this, [this](int v) { - *reinterpret_cast(instance) = (v == Qt::Checked); - }); - } - - void Refresh() override - { - box->setCheckState(*reinterpret_cast(instance) ? Qt::Checked : Qt::Unchecked); - } - - private: - QCheckBox* box; - }; - - template - class PropertyScalar : public PropertyWidget { - public: - explicit PropertyScalar(void *inst, const TypeNode *node, QWidget* parent) : PropertyWidget(inst, node, parent) - { - layout->setSpacing(0); - layout->addWidget(label); - - line = new QLineEdit(this); - if constexpr (std::is_floating_point_v) { - line->setValidator(new QDoubleValidator(this)); - } else if constexpr (std::is_integral_v) { - line->setValidator(new QIntValidator(std::numeric_limits::min(), std::numeric_limits::max(), this)); - } - layout->addWidget(line); - - connect(line, &QLineEdit::textEdited, this, [this](const QString &s) { - auto *ptr = reinterpret_cast(instance); - if constexpr (std::is_floating_point_v) { - *ptr = static_cast(s.toDouble()); - } else if constexpr (std::is_signed_v) { - *ptr = static_cast(s.toInt()); - } else if constexpr (std::is_unsigned_v) { - *ptr = static_cast(s.toUInt()); - } - }); - } - - void Refresh() override - { - const T* data = reinterpret_cast(instance); - line->setText(QString::number(*data)); - } - - ~PropertyScalar() override = default; - - private: - QLineEdit* line; - }; - - template - class PropertyVec : public PropertyWidget { - public: - explicit PropertyVec(QWidget* parent) : PropertyWidget(parent) - { - layout->setSpacing(0); - layout->addWidget(label); - auto *validator = new QDoubleValidator(this); - const float *val = reinterpret_cast(instance); - for (uint32_t i = 0; i < N; ++i) { - line[i] = new QLineEdit(this); - line[i]->setValidator(validator); - layout->addWidget(line[i]); - - connect(line[i], &QLineEdit::textEdited, this, [i, this](const QString &s) { - auto val = static_cast(s.toDouble()); - }); - } - } - - void Refresh() override - { - const auto *val = reinterpret_cast(instance); - for (uint32_t i = 0; i < N; ++i) { - line[i++]->setText(QString::number(val[i])); - } - } - - ~PropertyVec() override = default; - - private: - QLineEdit* line[N]; - }; - -} \ No newline at end of file diff --git a/editor/include/editor/inspector/PropertyWidget.h b/editor/include/editor/inspector/PropertyWidget.h deleted file mode 100644 index 4f05a3e0..00000000 --- a/editor/include/editor/inspector/PropertyWidget.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#pragma once -#include -#include -#include - -namespace sky { - struct TypeNode; -} - -class QHBoxLayout; - -namespace sky::editor { - - class PropertyWidget : public QWidget { - public: - explicit PropertyWidget(void *ptr, const TypeNode *node, QWidget* parent); - explicit PropertyWidget(QWidget* parent); - ~PropertyWidget() override = default; - - void SetInstance(void* instance, const TypeNode *node); - void SetLabel(const QString &str); - - virtual void Refresh(); - - protected: - QHBoxLayout *layout; - QLabel *label = nullptr; - - void* instance; - const TypeNode* typeNode; - QList children; - }; - -} diff --git a/editor/include/editor/viewport/Viewport.h b/editor/include/editor/viewport/Viewport.h deleted file mode 100644 index 52d87d29..00000000 --- a/editor/include/editor/viewport/Viewport.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by Zach Lee on 2021/12/13. -// - -#pragma once - -#include -#include -#include - -namespace sky::editor { - - enum class ViewportID : uint32_t { - EDITOR_PREVIEW - }; - - class Viewport : public QWindow { - Q_OBJECT - public: - Viewport(); - ~Viewport() override; - - void Init(ViewportID id); - bool event(QEvent *event) override; - - RenderWindow *GetRenderWindow() const { return window; } - - private: - ViewportID viewportId = ViewportID::EDITOR_PREVIEW; - RenderWindow *window = nullptr; - }; - - class ViewportManager : public Singleton { - public: - void Register(ViewportID key, Viewport* vp); - void UnRegister(ViewportID key); - Viewport *FindViewport(ViewportID key) const; - - private: - friend class Singleton; - - ViewportManager() = default; - ~ViewportManager() = default; - - std::unordered_map viewports; - }; -} diff --git a/editor/include/editor/viewport/ViewportWidget.h b/editor/include/editor/viewport/ViewportWidget.h deleted file mode 100644 index 84567069..00000000 --- a/editor/include/editor/viewport/ViewportWidget.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Created by Zach Lee on 2021/12/12. -// - -#pragma once -#include -#include - -namespace sky::editor { - - class ViewportWidget : public QWidget { - Q_OBJECT - public: - explicit ViewportWidget(QWidget* parent = nullptr); - ~ViewportWidget() override = default; - - void Init(); - - private: - Viewport* window; - }; -} diff --git a/editor/src/window/MainWindow.h b/editor/include/editor/window/MainWindow.h similarity index 60% rename from editor/src/window/MainWindow.h rename to editor/include/editor/window/MainWindow.h index 8b5548b4..767dcd31 100644 --- a/editor/src/window/MainWindow.h +++ b/editor/include/editor/window/MainWindow.h @@ -14,6 +14,7 @@ namespace sky::editor { class ActionManager; class ViewportWidget; + class ViewportWindow; class WorldWidget; class InspectorWidget; class AssetWidget; @@ -21,31 +22,38 @@ namespace sky::editor { class MainWindow : public QMainWindow { Q_OBJECT public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow() override; + Document* GetDoc() const { return document.get(); } + ViewportWindow* GetViewportWindow() const; private: void InitWidgets(); void InitMenu(); + void InitDocument(); - void OnTick(); + void OnOpenWorld(); + void OnNewWorld(); + void OnCloseWorld(); + void OnSaveWorld(); + void SaveCheck(); - void OnOpenProject(const QString &path); - void OnNewProject(const QString &path, const QString &name); - void OnCloseProject(); - - void OnOpenLevel(const QString &path); - void OnNewLevel(const QString &name); - void OnCloseLevel(); + void OnImport(); void UpdateActions(); + bool event(QEvent *event) override; + QMenuBar *menuBar = nullptr; ActionManager *actionManager = nullptr; WorldWidget *worldWidget = nullptr; InspectorWidget *inspector = nullptr; AssetWidget *assetBrowser = nullptr; + ViewportWidget *mainViewport = nullptr; + QWidget *emptyCentral = nullptr; + + QString projectPath; std::vector viewports; std::list docks; diff --git a/editor/src/application/EditorApplication.cpp b/editor/src/application/EditorApplication.cpp index 628ec3aa..6255eaa4 100644 --- a/editor/src/application/EditorApplication.cpp +++ b/editor/src/application/EditorApplication.cpp @@ -4,9 +4,17 @@ #include #include +#include #include +#include #include -#include +#include +#include +#include + +#include + +static const char* TAG = "EditorApplication"; namespace sky::editor { @@ -15,34 +23,52 @@ namespace sky::editor { Document::Reflect(); } - EditorApplication::EditorApplication() + EditorApplication::EditorApplication(int argc, char **argv) : QApplication(argc, argv) { } - EditorApplication::~EditorApplication() + EditorApplication::~EditorApplication() // NOLINT { - engine->DeInit(); - SkyEngine::Destroy(); + timer->stop(); } - bool EditorApplication::Init(StartInfo &info) + bool EditorApplication::Init(int argc, char **argv) { - // platform - sky::Platform* platform = sky::Platform::Get(); - if (!platform->Init({})) { + cxxopts::Options options("GameApplication Launcher", "SkyEngine Launcher"); + options.allow_unrecognised_options(); + + options.add_options()("p,project", "Project Directory", cxxopts::value()); + options.add_options()("e,engine", "Engine Directory", cxxopts::value()); + auto result = options.parse(argc, argv); + if (result.count("project") == 0u || result.count("engine") == 0u) { return false; } + std::string projectPath = result["project"].as(); + std::string enginePath = result["engine"].as(); - Application::Init(info); + workFs = new NativeFileSystem(projectPath); + engineFs = new NativeFileSystem(enginePath); - EditorReflect(); - SkyEngine::Reflect(); + AssetManager::Get()->SetWorkFileSystem(workFs); + AssetDataBase::Get()->SetEngineFs(engineFs); + AssetDataBase::Get()->SetWorkSpaceFs(workFs); + + SplashWindow(); - engine = SkyEngine::Get(); - engine->Init(); + if (!Application::Init(argc, argv)) { + return false; + } + + EditorReflect(); BindTick([this](float delta) { - engine->Tick(delta); + + TickEvent::BroadCast(&ITickEvent::Tick, delta); + auto world = mainWindow->GetDoc()->GetWorld(); + if (world) { + world->Tick(delta); + } +// engine->Tick(delta); }); timer = new QTimer(this); @@ -50,7 +76,75 @@ namespace sky::editor { connect(timer, &QTimer::timeout, this, [this]() { Loop(); }); - return true; } + + void EditorApplication::SplashWindow() + { + auto splashPath = engineFs->GetPath(); + splashPath /= "assets/splash/splash.jpg"; + + QPixmap pixmap(splashPath.GetStr().c_str()); + QSplashScreen splash(pixmap); + splash.show(); + + splash.showMessage("loadModules", Qt::AlignBottom, Qt::white); + std::this_thread::sleep_for(std::chrono::duration(200)); + processEvents(); + + splash.showMessage("loadAssets", Qt::AlignBottom, Qt::white); + std::this_thread::sleep_for(std::chrono::duration(200)); + processEvents(); + + mainWindow = std::make_unique(); + mainWindow->show(); + splash.finish(mainWindow.get()); + } + + void EditorApplication::LoadFromJson(std::unordered_map &modules) + { + std::string json; + auto file = workFs->OpenFile("configs/modules_editor.json"); + if (!file || !file->ReadString(json)) { + LOG_W(TAG, "Load Config Failed"); + return; + } + + rapidjson::Document document; + document.Parse(json.c_str()); + + if (document.HasMember("modules")) { + auto array = document["modules"].GetArray(); + for (auto &module : array) { + if (!module.HasMember("name")) { + continue; + } + + ModuleInfo info; + info.name = module["name"].GetString(); + + if (module.HasMember("dependencies")) { + auto depArray = module["dependencies"].GetArray(); + for (auto &dep : depArray) { + info.dependencies.emplace_back(dep.GetString()); + } + } + + modules.emplace(info.name, std::move(info)); + } + } + } + + void EditorApplication::LoadConfigs() + { + std::unordered_map modules = {}; + modules.emplace("SkyRender", ModuleInfo{"SkyRender", {"ShaderCompiler"}}); + modules.emplace("RenderBuilder", ModuleInfo{"RenderBuilder", {"SkyRender"}}); + + LoadFromJson(modules); + + for (auto &[key, info] : modules) { + moduleManager->RegisterModule(info); + } + } } diff --git a/editor/src/dialog/ProjectDialog.cpp b/editor/src/dialog/ProjectDialog.cpp deleted file mode 100644 index 493c7114..00000000 --- a/editor/src/dialog/ProjectDialog.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Created by Zach Lee on 2023/1/14. -// - -#include "ProjectDialog.h" -#include -#include -#include -#include -#include -#include - -namespace sky::editor { - - ProjectDialog::ProjectDialog() - { - setWindowTitle(tr("New Project")); - setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding); - - auto layout = new QVBoxLayout(this); - auto pathGroup = new QWidget(this); - auto projectPathText = new QLineEdit(pathGroup); - auto projectPathBtn = new QPushButton(tr("..."), pathGroup); - connect(projectPathBtn, &QPushButton::clicked, this, [projectPathText, this](bool checked) { - QFileDialog dlg; - dlg.setFileMode(QFileDialog::Directory); - dlg.setViewMode(QFileDialog::Detail); - QStringList fileNames; - if (dlg.exec()) { - fileNames = dlg.selectedFiles(); - if (!fileNames.empty()) { - projectPath = fileNames[0]; - projectPathText->setText(projectPath); - } - } - }); - - auto pathGroupLayout = new QHBoxLayout(pathGroup); - pathGroupLayout->setContentsMargins(0, 0, 0, 0); - pathGroupLayout->addWidget(projectPathText); - pathGroupLayout->addWidget(projectPathBtn); - - auto newGroup = new QWidget(this); - auto projectNameText = new QLineEdit(newGroup); - auto projectNameBtn = new QPushButton(tr("New"), newGroup); - connect(projectNameBtn, &QPushButton::clicked, this, [projectNameText, this](bool checked) { - projectName = projectNameText->text(); - accept(); - }); - auto nameGroupLayout = new QHBoxLayout(newGroup); - nameGroupLayout->setContentsMargins(0, 0, 0, 0); - nameGroupLayout->addWidget(projectNameText); - nameGroupLayout->addWidget(projectNameBtn); - - layout->addWidget(new QLabel(tr("Project Path:"), this)); - layout->addWidget(pathGroup); - layout->addWidget(new QLabel(tr("Project Name:"), this)); - layout->addWidget(newGroup); - setLayout(layout); - } - - const QString &ProjectDialog::ProjectPath() const - { - return projectPath; - } - - const QString &ProjectDialog::ProjectName() const - { - return projectName; - } -} // namespace sky::editor \ No newline at end of file diff --git a/editor/src/dialog/ProjectDialog.h b/editor/src/dialog/ProjectDialog.h deleted file mode 100644 index f42ee4da..00000000 --- a/editor/src/dialog/ProjectDialog.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Created by Zach Lee on 2023/1/14. -// - -#pragma once - -#include -#include - -namespace sky::editor { - - class ProjectDialog : public QDialog { - Q_OBJECT - public: - ProjectDialog(); - ~ProjectDialog() = default; - - const QString &ProjectPath() const; - const QString &ProjectName() const; - - private: - QString projectPath; - QString projectName; - }; - -} // namespace sky::editor \ No newline at end of file diff --git a/editor/src/dialog/LevelDialog.cpp b/editor/src/dialog/WorldDialog.cpp similarity index 53% rename from editor/src/dialog/LevelDialog.cpp rename to editor/src/dialog/WorldDialog.cpp index 573a6096..7be8d74f 100644 --- a/editor/src/dialog/LevelDialog.cpp +++ b/editor/src/dialog/WorldDialog.cpp @@ -2,7 +2,7 @@ // Created by Zach Lee on 2023/1/15. // -#include "LevelDialog.h" +#include "WorldDialog.h" #include #include #include @@ -11,29 +11,28 @@ namespace sky::editor { - LevelDialog::LevelDialog() + WorldDialog::WorldDialog() { - setWindowTitle(tr("New Level")); - setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Expanding); + setWindowTitle(tr("New World")); - auto layout = new QVBoxLayout(this); - auto levelText = new QLineEdit(this); + auto *layout = new QVBoxLayout(this); + auto *levelText = new QLineEdit(this); connect(levelText, &QLineEdit::textEdited, this, [this](const QString name) { - levelName = name + ".level"; + levelName = name + ".world"; }); - auto btn = new QPushButton(tr("New"), this); + auto *btn = new QPushButton(tr("New"), this); connect(btn, &QPushButton::clicked, this, [this]() { accept(); }); - layout->addWidget(new QLabel(tr("Level:"), this)); + layout->addWidget(new QLabel(tr("World:"), this)); layout->addWidget(levelText); layout->addWidget(btn); setLayout(layout); } - const QString &LevelDialog::LevelName() const + const QString &WorldDialog::LevelName() const { return levelName; } diff --git a/editor/src/dialog/LevelDialog.h b/editor/src/dialog/WorldDialog.h similarity index 73% rename from editor/src/dialog/LevelDialog.h rename to editor/src/dialog/WorldDialog.h index 30c22bea..c5f8406e 100644 --- a/editor/src/dialog/LevelDialog.h +++ b/editor/src/dialog/WorldDialog.h @@ -9,11 +9,11 @@ namespace sky::editor { - class LevelDialog : public QDialog { + class WorldDialog : public QDialog { Q_OBJECT public: - LevelDialog(); - ~LevelDialog() = default; + WorldDialog(); + ~WorldDialog() = default; const QString &LevelName() const; diff --git a/editor/src/dockwidget/AssetWidget.cpp b/editor/src/dockwidget/AssetWidget.cpp index b1a32786..38a49ea8 100644 --- a/editor/src/dockwidget/AssetWidget.cpp +++ b/editor/src/dockwidget/AssetWidget.cpp @@ -6,57 +6,105 @@ #include #include #include -#include +#include +#include +#include #include "../window/ActionManager.h" namespace sky::editor { - AssetWidget::AssetWidget(QWidget *parent) : QDockWidget(parent) + AssetDirBrowser::AssetDirBrowser(QWidget *parent) : QFrame(parent) { - fsModel = new QFileSystemModel(this); - fsModel->setRootPath(QDir::currentPath()); + const auto &projectFs = AssetDataBase::Get()->GetWorkSpaceFs(); + auto projectPath = QString(projectFs->GetPath().GetStr().c_str()); + + const auto &engineFs = AssetDataBase::Get()->GetEngineFs(); + auto enginePath = QString(engineFs->GetPath().GetStr().c_str()); + + auto *fsModel = new QFileSystemModel(this); + fsModel->setRootPath(projectPath); + + auto *engineModel = new QFileSystemModel(this); + engineModel->setRootPath(enginePath); + + modelRoot[static_cast(SourceAssetBundle::WORKSPACE)] = fsModel->setRootPath(projectPath); + modelRoot[static_cast(SourceAssetBundle::ENGINE)] = engineModel->setRootPath(enginePath); + + models.emplace(static_cast(SourceAssetBundle::WORKSPACE), fsModel); + models.emplace(static_cast(SourceAssetBundle::ENGINE), engineModel); treeView = new QTreeView(this); - treeView->setModel(fsModel); + treeView->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); - setWindowTitle(tr("Assets")); - auto widget = new QWidget(this); - setWidget(widget); - auto rootLayout = new QHBoxLayout(widget); - rootLayout->setContentsMargins(0, 0, 0, 0); - rootLayout->setAlignment(Qt::AlignLeft); - rootLayout->setContentsMargins(0, 0, 0, 0); - rootLayout->setSpacing(0); - rootLayout->addWidget(treeView); - - auto importAct = new ActionWithFlag(DocumentFlagBit::PROJECT_OPEN, tr("Import"), this); - connect(importAct, &ActionWithFlag::triggered, this, [this]() { - QFileDialog dialog(this); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setViewMode(QFileDialog::Detail); - if (dialog.exec()) { - auto fileNames = dialog.selectedFiles(); - if (!fileNames.empty()) { - for (auto &fileName : fileNames) { - AssetManager::Get()->ImportSource(fileName.toStdString(), SourceAssetImportOption{}); - } - } - } + auto *comboBox = new QComboBox(this); + comboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); + connect(comboBox, static_cast(&QComboBox::currentIndexChanged), this, + [this, comboBox](int index) { + auto id = comboBox->itemData(index).value(); + treeView->setModel(models[id]); + treeView->setRootIndex(modelRoot[id]); + currentModel = id; }); - ActionManager::Get()->AddAction(importAct); + comboBox->addItem("Engine", static_cast(SourceAssetBundle::ENGINE)); + comboBox->addItem("Project", static_cast(SourceAssetBundle::WORKSPACE)); + + setLayout(new QVBoxLayout(this)); + layout()->addWidget(comboBox); + layout()->addWidget(treeView); setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, &QWidget::customContextMenuRequested, this, [this, importAct](const QPoint &pos) { - QMenu menu(tr("Assets"), this); - menu.addAction(importAct); + connect(this, &QWidget::customContextMenuRequested, this, &AssetDirBrowser::OnContentMenuClicked); + } + + void AssetDirBrowser::OnContentMenuClicked(const QPoint &pos) + { + QMenu menu(tr("World Action"), this); - menu.exec(mapToGlobal(pos)); + auto *reloadAct = new QAction(tr("Reload"), &menu); + + auto indices = treeView->selectionModel()->selectedIndexes(); + auto *model = models[currentModel]; + if (model == nullptr || indices.empty()) { + return; + } + auto rootPath = QDir(model->rootPath()); + AssetSourcePath assetSourcePath; + assetSourcePath.bundle = static_cast(currentModel); + + for (auto index : indices) { + if (index.column() != 0) { + continue; + } + + QFileInfo file(static_cast(treeView->model())->filePath(index)); + if (file.isFile()) { + assetSourcePath.path = rootPath.relativeFilePath(file.filePath()).toStdString(); + } + } + + if (assetSourcePath.path.GetStr().empty()) { + return; + } + + connect(reloadAct, &QAction::triggered, this, [assetSourcePath]() { + AssetDataBase::Get()->RegisterAsset(assetSourcePath); }); + + menu.addAction(reloadAct); + menu.exec(mapToGlobal(pos)); } - void AssetWidget::OnProjectChange(const QString &projectPath) + AssetWidget::AssetWidget(QWidget *parent) : QDockWidget(parent) { - treeView->setRootIndex(fsModel->setRootPath(projectPath)); + setWindowTitle(tr("Assets")); + auto *widget = new QWidget(this); + widget->setLayout(new QHBoxLayout(widget)); + auto *splitter = new QSplitter(this); +// splitter->addWidget(new AssetDirBrowser(this)); + splitter->addWidget(new AssetBrowserWidget(this)); + widget->layout()->addWidget(splitter); + + setWidget(widget); } } diff --git a/editor/src/dockwidget/InspectorWidget.cpp b/editor/src/dockwidget/InspectorWidget.cpp new file mode 100644 index 00000000..e5ff773b --- /dev/null +++ b/editor/src/dockwidget/InspectorWidget.cpp @@ -0,0 +1,107 @@ +// +// Created by Zach Lee on 2021/12/15. +// + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace sky::editor { + + InspectorWidget::InspectorWidget(QWidget *parent) : QDockWidget(parent) + { + setWindowTitle(tr("Inspector")); + + auto *widget = new QWidget(this); + widget->setStyleSheet("background-color:white;"); + widget->setAcceptDrops(true); + setWidget(widget); + + auto *rootLayout = new QVBoxLayout(widget); + rootLayout->setAlignment(Qt::AlignTop); + + button = new QPushButton(tr("Add Component"), widget); + connect(button, &QPushButton::clicked, this, &InspectorWidget::OnAddComponentClicked); + + groupWidget = new QWidget(widget); + + rootLayout->addWidget(groupWidget); + rootLayout->addWidget(button); + + layout = new QVBoxLayout(groupWidget); + layout->setAlignment(Qt::AlignTop); + + // auto refreshTimer = new QTimer(this); + // connect(refreshTimer, &QTimer::timeout, this, [this]() { + // Refresh(); + // }); + // refreshTimer->setInterval(1000); + // refreshTimer->start(); + } + + void InspectorWidget::AddComponent(ComponentBase *comp) + { + auto *inspector = new ComponentInspector(groupWidget); + inspector->SetComponent(comp); + layout->addWidget(inspector); + groups.emplace_back(inspector); + } + + void InspectorWidget::Clear() + { + while (QLayoutItem *child = layout->takeAt(0)) { + delete child->widget(); + delete child; + } + groups.clear(); + } + + void InspectorWidget::OnSelectedItemChanged(ActorPtr actor_) + { + actor = std::move(actor_); + Refresh(); + } + + void InspectorWidget::OnAddComponentClicked() + { + QMenu menu(tr("Components"), this); + + const auto &typeMap = ComponentFactory::Get()->GetTypes(); + for (const auto &[group, types] : typeMap) { + auto *sub = menu.addMenu(group.c_str()); + + for (const auto &type : types) { + auto *action = new QAction(type.name.data(), sub); + connect(action, &QAction::triggered, this, [this, typeId = type.typeId](bool checked) { + if (actor != nullptr) { + actor->AddComponent(typeId); + Refresh(); + } + }); + + sub->addAction(action); + } + } + + menu.exec(mapToGlobal(button->pos())); + } + + void InspectorWidget::Refresh() + { + Clear(); + + if (actor) { + const auto &comps = actor->GetComponents(); + for (const auto &[id, comp] : comps) { + AddComponent(comp.get()); + } + } + } + +} // namespace sky::editor diff --git a/editor/src/dockwidget/WorldWidget.cpp b/editor/src/dockwidget/WorldWidget.cpp index 89ce2485..c40dcc84 100644 --- a/editor/src/dockwidget/WorldWidget.cpp +++ b/editor/src/dockwidget/WorldWidget.cpp @@ -3,85 +3,24 @@ // #include -#include -#include #include -#include +#include -#include -#include -#include +#include +#include namespace sky::editor { - static void RefreshTree(GameObject& object, WorldItem* item) - { - auto *trans = object.GetComponent(); - item->setText(0, object.GetName().c_str()); - const auto& children = trans->GetChildren(); - for (const auto& child : children) { - auto *childItem = new WorldItem(item); - childItem->go = child->object; - RefreshTree(*child->object, childItem); - } - } - WorldWidget::WorldWidget(QWidget* parent) : QDockWidget(parent) { - setWindowTitle("Hierarchy"); - worldTree = new QTreeWidget(this); - worldTree->setHeaderLabel("World"); - setWidget(worldTree); - - setContextMenuPolicy(Qt::CustomContextMenu); - connect(this, &QWidget::customContextMenuRequested, this, [this](const QPoint &pos) { - QMenu menu(tr("World Action"), this); - auto addAct = new QAction(tr("Add"), &menu); - connect(addAct, &QAction::triggered, this, [this]() { - if (world == nullptr) { - return; - } - - auto go = world->CreateGameObject("GameObject"); - auto items = worldTree->selectedItems(); - auto parent = static_cast(items.empty() ? rootItem : items[0]); - auto item = new WorldItem(parent); - item->go = go; - go->SetParent(parent->go); - RefreshTree(*go, item); - }); - - menu.addAction(addAct); - - menu.exec(mapToGlobal(pos)); - }); - - connect(worldTree, &QTreeWidget::itemClicked, this, [](QTreeWidgetItem* item, int column) { - WorldItem* worldItem = static_cast(item); - auto inspector = static_cast(DockManager::Get()->Find((uint32_t)DockId::INSPECTOR)); - inspector->SetWorldItem(worldItem); - }); - -// connect(worldTree, &QTreeWidget::itemDoubleClicked, this, [](QTreeWidgetItem* item, int column) { -// -// }); - } - - void WorldWidget::Refresh() - { - worldTree->clear(); - if (world != nullptr) { - auto root = world->GetRoot(); - rootItem = new WorldItem(worldTree); - rootItem->go = root; - RefreshTree(*root, rootItem); - } + setWindowTitle("Outline"); + treeView = new WorldTreeView(this); + setWidget(treeView); } - void WorldWidget::SetWorld(const WorldPtr &w) + void WorldWidget::SetWorld(const WorldPtr &world) { - world = w; - Refresh(); + treeView->BuildByWorld(world); // refreshTimer = new QTimer(this); // connect(refreshTimer, &QTimer::timeout, this, [this]() { diff --git a/editor/src/document/Document.cpp b/editor/src/document/Document.cpp index 6d733d39..fb7c6cfb 100644 --- a/editor/src/document/Document.cpp +++ b/editor/src/document/Document.cpp @@ -3,29 +3,24 @@ // #include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include +#include +#include namespace sky::editor { - Document::Document(const QString &path) + Document::Document() { - projectFullPath = path; + SetFlag(DocumentFlagBit::ProjectOpen); + AssetDataBase::Get()->Load(); } Document::~Document() { - ResetFlag(DocumentFlagBit::PROJECT_OPEN); - ResetFlag(DocumentFlagBit::LEVEL_OPEN); + ResetFlag(DocumentFlagBit::ProjectOpen); + AssetDataBase::Get()->Save(); } void Document::SetFlag(DocumentFlagBit bit) @@ -43,76 +38,61 @@ namespace sky::editor { return flags; } - const WorldPtr &Document::GetMainWorld() const - { - return currentLevel->GetWorld(); - } - void Document::Reflect() { SerializationContext::Get()->Register("ProjectData") .Member<&ProjectData::version>("version"); } - void Document::Init() + void Document::LoadWorld() { - QFileInfo file(projectFullPath); - if (!file.exists()) { - Save(); - } else { - Read(); + NativeFile file(FilePath(filePath.toStdString())); + auto archive = file.ReadAsArchive(); + if (!archive || !archive->IsOpen()) { + return; } - projectHome = file.path(); - auto mkdir = [&](const QString &path) { - QDir dir(projectHome); - QDir tmp(projectHome + QDir::separator() + path); - if (!tmp.exists()) { - dir.mkdir(path); - } - }; - mkdir("assets"); - mkdir("levels"); - - SetFlag(DocumentFlagBit::PROJECT_OPEN); - - AssetManager::Get()->Reset(projectHome.toStdString() + "/assets.db"); - AssetManager::Get()->RegisterSearchPath(projectHome.toStdString()); - AssetManager::Get()->RegisterSearchPath(ENGINE_ROOT + "/assets"); - Interface::Get()->GetApi()->GetSettings().SetValue("PROJECT_PATH", projectHome.toStdString()); + JsonInputArchive json(*archive); + world->LoadJson(json); } - void Document::Read() + void Document::SaveWorld() { - auto str = projectFullPath.toStdString(); - std::ifstream file(str, std::ios::binary); - JsonInputArchive archive(file); - archive.LoadValueObject(projectData); + NativeFile file(FilePath(filePath.toStdString())); + auto archive = file.WriteAsArchive(); + JsonOutputArchive json(*archive); + world->SaveJson(json); } - void Document::Save() + bool Document::NeedSave() const { - auto str = projectFullPath.toStdString(); - std::ofstream file(str, std::ios::binary); - JsonOutputArchive archive(file); - archive.SaveValueObject(projectData); + return world != nullptr; } - void Document::OpenLevel(const QString &path, bool newLevel) + WorldPtr Document::OpenWorld(const QString &path) { - currentLevel = std::make_unique(); - if (newLevel) { - currentLevel->New(projectHome + QDir::separator() + "levels" + QDir::separator() + path); - } else { - currentLevel->Open(path); - } - SetFlag(DocumentFlagBit::LEVEL_OPEN); + CloseWorld(); + + world = World::CreateWorld(); + world->Init({ + "RenderScene", + phy::PhysicsWorld::NAME.data() + }); + + filePath = path; + LoadWorld(); + SetFlag(DocumentFlagBit::WorldOpen); + return world; } - void Document::CloseLevel() + void Document::CloseWorld() { - currentLevel.reset(); - ResetFlag(DocumentFlagBit::LEVEL_OPEN); + if (!world) { + return; + } + SaveWorld(); + world = nullptr; + ResetFlag(DocumentFlagBit::WorldOpen); } } // namespace sky::editor diff --git a/editor/src/document/Level.cpp b/editor/src/document/Level.cpp deleted file mode 100644 index 0a942605..00000000 --- a/editor/src/document/Level.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Created by Zach Lee on 2023/1/15. -// - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace sky::editor { - - Level::~Level() - { - Save(); - } - - void Level::New(const QString &level) - { - path = level; - world = std::make_shared(); - auto *go = world->CreateGameObject("MainCamera"); - go->AddComponent(); - InitRenderScene(); - Save(); - } - - void Level::Open(const QString &level) - { - path = level; - world = std::make_shared(); - InitRenderScene(); - Load(); - } - - void Level::Load() - { - auto str = path.toStdString(); - std::ifstream file(str, std::ios::binary); - JsonInputArchive archive(file); - archive.LoadValueObject(*world); - } - - void Level::Save() - { - auto str = path.toStdString(); - std::ofstream file(str, std::ios::binary); - JsonOutputArchive archive(file); - archive.SaveValueObject(*world); - } - - void Level::InitRenderScene() - { - auto *ppl = new DefaultForward(); - ppl->SetOutput(ViewportManager::Get()->FindViewport(ViewportID::EDITOR_PREVIEW)->GetRenderWindow()); - - renderScene = std::make_unique(); - renderScene->GetRenderScene()->SetPipeline(ppl); - world->SetRenderScene(renderScene.get()); - } - - const WorldPtr &Level::GetWorld() const - { - return world; - } - -} // namespace sky::editor diff --git a/editor/src/inspector/ComponentInspector.cpp b/editor/src/inspector/ComponentInspector.cpp index 1381221b..634e7068 100644 --- a/editor/src/inspector/ComponentInspector.cpp +++ b/editor/src/inspector/ComponentInspector.cpp @@ -8,12 +8,11 @@ namespace sky::editor { - void ComponentInspector::SetComponent(Component *comp) + void ComponentInspector::SetComponent(ComponentBase *comp) { component = comp; - const TypeInfoRT *info = comp->GetTypeInfo(); - const auto *node = GetTypeNode(info); + const auto *node = GetTypeNode(comp->GetTypeId()); if (node == nullptr) { return; } diff --git a/editor/src/inspector/InspectorBase.cpp b/editor/src/inspector/InspectorBase.cpp index 92aac0fa..55041e45 100644 --- a/editor/src/inspector/InspectorBase.cpp +++ b/editor/src/inspector/InspectorBase.cpp @@ -5,12 +5,9 @@ #include #include #include -#include #include #include -#include -#include -#include +#include namespace sky::editor { @@ -21,8 +18,9 @@ namespace sky::editor { layout->setSpacing(0); label = new QLabel(this); - label->setStyleSheet("background-color: #333333; border-radius: 8px; border-style: solid; border-color: #1B1B1B; border-width: 1px; " - "border-left: none; border-right: none;"); + label->setStyleSheet("background-color: #999999; border-radius: 8px; border-style: solid; border-color: #1B1B1B; border-width: 1px; " + "border-left: none; border-right: none;" + "font-size: 12pt;"); label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); label->setFixedHeight(24); label->setMargin(0); @@ -32,9 +30,8 @@ namespace sky::editor { void InspectorBase::SetObject(void *ptr, const TypeNode *node) { - label->setText(node->info->markedName.data()); - auto *prop = new PropertyWidget(label); - prop->SetInstance(ptr, node); + label->setText(node->info->name.data()); + auto *prop = new ReflectedObjectWidget(ptr, node, this); layout->addWidget(prop); } diff --git a/editor/src/inspector/InspectorWidget.cpp b/editor/src/inspector/InspectorWidget.cpp deleted file mode 100644 index 0d899560..00000000 --- a/editor/src/inspector/InspectorWidget.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// Created by Zach Lee on 2021/12/15. -// - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace sky::editor { - - InspectorWidget::InspectorWidget(QWidget *parent) : QDockWidget(parent) - { - setWindowTitle(tr("Inspector")); - - auto *widget = new QWidget(this); - setWidget(widget); - auto *rootLayout = new QVBoxLayout(widget); - rootLayout->setContentsMargins(0, 0, 0, 0); - rootLayout->setAlignment(Qt::AlignTop); - - button = new QPushButton(tr("Add Component"), widget); - connect(button, &QPushButton::clicked, this, [this](bool checked) { - QMenu menu(tr("Components"), this); - - const auto &types = ComponentFactory::Get()->GetComponentTypes(); - auto *serializationContext = SerializationContext::Get(); - for (const auto &type : types) { - auto *node = serializationContext->FindTypeById(type.first); - if (node == nullptr) { - continue; - } - - auto *action = new QAction(node->info->markedName.data(), &menu); - const auto typeID = type.first; - connect(action, &QAction::triggered, this, [this, typeID](bool checked) { - selectedItem->go->AddComponent(typeID); - Refresh(); - }); - - menu.addAction(action); - } - - menu.exec(mapToGlobal(button->pos())); - }); - - groupWidget = new QWidget(widget); - - rootLayout->addWidget(groupWidget); - rootLayout->addWidget(button); - - layout = new QVBoxLayout(groupWidget); - layout->setAlignment(Qt::AlignTop); - layout->setContentsMargins(0, 0, 0, 0); - } - - void InspectorWidget::AddComponent(Component *comp) - { - auto *inspector = new ComponentInspector(groupWidget); - inspector->SetComponent(comp); - - layout->addWidget(inspector); - - groups.emplace_back(inspector); - } - - void InspectorWidget::Clear() - { - while (QLayoutItem *child = layout->takeAt(0)) { - delete child->widget(); - delete child; - } - groups.clear(); - } - - void InspectorWidget::SetWorldItem(WorldItem *item) - { - selectedItem = item; - Refresh(); - } - - void InspectorWidget::Refresh() - { - if (selectedItem == nullptr) { - return; - } - Clear(); - auto *go = selectedItem->go; - auto &comps = go->GetComponents(); - for (auto &comp : comps) { - AddComponent(comp); - } - } - -} // namespace sky::editor diff --git a/editor/src/inspector/PropertyColorWidget.cpp b/editor/src/inspector/PropertyColorWidget.cpp deleted file mode 100644 index 8501f51d..00000000 --- a/editor/src/inspector/PropertyColorWidget.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// Created by Zach Lee on 2023/8/23. -// - -#include -#include -#include -#include - -namespace sky::editor { - - PropertyColorWidget::PropertyColorWidget(void *inst, const TypeNode *node, QWidget* parent) : PropertyWidget(inst, node, parent) - { - layout->setSpacing(0); - layout->addWidget(label, 0, Qt::AlignLeft | Qt::AlignTop); - - button = new QPushButton(this); - layout->addWidget(button); - connect(button, &QPushButton::clicked, this, [this](bool checked) { - QColorDialog dialog; - if (dialog.exec() != 0) { - auto color = dialog.selectedColor(); - auto *val = reinterpret_cast(instance); - val[0] = static_cast(color.redF()); - val[1] = static_cast(color.greenF()); - val[2] = static_cast(color.blueF()); - val[3] = static_cast(color.alphaF()); - Refresh(); - } - }); - } - - void PropertyColorWidget::Refresh() - { - const auto *val = reinterpret_cast(instance); - QColor color; - color.setRedF(val[0]); - color.setGreenF(val[1]); - color.setBlueF(val[2]); - color.setAlphaF(val[3]); - QString qss = QString("background-color: %1").arg(color.name()); - button->setStyleSheet(qss); - } -} // sky::editor \ No newline at end of file diff --git a/editor/src/inspector/PropertyUtil.cpp b/editor/src/inspector/PropertyUtil.cpp deleted file mode 100644 index 7647a6c0..00000000 --- a/editor/src/inspector/PropertyUtil.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#include -#include -#include - -namespace sky::editor::util { - - bool CheckProperty(const PropertyMap &properties, CommonPropertyKey key, bool dft) - { - auto iter = properties.find(key); - if (iter != properties.end()) { - const auto *val = iter->second.GetAsConst(); - return val != nullptr ? *val : dft; - } - return true; - } -} // namespace sky::editor::util diff --git a/editor/src/inspector/PropertyWidget.cpp b/editor/src/inspector/PropertyWidget.cpp deleted file mode 100644 index 49876432..00000000 --- a/editor/src/inspector/PropertyWidget.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky::editor { - - PropertyWidget::PropertyWidget(void *ptr, const TypeNode *node, QWidget* parent) : QWidget(parent), instance(ptr), typeNode(node) - { - label = new QLabel(this); - - layout = new QHBoxLayout(this); - layout->addWidget(label); - - setLayout(layout); - setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - } - - PropertyWidget::PropertyWidget(QWidget *parent) : PropertyWidget(nullptr, nullptr, parent) - { - } - - void PropertyWidget::SetLabel(const QString &str) - { - label->setFixedWidth(120); - label->setText(str); - } - - void PropertyWidget::SetInstance(void *inst, const TypeNode *node) - { - instance = inst; - typeNode = node; - - if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyBool(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyScalar(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyScalar(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyScalar(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyScalar(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else if (node->info->typeId == TypeInfoObj::Get()->RtInfo()->typeId) { - auto *widget = new PropertyColorWidget(inst, node, this); - layout->addWidget(widget); - children.push_back(widget); - } else { - auto *childWidget = new QWidget(this); - auto *childLayout = new QVBoxLayout(childWidget); - childWidget->setLayout(childLayout); - - childLayout->setSpacing(0); - childLayout->setContentsMargins(0, 0, 0, 0); - childWidget->setContentsMargins(0, 0, 0, 0); - - for (const auto &member : node->members) { - if (!util::CheckProperty(member.second.properties, UI_PROP_VISIBLE)) { - continue; - } - const auto *childNode = GetTypeNode(member.second.info); - if (childNode == nullptr) { - continue; - } - auto *ptr = member.second.getterFn(instance); - auto *widget = new PropertyWidget(this); - - if (util::CheckProperty(member.second.properties, UI_LABEL_VISIBLE)) { - widget->SetLabel(member.first.data()); - } - - widget->SetInstance(ptr, childNode); - childLayout->addWidget(widget, 0, Qt::AlignLeft | Qt::AlignTop); - children.push_back(widget); - } - - layout->addWidget(childWidget); - } - - Refresh(); - } - - void PropertyWidget::Refresh() - { - for (auto &child : children) { - child->Refresh(); - } - } -} // namespace sky::editor \ No newline at end of file diff --git a/editor/src/main.cpp b/editor/src/main.cpp index af9d77be..471cb47a 100644 --- a/editor/src/main.cpp +++ b/editor/src/main.cpp @@ -3,24 +3,24 @@ // Created by Zach Lee on 2021/12/12. // -#include "window/MainWindow.h" #include +#include #include +#include using namespace sky::editor; int main(int argc, char *argv[]) { - QApplication a(argc, argv); + sky::Platform* platform = sky::Platform::Get(); + if (!platform->Init({})) { + return -1; + } - EditorApplication editorApp; - sky::StartInfo startInfo = {}; - startInfo.appName = "SkyEditor"; - startInfo.modules.emplace_back("BuiltinBuilder"); - startInfo.modules.emplace_back("SkyRender"); - editorApp.Init(startInfo); + EditorApplication editorApp(argc, argv); + if (!editorApp.Init(argc, argv)) { + return 0; + } - sky::editor::MainWindow mainWindow; - mainWindow.show(); - return a.exec(); + return editorApp.exec(); } diff --git a/editor/src/viewport/Viewport.cpp b/editor/src/viewport/Viewport.cpp deleted file mode 100644 index 8a57b982..00000000 --- a/editor/src/viewport/Viewport.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Created by Zach Lee on 2021/12/13. -// - -#include -#include - -namespace sky::editor { - - Viewport::Viewport() - { - setSurfaceType(SurfaceType::MetalSurface); - } - - Viewport::~Viewport() - { - if (window != nullptr) { - Renderer::Get()->DestroyRenderWindow(window); - ViewportManager::Get()->UnRegister(viewportId); - } - } - - void Viewport::Init(ViewportID id) - { - window = Renderer::Get()->CreateRenderWindow(reinterpret_cast(winId()), width(), height(), true); - viewportId = id; - ViewportManager::Get()->Register(viewportId, this); - } - - bool Viewport::event(QEvent *event) - { - switch (event->type()) { - case QEvent::Resize: - if (window != nullptr) { - window->Resize(width(), height()); - } - break; - case QEvent::MouseMove: - break; - case QEvent::Close: - break; - default: break; - } - return true; - } - - void ViewportManager::Register(ViewportID key, Viewport* vp) - { - viewports.emplace(key, vp); - } - - void ViewportManager::UnRegister(ViewportID key) - { - viewports.erase(key); - } - - Viewport *ViewportManager::FindViewport(ViewportID key) const - { - return viewports.at(key); - } -} // namespace sky::editor diff --git a/editor/src/viewport/ViewportWidget.cpp b/editor/src/viewport/ViewportWidget.cpp deleted file mode 100644 index 87c72c5a..00000000 --- a/editor/src/viewport/ViewportWidget.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by Zach Lee on 2021/12/12. -// - -#include -#include -#include -#include - -namespace sky::editor { - - ViewportWidget::ViewportWidget(QWidget *parent) : QWidget(parent), window(new Viewport()) - { - } - - void ViewportWidget::Init() - { - auto *container = QWidget::createWindowContainer(window, this, Qt::Widget); - window->Init(ViewportID::EDITOR_PREVIEW); - auto *layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(container); - } - -} // namespace sky::editor diff --git a/editor/src/window/ActionManager.cpp b/editor/src/window/ActionManager.cpp index 821b36bd..e176019b 100644 --- a/editor/src/window/ActionManager.cpp +++ b/editor/src/window/ActionManager.cpp @@ -15,7 +15,7 @@ namespace sky::editor { } ActionWithFlag::ActionWithFlag(const DocFlagArray &value, const QIcon &icon, const QString &text, QObject *parent) - : QAction(icon, text, parent), flags(value) + : QAction(icon, text, parent), flags(value) { } diff --git a/editor/src/window/CentralWidget.cpp b/editor/src/window/CentralWidget.cpp index 405f3e77..6e556176 100644 --- a/editor/src/window/CentralWidget.cpp +++ b/editor/src/window/CentralWidget.cpp @@ -7,35 +7,16 @@ namespace sky::editor { - CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent), viewport(new ViewportWidget(this)) + CentralWidget::CentralWidget(QWidget *parent) : QWidget(parent) { - } - - CentralWidget::~CentralWidget() - { - } - - void CentralWidget::Init() - { - viewport->Init(); - auto layout = new QVBoxLayout(this); + layout = new QVBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); - layout->addWidget(viewport); } - ViewportWidget *CentralWidget::GetViewport() const - { - return viewport; - } + CentralWidget::~CentralWidget() = default; - bool CentralWidget::event(QEvent *event) + void CentralWidget::Init() { - auto rect = geometry(); - switch (event->type()) { - case QEvent::Resize: break; - default: break; - } - return QWidget::event(event); } } // namespace sky::editor \ No newline at end of file diff --git a/editor/src/window/CentralWidget.h b/editor/src/window/CentralWidget.h index 14902e62..bd8e4401 100644 --- a/editor/src/window/CentralWidget.h +++ b/editor/src/window/CentralWidget.h @@ -4,23 +4,20 @@ #pragma once #include -#include +#include namespace sky::editor { class CentralWidget : public QWidget { public: - CentralWidget(QWidget *parent = nullptr); - ~CentralWidget(); + explicit CentralWidget(QWidget *parent = nullptr); + ~CentralWidget() override; void Init(); - - ViewportWidget *GetViewport() const; - - bool event(QEvent *event) override; - private: - ViewportWidget *viewport = nullptr; + void Update(); + + QVBoxLayout *layout = nullptr; }; } // namespace sky::editor \ No newline at end of file diff --git a/editor/src/window/MainWindow.cpp b/editor/src/window/MainWindow.cpp index 83f08e9b..dae58ebd 100644 --- a/editor/src/window/MainWindow.cpp +++ b/editor/src/window/MainWindow.cpp @@ -2,28 +2,30 @@ // Created by Zach Lee on 2021/12/12. // -#include "MainWindow.h" +#include #include "ActionManager.h" #include "CentralWidget.h" -#include "../dialog/ProjectDialog.h" -#include "../dialog/LevelDialog.h" #include #include #include #include #include +#include +#include +#include #include #include #include -#include -#include +#include namespace sky::editor { MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { + InitDocument(); InitWidgets(); InitMenu(); + UpdateActions(); } MainWindow::~MainWindow() @@ -31,80 +33,110 @@ namespace sky::editor { ActionManager::Destroy(); } - void MainWindow::OnOpenLevel(const QString &path) + void MainWindow::OnOpenWorld() { - document->OpenLevel(path, false); - worldWidget->SetWorld(document->GetMainWorld()); + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setNameFilter(tr("World (*.world)")); + dialog.setViewMode(QFileDialog::Detail); + dialog.setDirectory(projectPath); + QStringList fileNames; + if (dialog.exec() != 0) { + fileNames = dialog.selectedFiles(); + } + if (fileNames.empty()) { + return; + } + + auto world = document->OpenWorld(fileNames[0]); + if (!world) { + return; + } + + worldWidget->SetWorld(world); + mainViewport->ResetWorld(world); + setCentralWidget(mainViewport); UpdateActions(); } - void MainWindow::OnNewLevel(const QString &name) + void MainWindow::OnNewWorld() { - document->OpenLevel(name, true); - worldWidget->SetWorld(document->GetMainWorld()); + QString fineName = QFileDialog::getSaveFileName(nullptr, "Create", projectPath, tr("World (*.world)")); + if (fineName.isEmpty()) { + return; + } + + auto world = document->OpenWorld(fineName); + if (!world) { + return; + } + + worldWidget->SetWorld(world); + mainViewport->ResetWorld(world); UpdateActions(); } - void MainWindow::OnCloseLevel() + void MainWindow::OnCloseWorld() { - document->CloseLevel(); + SaveCheck(); worldWidget->SetWorld(nullptr); + inspector->OnSelectedItemChanged(nullptr); + mainViewport->ResetWorld(nullptr); + document->CloseWorld(); UpdateActions(); } - void MainWindow::OnOpenProject(const QString &path) + void MainWindow::OnSaveWorld() { - document = std::make_unique(path); - document->Init(); - - QFileInfo file(path); - auto dir = file.path().toStdString(); - assetBrowser->OnProjectChange(file.path()); - UpdateActions(); + document->SaveWorld(); } - void MainWindow::OnNewProject(const QString &path, const QString &name) + void MainWindow::SaveCheck() { - QDir dir(path); - QDir fullPath(path + QDir::separator() + name); - QDir fullPathFile(path + QDir::separator() + name + QDir::separator() + name + tr(".sproj")); - - if (dir.exists()){ - QDir check(path); - if (fullPath.exists()) { - QMessageBox msgWarning; - msgWarning.setText("Error!\nDirectory Exists."); - msgWarning.setIcon(QMessageBox::Critical); - msgWarning.setWindowTitle("Caution"); - msgWarning.exec(); - return; - } - - dir.mkdir(name); + if (!document->NeedSave()) { + return; + } + + QMessageBox msgBox; + msgBox.setText("The document has been modified."); + msgBox.setInformativeText("Do you want to save your changes?"); + msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); + msgBox.setDefaultButton(QMessageBox::Save); + int ret = msgBox.exec(); + + switch (ret) { + case QMessageBox::Save: + OnSaveWorld(); + break; + default: + break; } - OnOpenProject(fullPathFile.path()); } - void MainWindow::OnCloseProject() + void MainWindow::OnImport() { - document.reset(); - assetBrowser->OnProjectChange(""); - UpdateActions(); + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setViewMode(QFileDialog::Detail); + dialog.setDirectory(projectPath); + QStringList fileNames; + if (dialog.exec() != 0) { + fileNames = dialog.selectedFiles(); + } + if (fileNames.empty()) { + return; + } + AssetBuilderManager::Get()->ImportAsset({fileNames[0].toStdString()}); } void MainWindow::InitWidgets() { setWindowState(Qt::WindowMaximized); - auto *centralWidget = new CentralWidget(this); - setCentralWidget(centralWidget); - centralWidget->Init(); - auto *vp = centralWidget->GetViewport(); - if (vp != nullptr) { - viewports.emplace_back(vp); - } + emptyCentral = new CentralWidget(this); + setCentralWidget(emptyCentral); - auto *dockMgr = DockManager::Get(); + auto *dockMgr = DockManager::Get(); worldWidget = new WorldWidget(this); addDockWidget(Qt::DockWidgetArea::LeftDockWidgetArea, worldWidget); dockMgr->Register((uint32_t)DockId::WORLD, *worldWidget); @@ -113,9 +145,21 @@ namespace sky::editor { addDockWidget(Qt::DockWidgetArea::RightDockWidgetArea, inspector); dockMgr->Register((uint32_t)DockId::INSPECTOR, *inspector); + connect(worldWidget->GetWorldTreeView(), &WorldTreeView::WorldTreeSelectItemChanged, inspector, &InspectorWidget::OnSelectedItemChanged); + assetBrowser = new AssetWidget(this); addDockWidget(Qt::DockWidgetArea::BottomDockWidgetArea, assetBrowser); dockMgr->Register((uint32_t)DockId::BROWSER, *assetBrowser); + + mainViewport = new ViewportWidget(nullptr); + setCentralWidget(mainViewport); + + projectPath = AssetDataBase::Get()->GetWorkSpaceFs()->GetPath().GetStr().c_str(); + } + + void MainWindow::InitDocument() + { + document = std::make_unique(); } void MainWindow::InitMenu() @@ -125,96 +169,40 @@ namespace sky::editor { menuBar = new QMenuBar(this); // level - auto *openLevelAct = new ActionWithFlag(DocumentFlagBit::PROJECT_OPEN, "Open Level"); - auto *closeLevelAct = new ActionWithFlag(DocumentFlagBit::LEVEL_OPEN, "Close Level"); - auto *newLevelAct = new ActionWithFlag(DocumentFlagBit::PROJECT_OPEN, "New Level"); - - connect(openLevelAct, &QAction::triggered, this, [this](bool /**/) { - QFileDialog dialog(this); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setNameFilter(tr("Level (*.level)")); - dialog.setViewMode(QFileDialog::Detail); - QStringList fileNames; - if (dialog.exec() != 0) { - fileNames = dialog.selectedFiles(); - if (!fileNames.empty()) { - OnOpenLevel(fileNames[0]); - } - } - }); - - connect(newLevelAct, &QAction::triggered, this, [this](bool /**/) { - LevelDialog dialog; - if (dialog.exec() != 0) { - const auto& name = dialog.LevelName(); - if (!name.isEmpty()) { - OnNewLevel(name); - } - } - }); - - connect(closeLevelAct, &QAction::triggered, this, [this]() { - OnCloseLevel(); - }); - - auto *openProjectAct = new ActionWithFlag({}, "Open Project", this); - auto *newProjectAct = new ActionWithFlag({}, "New Project", this); - auto *closeProjectAct = new ActionWithFlag(DocumentFlagBit::PROJECT_OPEN, "Close Project", this); - - // project - connect(openProjectAct, &QAction::triggered, this, [this](bool /**/) { - QFileDialog dialog(this); - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setNameFilter(tr("Projects (*.sproj)")); - dialog.setViewMode(QFileDialog::Detail); - QStringList fileNames; - if (dialog.exec() != 0) { - fileNames = dialog.selectedFiles(); - if (!fileNames.empty()) { - OnOpenProject(fileNames[0]); - } - } - }); - - connect(newProjectAct, &QAction::triggered, this, [this](bool /**/) { - ProjectDialog dialog; - if (dialog.exec() != 0) { - const auto& projectPath = dialog.ProjectPath(); - const auto& projectName = dialog.ProjectName(); - if (!projectPath.isEmpty() && !projectName.isEmpty()) { - OnNewProject(projectPath, projectName); - } - } - }); - - connect(closeProjectAct, &QAction::triggered, this, [this](bool /**/) { - OnCloseProject(); - }); + auto *openWorldAct = new ActionWithFlag(DocumentFlagBit::ProjectOpen, "Open World"); + auto *closeWorldAct = new ActionWithFlag(DocumentFlagBit::WorldOpen, "Close World"); + auto *newWorldAct = new ActionWithFlag(DocumentFlagBit::ProjectOpen, "New World"); + auto *saveWorldAct = new ActionWithFlag(DocumentFlagBit::WorldOpen, "Save World"); + + connect(openWorldAct, &QAction::triggered, this, [this]() { OnOpenWorld(); }); + connect(newWorldAct, &QAction::triggered, this, [this]() { OnNewWorld(); }); + connect(closeWorldAct, &QAction::triggered, this, [this]() { OnCloseWorld(); }); + connect(saveWorldAct, &QAction::triggered, this, [this]() { OnSaveWorld(); }); + + // import + auto *importAct = new ActionWithFlag(DocumentFlagBit::ProjectOpen, "Import Asset"); + connect(importAct, &QAction::triggered, this, [this]() { OnImport(); }); // close editor auto *closeAct = new ActionWithFlag({}, "Close", this); connect(closeAct, &QAction::triggered, this, [this](bool /**/) { close(); }); auto *fileMenu = new QMenu("File", menuBar); - fileMenu->addAction(newProjectAct); - fileMenu->addAction(openProjectAct); - fileMenu->addAction(closeProjectAct); + fileMenu->addAction(newWorldAct); + fileMenu->addAction(openWorldAct); + fileMenu->addAction(saveWorldAct); + fileMenu->addAction(closeWorldAct); fileMenu->addSeparator(); - fileMenu->addAction(newLevelAct); - fileMenu->addAction(openLevelAct); - fileMenu->addAction(closeLevelAct); + fileMenu->addAction(importAct); fileMenu->addSeparator(); fileMenu->addAction(closeAct); menuBar->addMenu(fileMenu); setMenuBar(menuBar); - actionManager->AddAction(openLevelAct); - actionManager->AddAction(closeLevelAct); - actionManager->AddAction(newLevelAct); - actionManager->AddAction(newProjectAct); - actionManager->AddAction(openProjectAct); - actionManager->AddAction(closeProjectAct); + actionManager->AddAction(newWorldAct); + actionManager->AddAction(openWorldAct); + actionManager->AddAction(closeWorldAct); actionManager->AddAction(closeAct); UpdateActions(); } @@ -224,4 +212,21 @@ namespace sky::editor { actionManager->Update(document ? document->GetFlag() : DocFlagArray{}); } + bool MainWindow::event(QEvent *event) + { + switch (event->type()) { + case QEvent::Close: + OnCloseWorld(); + break; + default: + break; + } + return QMainWindow::event(event); + } + + ViewportWindow* MainWindow::GetViewportWindow() const + { + return mainViewport->GetViewportWindow(); + } + } // namespace sky::editor diff --git a/engine/include/engine/GlobalVariable.h b/engine/include/engine/GlobalVariable.h deleted file mode 100644 index b962ffe0..00000000 --- a/engine/include/engine/GlobalVariable.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Created by Zach Lee on 2022/8/11. -// - -#pragma once - -#include -#include -#include - -namespace sky { - - class GlobalVariable : public Singleton { - public: - ~GlobalVariable() override = default; - - template - const T *Find(const std::string &key) - { - auto iter = valueMap.find(key); - if (iter != valueMap.end()) { - return iter->second.GetAs(); - } - return nullptr; - } - - template - void Register(const std::string &key, const T &val) - { - valueMap[key] = Any(val); - } - - private: - friend class Singleton; - GlobalVariable() = default; - - std::unordered_map valueMap; - }; - -} // namespace sky \ No newline at end of file diff --git a/engine/include/engine/SkyEngine.h b/engine/include/engine/SkyEngine.h deleted file mode 100644 index b6880a69..00000000 --- a/engine/include/engine/SkyEngine.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by Zach Lee on 2021/11/12. -// - -#pragma once -#include -#include -#include - -#include -#include - -namespace sky { - - class SkyEngine : public Singleton { - public: - static void Reflect(); - - bool Init(); - void DeInit(); - - void Tick(float); - - void AddWorld(const WorldPtr& world); - void RemoveWorld(const WorldPtr& world); - - private: - template - friend class Singleton; - - SkyEngine() = default; - ~SkyEngine() override = default; - - std::set worlds; - }; - -} // namespace sky \ No newline at end of file diff --git a/engine/src/EngineReflect.cpp b/engine/src/EngineReflect.cpp deleted file mode 100644 index 27ff8f40..00000000 --- a/engine/src/EngineReflect.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Created by Zach Lee on 2021/12/15. -// - -#include -#include - -namespace sky { - - void SkyEngine::Reflect() - { - CoreReflection(); - World::Reflect(); - } - -} // namespace sky diff --git a/engine/src/SkyEngine.cpp b/engine/src/SkyEngine.cpp deleted file mode 100644 index 5e38c504..00000000 --- a/engine/src/SkyEngine.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by Zach Lee on 2021/11/11. -// - -#include -#include - -static const char *TAG = "SkyEngine"; - -namespace sky { - - bool SkyEngine::Init() - { - return true; - } - - void SkyEngine::Tick(float time) - { - for (const auto &world : worlds) { - world->Tick(time); - } - } - - void SkyEngine::DeInit() - { - } - - void SkyEngine::AddWorld(const WorldPtr& world) - { - worlds.emplace(world); - } - - void SkyEngine::RemoveWorld(const WorldPtr& world) - { - worlds.erase(world); - } -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/asset/Asset.h b/framework/include/framework/asset/Asset.h deleted file mode 100644 index 6fd424d4..00000000 --- a/framework/include/framework/asset/Asset.h +++ /dev/null @@ -1,185 +0,0 @@ -// -// Created by Zach on 2022/8/8. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - - class AssetBase { - public: - AssetBase() = default; - - virtual ~AssetBase() = default; - - enum class Status { INITIAL, LOADING, LOADED }; - - void SetUuid(const Uuid &id); - const Uuid &GetUuid() const { return uuid; } - - virtual const Uuid &GetType() const = 0; - Status GetStatus() const { return status; } - - virtual const uint8_t *GetData() const = 0; - - void BlockUtilLoaded() - { - if (future.valid()) { - future.wait(); - } - } - - protected: - friend class AssetManager; - friend class AssetManager; - - Uuid uuid; - Status status = Status::INITIAL; - tf::Future future; - }; - - using AssetPtr = std::shared_ptr; - - enum class SerializeType : uint8_t { JSON, BIN }; - - template - struct AssetTraits { - using DataType = std::vector; - static constexpr Uuid ASSET_TYPE; - static constexpr SerializeType SERIALIZE_TYPE = SerializeType::JSON; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return nullptr; - } - }; - - template - class Asset : public AssetBase { - public: - Asset() = default; - - ~Asset() override = default; - - using DataType = typename AssetTraits::DataType; - - const Uuid &GetType() const override - { - return AssetTraits::ASSET_TYPE; - } - - std::shared_ptr CreateInstance(bool useDefault = true) - { - if (useDefault) { - std::shared_ptr res; - std::lock_guard lock(mutex); - res = defaultInstance.lock(); - if (res) { - return res; - } - res = AssetTraits::CreateFromData(data); - defaultInstance = res; - return res; - } - return AssetTraits::CreateFromData(data); - } - - template - std::shared_ptr CreateInstanceAs(bool useDefault = true) - { - return std::static_pointer_cast(CreateInstance(useDefault)); - } - - const DataType &Data() const - { - return data; - } - DataType &Data() - { - return data; - } - - const uint8_t *GetData() const override { return reinterpret_cast(&data); } - private: - friend class AssetManager; - - DataType data; - - std::mutex mutex; - std::weak_ptr defaultInstance; - }; - - class AssetHandlerBase { - public: - AssetHandlerBase() = default; - - virtual ~AssetHandlerBase() = default; - - SKY_DISABLE_COPY(AssetHandlerBase) - - virtual std::shared_ptr CreateAsset() = 0; - - virtual void LoadFromPath(const std::string &path, const std::shared_ptr &asset) = 0; - - virtual void SaveToPath(const std::string &path, const std::shared_ptr &data) = 0; - }; - - template - class AssetHandler : public AssetHandlerBase { - public: - AssetHandler() = default; - - ~AssetHandler() override = default; - - using DataType = typename AssetTraits::DataType; - static constexpr SerializeType SERIALIZE_TYPE = AssetTraits::SERIALIZE_TYPE; - - std::shared_ptr CreateAsset() override - { - return std::make_shared>(); - } - - void LoadFromPath(const std::string &path, const std::shared_ptr &assetBase) override - { - std::ifstream file(path, std::ios::binary); - if (!file.is_open()) { - return; - } - - auto asset = std::static_pointer_cast>(assetBase); - DataType &assetData = asset->Data(); - if (SERIALIZE_TYPE == SerializeType::JSON) { - JsonInputArchive archive(file); - } else if (SERIALIZE_TYPE == SerializeType::BIN) { - BinaryInputArchive archive(file); - archive.LoadObject(&assetData, TypeInfo::Hash()); - } - } - - void SaveToPath(const std::string &path, const std::shared_ptr &assetBase) override - { - auto asset = std::static_pointer_cast>(assetBase); - auto &assetData = asset->Data(); - std::ofstream file(path, std::ios::binary); - if (!file.is_open()) { - return; - } - if (SERIALIZE_TYPE == SerializeType::JSON) { - JsonOutputArchive archive(file); - archive.SaveValueObject(assetBase->GetData(), TypeInfo::Hash()); - } else if (SERIALIZE_TYPE == SerializeType::BIN) { - BinaryOutputArchive archive(file); - archive.SaveObject(assetBase->GetData(), TypeInfo::Hash()); - } - } - }; -} // namespace sky diff --git a/framework/include/framework/asset/AssetBuilder.h b/framework/include/framework/asset/AssetBuilder.h deleted file mode 100644 index b10100d5..00000000 --- a/framework/include/framework/asset/AssetBuilder.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Created by Zach Lee on 2023/2/20. -// - -#pragma once -#include -#include -#include -#include -#include -#include - -namespace sky { - - struct BuildProduct { - std::string productKey; - std::shared_ptr asset; - std::vector deps; - }; - - struct BuildRequest { - Uuid uuid; - std::string relativePath; - std::string fullPath; - std::string name; - std::string ext; - PlatformType targetPlatform; - std::string buildKey; - const void *rawData = nullptr; - uint32_t dataSize = 0; - }; - - struct BuildResult { - bool success = false; - std::vector products; - }; - - class AssetBuilder { - public: - AssetBuilder() = default; - virtual ~AssetBuilder() = default; - - virtual void Request(const BuildRequest &build, BuildResult &result) = 0; - virtual const std::vector &GetExtensions() const = 0; - - virtual std::string GetConfigKey() const { return ""; } - virtual void LoadConfig(const std::string &path) {} - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/asset/AssetDataBase.h b/framework/include/framework/asset/AssetDataBase.h deleted file mode 100644 index 727282c7..00000000 --- a/framework/include/framework/asset/AssetDataBase.h +++ /dev/null @@ -1,52 +0,0 @@ -// -// Created by Zach Lee on 2023/2/20. -// - -#pragma once - -#include -#include -#include - -namespace sky { - - struct SourceData { - std::string path; - std::string folder; - std::string productKey; - Uuid uuid; - }; - - struct ProductData { - Uuid uuid; - std::string path; - }; - - class AssetDataBase { - public: - AssetDataBase() = default; - ~AssetDataBase(); - - void Init(const std::string &name); - - void AddSource(const SourceData &sourceData); - bool QueryProduct(const std::string &sourcePath, const std::string &key, Uuid &uuid) const; - bool QueryProduct(const Uuid &uuid, std::string &out); - - void AddProduct(const ProductData &productData); - - private: - std::unique_ptr dataBase; - - // source table - std::unique_ptr createSourceTableStat; - std::unique_ptr insertSourceTableStat; - std::unique_ptr selectSourceTableStat; - - // product table - std::unique_ptr createProductTableStat; - std::unique_ptr insertProductTableStat; - std::unique_ptr selectProductTableStat; - }; - -} \ No newline at end of file diff --git a/framework/include/framework/asset/AssetManager.h b/framework/include/framework/asset/AssetManager.h deleted file mode 100644 index 4f6af7e0..00000000 --- a/framework/include/framework/asset/AssetManager.h +++ /dev/null @@ -1,117 +0,0 @@ -// -// Created by blues on 2023/12/24. -// - -#pragma once - -#include -#include -#include -#include -#include - -namespace sky { - - enum class AssetGroup : uint32_t { - ENGINE, - PROJECT, - CUSTOM - }; - - struct AssetSearchPath { - std::string path; - AssetGroup group; - }; - - class AssetManager : public Singleton { - public: - AssetManager() = default; - ~AssetManager() override; - - void SetWorkPath(const std::string &path); - -#ifdef SKY_EDITOR - // --- editor only --- - void SetProjectPath(const std::string &path); - const std::string &GetProjectPath() const { return projectPath; } - - void LoadConfig(const std::string &path); - const std::vector &GetSearchPathList() const { return searchPathList; } - - // asset actions - const Uuid &ImportAsset(const std::string &path); - const Uuid &ImportAndBuildAsset(const std::string &path, PlatformType target = PlatformType::Default); - const Uuid &RegisterAsset(const SourceAssetInfo &info); - void RemoveAsset(const Uuid &uuid); - bool BuildAsset(const BuildRequest &request); - bool BuildAsset(const Uuid &uuid, PlatformType target = PlatformType::Default); - void SaveAsset(const Uuid &uuid, PlatformType target = PlatformType::Default); - void SaveAsset(const std::shared_ptr &asset, PlatformType target = PlatformType::Default); - const SourceAssetIDMap &GetIDMap() const { return package->GetIDMap(); } - - // asset builders - void RegisterBuilder(AssetBuilder *builder); - // --- editor only --- -#endif - - // load asset - std::string GetAssetPath(const Uuid &uuid); - std::shared_ptr LoadAsset(const Uuid &type, const Uuid &uuid, bool async); - std::shared_ptr LoadAsset(const Uuid &type, const std::string &path, bool async); - std::shared_ptr CreateAsset(const Uuid &type, const Uuid &uuid); - - template - std::shared_ptr> LoadAsset(const Uuid &uuid, bool async = false) - { - return std::static_pointer_cast>(LoadAsset(AssetTraits::ASSET_TYPE, uuid, async)); - } - - template - std::shared_ptr> LoadAsset(const std::string &path, bool async = false) - { - return std::static_pointer_cast>(LoadAsset(AssetTraits::ASSET_TYPE, path, async)); - } - - template - std::shared_ptr> CreateAsset(const Uuid &uuid) - { - return std::static_pointer_cast>(CreateAsset(AssetTraits::ASSET_TYPE, uuid)); - } - - // asset handlers - void RegisterAssetHandler(const Uuid &type, AssetHandlerBase *handler); - AssetHandlerBase *GetAssetHandler(const Uuid &type); - template - void RegisterAssetHandler() - { - RegisterAssetHandler(AssetTraits::ASSET_TYPE, new AssetHandler()); - } - - // util functions - static uint32_t CalculateFileHash(const std::string &loadPath); - static std::string GetPlatformPrefix(PlatformType platform); - static std::string GetBuildOutputPath(const std::string &parent, PlatformType platform); - static Uuid GetUUIDByPath(const std::string &path); - private: - std::string workDir; - -#ifdef SKY_EDITOR - std::string projectPath; - std::string projectAssetPath; - std::string engineAssetPath; - std::vector searchPathList; - std::unique_ptr package; - std::vector> assetBuilders; - std::unordered_map> assetBuilderMap; -#endif - - std::unique_ptr products; - std::unordered_map> assetHandlers; - - - // loaded assets. - mutable std::mutex assetMutex; - std::unordered_map> assetMap; - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/asset/AssetPackage.h b/framework/include/framework/asset/AssetPackage.h deleted file mode 100644 index d9380cf5..00000000 --- a/framework/include/framework/asset/AssetPackage.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Created by blues on 2023/12/22. -// - -#pragma once - -#include -#include -#include -#include -#include - -namespace sky { - - struct SourceAssetInfo { - std::string loadPath; - uint32_t hash = 0; - }; - - using SourceAssetIDMap = std::unordered_map; - - class AssetPackage { - public: - AssetPackage() = default; - ~AssetPackage() = default; - - void LoadFromFile(const std::string &path); - void SaveToFile(const std::string &path); - - const Uuid &RegisterAsset(const Uuid &uuid, const SourceAssetInfo &info); - void RemoveAsset(const Uuid &uuid); - const SourceAssetInfo *GetAssetInfo(const Uuid &uuid) const; - - void Merge(const AssetPackage &package); - - const SourceAssetIDMap &GetIDMap() const { return assetLists; } - private: - mutable std::mutex mutex; - SourceAssetIDMap assetLists; - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/asset/AssetProducts.h b/framework/include/framework/asset/AssetProducts.h deleted file mode 100644 index 14b1567d..00000000 --- a/framework/include/framework/asset/AssetProducts.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// Created by blues on 2023/12/31. -// - -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace sky { - - struct ProductAssetInfo { - }; - - using ProductAssetIDMap = std::unordered_map; - - class AssetProducts { - public: - AssetProducts() = default; - ~AssetProducts() = default; - - void LoadFromFile(const std::string &path); - void SaveToFile(const std::string &path); - - void AddAsset(const Uuid &uuid, const ProductAssetInfo &info); - void RemoveAsset(const Uuid &uuid); - void RegisterDependencies(const Uuid &src, const std::vector &dst); - bool HasAsset(const Uuid &uuid) const { return assetLists.count(uuid) != 0u; } - const ProductAssetInfo *GetProduct(const Uuid &uuid) const; - const ProductAssetIDMap &GetProducts() const { return assetLists; } - - private: - mutable std::mutex mutex; - ProductAssetIDMap assetLists; - std::unordered_map> dependencies; - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/asset/AssetStream.h b/framework/include/framework/asset/AssetStream.h deleted file mode 100644 index 7cfc0890..00000000 --- a/framework/include/framework/asset/AssetStream.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Created by bluesky on 2023/4/15. -// - -#pragma once - -#include - -namespace sky { - - class AssetStream { - public: - AssetStream(const std::string &p) : path(p) {} - ~AssetStream() = default; - - std::string ReadString(); - - protected: - std::string path; - }; - -} \ No newline at end of file diff --git a/framework/include/framework/interface/IRenderScene.h b/framework/include/framework/interface/IRenderScene.h deleted file mode 100644 index b70b209c..00000000 --- a/framework/include/framework/interface/IRenderScene.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Zach Lee on 2023/8/20. -// - -#pragma once - -namespace sky { - - class IRenderScene { - public: - IRenderScene() = default; - virtual ~IRenderScene() = default; - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/serialization/PropertyCommon.h b/framework/include/framework/serialization/PropertyCommon.h deleted file mode 100644 index 6f8cc9ba..00000000 --- a/framework/include/framework/serialization/PropertyCommon.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Zach Lee on 2021/12/16. -// - -#pragma once - -namespace sky { - - enum CommonPropertyKey { - UI_PROP_VISIBLE, - UI_LABEL_VISIBLE, - UI_LABEL_COLOR, - }; - -} diff --git a/framework/include/framework/serialization/SerializationContext.h b/framework/include/framework/serialization/SerializationContext.h deleted file mode 100644 index c19ac9bb..00000000 --- a/framework/include/framework/serialization/SerializationContext.h +++ /dev/null @@ -1,130 +0,0 @@ -// -// Created by Zach Lee on 2021/12/9. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky { - - class SerializationContext : public Singleton { - public: - template - auto Register(const std::string_view &key) - { - auto info = TypeInfoObj::Get()->RtInfo(); - SKY_ASSERT(!types.count(info->typeId)) - auto &type = types[info->typeId]; - type.info = info; - type.info->markedName = key; - if constexpr (std::is_default_constructible_v) { - type.constructList.emplace_back( - ConstructNode{0, - [](Any *args) { return true; }, - [](Any *args) -> Any { return Any(std::in_place_type); }}); - } - - SKY_ASSERT(lookupTable.emplace(key, &type).second) - return TypeFactory(type); - } - - TypeNode *FindType(const std::string &key); - TypeNode *FindTypeById(uint32_t id); - - private: - friend class Singleton; - - SerializationContext(); - ~SerializationContext() = default; - - std::unordered_map types; - std::unordered_map lookupTable; - }; - - template - Any MakeAny(uint32_t typeId, Args &&...args) - { - auto *context = SerializationContext::Get(); - TypeNode *node = context->FindTypeById(typeId); - if (node == nullptr || node->constructList.empty()) { - return {}; - } - for (auto &ctr : node->constructList) { - std::array anyArgs{std::forward(args)...}; - if (ctr.argsNum == sizeof...(Args) && ctr.checkFn(anyArgs.data())) { - return ctr.constructFn(anyArgs.data()); - } - } - - return {}; - } - - template - inline Any MakeAny(Args &&...args) - { - return MakeAny(TypeInfo::Hash(), std::forward(args)...); - } - - inline const TypeNode *GetTypeNode(uint32_t typeId) - { - auto context = SerializationContext::Get(); - return context->FindTypeById(typeId); - } - - inline const TypeNode *GetTypeNode(const Any &any) - { - auto rtInfo = any.Info(); - if (rtInfo == nullptr) { - return nullptr; - } - auto context = SerializationContext::Get(); - return context->FindTypeById(rtInfo->typeId); - } - - inline const TypeNode *GetTypeNode(const TypeInfoRT *rtInfo) - { - if (rtInfo == nullptr) { - return nullptr; - } - auto context = SerializationContext::Get(); - return context->FindTypeById(rtInfo->typeId); - } - - inline TypeMemberNode *GetTypeMember(const std::string &str, uint32_t typeId) - { - auto context = SerializationContext::Get(); - auto node = context->FindTypeById(typeId); - if (node == nullptr) { - return nullptr; - } - - auto it = node->members.find(str); - if (it == node->members.end()) { - return nullptr; - } - - return &it->second; - } - - enum class SerializeOption : uint8_t { BIN, JSON }; - -} // namespace sky - -#define TYPE_RTTI_BASE virtual const sky::TypeInfoRT *GetTypeInfo() const = 0; - -#define TYPE_RTTI_WITH_VT(name) \ - const sky::TypeInfoRT *GetTypeInfo() const override \ - { \ - static const sky::TypeInfoRT *info = sky::TypeInfoObj::Get()->RtInfo(); \ - return info; \ - } \ - static constexpr std::string_view NAME = #name; \ - static constexpr std::string_view S_TYPE = sky::TypeInfo::Name(); \ - static constexpr uint32_t TYPE = sky::TypeInfo::Hash(); \ - uint32_t GetType() const override { return TYPE; } \ - std::string_view GetTypeStr() const override { return S_TYPE; } - diff --git a/framework/include/framework/serialization/SerializationUtil.h b/framework/include/framework/serialization/SerializationUtil.h deleted file mode 100644 index 38dc4929..00000000 --- a/framework/include/framework/serialization/SerializationUtil.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by Zach Lee on 2023/2/19. -// - -#pragma once - -#include "framework/serialization/SerializationContext.h" - -namespace sky { - - void *GetValue(void *ptr, uint32_t typeId, const std::string &memberName); - const void*GetValueConst(const void *ptr, uint32_t typeId, const std::string &memberName); - - bool SetValue(void* ptr, uint32_t typeId, const std::string &memberName, const void* data); - template - bool SetValue(T &ptr, const std::string &memberName, const M &data) - { - return SetValue(static_cast(std::addressof(ptr)), TypeInfo::Hash(), memberName, static_cast(std::addressof(data))); - } - -} \ No newline at end of file diff --git a/framework/include/framework/window/IWindowEvent.h b/framework/include/framework/window/IWindowEvent.h deleted file mode 100644 index a9d73836..00000000 --- a/framework/include/framework/window/IWindowEvent.h +++ /dev/null @@ -1,160 +0,0 @@ -// -// Created by Zach Lee on 2022/1/3. -// - -#pragma once - -#include - -namespace sky { - class NativeWindow; - - namespace MouseButton { - static constexpr uint8_t MOUSE_BUTTON_LEFT = 1; - static constexpr uint8_t MOUSE_BUTTON_RIGHT = 2; - static constexpr uint8_t MOUSE_BUTTON_MIDDLE = 3; - } // namespace MouseButton - using MouseButtonType = uint8_t; - - namespace KeyButton { - static constexpr uint16_t KEY_A = 1; - static constexpr uint16_t KEY_B = 2; - static constexpr uint16_t KEY_C = 3; - static constexpr uint16_t KEY_D = 4; - static constexpr uint16_t KEY_E = 5; - static constexpr uint16_t KEY_F = 6; - static constexpr uint16_t KEY_G = 7; - static constexpr uint16_t KEY_H = 8; - static constexpr uint16_t KEY_I = 9; - static constexpr uint16_t KEY_J = 10; - static constexpr uint16_t KEY_K = 11; - static constexpr uint16_t KEY_L = 12; - static constexpr uint16_t KEY_M = 13; - static constexpr uint16_t KEY_N = 14; - static constexpr uint16_t KEY_O = 15; - static constexpr uint16_t KEY_P = 16; - static constexpr uint16_t KEY_Q = 17; - static constexpr uint16_t KEY_R = 18; - static constexpr uint16_t KEY_S = 19; - static constexpr uint16_t KEY_T = 20; - static constexpr uint16_t KEY_U = 21; - static constexpr uint16_t KEY_V = 22; - static constexpr uint16_t KEY_W = 23; - static constexpr uint16_t KEY_X = 24; - static constexpr uint16_t KEY_Y = 25; - static constexpr uint16_t KEY_Z = 26; - static constexpr uint16_t KEY_1 = 27; - static constexpr uint16_t KEY_2 = 28; - static constexpr uint16_t KEY_3 = 29; - static constexpr uint16_t KEY_4 = 30; - static constexpr uint16_t KEY_5 = 31; - static constexpr uint16_t KEY_6 = 32; - static constexpr uint16_t KEY_7 = 33; - static constexpr uint16_t KEY_8 = 34; - static constexpr uint16_t KEY_9 = 35; - static constexpr uint16_t KEY_0 = 36; - static constexpr uint16_t KEY_RETURN = 37; - static constexpr uint16_t KEY_ESCAPE = 38; - static constexpr uint16_t KEY_BACKSPACE = 39; - static constexpr uint16_t KEY_TAB = 40; - static constexpr uint16_t KEY_SPACE = 41; - static constexpr uint16_t KEY_MINUS = 42; - static constexpr uint16_t KEY_EQUALS = 43; - static constexpr uint16_t KEY_LEFTBRACKET = 44; - static constexpr uint16_t KEY_RIGHTBRACKET = 45; - static constexpr uint16_t KEY_BACKSLASH = 46; - static constexpr uint16_t KEY_NONUSHASH = 47; - static constexpr uint16_t KEY_SEMICOLON = 48; - static constexpr uint16_t KEY_APOSTROPHE = 49; - static constexpr uint16_t KEY_GRAVE = 50; - static constexpr uint16_t KEY_COMMA = 51; - static constexpr uint16_t KEY_PERIOD = 52; - static constexpr uint16_t KEY_SLASH = 53; - static constexpr uint16_t KEY_CAPSLOCK = 54; - static constexpr uint16_t KEY_F1 = 55; - static constexpr uint16_t KEY_F2 = 56; - static constexpr uint16_t KEY_F3 = 57; - static constexpr uint16_t KEY_F4 = 58; - static constexpr uint16_t KEY_F5 = 59; - static constexpr uint16_t KEY_F6 = 60; - static constexpr uint16_t KEY_F7 = 61; - static constexpr uint16_t KEY_F8 = 62; - static constexpr uint16_t KEY_F9 = 63; - static constexpr uint16_t KEY_F10 = 64; - static constexpr uint16_t KEY_F11 = 65; - static constexpr uint16_t KEY_F12 = 66; - static constexpr uint16_t KEY_PRINTSCREEN = 67; - static constexpr uint16_t KEY_SCROLLLOCK = 68; - static constexpr uint16_t KEY_PAUSE = 69; - static constexpr uint16_t KEY_INSERT = 70; - static constexpr uint16_t KEY_HOME = 71; - static constexpr uint16_t KEY_PAGEUP = 72; - static constexpr uint16_t KEY_DELETE = 73; - static constexpr uint16_t KEY_END = 74; - static constexpr uint16_t KEY_PAGEDOWN = 75; - static constexpr uint16_t KEY_RIGHT = 76; - static constexpr uint16_t KEY_LEFT = 77; - static constexpr uint16_t KEY_DOWN = 78; - static constexpr uint16_t KEY_UP = 79; - static constexpr uint16_t KEY_NUMLOCKCLEAR = 80; - static constexpr uint16_t KEY_KP_DIVIDE = 81; - static constexpr uint16_t KEY_KP_MULTIPLY = 82; - static constexpr uint16_t KEY_KP_MINUS = 83; - static constexpr uint16_t KEY_KP_PLUS = 84; - static constexpr uint16_t KEY_KP_ENTER = 85; - static constexpr uint16_t KEY_KP_1 = 86; - static constexpr uint16_t KEY_KP_2 = 87; - static constexpr uint16_t KEY_KP_3 = 88; - static constexpr uint16_t KEY_KP_4 = 89; - static constexpr uint16_t KEY_KP_5 = 90; - static constexpr uint16_t KEY_KP_6 = 91; - static constexpr uint16_t KEY_KP_7 = 92; - static constexpr uint16_t KEY_KP_8 = 93; - static constexpr uint16_t KEY_KP_9 = 94; - static constexpr uint16_t KEY_KP_0 = 95; - static constexpr uint16_t KEY_KP_PERIOD = 96; - } // namespace KeyButton - using KeyButtonType = uint16_t; - - class IWindowEvent : public EventTraits { - public: - using KeyType = const NativeWindow*; - - IWindowEvent() = default; - virtual ~IWindowEvent() = default; - - virtual void OnWindowResize(uint32_t width, uint32_t height) - { - } - - // focus - virtual void OnFocusChanged(bool focus) - { - } - - // mouse - virtual void OnMouseMove(int32_t x, int32_t y) - { - } - virtual void OnMouseButtonDown(MouseButtonType button) - { - } - virtual void OnMouseButtonUp(MouseButtonType button) - { - } - virtual void OnMouseWheel(int32_t wheelX, int32_t wheelY) - { - } - - virtual void OnKeyUp(KeyButtonType) - { - } - virtual void OnKeyDown(KeyButtonType) - { - } - virtual void OnTextInput(const char *text) - { - } - }; - -} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/world/Component.h b/framework/include/framework/world/Component.h deleted file mode 100644 index 9a3bfb9d..00000000 --- a/framework/include/framework/world/Component.h +++ /dev/null @@ -1,125 +0,0 @@ -// -// Created by Zach Lee on 2021/11/13. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - - class GameObject; - class JsonOutputArchive; - class JsonInputArchive; - - class Component { - public: - Component() = default; - virtual ~Component() = default; - - TYPE_RTTI_BASE - - GameObject *object = nullptr; - - virtual void OnActive() - { - } - - virtual void OnTick(float time) - { - } - - virtual void OnDestroy() - { - } - - virtual uint32_t GetType() const = 0; - virtual std::string_view GetTypeStr() const = 0; - - virtual void Save(JsonOutputArchive &ar) const {} - virtual void Load(JsonInputArchive &ar) {} - - protected: - friend class GameObject; - }; - - struct IComponentListener { - virtual void OnAddComponent(GameObject *go, Component *) - { - } - virtual void OnRemoveComponent(GameObject *go, Component *) - { - } - }; - - class ComponentFactory : public Singleton { - public: - ComponentFactory() = default; - ~ComponentFactory() override = default; - - template - static Component *CreateComponent(PmrResource *resource) - { - auto ptr = resource->allocate(sizeof(T)); - return new (ptr) T(); - } - using CompFn = Component*(*)(PmrResource *resource); - struct CompInfo { - CompFn fn; - std::string_view name; - }; - - template - void ForEach(GameObject *go, Component *component) - { - for (auto &listener : listeners) { - std::invoke(F, listener, go, component); - } - } - - template - void RegisterComponent() - { - ctorMap.emplace(T::TYPE, &ComponentFactory::CreateComponent); - } - - Component *CreateComponent(PmrResource *resource, const uint32_t &id) - { - auto iter = ctorMap.find(id); - if (iter != ctorMap.end()) { - return iter->second(resource); - } - return nullptr; - } - - void RegisterListener(IComponentListener *listener) - { - if (listener != nullptr) { - listeners.emplace(listener); - } - } - - void UnRegisterListener(IComponentListener *listener) - { - listeners.erase(listener); - } - - const std::unordered_map &GetComponentTypes() const - { - return ctorMap; - } - - private: - std::set listeners; - std::unordered_map ctorMap; - }; - -} // namespace sky diff --git a/framework/include/framework/world/GameObject.h b/framework/include/framework/world/GameObject.h deleted file mode 100644 index 33751400..00000000 --- a/framework/include/framework/world/GameObject.h +++ /dev/null @@ -1,137 +0,0 @@ -// -// Created by Zach Lee on 2021/11/12. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - class World; - - class JsonOutputArchive; - class JsonInputArchive; - - class GameObject : public Object { - public: - GameObject(GameObject &&) noexcept = default; - GameObject &operator=(GameObject&&) noexcept = default; - - GameObject(const GameObject &) = delete; - GameObject &operator=(const GameObject &) = delete; - - static void Reflect(); - - inline Component *AddComponent(uint32_t id) - { - auto iter = std::find_if(components.begin(), components.end(), [&id](Component *comp) { return comp->GetType() == id; }); - if (iter != components.end()) { - return *iter; - } - - auto comp = ComponentFactory::Get()->CreateComponent(resource, id); - if (comp != nullptr) { - comp->object = this; - comp->OnActive(); - ComponentFactory::Get()->template ForEach<&IComponentListener::OnAddComponent>(this, comp); - components.emplace_back(comp); - } - return comp; - } - - template - inline T *AddComponent() - { - auto info = TypeInfoObj::Get()->RtInfo(); - auto iter = std::find_if(components.begin(), components.end(), [info](Component *comp) { return comp->GetTypeInfo() == info; }); - if (iter == components.end()) { - auto comp = ComponentFactory::CreateComponent(resource); - comp->object = this; - comp->OnActive(); - ComponentFactory::Get()->template ForEach<&IComponentListener::OnAddComponent>(this, comp); - components.emplace_back(comp); - return static_cast(comp); - } - return static_cast(*iter); - } - - template - inline void RemoveComponent() - { - auto info = TypeInfoObj::Get()->RtInfo(); - auto iter = std::find_if(components.begin(), components.end(), [info](Component *comp) { return comp->GetTypeInfo() == info; }); - if (iter != components.end()) { - ComponentFactory::Get()->template ForEach<&IComponentListener::OnRemoveComponent>(this, *iter); - (*iter)->OnDestroy(); - (*iter)->~Component(); - resource->deallocate(*iter, info->size); - components.erase(iter); - } - } - - template - inline T *GetComponent() - { - auto info = TypeInfoObj::Get()->RtInfo(); - auto iter = std::find_if(components.begin(), components.end(), [info](Component *comp) { - return comp->GetTypeInfo() == info; - }); - if (iter != components.end()) { - return static_cast(*iter); - } - return nullptr; - } - - template - inline const T *GetComponent() const - { - auto info = TypeInfoObj::Get()->RtInfo(); - auto iter = std::find_if(components.begin(), components.end(), [info](Component *comp) { return comp->GetTypeInfo() == info; }); - if (iter != components.end()) { - return static_cast(*iter); - } - return nullptr; - } - - uint32_t GetId() const; - - void SetName(const std::string &name); - const std::string &GetName() const; - - World *GetWorld() const; - - void SetParent(GameObject *gameObject); - void SetParent(const Uuid &gameObject); - - GameObject *GetParent() const; - - void Tick(float time); - - using ComponentList = PmrList; - ComponentList &GetComponents(); - - void Save(JsonOutputArchive &ar) const; - void Load(JsonInputArchive &ar); - - private: - friend class World; - ~GameObject(); - GameObject() = default; - explicit GameObject(std::string str) : name(std::move(str)) - { - } - - World *world = nullptr; - PmrResource *resource = nullptr; - uint32_t objId = 0; - std::string name; - ComponentList components; - }; - -} // namespace sky diff --git a/framework/include/framework/world/Object.h b/framework/include/framework/world/Object.h deleted file mode 100644 index fb99f41f..00000000 --- a/framework/include/framework/world/Object.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// Created by Zach Lee on 2023/1/15. -// - -#pragma once - -#include - -namespace sky { - - class Object { - public: - Object() = default; - ~Object() = default; - - void SetUuid(const Uuid &id) { uuid = id; } - const Uuid &GetUuid() const { return uuid; } - - protected: - Uuid uuid; - }; - -} \ No newline at end of file diff --git a/framework/include/framework/world/TransformComponent.h b/framework/include/framework/world/TransformComponent.h deleted file mode 100644 index 4787d838..00000000 --- a/framework/include/framework/world/TransformComponent.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// Created by Zach Lee on 2021/11/13. -// - -#pragma once - -#include -#include -#include - -namespace sky { - - class TransformComponent : public Component { - public: - TransformComponent() = default; - ~TransformComponent() override; - - TYPE_RTTI_WITH_VT(TransformComponent) - - static void Reflect(); - - void SetParent(TransformComponent *); - - TransformComponent *GetParent() const; - - const std::vector &GetChildren() const; - - void SetWorldTranslation(const Vector3 &translation); - void SetWorldRotation(const Quaternion &rotation); - void SetWorldScale(const Vector3 &scale); - - void SetLocalTranslation(const Vector3 &translation); - void SetLocalRotation(const Quaternion &rotation); - void SetLocalScale(const Vector3 &scale); - - const Transform &GetLocal() const; - const Transform &GetWorld() const; - - void Print(); - - void Save(JsonOutputArchive &ar) const override; - void Load(JsonInputArchive &ar) override; - - private: - static void PrintChild(TransformComponent &comp, std::string str); - - void TransformChanged(); - - void UpdateLocal(); - - void UpdateWorld(); - - const Transform &GetParentTransform() const; - - Transform local; - Transform world; - bool suppressWorldChange = false; - TransformComponent *parent = nullptr; - std::vector children; - }; - -} // namespace sky diff --git a/framework/include/framework/world/World.h b/framework/include/framework/world/World.h deleted file mode 100644 index 191c0c7f..00000000 --- a/framework/include/framework/world/World.h +++ /dev/null @@ -1,63 +0,0 @@ -// -// Created by Zach Lee on 2021/11/12. -// - -#pragma once - -#include -#include -#include -#include -#include - -namespace sky { - - class World; - class IRenderScene; - class GameObject; - - class JsonOutputArchive; - class JsonInputArchive; - - class World { - public: - World(); - ~World(); - - World(const World&) = delete; - World &operator=(const World&) = delete; - - static void Reflect(); - - void SetRenderScene(IRenderScene *scn) { renderScene = scn; } - IRenderScene *GetRenderScene() const { return renderScene; } - - GameObject *CreateGameObject(const std::string &name); - GameObject *CreateGameObject(const std::string &name, const Uuid &uuid); - - void DestroyGameObject(GameObject *); - - void Tick(float); - - const PmrVector &GetGameObjects() const; - - GameObject *GetGameObjectByUuid(const Uuid &id) const; - - GameObject *GetRoot(); - - void ForEachBFS(GameObject *go, std::function && fn) const; - - void Save(JsonOutputArchive &ar) const; - void Load(JsonInputArchive &ar); - - private: - GameObject *AllocateGameObject(); - GameObject *root; - IRenderScene *renderScene; - PmrUnSyncPoolRes memoryResource; - PmrVector gameObjects; - PmrHashMap objectLut; - }; - using WorldPtr = std::shared_ptr; - -} // namespace sky diff --git a/framework/platform/android/AndroidWindow.cpp b/framework/platform/android/AndroidWindow.cpp deleted file mode 100644 index e9977d4f..00000000 --- a/framework/platform/android/AndroidWindow.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// -// Created by Zach Lee on 2022/9/26. -// - -#include "AndroidWindow.h" -#include - -namespace sky { - - bool AndroidWindow::Init(const Descriptor &desc) - { - descriptor = desc; - if (descriptor.nativeHandle != nullptr) { - winHandle = descriptor.nativeHandle; - descriptor.width = ANativeWindow_getWidth(static_cast(winHandle)); - descriptor.height = ANativeWindow_getHeight(static_cast(winHandle)); - } - return winHandle != nullptr; - } - - void AndroidWindow::PollEvent(bool &quit) - { - } - - NativeWindow *NativeWindow::Create(const Descriptor &des) - { - NativeWindow *window = new AndroidWindow(); - if (!window->Init(des)) { - delete window; - window = nullptr; - } - return window; - } -} diff --git a/framework/platform/genetic/GeneticAssetStream.cpp b/framework/platform/genetic/GeneticAssetStream.cpp deleted file mode 100644 index bc00a3ed..00000000 --- a/framework/platform/genetic/GeneticAssetStream.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by bluesky on 2023/4/15. -// - -#include -#include - -namespace sky { - - std::string AssetStream::ReadString() { - std::string res; - sky::ReadString(path, res); - return res; - } -} // namespace sky \ No newline at end of file diff --git a/framework/platform/genetic/SDLPlatform.cpp b/framework/platform/genetic/SDLPlatform.cpp deleted file mode 100644 index b079e659..00000000 --- a/framework/platform/genetic/SDLPlatform.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by Zach Lee on 2022/9/25. -// - -#include "SDLPlatform.h" -#include -#include - -static const char* TAG = "SDLPlatform"; - -namespace sky { - - SDLPlatform::~SDLPlatform() - { - SDL_Quit(); - } - - bool SDLPlatform::Init(const PlatformInfo &desc) - { - if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { - LOG_E(TAG, "SDL could not be initialized! Error: %s", SDL_GetError()); - return false; - } - return true; - } - - uint64_t SDLPlatform::GetPerformanceFrequency() const - { - return SDL_GetPerformanceFrequency(); - } - - uint64_t SDLPlatform::GetPerformanceCounter() const - { - return SDL_GetPerformanceCounter(); - } - -// std::string SDLPlatform::GetBundlePath() const -// { -// return SDL_GetBasePath(); -// } -} // namespace sky \ No newline at end of file diff --git a/framework/platform/genetic/SDLWindow.cpp b/framework/platform/genetic/SDLWindow.cpp deleted file mode 100644 index e2d82092..00000000 --- a/framework/platform/genetic/SDLWindow.cpp +++ /dev/null @@ -1,119 +0,0 @@ -// -// Created by Zach Lee on 2022/9/25. -// - -#include "SDLWindow.h" -#include -#include - -namespace sky { - - SDLWindow::~SDLWindow() - { - SDL_DestroyWindow(window); - } - - bool SDLWindow::Init(const Descriptor &desc) - { - descriptor = desc; - window = SDL_CreateWindow(desc.titleName.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, desc.width, desc.height, - SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MOUSE_CAPTURE | - SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_VULKAN); - return window != nullptr; - } - - void SDLWindow::PollEvent(bool &quit) - { - SDL_Event sdlEvent; - int cnt = 0; - while ((cnt = SDL_PollEvent(&sdlEvent)) != 0) { - Dispatch(sdlEvent, quit); - } - } - - void SDLWindow::Dispatch(const SDL_WindowEvent &event) { - switch (event.event) { - case SDL_WINDOWEVENT_SHOWN: { - break; - } - case SDL_WINDOWEVENT_RESTORED: { - break; - } -// case SDL_WINDOWEVENT_SIZE_CHANGED: - case SDL_WINDOWEVENT_RESIZED: { - UpdateWindow(); - Event::BroadCast(this, &IWindowEvent::OnWindowResize, - static_cast(event.data1), - static_cast(event.data2)); - break; - } - case SDL_WINDOWEVENT_FOCUS_GAINED: - case SDL_WINDOWEVENT_FOCUS_LOST: { - Event::BroadCast(this, &IWindowEvent::OnFocusChanged, event.event == SDL_WINDOWEVENT_FOCUS_GAINED); - break; - } - case SDL_WINDOWEVENT_HIDDEN: { - break; - } - case SDL_WINDOWEVENT_MINIMIZED: { - break; - } - case SDL_WINDOWEVENT_ENTER: { - // SDL_CaptureMouse(SDL_TRUE); - break; - } - case SDL_WINDOWEVENT_CLOSE: { - break; - } - } - } - - void SDLWindow::Dispatch(const SDL_Event &sdlEvent, bool &quit) - { - switch (sdlEvent.type) { - case SDL_QUIT: { - quit = true; - break; - } - case SDL_WINDOWEVENT: { - Dispatch(sdlEvent.window); - break; - } - case SDL_MOUSEBUTTONDOWN: { - const SDL_MouseButtonEvent &event = sdlEvent.button; - Event::BroadCast(this, &IWindowEvent::OnMouseButtonDown, event.button); - break; - } - case SDL_MOUSEBUTTONUP: { - const SDL_MouseButtonEvent &event = sdlEvent.button; - Event::BroadCast(this, &IWindowEvent::OnMouseButtonUp, event.button); - break; - } - case SDL_MOUSEMOTION: { - const SDL_MouseMotionEvent &event = sdlEvent.motion; - Event::BroadCast(this, &IWindowEvent::OnMouseMove, event.x, event.y); - break; - } - case SDL_MOUSEWHEEL: { - const SDL_MouseWheelEvent &event = sdlEvent.wheel; - Event::BroadCast(this, &IWindowEvent::OnMouseWheel, event.x, event.y); - break; - } - case SDL_KEYDOWN: { - const SDL_KeyboardEvent &event = sdlEvent.key; - Event::BroadCast(this, &IWindowEvent::OnKeyDown, event.keysym.scancode - 3); - break; - } - case SDL_KEYUP: { - const SDL_KeyboardEvent &event = sdlEvent.key; - Event::BroadCast(this, &IWindowEvent::OnKeyUp, event.keysym.scancode - 3); - break; - } - case SDL_TEXTINPUT: { - const SDL_TextInputEvent &event = sdlEvent.text; - Event::BroadCast(this, &IWindowEvent::OnTextInput, event.text); - } - default: break; - } - } -} \ No newline at end of file diff --git a/framework/src/asset/Asset.cpp b/framework/src/asset/Asset.cpp deleted file mode 100644 index c949442a..00000000 --- a/framework/src/asset/Asset.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// -// Created by Zach on 2022/8/8. -// - -#include - -namespace sky { - - void AssetBase::SetUuid(const Uuid &id) - { - uuid = id; - } - -} // namespace sky \ No newline at end of file diff --git a/framework/src/asset/AssetDataBase.cpp b/framework/src/asset/AssetDataBase.cpp deleted file mode 100644 index 19e4fb30..00000000 --- a/framework/src/asset/AssetDataBase.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// Created by Zach Lee on 2023/2/20. -// - -#include -#include - -namespace sky { - - static const char *CREATE_SOURCE_ASSET_TABLE = "CREATE TABLE IF NOT EXISTS SourceTable ( " - " Path TEXT PRIMARY KEY COLLATE NOCASE, " - " Folder TEXT NOT NULL COLLATE NOCASE, " - " ProductKey TEXT KEY COLLATE NOCASE, " - " Uuid TEXT NOT NULL COLLATE NOCASE);"; - - static const char *INSERT_SOURCE = "INSERT OR REPLACE INTO SourceTable (Path, Folder, ProductKey, Uuid) VALUES (:path, :folder, :pKey, :uuid);"; - static const char *SELECT_SOURCE = "SELECT * FROM SourceTable WHERE Path = :path AND ProductKey = :pKey;"; - - static const char *CREATE_PRODUCT_ASSET_TABLE = "CREATE TABLE IF NOT EXISTS ProductTable (" - " Uuid TEXT PRIMARY KEY, " - " Path TEXT NOT NULL COLLATE NOCASE);"; - - static const char *INSERT_PRODUCT = "INSERT OR REPLACE INTO ProductTable (Uuid, Path) VALUES (:uuid, :path);"; - static const char *SELECT_PRODUCT = "SELECT * FROM ProductTable WHERE Uuid = :uuid;"; - - AssetDataBase::~AssetDataBase() - { - createSourceTableStat = nullptr; - insertSourceTableStat = nullptr; - - dataBase = nullptr; - } - - void AssetDataBase::Init(const std::string &name) - { - dataBase = std::make_unique(); - dataBase->Init(name); - - { - createSourceTableStat.reset(dataBase->CreateStatement(CREATE_SOURCE_ASSET_TABLE)); - createSourceTableStat->Step(); - createSourceTableStat->Reset(); - - insertSourceTableStat.reset(dataBase->CreateStatement(INSERT_SOURCE)); - selectSourceTableStat.reset(dataBase->CreateStatement(SELECT_SOURCE)); - } - - { - createProductTableStat.reset(dataBase->CreateStatement(CREATE_PRODUCT_ASSET_TABLE)); - createProductTableStat->Step(); - createProductTableStat->Reset(); - - insertProductTableStat.reset(dataBase->CreateStatement(INSERT_PRODUCT)); - selectProductTableStat.reset(dataBase->CreateStatement(SELECT_PRODUCT)); - } - } - - void AssetDataBase::AddSource(const SourceData &sourceData) - { - insertSourceTableStat->BindText(1, sourceData.path); - insertSourceTableStat->BindText(2, sourceData.folder); - insertSourceTableStat->BindText(3, sourceData.productKey); - insertSourceTableStat->BindText(4, sourceData.uuid.ToString()); - insertSourceTableStat->Step(); - insertSourceTableStat->Reset(); - } - - bool AssetDataBase::QueryProduct(const std::string &sourcePath, const std::string &key, Uuid &uuid) const - { - selectSourceTableStat->BindText(1, sourcePath); - selectSourceTableStat->BindText(2, key); - - selectSourceTableStat->Step(); - std::string source; - source = selectSourceTableStat->GetText(3); - - selectSourceTableStat->Reset(); - if (source.empty()) { - return false; - } - uuid = Uuid::CreateFromString(source); - return true; - } - - bool AssetDataBase::QueryProduct(const Uuid &uuid, std::string &out) - { - std::string idStr = uuid.ToString(); - selectProductTableStat->BindText(1, idStr); - - selectProductTableStat->Step(); - out = selectProductTableStat->GetText(1); - selectProductTableStat->Reset(); - return !out.empty(); - } - - void AssetDataBase::AddProduct(const ProductData &productData) - { - insertProductTableStat->BindText(1, productData.uuid.ToString()); - insertProductTableStat->BindText(2, productData.path); - insertProductTableStat->Step(); - insertProductTableStat->Reset(); - } - -} // namespace sky \ No newline at end of file diff --git a/framework/src/asset/AssetManager.cpp b/framework/src/asset/AssetManager.cpp deleted file mode 100644 index 2ca77a6a..00000000 --- a/framework/src/asset/AssetManager.cpp +++ /dev/null @@ -1,403 +0,0 @@ -// -// Created by blues on 2023/12/24. -// - -#include - -#ifdef SKY_EDITOR - #include -#endif - -#include -#include - -#include -#include -#include - -#include -#include - -static const char* TAG = "AssetManager"; -static const char* PACKAGE_PATH = "package.repo"; -static const char* PRODUCTS_PATH = "products"; -static const char* PRODUCTS_ASSETS_PATH = "/assets"; -static const char* PRODUCTS_ASSETS_REPO_PATH = "/assets.bin"; -static const char* PROJECT_ASSET_PREFIX = "/assets"; -static const char* ENGINE_ASSET_PREFIX = "/engine_assets"; - -namespace sky { - static constexpr Uuid EMPTY_UUID; - - static std::string MakeStandardPath(const std::string &input) - { - auto path = std::filesystem::path(input).lexically_normal().string(); - size_t pos = 0; - while ((pos = path.find('\\', pos)) != std::string::npos) { - path.replace(pos, 1, "/"); - pos += 2; - } - return path; - } - - static std::filesystem::path GetAssetPathByUUID(const std::string &workDir, const Uuid &uuid) - { - std::filesystem::path assetPath(workDir); - auto strUuid = uuid.ToString(); - assetPath.append(strUuid.substr(0, 2)); - assetPath.append(strUuid + ".bin"); - - return assetPath; - } - - static std::string GetAssetLoadPath(const std::string &path, AssetGroup group = AssetGroup::PROJECT) - { - std::string res; - if (group == AssetGroup::ENGINE) { - res = ENGINE_ASSET_PREFIX; - } else { - res = PROJECT_ASSET_PREFIX; - } - - res += "/" + path; - return res; - } - - Uuid AssetManager::GetUUIDByPath(const std::string &path) - { - return Uuid::CreateWithSeed(Fnv1a32(MakeStandardPath(path))); - } - - uint32_t AssetManager::CalculateFileHash(const std::string &loadPath) - { - return 0; - } - - AssetManager::~AssetManager() - { -#ifdef SKY_EDITOR - if (package) { - package->SaveToFile(projectPath + PACKAGE_PATH); - } -#endif - - if (products) { - products->SaveToFile(workDir + PRODUCTS_ASSETS_REPO_PATH); - } - } - - void AssetManager::SetWorkPath(const std::string &path) - { - workDir = path; - products = std::make_unique(); - products->LoadFromFile(workDir + PRODUCTS_ASSETS_REPO_PATH); - } - - std::string AssetManager::GetPlatformPrefix(PlatformType platform) - { - if (platform == PlatformType::Default) { - platform = Platform::Get()->GetType(); - } - - switch (platform) { - case PlatformType::Windows: - return "win32"; - case PlatformType::MacOS: - return "macos"; - case PlatformType::IOS: - return "ios"; - case PlatformType::Android: - return "android"; - case PlatformType::Linux: - return "linux"; - default: - SKY_ASSERT(false && "invalid platform type"); - return ""; - }; - } - - std::string AssetManager::GetBuildOutputPath(const std::string &parent, PlatformType platform) - { - auto prefix = GetPlatformPrefix(platform); - return prefix.empty() ? prefix : parent + PRODUCTS_PATH + "/" + prefix + PRODUCTS_ASSETS_PATH; - } - - std::shared_ptr AssetManager::CreateAsset(const Uuid &type, const Uuid &uuid) - { - auto hIter = assetHandlers.find(type); - if (hIter == assetHandlers.end()) { - return {}; - } - auto asset = hIter->second->CreateAsset(); - asset->SetUuid(uuid); - - { - std::lock_guard lock(assetMutex); - assetMap.emplace(uuid, asset); - } - - return asset; - } - - std::string AssetManager::GetAssetPath(const Uuid &uuid) - { - return GetAssetPathByUUID(workDir, uuid).string(); - } - - std::shared_ptr AssetManager::LoadAsset(const Uuid &type, const std::string &path, bool async) - { - auto id = GetUUIDByPath(GetAssetLoadPath(path)); - if (!products->HasAsset(id)) { - id = GetUUIDByPath(GetAssetLoadPath(path, AssetGroup::ENGINE)); - } - return LoadAsset(type, id, async); - } - - std::shared_ptr AssetManager::LoadAsset(const Uuid &type, const Uuid &uuid, bool async) - { - std::shared_ptr asset; - // check asset loaded. - { - std::lock_guard lock(assetMutex); - - auto iter = assetMap.find(uuid); - if (iter != assetMap.end()) { - std::shared_ptr res = iter->second.lock(); - if (res) { - return res; - } - } - } - - // load asset from work path - const auto *info = products->GetProduct(uuid); - if (info == nullptr) { - // try build asset if exists - LOG_E(TAG, "Load Asset Failed %s", uuid.ToString().c_str()); - return {}; - } - - auto hIter = assetHandlers.find(type); - if (hIter == assetHandlers.end()) { - return {}; - } - auto *handler = hIter->second.get(); - - asset = CreateAsset(type, uuid); - asset->status = AssetBase::Status::LOADING; - - std::string loadPath = GetAssetPathByUUID(workDir, uuid).string(); - auto fn = [handler, asset, loadPath]() { - handler->LoadFromPath(loadPath, asset); - asset->status = AssetBase::Status::LOADED; - }; - - if (async) { - tf::Taskflow flow; - flow.emplace(std::move(fn)); - asset->future = JobSystem::Get()->Run(std::move(flow)); - } else { - fn(); - } - return asset; - } - - void AssetManager::RegisterAssetHandler(const Uuid &type, AssetHandlerBase *handler) - { - assetHandlers[type].reset(handler); - } - - AssetHandlerBase*AssetManager::GetAssetHandler(const Uuid &type) - { - auto iter = assetHandlers.find(type); - if (iter == assetHandlers.end()) { - return nullptr; - } - return iter->second.get(); - } - -#ifdef SKY_EDITOR - void AssetManager::LoadConfig(const std::string &path) - { - std::string json; - if (!ReadString(path, json)) { - LOG_W(TAG, "Load Config Failed"); - return; - } - - rapidjson::Document document; - document.Parse(json.c_str()); - - std::string parent = std::filesystem::path(path).parent_path().string(); - - for (auto iter = document.MemberBegin(); iter != document.MemberEnd(); iter++) { - const char* key = iter->name.GetString(); - const char* cfgPath = iter->value.GetString(); - for (auto &builder : assetBuilders) { - if (builder->GetConfigKey() == std::string(key)) { - builder->LoadConfig(parent + "/" + cfgPath); - } - } - } - } - - void AssetManager::SetProjectPath(const std::string &path) - { - projectPath = path + "/"; - projectAssetPath = path + PROJECT_ASSET_PREFIX; - engineAssetPath = path + ENGINE_ASSET_PREFIX; - - searchPathList.emplace_back(AssetSearchPath{projectPath}); - searchPathList.emplace_back(AssetSearchPath{engineAssetPath, AssetGroup::ENGINE}); - searchPathList.emplace_back(AssetSearchPath{projectAssetPath, AssetGroup::PROJECT}); - - package = std::make_unique(); - package->LoadFromFile(projectPath + PACKAGE_PATH); - - LoadConfig(projectPath + "config/asset.json"); - - SetWorkPath(GetBuildOutputPath(projectPath, PlatformType::Default)); - } - - const Uuid &AssetManager::RegisterAsset(const SourceAssetInfo &info) - { - return package->RegisterAsset(GetUUIDByPath(info.loadPath), info); - } - - const Uuid &AssetManager::ImportAndBuildAsset(const std::string &path, PlatformType target) - { - const auto &id = ImportAsset(path); - return BuildAsset(id, target) ? id : EMPTY_UUID; - } - - const Uuid &AssetManager::ImportAsset(const std::string &path) - { - SourceAssetInfo info = {}; - for (const auto &tmpPath : searchPathList) { - std::filesystem::path assetPath(tmpPath.path); - assetPath.append(path); - - if (std::filesystem::exists(assetPath)) { - info.loadPath = GetAssetLoadPath(path, tmpPath.group); - info.hash = CalculateFileHash(assetPath.string()); - break; - } - } - if (info.loadPath.empty()) { - LOG_E(TAG, "import asset failed %s", path.c_str()); - return EMPTY_UUID; - } - return RegisterAsset(info); - } - - void AssetManager::RemoveAsset(const Uuid &uuid) - { - package->RemoveAsset(uuid); - } - - bool AssetManager::BuildAsset(const BuildRequest &request) - { - auto iter = assetBuilderMap.find(request.ext); - if (iter == assetBuilderMap.end()) { - LOG_E(TAG, "Asset Builder not Found %s", request.fullPath.c_str()); - return false; - } - BuildResult result = {}; - - auto &builders = iter->second; - for (auto &builder : builders) { - builder->Request(request, result); - } - - if (!result.success) { - LOG_E(TAG, "Build Asset Failed. %s", request.name.c_str()); - return false; - } - for (auto &product : result.products) { - products->RegisterDependencies(product.asset->GetUuid(), product.deps); - SaveAsset(product.asset, request.targetPlatform); - } - - return true; - } - - bool AssetManager::BuildAsset(const Uuid &uuid, PlatformType target) - { - const auto *sourceInfo = package->GetAssetInfo(uuid); - if (sourceInfo == nullptr) { - LOG_E(TAG, "asset not imported. %s", uuid.ToString().c_str()); - return false; - } - - std::filesystem::path fs(sourceInfo->loadPath); - auto ext = fs.extension().string(); - - BuildRequest request = {}; - request.relativePath = sourceInfo->loadPath; - request.fullPath = projectPath + sourceInfo->loadPath; - request.ext = ext; - request.name = fs.filename().string(); - request.uuid = uuid; - request.targetPlatform = target; - - BuildResult result = {}; - auto iter = assetBuilderMap.find(ext); - if (iter == assetBuilderMap.end()) { - LOG_E(TAG, "Asset Build not Found %s", sourceInfo->loadPath.c_str()); - return false; - } - auto &builders = iter->second; - for (auto &builder : builders) { - builder->Request(request, result); - } - - if (!result.success) { - LOG_E(TAG, "Build Asset Failed. %s", sourceInfo->loadPath.c_str()); - return false; - } - for (auto &product : result.products) { - products->RegisterDependencies(product.asset->GetUuid(), product.deps); - SaveAsset(product.asset, target); - } - - return true; - } - - void AssetManager::SaveAsset(const Uuid &uuid, PlatformType target) - { - SaveAsset(assetMap[uuid].lock(), target); - } - - void AssetManager::SaveAsset(const std::shared_ptr &asset, PlatformType target) - { - auto hIter = assetHandlers.find(asset->GetType()); - if (hIter == assetHandlers.end()) { - return; - } - - auto outputPath = GetBuildOutputPath(projectPath, target); - if (outputPath.empty()) { - return; - } - std::filesystem::path fOut = GetAssetPathByUUID(outputPath, asset->GetUuid()); - if (!std::filesystem::exists(fOut.parent_path())) { - std::filesystem::create_directories(fOut.parent_path()); - } - - auto *assetHandler = hIter->second.get(); - assetHandler->SaveToPath(fOut.string(), asset); - - ProductAssetInfo info = {}; - products->AddAsset(asset->uuid, info); - } - - void AssetManager::RegisterBuilder(AssetBuilder *builder) - { - assetBuilders.emplace_back(builder); - const auto &extensions = builder->GetExtensions(); - for (const auto &ext : extensions) { - assetBuilderMap[ext].emplace_back(assetBuilders.back().get()); - } - } -#endif -} // namespace sky \ No newline at end of file diff --git a/framework/src/asset/AssetPackage.cpp b/framework/src/asset/AssetPackage.cpp deleted file mode 100644 index aee3fec6..00000000 --- a/framework/src/asset/AssetPackage.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// Created by blues on 2023/12/22. -// - -#include "framework/asset/AssetPackage.h" -#include -#include - -#include - -namespace sky { - static const char* TAG = "Asset"; - - void AssetPackage::LoadFromFile(const std::string &path) - { - std::fstream f(path, std::ios::in | std::ios::binary); - if (!f.is_open()) { - return; - } - - IStreamArchive archive(f); - - uint32_t number = 0; - archive.Load(number); - for (uint32_t i = 0; i < number; ++i) { - std::string id; - archive.Load(id); - - SourceAssetInfo info = {}; - archive.Load(info.loadPath); - archive.Load(info.hash); - - std::lock_guard lock(mutex); - assetLists.emplace(Uuid::CreateFromString(id), info); - } - } - - void AssetPackage::SaveToFile(const std::string &path) - { - std::fstream o(path, std::ios::out | std::ios::binary); - OStreamArchive archive(o); - - std::lock_guard lock(mutex); - archive.Save(static_cast(assetLists.size())); - for (auto &[id, info] : assetLists) { - archive.Save(id.ToString()); - archive.Save(info.loadPath); - archive.Save(info.hash); - } - } - - const Uuid &AssetPackage::RegisterAsset(const Uuid &uuid, const SourceAssetInfo &info) - { - std::lock_guard lock(mutex); - auto iter = assetLists.emplace(uuid, info); - if (!iter.second) { - LOG_I(TAG, "duplicated asset %s", uuid.ToString().c_str()); - } - return iter.first->first; - } - - void AssetPackage::RemoveAsset(const Uuid &uuid) - { - std::lock_guard lock(mutex); - assetLists.erase(uuid); - } - - const SourceAssetInfo *AssetPackage::GetAssetInfo(const Uuid &uuid) const - { - std::lock_guard lock(mutex); - auto iter = assetLists.find(uuid); - return iter != assetLists.end() ? &iter->second : nullptr; - } - - void AssetPackage::Merge(const AssetPackage &package) - { - std::lock_guard lock(mutex); - for (const auto &[id, relativePath] : package.assetLists) { - assetLists[id] = relativePath; - } - } - -} // namespace sky \ No newline at end of file diff --git a/framework/src/asset/AssetProducts.cpp b/framework/src/asset/AssetProducts.cpp deleted file mode 100644 index 95c85014..00000000 --- a/framework/src/asset/AssetProducts.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Created by blues on 2023/12/31. -// - -#include -#include -#include -#include - -namespace sky { - - void AssetProducts::LoadFromFile(const std::string &path) - { - std::fstream f(path, std::ios::in | std::ios::binary); - if (!f.is_open()) { - return; - } - - IStreamArchive archive(f); - - uint32_t number = 0; - archive.Load(number); - for (uint32_t i = 0; i < number; ++i) { - Uuid id; - ProductAssetInfo info = {}; - archive.Load(reinterpret_cast(&id), sizeof(Uuid)); - std::lock_guard lock(mutex); - assetLists.emplace(id, info); - } - } - - void AssetProducts::SaveToFile(const std::string &path) - { - std::fstream o(path, std::ios::out | std::ios::binary); - OStreamArchive archive(o); - - std::lock_guard lock(mutex); - archive.Save(static_cast(assetLists.size())); - for (auto &[id, info] : assetLists) { - archive.Save(reinterpret_cast(&id), sizeof(Uuid)); - } - } - - void AssetProducts::AddAsset(const Uuid &uuid, const ProductAssetInfo &info) - { - std::lock_guard lock(mutex); - assetLists[uuid] = info; - } - - void AssetProducts::RemoveAsset(const Uuid &uuid) - { - std::lock_guard lock(mutex); - assetLists.erase(uuid); - } - - void AssetProducts::RegisterDependencies(const Uuid &src, const std::vector &dst) - { - std::lock_guard lock(mutex); - dependencies[src] = dst; - } - - const ProductAssetInfo *AssetProducts::GetProduct(const Uuid &uuid) const - { - std::lock_guard lock(mutex); - auto iter = assetLists.find(uuid); - return iter != assetLists.end() ? &iter->second : nullptr; - } - -} // namespace sky \ No newline at end of file diff --git a/framework/src/platform/PlatformBase.cpp b/framework/src/platform/PlatformBase.cpp deleted file mode 100644 index cc271d39..00000000 --- a/framework/src/platform/PlatformBase.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// -// Created by bluesky on 2023/4/15. -// - -#include - -namespace sky { - void Platform::Shutdown() - { - platform = nullptr; - } - - uint64_t Platform::GetPerformanceFrequency() const - { - return platform->GetPerformanceFrequency(); - } - - uint64_t Platform::GetPerformanceCounter() const - { - return platform->GetPerformanceCounter(); - } - - std::string Platform::GetInternalPath() const - { - return platform->GetInternalPath(); - } - - void *Platform::GetMainWinHandle() const - { - return platform->GetMainWinHandle(); - } - - void *Platform::GetNativeApp() const - { - return platform->GetNativeApp(); - } - - AdaptivePerfManager *Platform::GetPerformanceManager() const - { - return platform->GetPerformanceManager(); - } - - bool Platform::RunCmd(const std::string &str, std::string &out) const - { - return platform->RunCmd(str, out); - } - - PlatformType Platform::GetType() const - { - return platform->GetType(); - } -} \ No newline at end of file diff --git a/framework/src/serialization/SerializationUtil.cpp b/framework/src/serialization/SerializationUtil.cpp deleted file mode 100644 index b7b62bc9..00000000 --- a/framework/src/serialization/SerializationUtil.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Created by Zach Lee on 2023/2/19. -// - -#include - -namespace sky { - - void *GetValue(void *ptr, uint32_t typeId, const std::string &memberName) - { - auto node = GetTypeMember(memberName, typeId); - if (node != nullptr && node->getterFn != nullptr) { - return node->getterFn(const_cast(ptr)); - } - return nullptr; - } - - const void*GetValueConst(const void *ptr, uint32_t typeId, const std::string &memberName) - { - auto node = GetTypeMember(memberName, typeId); - if (node != nullptr && node->getterFn != nullptr) { - return node->getterConstFn(const_cast(ptr)); - } - return nullptr; - } - - bool SetValue(void* ptr, uint32_t typeId, const std::string &memberName, const void* data) - { - auto node = GetTypeMember(memberName, typeId); - if (node != nullptr && node->setterFn != nullptr) { - return node->setterFn(ptr, data); - } - return false; - } - -} \ No newline at end of file diff --git a/framework/src/world/GameObject.cpp b/framework/src/world/GameObject.cpp deleted file mode 100644 index 720a0692..00000000 --- a/framework/src/world/GameObject.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// Created by Zach Lee on 2021/11/13. -// - -#include -#include -#include - -#include -#include -namespace sky { - - void GameObject::Reflect() - { - SerializationContext::Get()->Register("GameObject") - .JsonLoad<&GameObject::Load>() - .JsonSave<&GameObject::Save>(); - } - - GameObject::~GameObject() - { - for (auto comp : components) { - comp->~Component(); - resource->deallocate(comp, comp->GetTypeInfo()->size); - } - components.clear(); - } - - uint32_t GameObject::GetId() const - { - return objId; - } - - void GameObject::SetName(const std::string &name_) - { - name = name_; - } - - const std::string &GameObject::GetName() const - { - return name; - } - - World *GameObject::GetWorld() const - { - return world; - } - - void GameObject::SetParent(GameObject *gameObject) - { - auto trans = GetComponent(); - if (gameObject == nullptr) { - gameObject = world->GetRoot(); - } - TransformComponent *parent = gameObject != nullptr ? gameObject->GetComponent() : nullptr; - trans->SetParent(parent); - } - - void GameObject::SetParent(const Uuid &gameObject) - { - SetParent(world->GetGameObjectByUuid(gameObject)); - } - - GameObject *GameObject::GetParent() const - { - auto trans = GetComponent()->GetParent(); - return trans != nullptr ? trans->object : nullptr; - } - - void GameObject::Tick(float time) - { - for (auto &comp : components) { - comp->OnTick(time); - } - } - - GameObject::ComponentList &GameObject::GetComponents() - { - return components; - } - - void GameObject::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.SaveValueObject("uuid", uuid.ToString()); - ar.SaveValueObject("parent", GetParent()->GetUuid().ToString()); - ar.SaveValueObject("name", name); - - ar.Key("components"); - ar.StartArray(); - for (auto &comp : components) { - ar.StartObject(); - ar.Key("type"); - ar.SaveValue(comp->GetType()); - ar.Key("data"); - ar.SaveValueObject(*comp); - ar.EndObject(); - } - ar.EndArray(); - ar.EndObject(); - } - - void GameObject::Load(JsonInputArchive &ar) - { - std::string id; - ar.LoadKeyValue("uuid", id); - uuid = Uuid::CreateFromString(id.c_str()); - - std::string parentId; - ar.LoadKeyValue("parent", parentId); - auto parent = Uuid::CreateFromString(parentId.c_str()); - - ar.LoadKeyValue("name", name); - - uint32_t size = ar.StartArray("components"); - for (uint32_t i = 0; i < size; ++i) { - uint32_t typeId = 0; - ar.LoadKeyValue("type", typeId); - auto *comp = AddComponent(typeId); - ar.LoadKeyValue("data", *comp); - ar.NextArrayElement(); - } - ar.End(); - SetParent(parent); - } - -} // namespace sky diff --git a/framework/src/world/TransformComponent.cpp b/framework/src/world/TransformComponent.cpp deleted file mode 100644 index 9e5668c3..00000000 --- a/framework/src/world/TransformComponent.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// -// Created by Zach Lee on 2021/11/13. -// - -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - - static const char *TAG = "TransformComponent"; - - void TransformComponent::Reflect() - { - SerializationContext::Get() - ->Register(NAME) - .Member<&TransformComponent::local>("local") - .Property(UI_LABEL_VISIBLE, false) - .Member<&TransformComponent::world>("world") - .Property(UI_PROP_VISIBLE, false); - - ComponentFactory::Get()->RegisterComponent(); - } - - TransformComponent::~TransformComponent() - { - if (parent != nullptr) { - parent->children.erase(std::remove(parent->children.begin(), parent->children.end(), this), parent->children.end()); - } - for (auto &child : children) { - child->parent = nullptr; - } - children.clear(); - } - - void TransformComponent::SetParent(TransformComponent *newParent) - { - if (parent == newParent) { - return; - } - - if (parent != nullptr) { - parent->children.erase(std::remove(parent->children.begin(), parent->children.end(), this), parent->children.end()); - } - parent = newParent; - - if (parent != nullptr) { - auto iter = std::find(parent->children.begin(), parent->children.end(), this); - if (iter == parent->children.end()) { - newParent->children.emplace_back(this); - } - } - UpdateLocal(); - } - - TransformComponent *TransformComponent::GetParent() const - { - return parent; - } - - const std::vector &TransformComponent::GetChildren() const - { - return children; - } - - void TransformComponent::PrintChild(TransformComponent &comp, std::string str) - { - LOG_I(TAG, "%s%s", str.c_str(), comp.object->GetName().c_str()); - for (auto &child : comp.children) { - PrintChild(*child, str + " "); - } - } - - void TransformComponent::Print() - { - PrintChild(*this, ""); - } - - void TransformComponent::TransformChanged() - { - for (auto child : children) { - child->UpdateWorld(); - } - } - - void TransformComponent::UpdateLocal() - { - if (parent != nullptr) { - auto inverse = parent->world.GetInverse(); - local = inverse * world; - } else { - local = world; - } - TransformChanged(); - } - - void TransformComponent::UpdateWorld() - { - world = GetParentTransform() * local; - TransformChanged(); - } - - const Transform &TransformComponent::GetParentTransform() const - { - if (parent != nullptr) { - return parent->world; - } - return Transform::GetIdentity(); - } - - void TransformComponent::SetWorldTranslation(const Vector3 &translation) - { - world.translation = translation; - UpdateLocal(); - } - - void TransformComponent::SetWorldRotation(const Quaternion &rotation) - { - world.rotation = rotation; - UpdateLocal(); - } - - void TransformComponent::SetWorldScale(const Vector3 &scale) - { - world.scale = scale; - UpdateLocal(); - } - - void TransformComponent::SetLocalTranslation(const Vector3 &translation) - { - local.translation = translation; - if (!suppressWorldChange) { - UpdateWorld(); - } - } - - void TransformComponent::SetLocalRotation(const Quaternion &rotation) - { - local.rotation = rotation; - if (!suppressWorldChange) { - UpdateWorld(); - } - } - - void TransformComponent::SetLocalScale(const Vector3 &scale) - { - local.scale = scale; - if (!suppressWorldChange) { - UpdateWorld(); - } - } - - const Transform &TransformComponent::GetLocal() const - { - return local; - } - - const Transform &TransformComponent::GetWorld() const - { - return world; - } - - void TransformComponent::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.SaveValueObject("transform", local); - ar.EndObject(); - } - - void TransformComponent::Load(JsonInputArchive &ar) - { - ar.LoadKeyValue("transform", local); - } - -} // namespace sky diff --git a/framework/src/world/World.cpp b/framework/src/world/World.cpp deleted file mode 100644 index b094ab0b..00000000 --- a/framework/src/world/World.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// -// Created by Zach Lee on 2021/11/13. -// - -#include -#include -#include - -#include -#include - -#include -#include - -namespace sky { - - void World::Reflect() - { - SerializationContext::Get()->Register("World") - .JsonLoad<&World::Load>() - .JsonSave<&World::Save>(); - - SerializationContext::Get()->Register("Component") - .JsonLoad<&Component::Load>() - .JsonSave<&Component::Save>(); - - GameObject::Reflect(); - TransformComponent::Reflect(); - } - - World::World() : root(nullptr), renderScene(nullptr), gameObjects(&memoryResource), objectLut(&memoryResource) - { - root = CreateGameObject("root"); - } - - World::~World() - { - for (auto &go : gameObjects) { - go->~GameObject(); - memoryResource.deallocate(go, sizeof(GameObject)); - } - gameObjects.clear(); - } - - GameObject *World::AllocateGameObject() - { - static std::atomic_uint32_t index = 0; - index.fetch_add(1); - auto ptr = memoryResource.allocate(sizeof(GameObject)); - auto go = new (ptr) GameObject(); - go->resource = &memoryResource; - go->world = this; - go->objId = index.load(); - return go; - } - - GameObject *World::CreateGameObject(const std::string &name, const Uuid &uuid) - { - auto go = AllocateGameObject(); - go->AddComponent(); - go->SetParent(root); - go->SetUuid(uuid); - go->SetName(name); - gameObjects.emplace_back(go); - objectLut.emplace(uuid, go); - return go; - } - - GameObject *World::CreateGameObject(const std::string &name) - { - return CreateGameObject(name, Uuid::Create()); - } - - void World::DestroyGameObject(GameObject *go) - { - if (go == root) { - return; - } - - auto iter = std::find(gameObjects.begin(), gameObjects.end(), go); - if (iter != gameObjects.end()) { - (*iter)->~GameObject(); - gameObjects.erase(iter); - memoryResource.deallocate((*iter), sizeof(GameObject)); - } - } - - void World::Tick(float time) - { - for (auto &obj : gameObjects) { - obj->Tick(time); - } - } - - const PmrVector &World::GetGameObjects() const - { - return gameObjects; - } - - GameObject *World::GetGameObjectByUuid(const Uuid &id) const - { - auto iter = objectLut.find(id); - return iter != objectLut.end() ? iter->second : nullptr; - } - - GameObject *World::GetRoot() - { - return root; - } - - void World::ForEachBFS(GameObject *go, std::function && fn) const - { - std::deque queue; - queue.emplace_back(go); - - while (!queue.empty()) { - auto tgo = queue.front(); - queue.pop_front(); - if (tgo != root) { - fn(tgo); - } - - auto trans = tgo->GetComponent(); - auto &children = trans->GetChildren(); - for (auto &child : children) { - queue.emplace_back(child->object); - } - } - } - - void World::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.Key("objects"); - ar.StartArray(); - ForEachBFS(root, [&ar](GameObject *go) { - ar.SaveValueObject(*go); - }); - ar.EndArray(); - ar.EndObject(); - } - - void World::Load(JsonInputArchive &ar) - { - uint32_t size = ar.StartArray("objects"); - for (uint32_t i = 0; i < size; ++i) { - auto go = CreateGameObject(""); - ar.LoadArrayElement(*go); - } - ar.End(); - } -} // namespace sky diff --git a/launcher/android/app/.gitignore b/launcher/android/app/.gitignore index 3e6f6cf0..1be4d6e0 100644 --- a/launcher/android/app/.gitignore +++ b/launcher/android/app/.gitignore @@ -1,3 +1,4 @@ /build /.cxx -/main/assets \ No newline at end of file +/main/assets +/src/main/jniLibs/ diff --git a/launcher/android/app/build.gradle b/launcher/android/app/build.gradle index 627af67f..2d77974e 100644 --- a/launcher/android/app/build.gradle +++ b/launcher/android/app/build.gradle @@ -12,7 +12,7 @@ android { defaultConfig { applicationId "com.skyengine.launcher" - minSdk 31 + minSdk 29 targetSdk 32 versionCode 1 versionName "1.0" @@ -28,6 +28,7 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.release } } compileOptions { @@ -47,7 +48,7 @@ android { } dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation fileTree(include: ['*.so'], dir: 'libs') implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.games:games-activity:1.1.0' diff --git a/launcher/android/build.gradle b/launcher/android/build.gradle index a96fb5f4..3cb32a1c 100644 --- a/launcher/android/build.gradle +++ b/launcher/android/build.gradle @@ -6,9 +6,4 @@ plugins { task clean(type: Delete) { delete rootProject.buildDir -} - -task copyFiles(type: Copy) { - from '../../sample/RHISampleBase/assets' - into 'app/src/main/assets' -} +} \ No newline at end of file diff --git a/launcher/macos/MacosLauncher.mm b/launcher/macos/MacosLauncher.mm index a89be16d..856a58f3 100644 --- a/launcher/macos/MacosLauncher.mm +++ b/launcher/macos/MacosLauncher.mm @@ -1,37 +1,27 @@ // -// Created by Zach Lee on 2021/11/28. +// Created by Zach Lee on 2021/11/9. // -#include "Command.h" #include #include +#include + +using namespace sky; + int main(int argc, char **argv) { - sky::CommandInfo cmdInfo = {}; - sky::ProcessCommand(argc, argv, cmdInfo); - - sky::Platform *platform = sky::Platform::Get(); + // platform + sky::Platform* platform = sky::Platform::Get(); if (!platform->Init({})) { - return 1; + return -1; } - sky::StartInfo start = {}; - start.appName = "MacosLauncher"; - start.modules.swap(cmdInfo.modules); - sky::GameApplication app; - for (auto &[key, value] : cmdInfo.values) { - start.setting.SetValue(key, value); - } - - if (app.Init(start)) { + if (app.Init(argc, argv)) { app.Mainloop(); } app.Shutdown(); - - platform->Shutdown(); - return 0; } diff --git a/launcher/windows/Win32Launcher.cpp b/launcher/windows/Win32Launcher.cpp index 7b7c9231..a86d0583 100644 --- a/launcher/windows/Win32Launcher.cpp +++ b/launcher/windows/Win32Launcher.cpp @@ -4,7 +4,9 @@ #include #include +#include +#include #include using namespace sky; @@ -17,11 +19,25 @@ int main(int argc, char **argv) return -1; } - sky::GameApplication app; - if (app.Init(argc, argv)) { - app.Mainloop(); + cxxopts::Options options("SkyEngine Launcher", "SkyEngine Launcher"); + options.allow_unrecognised_options(); + options.add_options()("a, app", "app mode", cxxopts::value()); + auto result = options.parse(argc, argv); + bool isXRMode = (result.count("app") != 0u) && result["app"].as() == "xr"; + if (isXRMode) { + sky::XRApplication app; + if (app.Init(argc, argv)) { + app.Mainloop(); + } + app.Shutdown(); + } else { + sky::GameApplication app; + if (app.Init(argc, argv)) { + app.Mainloop(); + } + app.Shutdown(); } - app.Shutdown(); + return 0; } diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 00000000..f0a4dc56 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1,2 @@ +/__pycache__ +/*.ini \ No newline at end of file diff --git a/python/ProjectManager.py b/python/ProjectManager.py new file mode 100644 index 00000000..13a22881 --- /dev/null +++ b/python/ProjectManager.py @@ -0,0 +1,360 @@ +import configparser +import os +import sys +import ctypes +import platform as OSPlatform +from functools import partial + +from PySide6.QtGui import QAction, QCursor +from PySide6.QtCore import Slot +from PySide6.QtWidgets import QApplication, QWidget, QSizePolicy, QHBoxLayout, QVBoxLayout, QFormLayout, QLabel, \ + QFileDialog, QLineEdit, QPushButton, QMessageBox, QGridLayout, QDialog, QGroupBox, QTableWidget, QMenu, \ + QComboBox, QTableWidgetItem, QHeaderView + +from build.Project import ProjectBuilder, ProjectConfig +from build.Presets import PLATFORM_AVAILABLE_LIST, BUILD_TYPE_LIST, GENERATOR_LIST, PLATFORM_ARCH_LIST, \ + WindowsConfigPreset, AndroidConfigPreset + +from widgets import Asset + + +def is_admin(): + try: + return ctypes.windll.shell32.IsUserAnAdmin() + except: + return True + + +class BuildConfigWidget(QWidget): + def __init__(self, platform): + QWidget.__init__(self) + self.platform = platform + + self.fLayout = QFormLayout() + self.setLayout(self.fLayout) + self.setMinimumWidth(512) + + self.buildType = QComboBox() + self.buildType.addItems(BUILD_TYPE_LIST) + self.buildName = QLineEdit("%s" % platform) + self.generator = QComboBox() + self.generator.addItems(GENERATOR_LIST[platform]) + self.arch = QComboBox() + self.arch.addItems(PLATFORM_ARCH_LIST[platform]) + self.external = QLineEdit() + + self.fLayout.addRow("Name", self.buildName) + self.fLayout.addRow("Build Type", self.buildType) + self.fLayout.addRow("Generator", self.generator) + self.fLayout.addRow("Arch", self.arch) + self.fLayout.addRow("ThirdParty", self.external) + self.platform_config() + + self.preset = None + + def platform_config(self): + pass + + def save_config(self): + self.preset.set_name(self.buildName.text()) + self.preset.set_generator(self.generator.currentText()) + self.preset.set_description('%s Build (%s)' % (self.platform, self.buildType.currentText())) + self.preset.add_cache_variable('CMAKE_BUILD_TYPE', self.buildType.currentText()) + self.preset.add_cache_variable('3RD_PATH', self.external.text()) + + +class WindowsConfigWidget(BuildConfigWidget): + def __init__(self): + BuildConfigWidget.__init__(self, 'Windows') + self.preset = WindowsConfigPreset() + + def platform_config(self): + pass + + def save_config(self): + BuildConfigWidget.save_config(self) + self.preset.set_arch(self.arch.currentText()) + + +class AndroidConfigWidget(BuildConfigWidget): + def __init__(self): + BuildConfigWidget.__init__(self, 'Android') + self.preset = AndroidConfigPreset() + self.identifier = None + self.ndkPath = None + self.sdkPath = None + + def platform_config(self): + self.sdkPath = QLineEdit(os.environ.get('ANDROID_HOME')) + self.ndkPath = QLineEdit() + + self.identifier = QLineEdit("com.%s.MyProject" % os.getlogin()) + self.fLayout.addRow('SDK PATH', self.sdkPath) + self.fLayout.addRow('NDK PATH', self.ndkPath) + self.fLayout.addRow('Identifier', self.identifier) + + def save_config(self): + BuildConfigWidget.save_config(self) + self.preset.add_cache_variable('CMAKE_SYSTEM_NAME', 'Android') + self.preset.add_cache_variable('CMAKE_ANDROID_STL_TYPE', 'c++_static') + self.preset.add_cache_variable('CMAKE_ANDROID_ARCH_ABI', self.arch.currentText()) + + +PLATFORM_CONFIG_TYPE = { + 'Windows': WindowsConfigWidget, + 'Android': AndroidConfigWidget +} + + +def check_widget_en(widget: QWidget, enable): + widget.setEnabled(enable) + if not enable: + widget.setStyleSheet("color:grey") + + +class BuildConfigDialog(QDialog): + def __init__(self, platform): + QDialog.__init__(self) + self.setWindowTitle('%s Build Config' % platform) + + self.setLayout(QVBoxLayout()) + self.configWidget = PLATFORM_CONFIG_TYPE[platform]() + self.layout().addWidget(self.configWidget) + applyBtn = QPushButton("Save") + applyBtn.clicked.connect(self.apply_config) + cancelBtn = QPushButton("Cancel") + cancelBtn.clicked.connect(self.cancel) + self.layout().addWidget(applyBtn) + self.layout().addWidget(cancelBtn) + + @Slot() + def apply_config(self): + self.configWidget.save_config() + self.accept() + + @Slot() + def cancel(self): + self.close() + + +class ProjectConfigDialog(QDialog): + def __init__(self, parent, config: ProjectConfig): + QDialog.__init__(self, parent) + self.setWindowTitle("Project Config") + self.setMinimumWidth(512) + + self.vLayout = QGridLayout() + self.setLayout(self.vLayout) + self.config = config + + self.buildGroup = QGroupBox('builds') + self.buildGroup.setLayout(QVBoxLayout()) + self.table = QTableWidget() + self.table.setColumnCount(3) + self.table.horizontalHeader().hide() + self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) + self.addBuildBtn = QPushButton('Add') + self.addBuildBtn.clicked.connect(self.btn_add_clicked) + + self.buildGroup.layout().addWidget(self.addBuildBtn) + self.buildGroup.layout().addWidget(self.table) + + applyBtn = QPushButton("Save") + applyBtn.clicked.connect(self.apply_config) + cancelBtn = QPushButton("Cancel") + cancelBtn.clicked.connect(self.cancel) + self.vLayout.addWidget(self.buildGroup) + self.vLayout.addWidget(applyBtn) + self.vLayout.addWidget(cancelBtn) + + self.update_table_content() + + @Slot() + def apply_config(self): + self.config.save_config() + self.accept() + + @Slot() + def cancel(self): + self.close() + + @Slot() + def btn_add_clicked(self): + menu = QMenu('build list', self) + for platform in PLATFORM_AVAILABLE_LIST[OSPlatform.system()]: + action = QAction(platform, menu) + action.triggered.connect(partial(self.act_add_build_triggered, platform)) + menu.addAction(action) + menu.exec(QCursor.pos()) + + @Slot() + def act_add_build_triggered(self, platform): + dialog = BuildConfigDialog(platform) + if dialog.exec(): + if self.config.cmakePreset.add_preset(dialog.configWidget.preset): + self.update_table_content() + else: + QMessageBox(QMessageBox.Icon.Critical, + 'Failed', + 'Preset name %s exists' % dialog.configWidget.preset.data['name']).exec() + + def update_table_content(self): + self.table.clear() + self.table.setRowCount(len(self.config.cmakePreset.data['configurePresets']) - 1) + index = 0 + for preset in self.config.cmakePreset.data['configurePresets']: + if preset['hidden']: + continue + + nameItem = QTableWidgetItem('%s' % preset['name']) + generatorItem = QTableWidgetItem('%s' % preset['generator']) + buildType = QTableWidgetItem(preset['displayName']) + self.table.setItem(index, 0, nameItem) + self.table.setItem(index, 1, buildType) + self.table.setItem(index, 2, generatorItem) + index = index + 1 + + +class ProjectWidget(QWidget): + def __init__(self, *args): + QWidget.__init__(self, *args) + + self.vLayout = QFormLayout() + self.setLayout(self.vLayout) + + dft_engine_path = os.path.join(os.curdir, os.pardir) + self.enginePath = QLineEdit(os.path.abspath(dft_engine_path), self) + self.projectPath = QLineEdit(self) + self.projectName = QLineEdit(self) + self.enginePath.textChanged.connect(self.edit_line_changed) + self.projectPath.textChanged.connect(self.edit_line_changed) + self.projectName.textChanged.connect(self.edit_line_changed) + + self.filesBtn = QPushButton("Files...") + self.filesBtn.clicked.connect(self.on_files_clicked) + self.createBtn = QPushButton("Create") + self.createBtn.clicked.connect(self.on_create_clicked) + self.projectCfgBtn = QPushButton("Config") + self.projectCfgBtn.clicked.connect(self.on_config_clicked) + self.assetCfgBtn = QPushButton("Assets") + self.assetCfgBtn.clicked.connect(self.on_assets_clicked) + + self.vLayout.addRow(QLabel("Engine Dir"), self.enginePath) + self.vLayout.addRow(QLabel("Project Dir"), self.projectPath) + self.vLayout.addRow(QLabel("Project Name"), self.projectName) + + self.vLayout.addWidget(self.filesBtn) + self.vLayout.addWidget(self.createBtn) + self.vLayout.addWidget(self.projectCfgBtn) + self.vLayout.addWidget(self.assetCfgBtn) + + self.assetBrowser = None + + self.configFile = 'project_manager.ini' + self.load_config() + + def edit_line_changed(self, str): + if self.assetBrowser: + self.assetBrowser.update_path(self.enginePath.text(), + os.path.join(self.projectPath.text(), self.projectName.text())) + + def closeEvent(self, event): + self.save_config() + + def create_new_project(self, path): + os.mkdir(path, 0o777) + builder = ProjectBuilder(path, self.enginePath.text()) + builder.init_project() + + def update_project(self, path): + builder = ProjectBuilder(path, self.enginePath.text()) + builder.update_project() + pass + + def get_project_full_path(self): + project_path = os.path.abspath(self.projectPath.text()) + project_path = os.path.join(project_path, self.projectName.text()) + return project_path + + @Slot() + def on_config_clicked(self): + builder = ProjectBuilder(self.get_project_full_path(), self.enginePath.text()) + ProjectConfigDialog(self, builder.config).exec() + + @Slot() + def on_assets_clicked(self): + if not self.assetBrowser: + self.assetBrowser = Asset.AssetBrowserWidget(None, self.enginePath.text(), + os.path.join(self.projectPath.text(), self.projectName.text())) + self.assetBrowser.show() + + @Slot() + def on_create_clicked(self): + project_name = self.projectName.text() + if len(project_name) == 0: + QMessageBox(QMessageBox.Icon.Critical, 'Error', 'Project name must not be empty').exec() + return + + project_path = self.get_project_full_path() + if os.path.exists(project_path): + self.update_project(project_path) + else: + self.create_new_project(project_path) + + QMessageBox(QMessageBox.Icon.Information, 'Success', 'Project %s created successful' % project_path).exec() + + @Slot() + def on_files_clicked(self): + dialog = QFileDialog() + dialog.setFileMode(QFileDialog.FileMode.Directory) + dialog.setViewMode(QFileDialog.ViewMode.Detail) + + if dialog.exec(): + file_names = dialog.selectedFiles() + if len(file_names) > 0: + self.projectPath.setText(os.path.abspath(file_names[0])) + + def load_config(self): + config = configparser.ConfigParser() + config.read(self.configFile) + + project_path = config.get('SavedConfig', 'directory', fallback='') + project_name = config.get('SavedConfig', 'name', fallback='') + self.projectPath.setText(project_path) + self.projectName.setText(project_name) + + def save_config(self): + config = configparser.ConfigParser() + config['SavedConfig'] = { + 'directory': self.projectPath.text(), + 'name': self.projectName.text() + } + with open(self.configFile, 'w') as configfile: + config.write(configfile) + print("project saved") + + +def app_main(): + app = QApplication(sys.argv) + + mainWindow = QWidget() + mainWindow.setWindowTitle("ProjectManager") + mainWindow.setMinimumWidth(512) + + project = ProjectWidget(mainWindow) + project.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)) + + mainWindow.setLayout(QHBoxLayout()) + mainWindow.layout().setContentsMargins(0, 0, 0, 0) + mainWindow.layout().addWidget(project) + mainWindow.show() + + sys.exit(app.exec()) + + +if __name__ == "__main__": + if is_admin(): + app_main() + elif OSPlatform.system() == "Windows": + # Re-run the program with admin rights + ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1) diff --git a/python/build/Presets.py b/python/build/Presets.py new file mode 100644 index 00000000..b6e954eb --- /dev/null +++ b/python/build/Presets.py @@ -0,0 +1,137 @@ +import json +import os.path +from typing import List + +PLATFORM_LIST = [ + 'Windows', + 'Android', + 'Darwin', + 'IOS', +] + +PLATFORM_ARCH_LIST = { + 'Windows': ['x64'], + 'Android': ['arm64-v8a', 'armeabi-v7a', 'x86'], + 'Darwin': ['x86', 'arm64'], + 'IOS': ['arm64'], +} + +BUILD_TYPE_LIST = ['Debug', 'Release'] + +PLATFORM_AVAILABLE_LIST = { + 'Windows': ['Windows', 'Android'], + 'Darwin': ['Darwin', 'IOS', 'Android'], +} + +GENERATOR_LIST = { + 'Windows': ['Visual Studio 17 2022', 'Visual Studio 16 2019'], + 'Darwin': ['Xcode'], + 'IOS': ['Xcode'], + 'Android': ['Ninja'] +} + +COMMON_PRESET_TEMP = { + 'name': 'common', + 'hidden': True, + 'cacheVariables': { + 'ENGINE_ROOT': '' + } +} + + +class BuildPreset: + def __init__(self): + self.data = {} + + +class ConfigPreset: + def __init__(self): + self.data = {} + + def get_display_name(self): + return self.data['name'] + + def set_name(self, name): + self.data['name'] = name + + def set_generator(self, generator): + self.data['generator'] = generator + + def set_description(self, description): + self.data['description'] = description + + def add_cache_variable(self, key, val): + if 'cacheVariables' not in self.data: + self.data['cacheVariables'] = {} + self.data['cacheVariables'][key] = val + + +class WindowsConfigPreset(ConfigPreset): + + def __init__(self): + ConfigPreset.__init__(self) + + def get_display_name(self): + return '%s-%s-%s' % (self.data['name'], + self.data['cacheVariables']['CMAKE_BUILD_TYPE'], + self.data['architecture']['value']) + + def set_arch(self, arch): + self.data['architecture'] = {'value': '%s' % arch, 'strategy': 'set'} + + +class AndroidConfigPreset(ConfigPreset): + def __init__(self): + ConfigPreset.__init__(self) + + def get_display_name(self): + return '%s-%s-%s' % (self.data['name'], + self.data['cacheVariables']['CMAKE_BUILD_TYPE'], + self.data['cacheVariables']['CMAKE_ANDROID_ARCH_ABI']) + + +class DarwinConfigPreset(ConfigPreset): + def __init__(self): + ConfigPreset.__init__(self) + + +class IOSConfigPreset(ConfigPreset): + def __init__(self): + ConfigPreset.__init__(self) + + +class CmakePreset: + def __init__(self): + self.data = {'version': 3, + 'cmakeMinimumRequired': {'major': 3, 'minor': 19, 'patch': 0}, + 'configurePresets': [], + 'buildPresets': []} + + def add_preset(self, preset: ConfigPreset): + for current in self.data['configurePresets']: + if current['name'] == preset.data['name']: + return False + self.data['configurePresets'].append(preset.data) + + preset.data['hidden'] = False + preset.data['inherits'] = 'common' + preset.data['displayName'] = preset.get_display_name() + preset.data['binaryDir'] = '${sourceDir}/build/%s' % preset.data['displayName'] + buildPreset = BuildPreset() + buildPreset.data['name'] = preset.data['name'] + buildPreset.data['configurePreset'] = preset.data['name'] + buildPreset.data['description'] = preset.data['description'] + buildPreset.data['configuration'] = preset.data['cacheVariables']['CMAKE_BUILD_TYPE'] + buildPreset.data['displayName'] = preset.data['displayName'] + self.data['buildPresets'].append(buildPreset.data) + return True + + def load(self, path): + if not os.path.exists(path): + return + with open(path, 'r') as f: + self.data = json.load(f) + + def save(self, path): + with open(path, 'w', encoding='utf-8') as f: + json.dump(self.data, f, indent=4) diff --git a/python/build/Project.py b/python/build/Project.py new file mode 100644 index 00000000..c1f78f41 --- /dev/null +++ b/python/build/Project.py @@ -0,0 +1,120 @@ +import os.path +import shutil + +from build.Presets import CmakePreset, COMMON_PRESET_TEMP + + +def create_symlink(src, dst): + if os.path.exists(dst): + os.rmdir(dst) + os.symlink(src, dst, True) + + +class PlatformConfig: + def __init__(self): + self.enable = False + + def set_enable(self, enable): + self.enable = enable + + +class BuildConfig: + def __init__(self): + pass + + +class ProjectConfig: + def __init__(self, project_path): + self.projectPath = project_path + self.builds = list() + self.cmakePreset = CmakePreset() + self.config_file_name = 'project_config.json' + self.preset_file_name = 'CMakePresets.json' + + def save_config(self): + self.cmakePreset.save(os.path.join(self.projectPath, self.preset_file_name)) + + def load_config(self): + self.cmakePreset.load(os.path.join(self.projectPath, self.preset_file_name)) + + def update_path(self, engine_path): + commonPreset = None + for configPreset in self.cmakePreset.data['configurePresets']: + if configPreset['name'] == 'common': + commonPreset = configPreset + configPreset['cacheVariables']['ENGINE_ROOT'] = engine_path + break + + if commonPreset is None: + COMMON_PRESET_TEMP['cacheVariables']['ENGINE_ROOT'] = engine_path + self.cmakePreset.data['configurePresets'].append(COMMON_PRESET_TEMP) + + +class ProjectBuilder: + def __init__(self, project_path, engine_path): + self.projectPath = project_path + self.enginePath = engine_path + self.config = ProjectConfig(self.projectPath) + self.config.load_config() + self.config.update_path(engine_path) + + def init_project(self): + self.init_project_directory() + + def update_project(self): + self.update_project_symlink() + pass + + def config_native(self): + native_path = os.path.join(self.projectPath, 'native') + + # set cmake lists + cmake_native_template_path = os.path.join(self.enginePath, 'cmake', 'template', 'CMakeLists_native.txt') + cmake_template_path = os.path.join(self.enginePath, 'cmake', 'template', 'CMakeLists_project.txt') + with open(cmake_template_path, "r") as f: + data = f.read() + + cmake_native_target_path = os.path.join(native_path, 'CMakeLists.txt') + cmake_target_path = os.path.join(self.projectPath, 'CMakeLists.txt') + if os.path.exists(cmake_target_path): + os.remove(cmake_target_path) + + data = data.replace('@PROJECT_NAME@', '%s' % os.path.basename(self.projectPath)) + with open(cmake_target_path, 'w') as f: + f.write(data) + + shutil.copy(cmake_native_template_path, cmake_native_target_path) + + def config_asset(self): + pass + + def config_config(self): + pass + + def update_project_symlink(self): + engine_source_asset_path = os.path.join(self.enginePath, "assets") + engine_asset_link_path = os.path.join(self.projectPath, "engine_assets") + create_symlink(engine_source_asset_path, engine_asset_link_path) + + engine_runtime_path = os.path.join(self.enginePath, "runtime") + project_runtime_link_path = os.path.join(self.projectPath, "native", "runtime") + create_symlink(engine_runtime_path, project_runtime_link_path) + + engine_launcher_path = os.path.join(self.enginePath, "launcher") + project_launcher_link_path = os.path.join(self.projectPath, "native", "launcher") + create_symlink(engine_launcher_path, project_launcher_link_path) + + def init_project_directory(self): + asset_path = os.path.join(self.projectPath, "assets") + config_path = os.path.join(self.projectPath, "config") + native_path = os.path.join(self.projectPath, "native") + + path_list = [(asset_path, self.config_asset), + (config_path, self.config_config), + (native_path, self.config_native)] + for path, fn in path_list: + if not os.path.exists(path): + os.mkdir(path, 0o777) + fn() + + self.update_project_symlink() diff --git a/python/widgets/Asset.py b/python/widgets/Asset.py new file mode 100644 index 00000000..a0be1aa8 --- /dev/null +++ b/python/widgets/Asset.py @@ -0,0 +1,70 @@ +import os.path + +from PySide6.QtCore import Slot, QDir +from PySide6.QtWidgets import QWidget, QVBoxLayout, QTreeView, QFileSystemModel, QComboBox, QListView, QHBoxLayout, \ + QSplitter + + +class AssetTreeViewWidget(QWidget): + def __init__(self, parent, engine, workspace): + QWidget.__init__(self, parent) + + self.bundle = ["Engine", "Project"] + + self.modelDict = dict() + self.update_path(engine, workspace) + + self.model = QFileSystemModel(self) + + self.combo = QComboBox(self) + self.combo.addItems(self.bundle) + self.combo.activated.connect(self.combo_activated) + + self.model = QFileSystemModel() + + self.treeView = QTreeView(self) + self.treeView.setModel(self.model) + self.treeView.setRootIndex(self.model.setRootPath(self.modelDict[self.combo.currentText()])) + + self.setLayout(QVBoxLayout(self)) + self.layout().addWidget(self.combo) + self.layout().addWidget(self.treeView) + + def update_path(self, engine, workspace): + self.modelDict["Engine"] = os.path.join(engine, "assets") + self.modelDict["Project"] = os.path.join(workspace, "assets") + + @Slot() + def combo_activated(self, idx): + model = self.modelDict[self.combo.itemText(idx)] + self.treeView.setRootIndex(self.model.setRootPath(model)) + + +class AssetListViewWidget(QWidget): + def __init__(self, parent): + QWidget.__init__(self, parent) + + self.listView = QListView(self) + + self.setLayout(QVBoxLayout(self)) + self.layout().addWidget(self.listView) + + +class AssetBrowserWidget(QWidget): + def __init__(self, parent, engine, workspace): + QWidget.__init__(self, parent) + print("AssetBrowser %s, %s" % (engine, workspace)) + + self.tree = AssetTreeViewWidget(self, engine, workspace) + self.list = AssetListViewWidget(self) + + self.splitter = QSplitter(self) + self.splitter.setMinimumWidth(10) + self.splitter.addWidget(self.tree) + self.splitter.addWidget(self.list) + + self.setLayout(QHBoxLayout(self)) + self.layout().addWidget(self.splitter) + + def update_path(self, engine, workspace): + self.tree.update_path(engine, workspace) \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/Util.h b/render/adaptor/include/render/adaptor/Util.h deleted file mode 100644 index 8332db78..00000000 --- a/render/adaptor/include/render/adaptor/Util.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by Zach Lee on 2023/8/27. -// - -#pragma once - -#include - -namespace sky { - class GameObject; - - RenderScene *GetRenderSceneFromGameObject(GameObject *go); - - template - T *GetFeatureProcessor(const RenderScene *scene) - { - return scene->GetFeature(); - } - -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/VertexDescLibraryAsset.h b/render/adaptor/include/render/adaptor/assets/VertexDescLibraryAsset.h deleted file mode 100644 index f3b20786..00000000 --- a/render/adaptor/include/render/adaptor/assets/VertexDescLibraryAsset.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#pragma once - -#include -#include -#include -#include -#include - -namespace sky { - class BinaryInputArchive; - class BinaryOutputArchive; - - struct VertexDescLibraryAssetData { - std::unordered_map descriptions; - - void Load(BinaryInputArchive &archive); - void Save(BinaryOutputArchive &archive) const; - }; - - VertexDescLibrary *CreateVertexDescLibrary(const VertexDescLibraryAssetData &data); - - template <> - struct AssetTraits { - using DataType = VertexDescLibraryAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("f344d674-c0b1-4e1d-b6c5-87aba4aea204"); - static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - }; - using VertexDescLibraryAssetPtr = std::shared_ptr>; -} // namespace sky diff --git a/render/adaptor/include/render/adaptor/components/LightComponent.h b/render/adaptor/include/render/adaptor/components/LightComponent.h deleted file mode 100644 index ef05e4eb..00000000 --- a/render/adaptor/include/render/adaptor/components/LightComponent.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by Zach Lee on 2023/2/28. -// - -#pragma once - -#include -#include - -namespace sky { - - class LightComponent : public Component { - public: - LightComponent() = default; - ~LightComponent() override = default; - - TYPE_RTTI_WITH_VT(LightComponent) - - static void Reflect(); - - void Save(JsonOutputArchive &ar) const override; - void Load(JsonInputArchive &ar) override; - - private: - Color lightColor; - }; - -} // namespace sky - - - - diff --git a/render/adaptor/include/render/adaptor/components/MeshRenderer.h b/render/adaptor/include/render/adaptor/components/MeshRenderer.h deleted file mode 100644 index f4f19d4d..00000000 --- a/render/adaptor/include/render/adaptor/components/MeshRenderer.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by Zach Lee on 2023/2/28. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky { - - class MeshRenderer : public Component { - public: - MeshRenderer() = default; - ~MeshRenderer() override = default; - - TYPE_RTTI_WITH_VT(MeshRenderer) - - static void Reflect(); - - void OnActive() override; - void OnDestroy() override; - void OnTick(float time) override; - - void SetMesh(const MeshAssetPtr &mesh); - void SetMesh(const RDMeshPtr &mesh); - - void Save(JsonOutputArchive &ar) const override; - void Load(JsonInputArchive &ar) override; - - StaticMeshRenderer *GetRenderer() const { return renderer; } - - private: - void ResetMesh(); - - bool isStatic = true; - bool castShadow = false; - bool receiveShadow = false; - - MeshAssetPtr meshAsset; - RDMeshPtr meshInstance; - StaticMeshRenderer *renderer = nullptr; - }; - -} // namespace receiveShadow diff --git a/render/adaptor/include/render/adaptor/components/ParticleSystemComponent.h b/render/adaptor/include/render/adaptor/components/ParticleSystemComponent.h deleted file mode 100644 index 4af0e91e..00000000 --- a/render/adaptor/include/render/adaptor/components/ParticleSystemComponent.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Created by Zach Lee on 2023/9/17. -// - -#pragma once - -#include -#include - -namespace sky { - - class ParticleSystemComponent : public Component { - public: - ParticleSystemComponent() = default; - ~ParticleSystemComponent() override = default; - - TYPE_RTTI_WITH_VT(ParticleSystemComponent) - - void OnTick(float time) override; - void OnActive() override; - void OnDestroy() override; - - private: - ParticleSystem *particleSystem; - }; - -} // namespace sky diff --git a/render/adaptor/include/render/adaptor/pipeline/DefaultForward.h b/render/adaptor/include/render/adaptor/pipeline/DefaultForward.h deleted file mode 100644 index c1136c2c..00000000 --- a/render/adaptor/include/render/adaptor/pipeline/DefaultForward.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zach Lee on 2023/8/20. -// - -#pragma once - -#include -#include -#include - -namespace sky { - class RenderWindow; - - class DefaultForward : public RenderPipeline { - public: - DefaultForward() = default; - ~DefaultForward() override = default; - - void SetOutput(RenderWindow *wnd); - void OnSetup(rdg::RenderGraph &rdg) override; - - private: - RenderWindow *output = nullptr; - rhi::PixelFormat depthStencilFormat = rhi::PixelFormat::D24_S8; - RDResourceLayoutPtr forwardLayout; - }; - -} // namespace sky diff --git a/render/adaptor/src/Util.cpp b/render/adaptor/src/Util.cpp deleted file mode 100644 index 37487b6d..00000000 --- a/render/adaptor/src/Util.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// -// Created by Zach Lee on 2023/8/27. -// - -#include -#include -#include -#include - -namespace sky { - - RenderScene *GetRenderSceneFromGameObject(GameObject *go) - { - return static_cast(go->GetWorld()->GetRenderScene())->GetRenderScene(); - } - -} // namespace sky diff --git a/render/adaptor/src/assets/ImageAsset.cpp b/render/adaptor/src/assets/ImageAsset.cpp deleted file mode 100644 index d0b935a7..00000000 --- a/render/adaptor/src/assets/ImageAsset.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// -// Created by Zach Lee on 2023/2/26. -// - -#include -#include -#include - -namespace sky { - void ImageAssetData::Load(BinaryInputArchive &archive) - { - archive.LoadValue(format); - archive.LoadValue(type); - archive.LoadValue(width); - archive.LoadValue(height); - archive.LoadValue(depth); - archive.LoadValue(mipLevels); - archive.LoadValue(arrayLayers); - archive.LoadValue(dataSize); - archive.LoadValue(reinterpret_cast(&bufferID), sizeof(Uuid)); - } - - void ImageAssetData::Save(BinaryOutputArchive &archive) const - { - archive.SaveValue(format); - archive.SaveValue(type); - archive.SaveValue(width); - archive.SaveValue(height); - archive.SaveValue(depth); - archive.SaveValue(mipLevels); - archive.SaveValue(arrayLayers); - archive.SaveValue(dataSize); - archive.SaveValue(reinterpret_cast(&bufferID), sizeof(Uuid)); - } - - std::shared_ptr CreateTexture(const ImageAssetData &data) - { - auto *queue = RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER); - auto bufferPath = AssetManager::Get()->GetAssetPath(data.bufferID); - if (data.type == TextureType::TEXTURE_2D) { - auto texture2D = std::make_shared(); - texture2D->Init(data.format, data.width, data.height, data.mipLevels); - auto handle = texture2D->Upload(bufferPath, *queue, 0); - queue->Wait(handle); - return texture2D; - } - - if (data.type == TextureType::TEXTURE_CUBE) { - auto textureCube = std::make_shared(); - textureCube->Init(data.format, data.width, data.height, data.mipLevels); - return textureCube; - } - -// queue->Wait(texture2D->Upload(data.bufferAsset->GetPath(), *queue, data.bufferAsset->Data().GetDataOffset())); - return {}; - } -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/assets/MaterialAsset.cpp b/render/adaptor/src/assets/MaterialAsset.cpp deleted file mode 100644 index c9dfb4a0..00000000 --- a/render/adaptor/src/assets/MaterialAsset.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// -// Created by Zach Lee on 2023/2/23. -// - -#include -#include -#include - -namespace sky { - void LoadProperties(BinaryInputArchive &archive, MaterialProperties &properties) - { - uint32_t size = 0; - archive.LoadValue(size); - properties.images.resize(size); - for (uint32_t i = 0; i < size; ++i) { - archive.LoadValue(properties.images[i]); - } - - size = 0; - archive.LoadValue(size); - for (uint32_t i = 0; i < size; ++i) { - std::string key; - archive.LoadValue(key); - MaterialValueType type; - archive.LoadValue(type); - switch (type) { - case MaterialValueType::TEXTURE: { - MaterialTexture tex = {}; - archive.LoadValue(tex.texIndex); - properties.valueMap[key] = tex; - } - break; - case MaterialValueType::VEC2: { - Vector2 vec = {}; - archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector2)); - properties.valueMap[key] = vec; - } - break; - case MaterialValueType::VEC3: { - Vector3 vec = {}; - archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector3)); - properties.valueMap[key] = vec; - } - break; - case MaterialValueType::VEC4: { - Vector4 vec = {}; - archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector4)); - properties.valueMap[key] = vec; - } - break; - case MaterialValueType::FLOAT: { - float val = {}; - archive.LoadValue(val); - properties.valueMap[key] = val; - } - break; - case MaterialValueType::U32: { - uint32_t val = {}; - archive.LoadValue(val); - properties.valueMap[key] = val; - } - break; - case MaterialValueType::I32: { - int32_t val = {}; - archive.LoadValue(val); - properties.valueMap[key] = val; - } - break; - default: - SKY_UNEXPECTED; - } - } - } - - void SaveProperties(BinaryOutputArchive &archive, const MaterialProperties &properties) { - archive.SaveValue(static_cast(properties.images.size())); - for (const auto &image: properties.images) { - archive.SaveValue(image); - } - - archive.SaveValue(static_cast(properties.valueMap.size())); - for (const auto &[key, value]: properties.valueMap) { - archive.SaveValue(key); - - std::visit(Overloaded{ - [&archive](const MaterialTexture &v) { - archive.SaveValue(MaterialValueType::TEXTURE); - archive.SaveValue(v.texIndex); - }, - [&archive](const Vector2 &v) { - archive.SaveValue(MaterialValueType::VEC2); - archive.SaveValue(reinterpret_cast(&v), sizeof(Vector2)); - }, - [&archive](const Vector3 &v) { - archive.SaveValue(MaterialValueType::VEC3); - archive.SaveValue(reinterpret_cast(&v), sizeof(Vector3)); - }, - [&archive](const Vector4 &v) { - archive.SaveValue(MaterialValueType::VEC4); - archive.SaveValue(reinterpret_cast(&v), sizeof(Vector4)); - }, - [&archive](const float &v) { - archive.SaveValue(MaterialValueType::FLOAT); - archive.SaveValue(v); - }, - [&archive](const uint32_t &v) { - archive.SaveValue(MaterialValueType::U32); - archive.SaveValue(v); - }, - [&archive](const int32_t &v) { - archive.SaveValue(MaterialValueType::I32); - archive.SaveValue(v); - }, - }, value); - } - } - - void MaterialAssetData::LoadBin(BinaryInputArchive &archive) - { - uint32_t size = 0; - archive.LoadValue(size); - techniques.resize(size); - for (uint32_t i = 0; i < size; ++i) { - archive.LoadValue(techniques[i]); - } - - LoadProperties(archive, defaultProperties); - } - - void MaterialAssetData::SaveBin(BinaryOutputArchive &archive) const - { - archive.SaveValue(static_cast(techniques.size())); - for (const auto &tech :techniques) { - archive.SaveValue(tech); - } - SaveProperties(archive, defaultProperties); - } - - void MaterialInstanceData::LoadBin(BinaryInputArchive &archive) - { - auto *am = AssetManager::Get(); - archive.LoadValue(material); - LoadProperties(archive, properties); - } - - void MaterialInstanceData::SaveBin(BinaryOutputArchive &archive) const - { - archive.SaveValue(material); - SaveProperties(archive, properties); - } - - std::shared_ptr CreateMaterial(const MaterialAssetData &data) - { - auto *am = AssetManager::Get(); - - auto mat = std::make_shared(); - for (const auto &tech : data.techniques) { - mat->AddTechnique(am->LoadAsset(tech)->CreateInstanceAs()); - } - return mat; - } - - std::shared_ptr CreateMaterialInstance(const MaterialInstanceData &data) - { - auto *am = AssetManager::Get(); - - auto mi = std::make_shared(); - mi->SetMaterial(am->LoadAsset(data.material)->CreateInstance()); - for (const auto &[key, val] : data.properties.valueMap) { - std::visit(Overloaded{ - [&mi, &data, &am, key_ = key](const MaterialTexture &v) { - auto imageAsset = am->LoadAsset(data.properties.images[v.texIndex]); - mi->SetTexture(key_, imageAsset->CreateInstance(), 0); - }, - [&mi, key_ = key](const auto &v) { - mi->SetValue(key_, reinterpret_cast(&v), sizeof(decltype(v))); - } - }, val); - } - mi->Upload(); - return mi; - } -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/assets/MeshAsset.cpp b/render/adaptor/src/assets/MeshAsset.cpp deleted file mode 100644 index 8416589a..00000000 --- a/render/adaptor/src/assets/MeshAsset.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created by Zach Lee on 2023/2/26. -// - -#include -#include -#include -#include - -namespace sky { - void MeshAssetData::Load(BinaryInputArchive &archive) - { - auto *am = AssetManager::Get(); - uint32_t size = 0; - archive.LoadValue(size); - subMeshes.resize(size); - for (uint32_t i = 0; i < size; ++i) { - archive.LoadValue(reinterpret_cast(&subMeshes[i]), sizeof(SubMeshAssetData)); - } - archive.LoadValue(size); - vertexBuffers.resize(size); - for (uint32_t i = 0; i < size; ++i){ - archive.LoadValue(reinterpret_cast(&vertexBuffers[i]), sizeof(BufferViewData)); - } - archive.LoadValue(reinterpret_cast(&indexBuffer), sizeof(BufferViewData)); - archive.LoadValue(indexType); - archive.LoadValue(size); - vertexDescriptions.resize(size); - for (uint32_t i = 0; i < size; ++i) { - archive.LoadValue(vertexDescriptions[i]); - } - } - - void MeshAssetData::Save(BinaryOutputArchive &archive) const - { - archive.SaveValue(static_cast(subMeshes.size())); - for (const auto &subMesh : subMeshes) { - archive.SaveValue(reinterpret_cast(&subMesh), sizeof(SubMeshAssetData)); - } - - archive.SaveValue(static_cast(vertexBuffers.size())); - for (const auto &vtx : vertexBuffers) { - archive.SaveValue(reinterpret_cast(&vtx), sizeof(BufferViewData)); - } - archive.SaveValue(reinterpret_cast(&indexBuffer), sizeof(BufferViewData)); - archive.SaveValue(indexType); - archive.SaveValue(static_cast(vertexDescriptions.size())); - for (const auto &vtx : vertexDescriptions) { - archive.SaveValue(vtx); - } - } - - std::shared_ptr CreateMesh(const MeshAssetData &data) - { - auto mesh = std::make_shared(); - - auto *am = AssetManager::Get(); - auto *queue = RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER); - rhi::TransferTaskHandle handle = 0; - for (const auto &vb : data.vertexBuffers) { - auto bufferPath = am->GetAssetPath(vb.buffer); - auto buffer = std::make_shared(); - buffer->Init(vb.size, rhi::BufferUsageFlagBit::VERTEX | rhi::BufferUsageFlagBit::TRANSFER_DST, rhi::MemoryType::GPU_ONLY); - handle = buffer->Upload(bufferPath, *queue, sizeof(BufferAssetHeader) + vb.offset); - mesh->AddVertexBuffer(buffer); - } - - if (data.indexBuffer.buffer) { - auto bufferPath = am->GetAssetPath(data.indexBuffer.buffer); - auto buffer = std::make_shared(); - buffer->Init(data.indexBuffer.size, rhi::BufferUsageFlagBit::INDEX | rhi::BufferUsageFlagBit::TRANSFER_DST, rhi::MemoryType::GPU_ONLY); - handle = buffer->Upload(bufferPath, *queue, sizeof(BufferAssetHeader) + data.indexBuffer.offset); - mesh->SetIndexBuffer(buffer); - } - mesh->SetIndexType(data.indexType); - - for (const auto &sub : data.subMeshes) { - auto mat = am->LoadAsset(sub.material)->CreateInstance(); - - mesh->AddSubMesh(SubMesh { - sub.firstVertex, - sub.vertexCount, - sub.firstIndex, - sub.indexCount, - mat, - sub.aabb - }); - } - queue->Wait(handle); - - return mesh; - } - -} \ No newline at end of file diff --git a/render/adaptor/src/assets/RenderPrefab.cpp b/render/adaptor/src/assets/RenderPrefab.cpp deleted file mode 100644 index ed755e0f..00000000 --- a/render/adaptor/src/assets/RenderPrefab.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// Created by Zach Lee on 2023/2/26. -// - -#include - -namespace sky { - void RenderPrefabAssetData::Load(BinaryInputArchive &archive) - { - uint32_t size = 0; - archive.LoadValue(size); - nodes.resize(size); - for (uint32_t i = 0; i < size; ++i) { - auto &node = nodes[i]; - archive.LoadValue(reinterpret_cast(&node.mesh), sizeof(Uuid)); - archive.LoadValue(node.parentIndex); - archive.LoadValue(reinterpret_cast(&node.localMatrix), sizeof(Matrix4)); - } - } - - void RenderPrefabAssetData::Save(BinaryOutputArchive &archive) const - { - archive.SaveValue(static_cast(nodes.size())); - for (const auto &node : nodes) { - archive.SaveValue(reinterpret_cast(&node.mesh), sizeof(Uuid)); - archive.SaveValue(node.parentIndex); - archive.SaveValue(reinterpret_cast(&node.localMatrix), sizeof(Matrix4)); - } - } -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/assets/VertexDescLibraryAsset.cpp b/render/adaptor/src/assets/VertexDescLibraryAsset.cpp deleted file mode 100644 index 515a9396..00000000 --- a/render/adaptor/src/assets/VertexDescLibraryAsset.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include -#include -#include - -namespace sky { - - void VertexDescLibraryAssetData::Load(BinaryInputArchive &archive) - { - uint32_t descCount = 0; - archive.LoadValue(descCount); - for (uint32_t i = 0; i < descCount; ++i) { - std::string key; - archive.LoadValue(key); - uint32_t count = 0; - - auto &desc = descriptions[key]; - archive.LoadValue(count); - desc.attributes.resize(count); - for (uint32_t j = 0; j < count; ++j) { - auto &attribute = desc.attributes[j]; - archive.LoadValue(attribute.binding); - archive.LoadValue(attribute.offset); - archive.LoadValue(attribute.location); - archive.LoadValue(attribute.format); - } - archive.LoadValue(count); - desc.bindings.resize(count); - for (uint32_t j = 0; j < count; ++j) { - auto &binding = desc.bindings[j]; - archive.LoadValue(binding.binding); - archive.LoadValue(binding.stride); - archive.LoadValue(binding.inputRate); - } - } - } - - void VertexDescLibraryAssetData::Save(BinaryOutputArchive &archive) const - { - archive.SaveValue(static_cast(descriptions.size())); - for (const auto &[key, desc] : descriptions) { - archive.SaveValue(key); - archive.SaveValue(static_cast(desc.attributes.size())); - for (const auto &attribute : desc.attributes) { - archive.SaveValue(attribute.binding); - archive.SaveValue(attribute.offset); - archive.SaveValue(attribute.location); - archive.SaveValue(attribute.format); - } - archive.SaveValue(static_cast(desc.bindings.size())); - for (const auto &binding : desc.bindings) { - archive.SaveValue(binding.binding); - archive.SaveValue(binding.stride); - archive.SaveValue(binding.inputRate); - } - } - } - - VertexDescLibrary *CreateVertexDescLibrary(const VertexDescLibraryAssetData &data) - { - auto *vtxLib = new VertexDescLibrary(); - auto *device = RHI::Get()->GetDevice(); - for (const auto &[key, desc] : data.descriptions) { - vtxLib->RegisterVertexDesc(key, device->CreateVertexInput(desc)); - } - return vtxLib; - } -} // namespace sky diff --git a/render/adaptor/src/components/CameraComponent.cpp b/render/adaptor/src/components/CameraComponent.cpp deleted file mode 100644 index 49f11849..00000000 --- a/render/adaptor/src/components/CameraComponent.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// Created by Zach Lee on 2021/12/1. -// - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace sky { - - void CameraComponent::Reflect() - { - SerializationContext::Get() - ->Register("ProjectType")() - .Property(ProjectType::PROJECTIVE, std::string("PROJECTIVE")) - .Property(ProjectType::ORTHOGONAL, std::string("ORTHOGONAL")); - - SerializationContext::Get() - ->Register(NAME) - .Member<&CameraComponent::near>("near") - .Member<&CameraComponent::far>("far") - .Member<&CameraComponent::fov>("fov") - .Member<&CameraComponent::aspect>("aspect") - .Member<&CameraComponent::type>("projectType") - .Property(UI_PROP_VISIBLE, false); - - ComponentFactory::Get()->RegisterComponent(); - } - - void CameraComponent::Perspective(float near_, float far_, float fov_) - { - near = near_; - far = far_; - fov = fov_; - type = ProjectType::PROJECTIVE; - } - - void CameraComponent::Otho(float height) - { - othoH = height; - type = ProjectType::ORTHOGONAL; - } - - void CameraComponent::SetAspect(uint32_t width, uint32_t height) - { - aspect = static_cast(width) / static_cast(height); - } - - void CameraComponent::OnTick(float time) - { - auto *transform = object->GetComponent(); - sceneView->SetMatrix(transform->GetWorld().ToMatrix()); - if (type == ProjectType::PROJECTIVE) { - sceneView->SetProjective(near, far, fov, aspect); - } - } - - void CameraComponent::OnActive() - { - sceneView = GetRenderSceneFromGameObject(object)->CreateSceneView(1); - } - - void CameraComponent::OnDestroy() - { - GetRenderSceneFromGameObject(object)->RemoveSceneView(sceneView); - } - - void CameraComponent::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.SaveValueObject(std::string("near"), near); - ar.SaveValueObject(std::string("far"), far); - ar.SaveValueObject(std::string("fov"), fov); - ar.SaveValueObject(std::string("aspect"), aspect); - ar.SaveValueObject(std::string("othoH"), othoH); - ar.SaveValueObject(std::string("type"), type); - ar.EndObject(); - } - - void CameraComponent::Load(JsonInputArchive &ar) - { - ar.LoadKeyValue("near", near); - ar.LoadKeyValue("far", far); - ar.LoadKeyValue("fov", fov); - ar.LoadKeyValue("aspect", aspect); - ar.LoadKeyValue("othoH", othoH); - ar.LoadKeyValue("type", type); - } -} // namespace sky diff --git a/render/adaptor/src/components/LightComponent.cpp b/render/adaptor/src/components/LightComponent.cpp deleted file mode 100644 index 141cf3ef..00000000 --- a/render/adaptor/src/components/LightComponent.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2023/2/28. -// - -#include -#include -#include - -namespace sky { - - void LightComponent::Reflect() - { - SerializationContext::Get() - ->Register(NAME) - .Member<&LightComponent::lightColor>("lightColor"); - - ComponentFactory::Get()->RegisterComponent(); - } - - void LightComponent::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.SaveValueObject(std::string("lightColor"), lightColor); - ar.EndObject(); - } - - void LightComponent::Load(JsonInputArchive &ar) - { - ar.LoadKeyValue("lightColor", lightColor); - } - - -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/components/MeshRenderer.cpp b/render/adaptor/src/components/MeshRenderer.cpp deleted file mode 100644 index 714beca3..00000000 --- a/render/adaptor/src/components/MeshRenderer.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// -// Created by Zach Lee on 2023/2/28. -// - -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - - void MeshRenderer::Reflect() - { - SerializationContext::Get() - ->Register(NAME) - .Member<&MeshRenderer::isStatic>("static") - .Member<&MeshRenderer::castShadow>("castShadow") - .Member<&MeshRenderer::receiveShadow>("receiveShadow"); - - ComponentFactory::Get()->RegisterComponent(); - } - - void MeshRenderer::Save(JsonOutputArchive &ar) const - { - ar.StartObject(); - ar.SaveValueObject(std::string("static"), isStatic); - ar.SaveValueObject(std::string("castShadow"), castShadow); - ar.SaveValueObject(std::string("receiveShadow"), receiveShadow); - ar.SaveValueObject(std::string("mesh"), meshAsset ? meshAsset->GetUuid() : Uuid()); - ar.EndObject(); - } - - void MeshRenderer::Load(JsonInputArchive &ar) - { - ar.LoadKeyValue("static", isStatic); - ar.LoadKeyValue("castShadow", castShadow); - ar.LoadKeyValue("receiveShadow", receiveShadow); - Uuid uuid; - ar.LoadKeyValue("mesh", uuid); -// meshAsset = AssetManager::Get()->LoadAsset(uuid); - ResetMesh(); - } - - void MeshRenderer::SetMesh(const MeshAssetPtr &mesh_) - { - meshAsset = mesh_; - meshInstance = meshAsset->CreateInstance(); - ResetMesh(); - } - - void MeshRenderer::SetMesh(const RDMeshPtr &mesh) - { - meshInstance = mesh; - ResetMesh(); - } - - void MeshRenderer::ResetMesh() - { - if (renderer == nullptr) { - auto *mf = GetFeatureProcessor(GetRenderSceneFromGameObject(object)); - renderer = mf->CreateStaticMesh(); - } - renderer->SetMesh(meshInstance); - } - - void MeshRenderer::OnActive() - { - } - - void MeshRenderer::OnDestroy() - { - GetFeatureProcessor(GetRenderSceneFromGameObject(object))->RemoveStaticMesh(renderer); - } - - void MeshRenderer::OnTick(float time) - { - if (renderer != nullptr) { - auto *ts = object->GetComponent(); - renderer->UpdateTransform(ts->GetWorld().ToMatrix()); - } - } -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/components/ParticleSystemComponent.cpp b/render/adaptor/src/components/ParticleSystemComponent.cpp deleted file mode 100644 index 6901a4e6..00000000 --- a/render/adaptor/src/components/ParticleSystemComponent.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Created by Zach Lee on 2023/9/17. -// - -#include -#include -#include -#include - -namespace sky { - - void ParticleSystemComponent::OnTick(float time) - { - if (particleSystem != nullptr) { - particleSystem->Tick(time); - } - } - - void ParticleSystemComponent::OnActive() - { - // todo: data driven. - if (particleSystem == nullptr) { - auto *pf = GetFeatureProcessor(GetRenderSceneFromGameObject(object)); - particleSystem = pf->CreateParticleSystem(); - - auto *emitter = particleSystem->AddEmitter(); - emitter->RegisterPerParticleComponent(); - emitter->RegisterPerParticleComponent(); - - emitter->AddSpawnModule(ParticleSpawnSimple{10.f}); - emitter->AddInitModule(ParticleInitAlignedBox{VEC3_ZERO, VEC3_ONE}); - emitter->AddSolverModule(ParticlePositionSolver{}); - } - } - - void ParticleSystemComponent::OnDestroy() - { - - } -} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/pipeline/DefaultForward.cpp b/render/adaptor/src/pipeline/DefaultForward.cpp deleted file mode 100644 index ae1a4643..00000000 --- a/render/adaptor/src/pipeline/DefaultForward.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// Created by Zach Lee on 2023/8/20. -// - -#include "render/RenderScene.h" -#include "render/RenderWindow.h" -#include "render/rdg/RenderGraph.h" -#include - -namespace sky { - - void DefaultForward::SetOutput(RenderWindow *wnd) - { - output = wnd; - if (!rdgContext->device->CheckFormatFeature(depthStencilFormat, rhi::PixelFormatFeatureFlagBit::DEPTH_STENCIL)) { - depthStencilFormat = rhi::PixelFormat::D32_S8; - } - - rhi::DescriptorSetLayout::Descriptor desc = {}; - desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::UNIFORM_BUFFER, 1, 0, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS, "passInfo"}); - desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::UNIFORM_BUFFER, 1, 1, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS, "viewInfo"}); - - forwardLayout = std::make_shared(); - forwardLayout->SetRHILayout(rdgContext->device->CreateDescriptorSetLayout(desc)); - forwardLayout->AddNameHandler("passInfo", {0, sizeof(ShaderPassInfo)}); - forwardLayout->AddNameHandler("viewInfo", {1, sizeof(SceneViewInfo)}); - } - - void DefaultForward::OnSetup(rdg::RenderGraph &rdg) - { - const auto &swapchain = output->GetSwaChain(); - const auto &ext = swapchain->GetExtent(); - const auto width = ext.width; - const auto height = ext.height; - - auto &rg = rdg.resourceGraph; - - const auto &views = rdg.scene->GetSceneViews(); - if (views.empty()) { - return; - } - auto *sceneView = views[0].get(); - const auto uboName = GetDefaultSceneViewUBOName(*sceneView); - rg.ImportUBO(uboName.c_str(), sceneView->GetUBO()); - - rg.ImportSwapChain("ForwardColor", swapchain); - rg.AddImage("ForwardDepthStencil", rdg::GraphImage{{width, height, 1}, 1, 1, depthStencilFormat, rhi::ImageUsageFlagBit::DEPTH_STENCIL | rhi::ImageUsageFlagBit::SAMPLED}); - - auto forwardPass = rdg.AddRasterPass("forwardColor", width, height) - .AddAttachment({"ForwardColor", rhi::LoadOp::CLEAR, rhi::StoreOp::STORE}, rhi::ClearValue(0.2f, 0.2f, 0.2f, 1.f)) - .AddAttachment({"ForwardDepthStencil", rhi::LoadOp::CLEAR, rhi::StoreOp::DONT_CARE}, rhi::ClearValue(1.f, 0)); - - auto sub = forwardPass.AddRasterSubPass("color0_sub0") - .AddColor("ForwardColor", rdg::ResourceAccessBit::WRITE) - .AddDepthStencil("ForwardDepthStencil", rdg::ResourceAccessBit::WRITE) - .AddComputeView(uboName, {"viewInfo", rdg::ComputeType::CBV, rhi::ShaderStageFlagBit::VS}); - - sub.AddQueue("queue1") - .SetRasterID("ForwardColor") - .SetView(sceneView) - .SetLayout(forwardLayout); - - sub.AddQueue("ui") - .SetRasterID("ui"); - - rdg.AddPresentPass("present", "ForwardColor"); - } - -} // namespace sky diff --git a/render/backend/dx12/include/dx12/BufferView.h b/render/backend/dx12/include/dx12/BufferView.h deleted file mode 100644 index 4261307b..00000000 --- a/render/backend/dx12/include/dx12/BufferView.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#pragma once - -#include -#include -#include - -namespace sky::dx { - - class BufferView : public rhi::BufferView, public DevObject { - public: - explicit BufferView(Device &dev); - ~BufferView() override; - - std::shared_ptr CreateView(const rhi::BufferViewDesc &) const override; - - private: - BufferPtr source; - }; - -} // namespace sky::dx \ No newline at end of file diff --git a/render/backend/dx12/src/BufferView.cpp b/render/backend/dx12/src/BufferView.cpp deleted file mode 100644 index 94ceaffc..00000000 --- a/render/backend/dx12/src/BufferView.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#include - -namespace sky::dx { - - BufferView::BufferView(Device &dev) : DevObject(dev) - { - } - - BufferView::~BufferView() = default; - - std::shared_ptr BufferView::CreateView(const rhi::BufferViewDesc &desc) const - { - return source->CreateView(desc); - } -} \ No newline at end of file diff --git a/render/backend/rhi/include/rhi/BufferView.h b/render/backend/rhi/include/rhi/BufferView.h deleted file mode 100644 index c3a7b73d..00000000 --- a/render/backend/rhi/include/rhi/BufferView.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by Zach Lee on 2022/11/13. -// - -#pragma once - -#include -#include - -namespace sky::rhi { - - class BufferView { - public: - BufferView() = default; - ~BufferView() = default; - - const BufferViewDesc &GetViewDesc() const { return viewDesc; } - - virtual std::shared_ptr CreateView(const BufferViewDesc &) const = 0; - - protected: - BufferViewDesc viewDesc; - }; - using BufferViewPtr = std::shared_ptr; -} \ No newline at end of file diff --git a/render/backend/rhi/include/rhi/Stream.h b/render/backend/rhi/include/rhi/Stream.h deleted file mode 100644 index 0cf21ca2..00000000 --- a/render/backend/rhi/include/rhi/Stream.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by Zach Lee on 2023/9/12. -// - -#pragma once - -#include -#include -#include - -namespace sky::rhi { - - class FileStream : public IStream { - public: - explicit FileStream(const std::string &path, uint32_t baseOffset); - ~FileStream() override = default; - - const uint8_t *GetData(uint64_t offset) override; - void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; - - private: - std::ifstream stream; - uint32_t baseOffset; - std::unique_ptr hostData; - }; - - class RawPtrStream : public IStream { - public: - explicit RawPtrStream(const uint8_t *ptr) : data(ptr) {} - ~RawPtrStream() override = default; - - const uint8_t *GetData(uint64_t offset) override; - void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; - - private: - const uint8_t *data; - }; - -} // namespace sky::rhi \ No newline at end of file diff --git a/render/backend/rhi/src/Stream.cpp b/render/backend/rhi/src/Stream.cpp deleted file mode 100644 index 4b022feb..00000000 --- a/render/backend/rhi/src/Stream.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// Created by Zach Lee on 2023/9/12. -// - -#include - -namespace sky::rhi { - - FileStream::FileStream(const std::string &path, uint32_t offset) : stream(path, std::ios::binary), baseOffset(offset) - { - } - - const uint8_t *FileStream::GetData(uint64_t offset) - { - if (!stream.is_open()) { - return nullptr; - } - - if (!hostData) { - auto fileSize = stream.tellg(); - hostData.reset(new uint8_t[stream.tellg()]); - stream.seekg(static_cast(baseOffset + offset), std::ios::beg); - stream.read((char *)hostData.get(), fileSize); - stream.close(); - } - - return hostData.get() + offset; - } - - void FileStream::ReadData(uint64_t offset, uint64_t size, uint8_t *out) - { - if (!stream.is_open()) { - return; - } - - stream.seekg(static_cast(baseOffset + offset), std::ios::beg); - stream.read(reinterpret_cast(out), static_cast(size)); - } - - const uint8_t *RawPtrStream::GetData(uint64_t offset) - { - return data + offset; - } - - void RawPtrStream::ReadData(uint64_t offset, uint64_t size, uint8_t *out) - { - memcpy(out, data + offset, size); - } -} // namespace sky::rhi \ No newline at end of file diff --git a/render/backend/vulkan/include/vulkan/BufferView.h b/render/backend/vulkan/include/vulkan/BufferView.h deleted file mode 100644 index 6656c798..00000000 --- a/render/backend/vulkan/include/vulkan/BufferView.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2022/10/14. -// - -#pragma once -#include -#include -#include -#include - -namespace sky::vk { - class Device; - class Image; - - class BufferView : public rhi::BufferView, public DevObject { - public: - explicit BufferView(Device &); - ~BufferView() override = default; - - std::shared_ptr CreateView(const rhi::BufferViewDesc &) const override; - - const BufferPtr &GetBuffer() const { return source; } - - private: - friend class Buffer; - - bool Init(const rhi::BufferViewDesc &); - - BufferPtr source; - }; - - using BufferViewPtr = std::shared_ptr; -} // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/VertexAssembly.h b/render/backend/vulkan/include/vulkan/VertexAssembly.h deleted file mode 100644 index 65d1b346..00000000 --- a/render/backend/vulkan/include/vulkan/VertexAssembly.h +++ /dev/null @@ -1,50 +0,0 @@ -// -// Created by Zach Lee on 2022/7/31. -// - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace sky::vk { - class Device; - - class VertexAssembly : public rhi::VertexAssembly, public DevObject { - public: - VertexAssembly(Device &dev) : DevObject(dev) {} - ~VertexAssembly() = default; - - void SetVertexInput(VertexInputPtr input); - - void ResetVertexBuffer(); - - void AddVertexBuffer(const BufferViewPtr &buffer); - - void SetIndexBuffer(const BufferViewPtr &buffer); - - void SetIndexType(VkIndexType); - - void OnBind(VkCommandBuffer) const; - - bool IsIndexed() const; - - private: - friend class Device; - bool Init(const Descriptor &desc); - - VertexInputPtr vertexInput; - std::vector vertexBuffers; - std::vector vkBuffers; - std::vector offsets; - BufferViewPtr indexBuffer; - VkDeviceSize indexOffset = 0; - VkIndexType indexType = VK_INDEX_TYPE_UINT32; - }; - using VertexAssemblyPtr = std::shared_ptr; - -} // namespace sky::vk diff --git a/render/backend/vulkan/src/BufferView.cpp b/render/backend/vulkan/src/BufferView.cpp deleted file mode 100644 index bbf571cf..00000000 --- a/render/backend/vulkan/src/BufferView.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zach Lee on 2022/10/14. -// - -#include -#include -#include -#include - -static const char *TAG = "Vulkan"; - -namespace sky::vk { - - BufferView::BufferView(Device &dev) : DevObject(dev) - { - } - - bool BufferView::Init(const rhi::BufferViewDesc &des) - { - viewDesc = des; - return true; - } - - std::shared_ptr BufferView::CreateView(const rhi::BufferViewDesc &desc) const - { - return source->CreateView(desc); - } -} diff --git a/render/backend/vulkan/src/VertexAssembly.cpp b/render/backend/vulkan/src/VertexAssembly.cpp deleted file mode 100644 index 240f5c7c..00000000 --- a/render/backend/vulkan/src/VertexAssembly.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Created by Zach Lee on 2022/7/31. -// - -#include -#include - -namespace sky::vk { - - void VertexAssembly::SetVertexInput(VertexInputPtr input) - { - vertexInput = input; - } - - void VertexAssembly::ResetVertexBuffer() - { - vertexBuffers.clear(); - vkBuffers.clear(); - offsets.clear(); - } - - void VertexAssembly::AddVertexBuffer(const BufferViewPtr &buffer) - { - vertexBuffers.emplace_back(buffer); - vkBuffers.emplace_back(buffer->GetBuffer()->GetNativeHandle()); - offsets.emplace_back(buffer->GetViewDesc().offset); - } - - void VertexAssembly::SetIndexBuffer(const BufferViewPtr &buffer) - { - indexBuffer = buffer; - indexOffset = buffer ? buffer->GetViewDesc().offset : 0; - } - - void VertexAssembly::SetIndexType(VkIndexType type) - { - indexType = type; - } - - void VertexAssembly::OnBind(VkCommandBuffer cmd) const - { - if (!vkBuffers.empty()) { - vkCmdBindVertexBuffers(cmd, 0, static_cast(vkBuffers.size()), vkBuffers.data(), offsets.data()); - } - if (indexBuffer) { - vkCmdBindIndexBuffer(cmd, indexBuffer->GetBuffer()->GetNativeHandle(), indexOffset, indexType); - } - } - - bool VertexAssembly::IsIndexed() const - { - return !!indexBuffer; - } - - bool VertexAssembly::Init(const Descriptor &desc) - { - ResetVertexBuffer(); - SetVertexInput(std::static_pointer_cast(desc.vertexInput)); - for (auto &vb : desc.vertexBuffers) { - AddVertexBuffer(std::static_pointer_cast(vb)); - } - SetIndexBuffer(std::static_pointer_cast(desc.indexBuffer)); - SetIndexType(FromRHI(desc.indexType)); - return true; - } - -} // namespace sky::vk diff --git a/render/builder/module/BuilderModule.cpp b/render/builder/module/BuilderModule.cpp deleted file mode 100644 index f05e3a79..00000000 --- a/render/builder/module/BuilderModule.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// Created by Zach Lee on 2023/2/20. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky::builder { - - class BuilderModule : public IModule { - public: - BuilderModule() = default; - ~BuilderModule() override = default; - - bool Init(const StartArguments &args) override; - void Tick(float delta) override {} - }; - - bool BuilderModule::Init(const StartArguments &args) - { - auto *serializationContext = SerializationContext::Get(); - ReflectRenderAsset(serializationContext); - ReflectRHI(serializationContext); - - auto *am = AssetManager::Get(); - am->RegisterBuilder(new ShaderBuilder()); - am->RegisterBuilder(new TechniqueBuilder()); - am->RegisterBuilder(new MaterialBuilder()); - am->RegisterBuilder(new VertexLibraryBuilder()); - am->RegisterBuilder(new ImageBuilder()); - am->RegisterBuilder(new PrefabBuilder()); - - - // init shader compiler - auto *compiler = ShaderCompiler::Get(); - for (const auto &path : am->GetSearchPathList()) { - compiler->AddSearchPath(path.path); - } - return true; - } -} -REGISTER_MODULE(sky::builder::BuilderModule) diff --git a/render/builder/render/include/builder/render/ImageBuilder.h b/render/builder/render/include/builder/render/ImageBuilder.h deleted file mode 100644 index c4ac2a22..00000000 --- a/render/builder/render/include/builder/render/ImageBuilder.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by Zach Lee on 2023/2/26. -// - -#pragma once - -#include -#include - -namespace sky::builder { - class ImageBuilder : public AssetBuilder { - public: - ImageBuilder(); - ~ImageBuilder() override = default; - - static constexpr std::string_view KEY = "GFX_IMAGE"; - - void Request(const BuildRequest &build, BuildResult &result) override; - - const std::vector &GetExtensions() const override { return extensions; } - - void UseCompress(bool en) { compress = en; } - private: - void RequestDDS(const BuildRequest &build, BuildResult &result); - void RequestSTB(const BuildRequest &build, BuildResult &result); - - std::vector extensions = {".jpg", ".dds", ".ktx"}; - - bool compress = false; - }; -} diff --git a/render/builder/render/include/builder/render/MaterialBuilder.h b/render/builder/render/include/builder/render/MaterialBuilder.h deleted file mode 100644 index 0e2613bc..00000000 --- a/render/builder/render/include/builder/render/MaterialBuilder.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Created by Zach Lee on 2023/2/23. -// - -#pragma once - -#include -#include - -namespace sky::builder { - - class MaterialBuilder : public AssetBuilder { - public: - MaterialBuilder() = default; - ~MaterialBuilder() override = default; - - static constexpr std::string_view KEY = "GFX_MATERIAL"; - - void Request(const BuildRequest &build, BuildResult &result) override; - - const std::vector &GetExtensions() const override { return extensions; } - - private: - void BuildMaterial(const BuildRequest &build, BuildResult &result); - void BuildMaterialInstance(const BuildRequest &build, BuildResult &result); - - std::vector extensions = {".mat", ".mati"}; - }; - -} diff --git a/render/builder/render/include/builder/render/VertexLibraryBuilder.h b/render/builder/render/include/builder/render/VertexLibraryBuilder.h deleted file mode 100644 index 81ff7833..00000000 --- a/render/builder/render/include/builder/render/VertexLibraryBuilder.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#pragma once - -#include -#include - -namespace sky::builder { - class VertexLibraryBuilder : public AssetBuilder { - public: - VertexLibraryBuilder() = default; - ~VertexLibraryBuilder() = default; - - static constexpr std::string_view KEY = "GFX_VLIB"; - - void Request(const BuildRequest &request, BuildResult &result) override; - const std::vector &GetExtensions() const override { return extensions; } - - private: - std::vector extensions = {".vtxlib"}; - }; -} // sky::builder diff --git a/render/builder/render/src/ImageBuilder.cpp b/render/builder/render/src/ImageBuilder.cpp deleted file mode 100644 index 9899fbc1..00000000 --- a/render/builder/render/src/ImageBuilder.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// -// Created by Zach Lee on 2023/2/26. -// - -#include -#include -#include -#include -#include -#include -#include -#include - -#define STB_IMAGE_IMPLEMENTATION -#include -#include - -namespace sky::builder { - - Uuid CreateBufferID(const Uuid &imageId) - { - uint32_t seed = 0; - HashCombine32(seed, imageId.u32[0]); - HashCombine32(seed, imageId.u32[1]); - HashCombine32(seed, imageId.u32[2]); - HashCombine32(seed, imageId.u32[3]); - return Uuid::CreateWithSeed(seed); - } - - ImageBuilder::ImageBuilder() - { - InitializeCompressor(); - } - - void ImageBuilder::RequestDDS(const BuildRequest &request, BuildResult &result) - { - std::vector data; - ReadBin(request.fullPath, data); - - rhi::Image::Descriptor imageDesc = {}; - uint32_t offset = rhi::ProcessDDSHeader(data.data(), data.size(), imageDesc); - - auto asset = AssetManager::Get()->CreateAsset(request.uuid); - auto &imageData = asset->Data(); - - imageData.format = imageDesc.format; - imageData.width = imageDesc.extent.width; - imageData.height = imageDesc.extent.height; - imageData.depth = imageDesc.extent.depth; - imageData.arrayLayers = imageDesc.arrayLayers; - imageData.mipLevels = imageDesc.mipLevels; - imageData.type = imageData.arrayLayers == 6 ? TextureType::TEXTURE_CUBE : TextureType::TEXTURE_2D; - imageData.dataSize = static_cast(data.size() - offset); - imageData.bufferID = CreateBufferID(request.uuid); - - auto buffer = AssetManager::Get()->CreateAsset(imageData.bufferID); - auto &bufferData = buffer->Data(); - bufferData.rawData.resize(imageData.dataSize); - - memcpy(bufferData.rawData.data(), data.data() + offset, imageData.dataSize); - - result.products.emplace_back(BuildProduct{KEY.data(), asset}); - result.products.emplace_back(BuildProduct{"GFX_BUFFER", buffer}); - result.success = true; - } - - void ImageBuilder::RequestSTB(const BuildRequest &request, BuildResult &result) - { - int x; - int y; - int n; - int request_comp = compress ? 0 : 4; - - unsigned char *data = nullptr; - if (request.rawData != nullptr) { - data = stbi_load_from_memory(static_cast(request.rawData), request.dataSize, &x, &y, &n, request_comp); - } else { - data = stbi_load(request.fullPath.c_str(), &x, &y, &n, request_comp); - } - if (data == nullptr) { - return; - } - auto *am = AssetManager::Get(); - - auto asset = am->CreateAsset(request.uuid); - auto &imageData = asset->Data(); - imageData.width = static_cast(x); - imageData.height = static_cast(y); - imageData.type = TextureType::TEXTURE_2D; - imageData.bufferID = CreateBufferID(request.uuid); - - auto buffer = AssetManager::Get()->CreateAsset(imageData.bufferID); - auto &bufferData = buffer->Data(); - - BufferImageInfo info = {}; - info.width = imageData.width; - info.height = imageData.height; - info.stride = imageData.width * n; - - if (compress) { - CompressOption option = {}; - option.quality = Quality::SLOW; - option.targetFormat = rhi::PixelFormat::BC7_UNORM_BLOCK; - option.hasAlpha = n == 4; - imageData.format = option.targetFormat; - CompressImage(data, info, bufferData.rawData, option); - - imageData.dataSize = static_cast(bufferData.rawData.size()); - } else { - imageData.format = rhi::PixelFormat::RGBA8_UNORM; - - imageData.dataSize = imageData.width * imageData.height * 4; - bufferData.rawData.resize(imageData.dataSize); - memcpy(bufferData.rawData.data(), data, imageData.dataSize); - } - - result.products.emplace_back(BuildProduct{KEY.data(), asset}); - result.products.emplace_back(BuildProduct{"GFX_BUFFER", buffer}); - result.success = true; - - stbi_image_free(data); - } - - void ImageBuilder::Request(const BuildRequest &request, BuildResult &result) - { - if (request.ext == ".dds") { - RequestDDS(request, result); - } else { - RequestSTB(request, result); - } - } -} diff --git a/render/builder/render/src/MaterialBuilder.cpp b/render/builder/render/src/MaterialBuilder.cpp deleted file mode 100644 index 65cf1588..00000000 --- a/render/builder/render/src/MaterialBuilder.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// Created by Zach Lee on 2023/2/23. -// - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -namespace sky::builder { - - void ProcessProperties(rapidjson::Document &document, MaterialProperties &properties, const BuildRequest &request) - { - if (!document.HasMember("properties")) { - return; - } - auto *am = AssetManager::Get(); - - auto &proValues = document["properties"]; - if (proValues.IsObject()) { - for (auto iter = proValues.MemberBegin(); iter != proValues.MemberEnd(); ++iter) { - auto &obj = iter->value; - - if (obj.IsString()) { - const auto *imagePath = obj.GetString(); - auto texId = am->ImportAsset(imagePath); - am->BuildAsset(texId, request.targetPlatform); - properties.valueMap[iter->name.GetString()] = MaterialTexture{static_cast(properties.images.size())}; - properties.images.emplace_back(texId); - - } else if (obj.IsFloat()) { - properties.valueMap[iter->name.GetString()] = obj.GetFloat(); - } else if (obj.IsBool()) { - properties.valueMap[iter->name.GetString()] = static_cast(obj.GetBool()); - } else if (obj.IsArray()) { - auto array = obj.GetArray(); - float *v = nullptr; - if (array.Size() == 2) { - v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector2{}).first->second).v; - } else if (array.Size() == 3) { - v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector3{}).first->second).v; - } else if (array.Size() == 4) { - v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector4{}).first->second).v; - } - for (auto &val : array) { - (*v) = val.GetFloat(); - ++v; - } - } - } - } - } - - void MaterialBuilder::Request(const BuildRequest &request, BuildResult &result) - { - if (!request.buildKey.empty() && request.buildKey != std::string(KEY)) { - return; - } - - if (request.ext == ".mat") { - BuildMaterial(request, result); - } else if (request.ext == ".mati") { - BuildMaterialInstance(request, result); - } - } - - void MaterialBuilder::BuildMaterialInstance(const BuildRequest &request, BuildResult &result) - { - std::string json; - ReadString(request.fullPath, json); - - rapidjson::Document document; - document.Parse(json.c_str()); - - if (!document.HasMember("material")) { - return; - } - auto *am = AssetManager::Get(); - auto asset = am->CreateAsset(request.uuid); - auto &assetData = asset->Data(); - - auto materialPath = document["material"].GetString(); - assetData.material = am->ImportAsset(materialPath); - am->BuildAsset(assetData.material , request.targetPlatform); - - ProcessProperties(document, assetData.properties, request); - result.products.emplace_back(BuildProduct{KEY.data(), asset, {assetData.material}}); - } - - void MaterialBuilder::BuildMaterial(const BuildRequest &request, BuildResult &result) - { - std::string json; - ReadString(request.fullPath, json); - - rapidjson::Document document; - document.Parse(json.c_str()); - - if (!document.HasMember("techniques")) { - return; - } - - auto *am = AssetManager::Get(); - std::filesystem::path fullPath(request.fullPath); - auto asset = am->CreateAsset(request.uuid); - auto &assetData = asset->Data(); - - std::vector deps; - auto &val = document["techniques"]; - if (val.IsArray()) { - auto techArray = val.GetArray(); - for (auto &tech : techArray) { - if (tech.IsString()) { - const auto *techPath = tech.GetString(); - auto techId = am->ImportAsset(techPath); - am->BuildAsset(techId, request.targetPlatform); - deps.emplace_back(techId); - assetData.techniques.emplace_back(techId); - } - } - } - - ProcessProperties(document, assetData.defaultProperties, request); - result.products.emplace_back(BuildProduct{KEY.data(), asset, deps}); - result.success = true; - } -} diff --git a/render/builder/render/src/PrefabBuilder.cpp b/render/builder/render/src/PrefabBuilder.cpp deleted file mode 100644 index c3b099a2..00000000 --- a/render/builder/render/src/PrefabBuilder.cpp +++ /dev/null @@ -1,432 +0,0 @@ -// -// Created by Zach Lee on 2023/2/20. -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -//#include - -#include -#include - -static const char* TAG = "PrefabBuilder"; - -namespace sky::builder { - - enum class MeshAttributeType : uint32_t { - POSITION = 0, - UV, - NORMAL, - TANGENT, - COLOR, - NUM, - }; - - struct StandardVertexData { - Vector4 normal; - Vector4 tangent; - Vector4 color; - Vector4 uv; - }; - - struct MeshBuildContext { - std::vector position; - std::vector ext; - std::vector indices; - }; - - struct PrefabBuildContext { - std::vector materials; - std::vector meshes; - std::vector buffers; - std::unordered_map textures; - std::vector nodes; - }; - - static inline Matrix4 FromAssimp(const aiMatrix4x4& trans) - { - Matrix4 res; - for (int i = 0; i < 4; ++i) { - for (int j = 0; j < 4; ++j) { - res[i][j] = trans[j][i]; - } - } - return res; - } - - static std::string GetIndexedName(const std::string_view &prefix, const std::string &name, const std::string_view &type, size_t index) - { - std::stringstream ss; - if (!name.empty()) { - ss << prefix << "_" << name << "_" << type; - } else { - ss << prefix << "_" << type << "_" << index; - } - - return ss.str(); - } - - static Uuid ProcessTexture(const aiScene *scene, const aiString& str, PrefabBuildContext &context, const BuildRequest &request) - { - auto *am = AssetManager::Get(); - auto texPath = std::filesystem::path(request.fullPath).parent_path().append(str.C_Str()); - if (std::filesystem::exists(texPath)) { - auto path = texPath.make_preferred().string(); - auto id = am->ImportAndBuildAsset(path); - return id; - } - - const auto *tex = scene->GetEmbeddedTexture(str.C_Str()); - if (tex == nullptr) { - return {}; - } - - BuildRequest textureRequest = {}; - textureRequest.name = request.relativePath + std::string("\\embedded_") + str.C_Str(); - textureRequest.ext = std::string(".") + tex->achFormatHint; - textureRequest.buildKey = ImageBuilder::KEY; - textureRequest.rawData = tex->pcData; - textureRequest.dataSize = tex->mWidth; - textureRequest.name.erase(std::remove(textureRequest.name.begin(), textureRequest.name.end(), '*'), textureRequest.name.end()); - textureRequest.uuid = sky::AssetManager::GetUUIDByPath(textureRequest.name); - - BuildResult result = {}; - am->BuildAsset(textureRequest); - - return textureRequest.uuid; - } - - static MaterialInstanceAssetPtr CreateMaterialInstanceByMaterial(aiMaterial* material, PrefabBuildContext &context, const BuildRequest &request) - { - std::string matName = GetIndexedName(request.relativePath, material->GetName().C_Str(), "mat", context.materials.size()); - - auto *am = AssetManager::Get(); - auto matInstanceId = am->GetUUIDByPath(matName); - auto matInstance = am->CreateAsset(matInstanceId); - - matInstance->Data().material = am->ImportAndBuildAsset("materials/standard_pbr.mat"); - return matInstance; - } - - static void ProcessMaterials(const aiScene *scene, PrefabBuildContext &context, const BuildRequest &request) - { - uint32_t matSize = scene->mNumMaterials; - for (uint32_t i = 0; i < matSize; ++i) { - aiMaterial* material = scene->mMaterials[i]; - aiShadingMode shadingModel = aiShadingMode_Flat; - material->Get(AI_MATKEY_SHADING_MODEL, shadingModel); - - LOG_I(TAG, "shader model %d", shadingModel); - auto matAsset = CreateMaterialInstanceByMaterial(material, context, request); - auto &data = matAsset->Data(); - - aiString str; - bool useAOMap = false; - bool useEmissiveMap = false; - bool useBaseColorMap = false; - bool useNormalMap = false; - bool useMetallicRoughnessMap = false; - bool useMask = false; - Vector4 baseColor = Vector4(1.f, 1.f, 1.f, 1.f); - float metallic = 1.f; - float roughness = 1.f; - Uuid normalMap; - Uuid emissiveMap; - Uuid aoMap; - Uuid baseColorMap; - Uuid metallicRoughnessMap; - - aiString aiAlphaMode; - if (material->Get(AI_MATKEY_GLTF_ALPHAMODE, aiAlphaMode) == 0) { - std::string mode = aiAlphaMode.data; - if (mode == "MASK") { - useMask = true; - } - } - - float alphaCutoff = 0.5f; - material->Get(AI_MATKEY_GLTF_ALPHACUTOFF, alphaCutoff); - - if (material->Get(AI_MATKEY_TEXTURE_NORMALS(0), str) == 0) { - // normalMap - normalMap = ProcessTexture(scene, str, context, request); - useNormalMap = static_cast(normalMap); - } - - if (material->Get(AI_MATKEY_TEXTURE_EMISSIVE(0), str) == 0) { - // emissiveMap - emissiveMap = ProcessTexture(scene, str, context, request); - useEmissiveMap = static_cast(emissiveMap); - } - - if (material->Get(AI_MATKEY_TEXTURE_LIGHTMAP(0), str) == 0) { - // aoMap; - aoMap = ProcessTexture(scene, str, context, request); - useAOMap = static_cast(aoMap); - } - - if (shadingModel == aiShadingMode_PBR_BRDF) { - material->Get(AI_MATKEY_BASE_COLOR, baseColor); - material->Get(AI_MATKEY_METALLIC_FACTOR, metallic); - material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness); - - - if (material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &str) == 0) { - // baseColorMap - baseColorMap = ProcessTexture(scene, str, context, request); - useBaseColorMap = static_cast(baseColorMap); - } - - if (material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &str) == 0) { - // metallicRoughnessMap - metallicRoughnessMap = ProcessTexture(scene, str, context, request); - useMetallicRoughnessMap = static_cast(metallicRoughnessMap); - } - } - - data.properties.valueMap.emplace("useAOMap", static_cast(useAOMap)); - if (useAOMap) { - data.properties.valueMap.emplace("AoMap", MaterialTexture{static_cast(data.properties.images.size())}); - data.properties.images.emplace_back(aoMap); - } - - data.properties.valueMap.emplace("useEmissiveMap", static_cast(useEmissiveMap)); - if (useEmissiveMap) { - data.properties.valueMap.emplace("EmissiveMap", MaterialTexture{static_cast(data.properties.images.size())}); - data.properties.images.emplace_back(emissiveMap); - } - - data.properties.valueMap.emplace("useBaseColorMap", static_cast(useBaseColorMap)); - if (useBaseColorMap) { - data.properties.valueMap.emplace("AlbedoMap", MaterialTexture{static_cast(data.properties.images.size())}); - data.properties.images.emplace_back(baseColorMap); - } - - data.properties.valueMap.emplace("useMetallicRoughnessMap", static_cast(useMetallicRoughnessMap)); - if (useMetallicRoughnessMap) { - data.properties.valueMap.emplace("MetallicRoughnessMap", MaterialTexture{static_cast(data.properties.images.size())}); - data.properties.images.emplace_back(metallicRoughnessMap); - } - - data.properties.valueMap.emplace("useNormalMap", static_cast(useNormalMap)); - if (useNormalMap) { - data.properties.valueMap.emplace("NormalMap", MaterialTexture{static_cast(data.properties.images.size())}); - data.properties.images.emplace_back(normalMap); - } - - data.properties.valueMap.emplace("useMask", static_cast(useMask)); - - data.properties.valueMap.emplace("Albedo", baseColor); - data.properties.valueMap.emplace("Metallic", metallic); - data.properties.valueMap.emplace("Roughness", roughness); - data.properties.valueMap.emplace("AlphaCutoff", alphaCutoff); - - context.materials.emplace_back(matAsset); - } - } - - static void ProcessSubMesh(aiMesh *mesh, const aiScene *scene, PrefabBuildContext& prefabContext, MeshAssetData &meshData, MeshBuildContext &context) - { - uint32_t vertexNum = mesh->mNumVertices; - SubMeshAssetData subMesh = {}; - subMesh.firstVertex = static_cast(context.position.size()); - subMesh.vertexCount = mesh->mNumVertices; - subMesh.firstIndex = static_cast(context.indices.size()); - subMesh.indexCount = mesh->mNumFaces * 3; - subMesh.material = prefabContext.materials[mesh->mMaterialIndex]->GetUuid(); - - context.position.resize(context.position.size() + subMesh.vertexCount); - context.ext.resize(context.position.size() + subMesh.vertexCount); - - subMesh.aabb.min = {mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z}; - subMesh.aabb.max = {mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z}; - - Vector4 *position = &context.position[subMesh.firstVertex]; - StandardVertexData *vtx = &context.ext[subMesh.firstVertex]; - - for (unsigned int i = 0; i < mesh->mNumVertices; i++) { - auto &p = mesh->mVertices[i]; - auto &n = mesh->mNormals[i]; - auto &t = mesh->mTangents[i]; - auto &b = mesh->mBitangents[i]; - - position[i].x = p.x; - position[i].y = p.y; - position[i].z = p.z; - position[i].w = 1.f; - subMesh.aabb.min = Min(subMesh.aabb.min, Vector3(p.x, p.y, p.z)); - subMesh.aabb.max = Max(subMesh.aabb.max, Vector3(p.x, p.y, p.z)); - - vtx[i].normal.x = n.x; - vtx[i].normal.y = n.y; - vtx[i].normal.z = n.z; - vtx[i].normal.w = 1.f; - - vtx[i].tangent.x = t.x; - vtx[i].tangent.y = t.y; - vtx[i].tangent.z = t.z; - vtx[i].tangent.w = 1.f; - - if (mesh->HasVertexColors(0)) { - auto &c = mesh->mColors[0][i]; - vtx[i].color.x = c.r; - vtx[i].color.y = c.g; - vtx[i].color.z = c.b; - vtx[i].color.w = c.a; - } else { - vtx[i].color.x = 1.f; - vtx[i].color.y = 1.f; - vtx[i].color.z = 1.f; - vtx[i].color.w = 1.f; - } - - if (mesh->HasTextureCoords(0)) { - auto &u = mesh->mTextureCoords[0][i]; - vtx[i].uv.x = u.x; - vtx[i].uv.y = u.y; - } else { - vtx[i].uv.x = 0.f; - vtx[i].uv.y = 0.f; - } - } - - context.indices.resize(context.indices.size() + subMesh.indexCount); - - uint32_t *indices = &context.indices[subMesh.firstIndex]; - for(unsigned int i = 0; i < mesh->mNumFaces; i++) - { - const aiFace &face = mesh->mFaces[i]; - indices[3 * i + 0] = face.mIndices[0]; - indices[3 * i + 1] = face.mIndices[1]; - indices[3 * i + 2] = face.mIndices[2]; - } - meshData.subMeshes.emplace_back(subMesh); - } - - static Uuid ProcessMesh(const aiScene *scene, const aiNode *node, PrefabBuildContext& prefabContext, const BuildRequest &request) - { - std::string meshName = GetIndexedName(request.relativePath, node->mName.C_Str(), "mesh", prefabContext.meshes.size()); - - auto *am = AssetManager::Get(); - auto meshId = am->GetUUIDByPath(meshName); - auto mesh = am->CreateAsset(meshId); - prefabContext.meshes.emplace_back(mesh); - - auto &meshData = mesh->Data(); - - meshData.vertexDescriptions.emplace_back("standard"); - meshData.vertexDescriptions.emplace_back("unlit"); - meshData.vertexDescriptions.emplace_back("position_only"); - - uint32_t meshNum = node->mNumMeshes; - MeshBuildContext meshContext; - for (uint32_t i = 0; i < meshNum; i++) { - aiMesh *aMesh = scene->mMeshes[node->mMeshes[i]]; - ProcessSubMesh(aMesh, scene, prefabContext, meshData, meshContext); - } - - // save vertex && index buffer - auto bufferName = GetIndexedName(request.relativePath, node->mName.C_Str(), "buffer", prefabContext.buffers.size()); - auto bufferId = am->GetUUIDByPath(bufferName); - auto buffer = am->CreateAsset(bufferId); - auto &bufferData = buffer->Data(); - prefabContext.buffers.emplace_back(buffer); - - MemoryArchive archive = {}; - size_t offset = 0; - - // save positions - size_t size = meshContext.position.size() * sizeof(Vector4); - archive.Save(reinterpret_cast(meshContext.position.data()), size); - meshData.vertexBuffers.emplace_back(BufferViewData{bufferId, static_cast(offset), static_cast(size)}); - offset += size; - - // save primitives - size = meshContext.ext.size() * sizeof(StandardVertexData); - archive.Save(reinterpret_cast(meshContext.ext.data()), size); - meshData.vertexBuffers.emplace_back(BufferViewData{bufferId, static_cast(offset), static_cast(size)}); - offset += size; - - // save indices - size = meshContext.indices.size() * sizeof(uint32_t); - archive.Save(reinterpret_cast(meshContext.indices.data()), size); - meshData.indexBuffer = BufferViewData{bufferId, static_cast(offset), static_cast(size)}; - - archive.Swap(bufferData.rawData); - return meshId; - } - - static void ProcessNode(aiNode *node, const aiScene *scene, uint32_t parent, PrefabBuildContext& context, const BuildRequest &request) - { - auto *am = AssetManager::Get(); - auto index = static_cast(context.nodes.size()); - context.nodes.emplace_back(); - auto& current = context.nodes.back(); - current.parentIndex = parent; - current.localMatrix = FromAssimp(node->mTransformation); - - if (node->mNumMeshes != 0) { - current.mesh = ProcessMesh(scene, node, context, request); - } - - for(unsigned int i = 0; i < node->mNumChildren; i++) { - ProcessNode(node->mChildren[i], scene, index, context, request); - } - } - - - void PrefabBuilder::Request(const BuildRequest &request, BuildResult &result) - { - Assimp::Importer importer; - if (!std::filesystem::exists(request.fullPath)) { - return; - } - - const aiScene* scene = importer.ReadFile(request.fullPath.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); - if((scene == nullptr) || ((scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) != 0u) || (scene->mRootNode == nullptr)) { - return; - } - auto *am = AssetManager::Get(); - - PrefabBuildContext context; - ProcessMaterials(scene, context, request); - ProcessNode(scene->mRootNode, scene, -1, context, request); - - for (auto &mat : context.materials) { - result.products.emplace_back(BuildProduct{"GFX_MATERIAL", mat}); - } - - for (auto &buffer : context.buffers) { - result.products.emplace_back(BuildProduct{"GFX_BUFFER", buffer}); - } - - for (auto &mesh : context.meshes) { - result.products.emplace_back(BuildProduct{"GFX_MESH", mesh}); - } - - for (auto &[key, tex] : context.textures) { - result.products.emplace_back(BuildProduct{"GFX_TEXTURE", tex}); - } - - auto asset = am->CreateAsset(request.uuid); - auto &assetData = asset->Data(); - assetData.nodes = context.nodes; - - result.products.emplace_back(BuildProduct{KEY.data(), asset}); - result.success = true; - } - -} // namespace sky::builder diff --git a/render/builder/render/src/ShaderBuilder.cpp b/render/builder/render/src/ShaderBuilder.cpp deleted file mode 100644 index baaa8ac3..00000000 --- a/render/builder/render/src/ShaderBuilder.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by Zach Lee on 2023/2/23. -// - -#include - -#include - -#include -#include -#include - -#include - -namespace sky::builder { - - void ShaderBuilder::Request(const BuildRequest &request, BuildResult &result) - { - auto shader = AssetManager::Get()->CreateAsset(request.uuid); - shader->Data().name = request.name; - shader->Data().shaderSource = ShaderCompiler::Get()->LoadShader(request.relativePath); - shader->Data().hash = Crc32::Cal(shader->Data().shaderSource); - - result.products.emplace_back(BuildProduct{"GFX_SHASER", shader}); - result.success = true; - } - - void ShaderBuilder::LoadConfig(const std::string &path) - { - } -} diff --git a/render/builder/render/src/VertexLibraryBuilder.cpp b/render/builder/render/src/VertexLibraryBuilder.cpp deleted file mode 100644 index 5601e4ee..00000000 --- a/render/builder/render/src/VertexLibraryBuilder.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include - -#include - -#include - -#include -#include - -#include -#include -#include - -namespace sky::builder { - - std::unordered_map FORMAT_MAP = { - {"F_R32", rhi::Format::F_R32 }, - {"F_RG32", rhi::Format::F_RG32 }, - {"F_RGB32", rhi::Format::F_RGB32 }, - {"F_RGBA32", rhi::Format::F_RGBA32}, - {"F_R8", rhi::Format::F_R8 }, - {"F_RG8", rhi::Format::F_RG8 }, - {"F_RGBA8", rhi::Format::F_RGBA8 }, - }; - - std::unordered_map RATE_MAP = { - {"PER_VERTEX", rhi::VertexInputRate::PER_VERTEX }, - {"PER_INSTANCE", rhi::VertexInputRate::PER_INSTANCE }, - }; - - template - static void ProcessDescriptions(rhi::VertexInput::Descriptor &desc, const T &value) - { - if (value.HasMember("attributes")) { - auto &attributes = value["attributes"]; - auto array = attributes.GetArray(); - desc.attributes.reserve(array.Size()); - for (auto &attribute : array) { - desc.attributes.emplace_back(); - rhi::VertexAttributeDesc &vtxAttribute = desc.attributes.back(); - if (attribute.HasMember("location")) { - vtxAttribute.location = attribute["location"].GetUint(); - } - if (attribute.HasMember("binding")) { - vtxAttribute.binding = attribute["binding"].GetUint(); - } - if (attribute.HasMember("offset")) { - vtxAttribute.offset = attribute["offset"].GetUint(); - } - if (attribute.HasMember("format")) { - auto fmtStr = attribute["format"].GetString(); - auto iter = FORMAT_MAP.find(fmtStr); - vtxAttribute.format = iter != FORMAT_MAP.end() ? iter->second : rhi::Format::UNDEFINED; - } - } - } - if (value.HasMember("bindings")) { - auto &bindings = value["bindings"]; - auto array = bindings.GetArray(); - desc.bindings.reserve(array.Size()); - for (auto &binding : array) { - desc.bindings.emplace_back(); - rhi::VertexBindingDesc &vtxBinding = desc.bindings.back(); - if (binding.HasMember("binding")) { - vtxBinding.binding = binding["binding"].GetUint(); - } - if (binding.HasMember("stride")) { - vtxBinding.stride = binding["stride"].GetUint(); - } - if (binding.HasMember("rate")) { - auto fmtStr = binding["rate"].GetString(); - auto iter = RATE_MAP.find(fmtStr); - vtxBinding.inputRate = iter != RATE_MAP.end() ? iter->second : rhi::VertexInputRate::PER_VERTEX; - } - } - } - } - - void VertexLibraryBuilder::Request(const BuildRequest &request, BuildResult &result) - { - if (!request.buildKey.empty() && request.buildKey != std::string(KEY)) { - return; - } - - std::string json; - ReadString(request.fullPath, json); - - rapidjson::Document document; - document.Parse(json.c_str()); - - if (!document.HasMember("descriptions")) { - return; - } - - auto &val = document["descriptions"]; - if (!val.IsArray()) { - return; - } - - auto *am = AssetManager::Get(); - std::filesystem::path fullPath(request.fullPath); - - auto asset = am->CreateAsset(request.uuid); - auto &assetData = asset->Data(); - - auto array = val.GetArray(); - for (auto &desc : array) { - for (auto iter = desc.MemberBegin(); iter != desc.MemberEnd(); ++iter) { - ProcessDescriptions(assetData.descriptions[iter->name.GetString()], iter->value); - } - } - result.products.emplace_back(BuildProduct{KEY.data(), asset}); - result.success = true; - } - -} // namespace sky::builder diff --git a/render/core/include/render/RenderPrimitive.h b/render/core/include/render/RenderPrimitive.h deleted file mode 100644 index 7325192f..00000000 --- a/render/core/include/render/RenderPrimitive.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Created by Zach Lee on 2023/8/19. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - - struct TechniqueInstance { - RDGfxTechPtr technique; - rhi::RenderPassPtr renderPass; - rhi::GraphicsPipelinePtr pso; - std::vector processors; - - bool rebuildPso = true; - }; - - struct RenderPrimitive { - explicit RenderPrimitive(PmrResource *res = nullptr) : args(res != nullptr ? res : &defaultRes) {} - std::vector techniques; - - PmrUnSyncPoolRes defaultRes; - uint32_t sortKey = 0; - AABB boundingBox {Vector3(std::numeric_limits::min()), Vector3(std::numeric_limits::max())}; - - RDResourceGroupPtr batchSet; - RDResourceGroupPtr instanceSet; - - rhi::VertexAssemblyPtr va; - rhi::BufferPtr indirectBuffer; - PmrVector args; - }; - - struct RenderDrawItem { - RenderPrimitive *primitive = nullptr; - uint32_t techIndex = 0; - }; - -} // namespace sky diff --git a/render/core/include/render/VertexDescLibrary.h b/render/core/include/render/VertexDescLibrary.h deleted file mode 100644 index f7bc379b..00000000 --- a/render/core/include/render/VertexDescLibrary.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#pragma once - -#include -#include -#include - -namespace sky { - - class VertexDescLibrary { - public: - VertexDescLibrary() = default; - ~VertexDescLibrary() = default; - - void RegisterVertexDesc(const std::string &key, const rhi::VertexInputPtr &desc); - rhi::VertexInputPtr FindVertexDesc(const std::string &key) const; - - private: - std::unordered_map descriptions; - }; - -} // namespace sky diff --git a/render/core/include/render/mesh/SkeletonMeshRenderer.h b/render/core/include/render/mesh/SkeletonMeshRenderer.h deleted file mode 100644 index 0a5bb4d6..00000000 --- a/render/core/include/render/mesh/SkeletonMeshRenderer.h +++ /dev/null @@ -1,10 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#pragma once - - -namespace sky { - -} // namespace sky diff --git a/render/core/include/render/resource/Buffer.h b/render/core/include/render/resource/Buffer.h deleted file mode 100644 index 57837bb1..00000000 --- a/render/core/include/render/resource/Buffer.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Created by Zach Lee on 2023/9/1. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky { - - class Buffer { - public: - Buffer(); - virtual ~Buffer(); - - void Init(uint64_t size, rhi::BufferUsageFlags usage, rhi::MemoryType memoryType); - virtual void Resize(uint64_t size); - virtual uint64_t GetRange() const { return bufferDesc.size; } - - const rhi::BufferPtr &GetRHIBuffer() const { return buffer; } - - rhi::TransferTaskHandle Upload(const std::string &path, rhi::Queue &queue, uint32_t offset); - - protected: - rhi::Device *device = nullptr; - rhi::Buffer::Descriptor bufferDesc = {}; - rhi::BufferPtr buffer; - }; - using RDBufferPtr = std::shared_ptr; - - class UniformBuffer : public Buffer { - public: - UniformBuffer() = default; - ~UniformBuffer() override = default; - - bool Init(uint32_t size); - void Write(uint32_t offset, const uint8_t *ptr, uint32_t size); - template - void Write(uint32_t offset, const T& val) - { - SKY_ASSERT(offset + sizeof(T) <= bufferDesc.size); - new (ptr + offset) T(val); - dirty = true; - } - - virtual void Upload(rhi::BlitEncoder &encoder); - - protected: - bool dirty = true; - uint8_t *ptr = nullptr; - std::vector data; - rhi::BufferPtr stagingBuffer; - }; - using RDUniformBufferPtr = std::shared_ptr; - - class DynamicUniformBuffer : public UniformBuffer { - public: - DynamicUniformBuffer() = default; - ~DynamicUniformBuffer() override = default; - - bool Init(uint32_t size, uint32_t inflightCount); - void Upload(); - void Upload(rhi::BlitEncoder &encoder) override; - - uint32_t GetOffset() const { return frameIndex * alignedFrameSize; } - uint64_t GetRange() const override { return frameSize; } - private: - uint32_t frameSize = 0; - uint32_t alignedFrameSize; - uint32_t frameIndex = 0; - uint32_t inflightCount = 1; - }; - using RDDynamicUniformBufferPtr = std::shared_ptr; - -} // namespace sky diff --git a/render/core/include/render/resource/Mesh.h b/render/core/include/render/resource/Mesh.h deleted file mode 100644 index ac317548..00000000 --- a/render/core/include/render/resource/Mesh.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Created by Zach Lee on 2023/8/31. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky { - - struct SubMesh { - uint32_t firstVertex = 0; - uint32_t vertexCount = 0; - uint32_t firstIndex = 0; - uint32_t indexCount = 0; - RDMaterialInstancePtr material; - AABB aabb; - }; - - class Mesh { - public: - Mesh() = default; - ~Mesh() = default; - - void AddSubMesh(const SubMesh &sub); - void AddVertexBuffer(const RDBufferPtr &vb); - void SetIndexBuffer(const RDBufferPtr &ib); - void SetIndexType(rhi::IndexType type); - void SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh); - void AddVertexDescriptions(const std::string &key); - - const std::vector &GetSubMeshes() const { return subMeshes; } - const std::vector &GetVertexBuffers() const { return vertexBuffers; } - const std::vector &GetVertexDescriptions() const { return vertexDescriptions; } - const RDBufferPtr &GetIndexBuffer() const { return indexBuffer; } - rhi::IndexType GetIndexType() const { return indexType; } - - private: - std::vector subMeshes; - std::vector vertexBuffers; - std::vector vertexDescriptions; - RDBufferPtr indexBuffer; - rhi::IndexType indexType = rhi::IndexType::U32; - }; - - using RDMeshPtr = std::shared_ptr; - -} // namespace sky \ No newline at end of file diff --git a/render/core/src/RHI.cpp b/render/core/src/RHI.cpp deleted file mode 100644 index 3c2fbc90..00000000 --- a/render/core/src/RHI.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// Created by Zach Lee on 2023/4/16. -// - -#include - -namespace sky { - - RHI::~RHI() - { - device = nullptr; - rhi::Instance::Destroy(instance); - instance = nullptr; - } - - void RHI::InitInstance(const rhi::Instance::Descriptor &desc) - { - instance = rhi::Instance::Create(desc); - api = desc.api; - } - - void RHI::InitDevice(const rhi::Device::Descriptor &desc) - { - device.reset(instance->CreateDevice(desc)); - } -} \ No newline at end of file diff --git a/render/core/src/VertexDescLibrary.cpp b/render/core/src/VertexDescLibrary.cpp deleted file mode 100644 index 8a9a13a0..00000000 --- a/render/core/src/VertexDescLibrary.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include - -namespace sky { - - void VertexDescLibrary::RegisterVertexDesc(const std::string &key, const rhi::VertexInputPtr &desc) - { - descriptions.emplace(key, desc); - } - - rhi::VertexInputPtr VertexDescLibrary::FindVertexDesc(const std::string &key) const - { - auto iter = descriptions.find(key); - return iter != descriptions.end() ? iter->second : nullptr; - } - -} // namespace sky diff --git a/render/core/src/mesh/MeshFeatureProcessor.cpp b/render/core/src/mesh/MeshFeatureProcessor.cpp deleted file mode 100644 index fd3804c9..00000000 --- a/render/core/src/mesh/MeshFeatureProcessor.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include - -namespace sky { - - void MeshFeatureProcessor::Tick(float time) - { - - } - - void MeshFeatureProcessor::Render(rdg::RenderGraph &rdg) - { - - } - - StaticMeshRenderer *MeshFeatureProcessor::CreateStaticMesh() - { - auto *renderer = new StaticMeshRenderer(); - renderer->AttachScene(scene); - return staticMeshes.emplace_back(renderer).get(); - } - - void MeshFeatureProcessor::RemoveStaticMesh(StaticMeshRenderer *mesh) - { - staticMeshes.remove_if([mesh](const auto &val) { - return mesh == val.get(); - }); - } - -} // namespace sky diff --git a/render/core/src/mesh/SkeletonMeshRenderer.cpp b/render/core/src/mesh/SkeletonMeshRenderer.cpp deleted file mode 100644 index c726ca0b..00000000 --- a/render/core/src/mesh/SkeletonMeshRenderer.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include - -namespace sky { - -} // namespace sky diff --git a/render/core/src/mesh/StaticMeshRenderer.cpp b/render/core/src/mesh/StaticMeshRenderer.cpp deleted file mode 100644 index a48ee77d..00000000 --- a/render/core/src/mesh/StaticMeshRenderer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// Created by Zach Lee on 2023/9/9. -// - -#include -#include -#include -#include -#include -#include - -namespace sky { - - StaticMeshRenderer::~StaticMeshRenderer() - { - for (auto &prim : primitives) { - scene->RemovePrimitive(prim.get()); - } - } - - void StaticMeshRenderer::AttachScene(RenderScene *scn) - { - scene = scn; - } - - void StaticMeshRenderer::SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh) - { - mesh->SetMaterial(mat, subMesh); - - auto &primitive = primitives[subMesh]; - primitive->techniques.clear(); - - const auto &techniques = mat->GetMaterial()->GetGfxTechniques(); - primitive->techniques.reserve(techniques.size()); - for (const auto &tech : techniques) { - primitive->techniques.emplace_back(TechniqueInstance{tech}); - } - - primitive->batchSet = mat->GetResourceGroup(); - } - - void StaticMeshRenderer::SetMesh(const RDMeshPtr &mesh_) - { - mesh = mesh_; - - if (!ubo) { - ubo = std::make_shared(); - ubo->Init(sizeof(InstanceLocal), Renderer::Get()->GetInflightFrameCount()); - ubo->Write(0, InstanceLocal{Matrix4::Identity(), Matrix4::Identity()}); - ubo->Upload(); - } - - if (!va) { - rhi::VertexAssembly::Descriptor desc = {}; - const auto &vbs = mesh->GetVertexBuffers(); - desc.vertexBuffers.resize(vbs.size()); - for (uint32_t i = 0; i < vbs.size(); ++i) { - desc.vertexBuffers[i] = vbs[i]->GetRHIBuffer()->CreateView({0, vbs[i]->GetRange()}); - } - desc.indexBuffer = mesh->GetIndexBuffer()->GetRHIBuffer()->CreateView({0, mesh->GetIndexBuffer()->GetRange()}); - desc.indexType = mesh->GetIndexType(); - va = RHI::Get()->GetDevice()->CreateVertexAssembly(desc); - } - - uint32_t index = 0; - auto *meshFeature = MeshFeature::Get(); - for (const auto &sub : mesh->GetSubMeshes()) { - auto &primitive = primitives.emplace_back(std::make_unique()); - SetMaterial(sub.material, index++); - - primitive->instanceSet = meshFeature->RequestResourceGroup(); - primitive->instanceSet->BindDynamicUBO("localData", ubo, 0); - primitive->instanceSet->Update(); - - primitive->boundingBox = sub.aabb; - primitive->va = va; - primitive->args.emplace_back(rhi::CmdDrawIndexed { - sub.indexCount, - 1, - sub.firstIndex, - static_cast(sub.firstVertex), - 0 - }); - - scene->AddPrimitive(primitive.get()); - } - } - - void StaticMeshRenderer::UpdateTransform(const Matrix4 &matrix) - { - ubo->Write(0, matrix); - ubo->Write(sizeof(Matrix4), matrix.InverseTranspose()); - ubo->Upload(); - } - -} // namespace sky diff --git a/render/core/src/rdg/RenderSceneVisitor.cpp b/render/core/src/rdg/RenderSceneVisitor.cpp deleted file mode 100644 index f7e40167..00000000 --- a/render/core/src/rdg/RenderSceneVisitor.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by Zach Lee on 2023/8/27. -// - -#include -#include -#include -#include - -namespace sky::rdg { - - void RenderSceneVisitor::BuildRenderQueue() - { - const auto &primitives = graph.scene->GetPrimitives(); - for (auto &queue : graph.rasterQueues) { - const auto &subPass = graph.subPasses[Index(queue.passID, graph)]; - const auto &rasterPass = graph.rasterPasses[Index(subPass.parent, graph)]; - const auto &renderPass = rasterPass.renderPass; - - for (const auto &prim : primitives) { - if (queue.culling && queue.sceneView != nullptr && !queue.sceneView->FrustumCulling(prim->boundingBox)) { - continue; - } - - for (auto &tech : prim->techniques) { - uint32_t viewMask = tech.technique->GetViewMask(); - uint32_t rasterID = tech.technique->GetRasterID(); - - uint32_t sceneMask = queue.sceneView != nullptr ? queue.sceneView->GetViewMask() : 0xFFFFFFFF; - if ((sceneMask & viewMask) != sceneMask || rasterID != queue.rasterID) { - continue; - } - - if (tech.rebuildPso || !tech.pso || (tech.renderPass->GetCompatibleHash() != renderPass->GetCompatibleHash())) { - tech.renderPass = renderPass; - tech.pso = GraphicsTechnique::BuildPso(*tech.technique, renderPass, subPass.subPassID); - - tech.rebuildPso = false; - } - - queue.drawItems.emplace_back(RenderDrawItem{prim, 0}); - } - } - } - } - - -} // namespace sky::rdg diff --git a/render/core/src/resource/Buffer.cpp b/render/core/src/resource/Buffer.cpp deleted file mode 100644 index b96c4a5c..00000000 --- a/render/core/src/resource/Buffer.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// Created by Zach Lee on 2023/9/1. -// - -#include -#include -#include -#include -#include - -namespace sky { - - Buffer::~Buffer() - { - Renderer::Get()->GetResourceGC()->CollectBuffer(buffer); - } - - Buffer::Buffer() - { - device = RHI::Get()->GetDevice(); - } - - void Buffer::Init(uint64_t size, rhi::BufferUsageFlags usage, rhi::MemoryType memoryType) - { - bufferDesc.size = size; - bufferDesc.usage = usage; - bufferDesc.memory = memoryType; - - buffer = device->CreateBuffer(bufferDesc); - } - - void Buffer::Resize(uint64_t size) - { - Renderer::Get()->GetResourceGC()->CollectBuffer(buffer); - bufferDesc.size = size; - buffer = device->CreateBuffer(bufferDesc); - } - - rhi::TransferTaskHandle Buffer::Upload(const std::string &path, rhi::Queue &queue, uint32_t offset) - { - rhi::BufferUploadRequest request = {}; - request.source = std::make_shared(path, offset); - request.offset = 0; - request.size = bufferDesc.size; - return queue.UploadBuffer(buffer, request); - } - - bool UniformBuffer::Init(uint32_t size) - { - Buffer::Init(size, rhi::BufferUsageFlagBit::UNIFORM | rhi::BufferUsageFlagBit::TRANSFER_DST, rhi::MemoryType::GPU_ONLY); - - rhi::Buffer::Descriptor desc = {}; - desc.size = size; - desc.memory = rhi::MemoryType::CPU_TO_GPU; - desc.usage = rhi::BufferUsageFlagBit::UNIFORM | rhi::BufferUsageFlagBit::TRANSFER_SRC; - stagingBuffer = RHI::Get()->GetDevice()->CreateBuffer(desc); - - data.resize(size); - ptr = data.data(); - return static_cast(buffer); - } - - void UniformBuffer::Write(uint32_t offset, const uint8_t *src, uint32_t size) - { - SKY_ASSERT(offset + size <= bufferDesc.size); - memcpy(ptr + offset, src, size); - dirty = true; - } - - void UniformBuffer::Upload(rhi::BlitEncoder &encoder) - { - uint8_t *tmp = stagingBuffer->Map(); - memcpy(tmp, data.data(), data.size()); - stagingBuffer->UnMap(); - - encoder.CopyBuffer(stagingBuffer, buffer, data.size(), 0, 0); - } - - void DynamicUniformBuffer::Upload() - { - if (!dirty) { - return; - } - - frameIndex = (frameIndex + 1) % inflightCount; - - auto *mapPtr = buffer->Map() + frameIndex * frameSize; - memcpy(mapPtr, ptr, frameSize); - buffer->UnMap(); - - dirty = false; - } - - void DynamicUniformBuffer::Upload(rhi::BlitEncoder &/*encoder*/) - { - Upload(); - } - - bool DynamicUniformBuffer::Init(uint32_t size, uint32_t inflightCount) - { - frameSize = size; - alignedFrameSize = Align(size, device->GetLimitations().minUniformBufferOffsetAlignment); - - Buffer::Init(alignedFrameSize * inflightCount, rhi::BufferUsageFlagBit::UNIFORM, rhi::MemoryType::CPU_TO_GPU); - - data.resize(size, 0); - ptr = data.data(); - return static_cast(buffer); - } - -} // namespace sky diff --git a/render/core/src/resource/Mesh.cpp b/render/core/src/resource/Mesh.cpp deleted file mode 100644 index 0fbd9b4d..00000000 --- a/render/core/src/resource/Mesh.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// Created by Zach Lee on 2023/8/31. -// - -#include - -namespace sky { - - void Mesh::AddSubMesh(const SubMesh &sub) - { - subMeshes.emplace_back(sub); - } - - void Mesh::AddVertexBuffer(const RDBufferPtr &vb) - { - vertexBuffers.emplace_back(vb); - } - - void Mesh::SetIndexBuffer(const RDBufferPtr &ib) - { - indexBuffer = ib; - } - - void Mesh::SetIndexType(rhi::IndexType type) - { - indexType = type; - } - - void Mesh::SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh) - { - subMeshes[subMesh].material = mat; - } - - void Mesh::AddVertexDescriptions(const std::string &key) - { - vertexDescriptions.emplace_back(key); - } - - -} // namespace sky \ No newline at end of file diff --git a/render/imgui/include/imgui/ImGuiInstance.h b/render/imgui/include/imgui/ImGuiInstance.h deleted file mode 100644 index 1dfd404a..00000000 --- a/render/imgui/include/imgui/ImGuiInstance.h +++ /dev/null @@ -1,98 +0,0 @@ -// -// Created by blues on 2023/9/20. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky { - namespace rdg { - struct RenderGraph; - } // namespace rdg - class RenderScene; - - using UIFunc = std::function; - - class ImWidget { - public: - ImWidget() = default; - virtual ~ImWidget() = default; - - virtual void Execute(ImGuiContext *context) = 0; - }; - - class LambdaWidget : public ImWidget { - public: - template - explicit LambdaWidget(Func &&f) : fn(std::forward(f)) {} - ~LambdaWidget() override = default; - - virtual void Execute(ImGuiContext *context) override { fn(context); } - - private: - UIFunc fn; - }; - - class ImGuiInstance : public IWindowEvent { - public: - ImGuiInstance(); - ~ImGuiInstance() override; - - template - void AddFunctions(Func &&func) - { - widgets.emplace_back(new LambdaWidget(std::forward(func))); - } - - template - T *AddWidget(Args &&... args) - { - auto *widget = new T(std::forward(args)...); - widgets.emplace_back(widget); - return widget; - } - - void Tick(float delta); - void Render(rdg::RenderGraph &rdg); - - void MakeCurrent(); - - void BindNativeWindow(const NativeWindow *window); - - void OnMouseMove(int32_t x, int32_t y) override; - void OnMouseButtonDown(MouseButtonType button) override; - void OnMouseButtonUp(MouseButtonType button) override; - void OnMouseWheel(int32_t wheelX, int32_t wheelY) override; - void OnFocusChanged(bool focus) override; - void OnWindowResize(uint32_t width, uint32_t height) override; - void OnTextInput(const char *text) override; - - void AttachScene(RenderScene *scene); - void DetachScene(); - - private: - void CheckVertexBuffers(uint32_t vertexCount, uint32_t indexCount); - - RenderScene *renderScene = nullptr; - ImGuiContext *context = nullptr; - std::unique_ptr primitive; - RDBufferPtr stagingBuffer; - RDBufferPtr vertexBuffer; - RDBufferPtr indexBuffer; - RDResourceGroupPtr globalSet; - - RDTexture2DPtr fontTexture; - RDDynamicUniformBufferPtr ubo; - uint32_t uploadHandle = 0; - uint64_t vertexSize = 0; - uint64_t indexSize = 0; - - ImDrawData* drawData = nullptr; - std::list> widgets; - }; - -} // namespace sky diff --git a/render/imgui/src/ImGuiFeatureProcessor.cpp b/render/imgui/src/ImGuiFeatureProcessor.cpp deleted file mode 100644 index cba56179..00000000 --- a/render/imgui/src/ImGuiFeatureProcessor.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// Created by blues on 2023/9/20. -// - -#include - -namespace sky { - - void ImGuiFeatureProcessor::Tick(float time) - { - for (auto &gui : guis) { - gui->Tick(time); - } - } - - void ImGuiFeatureProcessor::Render(rdg::RenderGraph &rdg) - { - for (auto &gui : guis) { - gui->Render(rdg); - } - } - - ImGuiInstance *ImGuiFeatureProcessor::CreateGUIInstance() - { - auto *gui = new ImGuiInstance(); - gui->AttachScene(scene); - return guis.emplace_back(gui).get(); - } - - void ImGuiFeatureProcessor::RemoveGUIInstance(ImGuiInstance *mesh) - { - guis.remove_if([mesh](const auto &val) { - return mesh == val.get(); - }); - } - -} // namespace \ No newline at end of file diff --git a/render/imgui/src/ImGuiInstance.cpp b/render/imgui/src/ImGuiInstance.cpp deleted file mode 100644 index 362572a7..00000000 --- a/render/imgui/src/ImGuiInstance.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// -// Created by blues on 2023/9/20. -// - -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - struct UITransform { - ImVec2 scale; - ImVec2 translate; - }; - - ImGuiInstance::ImGuiInstance() - { - IMGUI_CHECKVERSION(); - context = ImGui::CreateContext(); - ImGui::SetCurrentContext(context); - ImGuiIO& io = ImGui::GetIO(); - - unsigned char *pixels; - int width; - int height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - uint32_t uploadSize = width * height * 4 * sizeof(char); - - auto *queue = RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER); - fontTexture = std::make_shared(); - fontTexture->Init(rhi::PixelFormat::RGBA8_UNORM, width, height, 1); - uploadHandle = fontTexture->Upload(pixels, uploadSize, *queue); - - ubo = std::make_shared(); - ubo->Init(sizeof(UITransform), Renderer::Get()->GetInflightFrameCount()); - - io.Fonts->SetTexID((ImTextureID)(intptr_t)fontTexture->GetImageView().get()); - - auto *feature = ImGuiFeature::Get(); - primitive = std::make_unique(); - primitive->techniques.emplace_back(feature->GetDefaultTech()); - - queue->Wait(uploadHandle); - globalSet = feature->RequestResourceGroup(); - globalSet->BindTexture("fontTexture", fontTexture->GetImageView(), 0); - globalSet->BindDynamicUBO("pc", ubo, 0); - globalSet->Update(); - - primitive->batchSet = globalSet; - } - - ImGuiInstance::~ImGuiInstance() - { - ImGui::DestroyContext(context); - Event::DisConnect( this); - } - - void ImGuiInstance::Tick(float delta) - { - MakeCurrent(); - ImGuiIO& io = ImGui::GetIO(); - io.DeltaTime = delta; - - ImGui::NewFrame(); - - for (auto &widget : widgets) { - widget->Execute(context); - } - - ImGui::EndFrame(); - - ImGui::Render(); - drawData = ImGui::GetDrawData(); - } - - void ImGuiInstance::Render(rdg::RenderGraph &rdg) - { - UITransform transform; - transform.scale.x = 2.0f / drawData->DisplaySize.x; - transform.scale.y = 2.0f / drawData->DisplaySize.y; - transform.translate.x = -1.0f - drawData->DisplayPos.x * transform.scale.x; - transform.translate.y = -1.0f - drawData->DisplayPos.y * transform.scale.y; - ubo->Write(0, transform); - ubo->Upload(); - - float fbWidth = drawData->DisplaySize.x * drawData->FramebufferScale.x; - float fbHeight = drawData->DisplaySize.y * drawData->FramebufferScale.y; - - ImVec2 clipOff = drawData->DisplayPos; - ImVec2 clipScale = drawData->FramebufferScale; - - int globalVtxOffset = 0; - int globalIdxOffset = 0; - - if (drawData->TotalIdxCount == 0 || drawData->TotalVtxCount == 0) { - return; - } - - RenderCmdList package; - CheckVertexBuffers(drawData->TotalVtxCount, drawData->TotalIdxCount); - auto *vtxDst = reinterpret_cast(stagingBuffer->GetRHIBuffer()->Map()); - auto *idxDst = reinterpret_cast(stagingBuffer->GetRHIBuffer()->Map() + vertexSize); - - primitive->args.clear(); - for (int n = 0; n < drawData->CmdListsCount; n++) { - const ImDrawList *cmdList = drawData->CmdLists[n]; - // upload vertex buffers - memcpy(vtxDst, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idxDst, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx)); - vtxDst += cmdList->VtxBuffer.Size; - idxDst += cmdList->IdxBuffer.Size; - - for (int i = 0; i < cmdList->CmdBuffer.Size; i++) { - const ImDrawCmd *pCmd = &cmdList->CmdBuffer[i]; - ImVec2 clipMin((pCmd->ClipRect.x - clipOff.x) * clipScale.x, (pCmd->ClipRect.y - clipOff.y) * clipScale.y); - ImVec2 clipMax((pCmd->ClipRect.z - clipOff.x) * clipScale.x, (pCmd->ClipRect.w - clipOff.y) * clipScale.y); - - if (clipMin.x < 0.0f) { clipMin.x = 0.0f; } - if (clipMin.y < 0.0f) { clipMin.y = 0.0f; } - if (clipMax.x > fbWidth) { clipMax.x = fbWidth; } - if (clipMax.y > fbHeight) { clipMax.y = fbHeight; } - if (clipMax.x < clipMin.x || clipMax.y < clipMin.y) { continue; } - - primitive->args.emplace_back(rhi::Rect2D{ - {static_cast((clipMin.x)), static_cast((clipMin.y))}, - {static_cast((clipMax.x - clipMin.x)), static_cast((clipMax.y - clipMin.y))} - }); - primitive->args.emplace_back(rhi::CmdDrawIndexed { - pCmd->ElemCount, - 1, - pCmd->IdxOffset + globalIdxOffset, - static_cast(pCmd->VtxOffset + globalVtxOffset), - 0 - }); - } - globalVtxOffset += cmdList->VtxBuffer.Size; - globalIdxOffset += cmdList->IdxBuffer.Size; - } - - stagingBuffer->GetRHIBuffer()->UnMap(); - rdg.AddUploadPass("UploadImGuiVtx", {stagingBuffer, vertexBuffer, 0, 0, vertexSize}); - rdg.AddUploadPass("UploadImGuiIdx", {stagingBuffer, indexBuffer, vertexSize, 0, indexSize}); - } - - void ImGuiInstance::MakeCurrent() - { - ImGui::SetCurrentContext(context); - } - - void ImGuiInstance::BindNativeWindow(const NativeWindow *nativeWindow) - { - Event::Connect(nativeWindow, this); - - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize = ImVec2(static_cast(nativeWindow->GetWidth()), static_cast(nativeWindow->GetHeight())); - io.DisplayFramebufferScale = ImVec2(1.f, 1.f); - } - - void ImGuiInstance::OnMouseWheel(int32_t wheelX, int32_t wheelY) - { - ImGuiIO& io = ImGui::GetIO(); - if (wheelX > 0) { io.MouseWheelH += 1; } - if (wheelX < 0) { io.MouseWheelH -= 1; } - if (wheelY > 0) { io.MouseWheel += 1; } - if (wheelY < 0) { io.MouseWheel -= 1; } - } - - void ImGuiInstance::OnFocusChanged(bool focus) - { - MakeCurrent(); - ImGuiIO& io = ImGui::GetIO(); - io.AddFocusEvent(focus); - } - - void ImGuiInstance::OnWindowResize(uint32_t width, uint32_t height) - { - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize = ImVec2(static_cast(width), static_cast(height)); - io.DisplayFramebufferScale = ImVec2(1.f, 1.f); - } - - void ImGuiInstance::OnTextInput(const char *text) - { - ImGuiIO& io = ImGui::GetIO(); - io.AddInputCharactersUTF8(text); - } - - void ImGuiInstance::OnMouseMove(int32_t x, int32_t y) - { - ImGuiIO& io = ImGui::GetIO(); - io.MousePos = ImVec2(static_cast(x), static_cast(y)); - } - - void ImGuiInstance::OnMouseButtonDown(MouseButtonType button) - { - ImGuiIO& io = ImGui::GetIO(); - io.MouseDown[button - 1] = true; - } - - void ImGuiInstance::OnMouseButtonUp(MouseButtonType button) - { - ImGuiIO& io = ImGui::GetIO(); - io.MouseDown[button - 1] = false; - } - - void ImGuiInstance::CheckVertexBuffers(uint32_t vertexCount, uint32_t indexCount) - { - bool rebuildVA = false; - auto vs = vertexCount * sizeof(ImDrawVert); - auto is = indexCount * sizeof(ImDrawIdx); - - if (vs > vertexSize) { - vertexSize = std::max(vertexSize * 2, vs); - if (!vertexBuffer) { - vertexBuffer = std::make_shared(); - vertexBuffer->Init(vertexSize, rhi::BufferUsageFlagBit::TRANSFER_DST | rhi::BufferUsageFlagBit::VERTEX, rhi::MemoryType::GPU_ONLY); - } else { - vertexBuffer->Resize(vertexSize); - } - rebuildVA = true; - } - - if (is > indexSize) { - indexSize = std::max(indexSize * 2, is); - if (!indexBuffer) { - indexBuffer = std::make_shared(); - indexBuffer->Init(indexSize, rhi::BufferUsageFlagBit::TRANSFER_DST | rhi::BufferUsageFlagBit::INDEX, rhi::MemoryType::GPU_ONLY); - } else { - indexBuffer->Resize(indexSize); - } - rebuildVA = true; - } - - if (rebuildVA) { - rhi::VertexAssembly::Descriptor desc = {}; - desc.vertexBuffers.emplace_back(vertexBuffer->GetRHIBuffer()->CreateView({0, vertexSize})); - desc.indexBuffer = indexBuffer->GetRHIBuffer()->CreateView({0, indexSize}); - desc.indexType = sizeof(ImDrawIdx) == 2 ? rhi::IndexType::U16 : rhi::IndexType::U32; - - primitive->va = RHI::Get()->GetDevice()->CreateVertexAssembly(desc); - - // rebuild staging buffer - if (!stagingBuffer) { - stagingBuffer = std::make_shared(); - stagingBuffer->Init(vertexSize + indexSize, rhi::BufferUsageFlagBit::TRANSFER_SRC, rhi::MemoryType::CPU_TO_GPU); - } else { - stagingBuffer->Resize(vertexSize + indexSize); - } - } - } - - void ImGuiInstance::AttachScene(RenderScene *scene) - { - if (renderScene != nullptr) { - renderScene->RemovePrimitive(primitive.get()); - } else { - renderScene = scene; - renderScene->AddPrimitive(primitive.get()); - } - } - - void ImGuiInstance::DetachScene() - { - if (renderScene != nullptr) { - renderScene->RemovePrimitive(primitive.get()); - } - renderScene = nullptr; - } -} // namespace sky \ No newline at end of file diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt new file mode 100644 index 00000000..4fe551d2 --- /dev/null +++ b/runtime/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(framework) +add_subdirectory(core) +add_subdirectory(render) +add_subdirectory(physics) +add_subdirectory(navigation) +add_subdirectory(plugins) \ No newline at end of file diff --git a/core/CMakeLists.txt b/runtime/core/CMakeLists.txt similarity index 70% rename from core/CMakeLists.txt rename to runtime/core/CMakeLists.txt index 530ac879..c1f27df7 100644 --- a/core/CMakeLists.txt +++ b/runtime/core/CMakeLists.txt @@ -1,6 +1,8 @@ file(GLOB_RECURSE SRC_FILES src/*) file(GLOB_RECURSE INC_FILES include/*) +file(GLOB_RECURSE UNIX_ASYNC_SRC platform/unix/async/*) + if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") file(GLOB_RECURSE CORE_PLATFORM_SRC platform/windows/*) @@ -9,7 +11,13 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") platform/macos/*) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") file(GLOB_RECURSE CORE_PLATFORM_SRC - platform/unix/async/*) + platform/android/*) + list(APPEND CORE_PLATFORM_SRC ${UNIX_ASYNC_SRC}) +endif () + +set(CORE_OPT_LIBS) +if (SKY_USE_TRACY) + list(APPEND CORE_OPT_LIBS 3rdParty::tracy) endif () sky_add_library(TARGET Core STATIC @@ -26,4 +34,6 @@ sky_add_library(TARGET Core STATIC 3rdParty::crc32 3rdParty::taskflow 3rdParty::boost +# 3rdParty::mimalloc + ${CORE_OPT_LIBS} ) diff --git a/core/include/core/archive/ArchiveConcept.h b/runtime/core/include/core/archive/Concept.h similarity index 100% rename from core/include/core/archive/ArchiveConcept.h rename to runtime/core/include/core/archive/Concept.h diff --git a/runtime/core/include/core/archive/FileArchive.h b/runtime/core/include/core/archive/FileArchive.h new file mode 100644 index 00000000..dc4e0d33 --- /dev/null +++ b/runtime/core/include/core/archive/FileArchive.h @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/2/7. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class IFileArchive : public IStreamArchive { + public: + explicit IFileArchive(const FilePath &path, std::ios::openmode mode = std::ios::binary); + ~IFileArchive() override = default; + + using IInputArchive::LoadRaw; + + bool IsOpen() const override { return stream.is_open(); } + private: + std::fstream stream; + }; + + class OFileArchive : public OStreamArchive { + public: + explicit OFileArchive(const FilePath &path, std::ios::openmode mode = std::ios::binary); + ~OFileArchive() override = default; + + using IOutputArchive::SaveRaw; + + bool IsOpen() const override { return stream.is_open(); } + private: + std::fstream stream; + }; + +} // namespace sky diff --git a/runtime/core/include/core/archive/IArchive.h b/runtime/core/include/core/archive/IArchive.h new file mode 100644 index 00000000..c8d92581 --- /dev/null +++ b/runtime/core/include/core/archive/IArchive.h @@ -0,0 +1,101 @@ +// +// Created by blues on 2024/5/16. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class IInputArchive { + public: + IInputArchive() = default; + virtual ~IInputArchive() = default; + + virtual bool LoadRaw(char *data, size_t size) = 0; + + template + bool Load(T &v) + { + uint32_t size = 0; + bool res = true; + res &= Load(size); + v.resize(size / sizeof(typename T::value_type)); + res &= LoadRaw(reinterpret_cast(v.data()), size); + return res; + } + + template + bool Load(T &val) + { + return LoadRaw(reinterpret_cast(&val), sizeof(T)); + } + + template + IInputArchive &operator>>(T &v) + { + Load(v); + return *this; + } + + template + IInputArchive &operator>>(T &v) + { + Load(v); + return *this; + } + + virtual int Peek() { return std::char_traits::eof(); } + virtual int Get() { return std::char_traits::eof(); } + virtual size_t Tell() const { return 0; } + + virtual bool IsOpen() const { return true; } + }; + + class IOutputArchive { + public: + IOutputArchive() = default; + virtual ~IOutputArchive() = default; + + virtual bool SaveRaw(const char *data, size_t size) = 0; + + template + bool Save(const T &v) + { + auto size = v.size() * sizeof(typename T::value_type); + bool res = true; + res &= Save(static_cast(size)); + res &= SaveRaw(reinterpret_cast(v.data()), size); + return res; + } + + template + bool Save(const T &v) + { + return SaveRaw(reinterpret_cast(&v), sizeof(T)); + } + + template + IOutputArchive &operator<<(const T &v) + { + Save(v); + return *this; + } + + template + IOutputArchive &operator<<(const T &v) + { + Save(v); + return *this; + } + + virtual void Put(char ch) {} + virtual void Flush() {} + + virtual bool IsOpen() const { return true; } + }; + +} // namespace sky diff --git a/runtime/core/include/core/archive/MemoryArchive.h b/runtime/core/include/core/archive/MemoryArchive.h new file mode 100644 index 00000000..7b52e60a --- /dev/null +++ b/runtime/core/include/core/archive/MemoryArchive.h @@ -0,0 +1,25 @@ +// +// Created by blues on 2024/1/14. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class MemoryArchive : public StreamArchive { + public: + MemoryArchive() : StreamArchive(ss) {} + ~MemoryArchive() override = default; + + const char* Data() const override { return ss.rdbuf()->view().data(); } + uint32_t Size() const override { return static_cast(ss.rdbuf()->view().size()); } + private: + std::stringstream ss; + }; + +} // namespace sky diff --git a/runtime/core/include/core/archive/StreamArchive.h b/runtime/core/include/core/archive/StreamArchive.h new file mode 100644 index 00000000..033661cb --- /dev/null +++ b/runtime/core/include/core/archive/StreamArchive.h @@ -0,0 +1,85 @@ +// +// Created by bluesky on 2023/10/11. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class StreamArchive; + using StreamArchivePtr = CounterPtr; + + class IStreamArchive; + using IStreamArchivePtr = CounterPtr; + + class OStreamArchive; + using OStreamArchivePtr = CounterPtr; + + class StreamArchive : public IInputArchive, public IOutputArchive, public RefObject { + public: + explicit StreamArchive(std::iostream &stream_) : stream(stream_) {} + ~StreamArchive() override = default; + + virtual const char* Data() const { return nullptr; } + virtual uint32_t Size() const { return 0; } + + bool LoadRaw(char *data, size_t size) override; + + template + void LoadFromStream(Archive &ar) + { + stream << ar.stream.rdbuf(); + } + + bool SaveRaw(const char *data, size_t size) override; + + std::iostream &GetStream() const { return stream; } + + int Peek() override; + int Get() override; + size_t Tell() const override; + void Put(char ch) override; + protected: + std::iostream &stream; + }; + + class IStreamArchive : public IInputArchive, public RefObject { + public: + explicit IStreamArchive(std::istream &s) : stream(s) {} + ~IStreamArchive() override = default; + + bool LoadRaw(char *data, size_t size) override; + + std::istream &GetStream() const { return stream; } + + int Peek() override; + int Get() override; + size_t Tell() const override; + private: + friend class StreamArchive; + + std::istream &stream; + }; + + class OStreamArchive : public IOutputArchive, public RefObject { + public: + explicit OStreamArchive(std::ostream &s) : stream(s) {} + ~OStreamArchive() override = default; + + bool SaveRaw(const char *data, size_t size) override; + + std::ostream &GetStream() const { return stream; } + + void Put(char ch) override; + void Flush() override; + private: + friend class StreamArchive; + + std::ostream &stream; + }; + +} // namespace sky \ No newline at end of file diff --git a/core/include/core/async/Semaphore.h b/runtime/core/include/core/async/Semaphore.h similarity index 100% rename from core/include/core/async/Semaphore.h rename to runtime/core/include/core/async/Semaphore.h diff --git a/runtime/core/include/core/async/Task.h b/runtime/core/include/core/async/Task.h new file mode 100644 index 00000000..2c1d0c77 --- /dev/null +++ b/runtime/core/include/core/async/Task.h @@ -0,0 +1,35 @@ +// +// Created by blues on 2024/9/6. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class Task : public RefObject { + public: + Task() = default; + ~Task() override = default; + + virtual bool DoWork() = 0; + virtual void OnComplete(bool result) {} + }; + using TaskPtr = CounterPtr; + + class TaskExecutor : public Singleton { + public: + TaskExecutor() = default; + ~TaskExecutor() override = default; + + void ExecuteTask(const TaskPtr &task); + void WaitForAll(); + + private: + tf::Executor executor; + }; + +} // namespace sky diff --git a/core/include/core/environment/Environment.h b/runtime/core/include/core/environment/Environment.h similarity index 100% rename from core/include/core/environment/Environment.h rename to runtime/core/include/core/environment/Environment.h diff --git a/core/include/core/environment/Singleton.h b/runtime/core/include/core/environment/Singleton.h similarity index 94% rename from core/include/core/environment/Singleton.h rename to runtime/core/include/core/environment/Singleton.h index 99b5cf56..1ab5e284 100644 --- a/core/include/core/environment/Singleton.h +++ b/runtime/core/include/core/environment/Singleton.h @@ -13,7 +13,7 @@ namespace sky { template class Singleton { public: - static constexpr uint32_t ID = TypeInfo::Hash(); + static constexpr uint32_t ID = RuntimeTypeId(); static T *Get() { diff --git a/core/include/core/event/Delegate.h b/runtime/core/include/core/event/Delegate.h similarity index 100% rename from core/include/core/event/Delegate.h rename to runtime/core/include/core/event/Delegate.h diff --git a/framework/include/framework/event/Event.h b/runtime/core/include/core/event/Event.h similarity index 75% rename from framework/include/framework/event/Event.h rename to runtime/core/include/core/event/Event.h index 6c993c8c..4f5e2630 100644 --- a/framework/include/framework/event/Event.h +++ b/runtime/core/include/core/event/Event.h @@ -4,8 +4,8 @@ #pragma once -#include "core/environment/Singleton.h" -#include +#include +#include #include namespace sky { @@ -57,7 +57,7 @@ namespace sky { friend class Singleton; Storage() = default; ~Storage() = default; - std::map> listeners; + std::unordered_map> listeners; }; static void Connect(const KeyType &key, Interface *listener) @@ -129,4 +129,58 @@ namespace sky { Storage::Get()->BroadCast(std::forward(func), std::forward(args)...); } }; + + template + class EventBinder { + public: + EventBinder() = default; + ~EventBinder() + { + Reset(); + } + + void Bind(T *inter, KeyType key) + { + Event::Connect(key, inter); + val = inter; + } + + void Reset() + { + if (val != nullptr) { + Event::DisConnect(val); + val = nullptr; + } + } + + private: + T *val = nullptr; + }; + + template + class EventBinder { + public: + EventBinder() = default; + ~EventBinder() + { + Reset(); + } + + void Bind(T *inter) + { + Event::Connect(inter); + val = inter; + } + + void Reset() + { + if (val != nullptr) { + Event::DisConnect(val); + val = nullptr; + } + } + + private: + T *val = nullptr; + }; } // namespace sky \ No newline at end of file diff --git a/runtime/core/include/core/file/FileIO.h b/runtime/core/include/core/file/FileIO.h new file mode 100644 index 00000000..2d554fd5 --- /dev/null +++ b/runtime/core/include/core/file/FileIO.h @@ -0,0 +1,21 @@ +// +// Created by Zach Lee on 2022/1/16. +// + +#pragma once +#include +#include +#include + +namespace sky { + + void WriteBin(const FilePath &path, const char *data, size_t size); + void WriteString(const FilePath &path, const std::string &out); + + bool ReadBin(const FilePath &path, uint8_t *&out, uint32_t &size); + bool ReadBin(const FilePath &path, std::vector &out); + bool ReadBin(const FilePath &path, std::vector &out); + + bool ReadString(const FilePath &path, std::string &out); + +} // namespace sky \ No newline at end of file diff --git a/runtime/core/include/core/file/FileSystem.h b/runtime/core/include/core/file/FileSystem.h new file mode 100644 index 00000000..52cdc037 --- /dev/null +++ b/runtime/core/include/core/file/FileSystem.h @@ -0,0 +1,146 @@ +// +// Created by blues on 2024/4/1. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#if WIN32 +#define SKY_FS_USE_WCHAR +#endif + +namespace sky { + + class IFile; + class IFileSystem; + + using FilePtr = CounterPtr; + using FileSystemPtr = CounterPtr; + + class NativeFileSystem; + using NativeFileSystemPtr = CounterPtr; + + + // maybe support for wstring + class FilePath { + public: + FilePath(); + FilePath(const char *filePath_); // NOLINT + FilePath(const std::string &filePath_); // NOLINT + FilePath(const std::filesystem::path &filePath_); // NOLINT + ~FilePath() = default; + + FilePath& operator/=(const FilePath& sub); + FilePath operator/(const FilePath& sub) const; + + std::string GetStr() const; + void MakeDirectory() const; + bool Exist() const; + FilePath Parent() const; + std::string FileName() const; + std::string FileNameWithoutExt() const; + std::string Extension() const; + + std::fstream OpenFStream(std::ios_base::openmode) const; + + bool operator==(const FilePath &rhs) const { return filePath == rhs.filePath; } + private: + friend class NativeFileSystem; + + std::filesystem::path filePath; + }; + + class IFile : public RefObject { + public: + explicit IFile() = default; + ~IFile() override = default; + + virtual void ReadData(uint64_t offset, uint64_t size, uint8_t *out) = 0; + + virtual IStreamArchivePtr ReadAsArchive() = 0; + virtual OStreamArchivePtr WriteAsArchive() = 0; + + virtual bool ReadBin(std::vector &out) = 0; + virtual bool ReadString(std::string &out) = 0; + +// virtual std::istream ReadAsStream(const FilePath &name) = 0; +// virtual std::ostream WriteAsStream(const FilePath &name) = 0; + virtual std::string GetPath() const = 0; + }; + + class NativeFile : public IFile { + public: + explicit NativeFile(const FilePath &path) : filePath(path) {} + ~NativeFile() override = default; + + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + bool ReadBin(std::vector &out) override; + bool ReadString(std::string &out) override; + + IStreamArchivePtr ReadAsArchive() override; + OStreamArchivePtr WriteAsArchive() override; + + std::string GetPath() const override; + +// std::istream ReadAsStream(const FilePath &name) override; +// std::ostream WriteAsStream(const FilePath &name) override; + + private: + FilePath filePath; + }; + + class RawBufferView : public IFile { + public: + explicit RawBufferView() = default; + ~RawBufferView() override = default; + + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + bool ReadBin(std::vector &out) override; + bool ReadString(std::string &out) override; + + std::string GetPath() const override { return ""; } + + IStreamArchivePtr ReadAsArchive() override; + OStreamArchivePtr WriteAsArchive() override; + }; + + class IFileSystem : public RefObject { + public: + IFileSystem() = default; + ~IFileSystem() override = default; + + virtual bool FileExist(const FilePath &path) const = 0; + virtual FilePtr OpenFile(const FilePath &name) = 0; + virtual FilePtr CreateOrOpenFile(const FilePath &name) = 0; + }; + + class NativeFileSystem : public IFileSystem { + public: + explicit NativeFileSystem(const FilePath &root) : fsRoot(root) {} + ~NativeFileSystem() override = default; + + bool FileExist(const FilePath &path) const override; + FilePtr OpenFile(const FilePath &path) override; + FilePtr CreateOrOpenFile(const FilePath &path) override; + const FilePath &GetPath() const { return fsRoot; } + + void Copy(const FilePath &from, const FilePath &to) const; + bool IsSubDir(const std::string &path) const; + NativeFileSystemPtr CreateSubSystem(const std::string &path, bool createDir); + private: + FilePath fsRoot; + }; + + class PackageFileSystem : public IFileSystem { + public: + explicit PackageFileSystem(const std::string &pakPath) {} + ~PackageFileSystem() override = default; + }; +} // namespace sky \ No newline at end of file diff --git a/core/include/core/file/FileUtil.h b/runtime/core/include/core/file/FileUtil.h similarity index 91% rename from core/include/core/file/FileUtil.h rename to runtime/core/include/core/file/FileUtil.h index ebd72de0..69d9f70c 100644 --- a/core/include/core/file/FileUtil.h +++ b/runtime/core/include/core/file/FileUtil.h @@ -8,5 +8,4 @@ namespace sky { bool ConstructFullPath(const std::string &root, const std::string &relative, std::string &out); - -} \ No newline at end of file +} // namespace sky \ No newline at end of file diff --git a/core/include/core/hash/Crc32.h b/runtime/core/include/core/hash/Crc32.h similarity index 100% rename from core/include/core/hash/Crc32.h rename to runtime/core/include/core/hash/Crc32.h diff --git a/core/include/core/hash/Fnv1a.h b/runtime/core/include/core/hash/Fnv1a.h similarity index 100% rename from core/include/core/hash/Fnv1a.h rename to runtime/core/include/core/hash/Fnv1a.h diff --git a/core/include/core/hash/Hash.h b/runtime/core/include/core/hash/Hash.h similarity index 100% rename from core/include/core/hash/Hash.h rename to runtime/core/include/core/hash/Hash.h diff --git a/core/include/core/logger/Logger.h b/runtime/core/include/core/logger/Logger.h similarity index 100% rename from core/include/core/logger/Logger.h rename to runtime/core/include/core/logger/Logger.h diff --git a/core/include/core/math/Color.h b/runtime/core/include/core/math/Color.h similarity index 100% rename from core/include/core/math/Color.h rename to runtime/core/include/core/math/Color.h diff --git a/core/include/core/math/Euler.h b/runtime/core/include/core/math/Euler.h similarity index 100% rename from core/include/core/math/Euler.h rename to runtime/core/include/core/math/Euler.h diff --git a/core/include/core/math/Math.h b/runtime/core/include/core/math/Math.h similarity index 100% rename from core/include/core/math/Math.h rename to runtime/core/include/core/math/Math.h diff --git a/core/include/core/math/MathUtil.h b/runtime/core/include/core/math/MathUtil.h similarity index 59% rename from core/include/core/math/MathUtil.h rename to runtime/core/include/core/math/MathUtil.h index 5f665d40..dfb60d1f 100644 --- a/core/include/core/math/MathUtil.h +++ b/runtime/core/include/core/math/MathUtil.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include namespace sky { @@ -40,6 +42,11 @@ namespace sky { return {vec.x, vec.y, vec.z, 1.f}; } + inline Vector3 Cast(const Vector4 &vec) + { + return {vec.x, vec.y, vec.z}; + } + inline Matrix4 Cast(const Matrix3 &mat) { Matrix4 ret; @@ -50,6 +57,20 @@ namespace sky { return ret; } + inline Matrix3 Cast(const Matrix4 &mat) + { + Matrix3 ret; + ret.m[0] = Cast(mat[0]); + ret.m[1] = Cast(mat[1]); + ret.m[2] = Cast(mat[2]); + return ret; + } + + inline Vector4 Cast(const Color& color) + { + return {color.r, color.g, color.b, color.a}; + } + inline Matrix4 MakePerspective(float fovy, float aspect, float near, float far) { float const inverseHalfTan = cos(0.5f * fovy) / sin(0.5f * fovy); @@ -72,9 +93,80 @@ namespace sky { ret[3][0] = - (right + left) / (right - left); ret[3][1] = - (top + bottom) / (top - bottom); ret[3][2] = - (far + near) / (far - near); + ret[3][3] = 1.f; return ret; } + inline void Decompose(const Matrix4 &m, Vector3 &trans, Quaternion &quat, Vector3 &scale) + { + trans.x = m.v[12]; + trans.y = m.v[13]; + trans.z = m.v[14]; + + Vector3 xAxis(m.v[0], m.v[1], m.v[2]); + float scaleX = xAxis.Length(); + + Vector3 yAxis(m.v[4], m.v[5], m.v[6]); + float scaleY = yAxis.Length(); + + Vector3 zAxis(m.v[8], m.v[9], m.v[10]); + float scaleZ = zAxis.Length(); + + float det = m.Determinant(); + if (det < 0) { + scaleX = -scaleX; + } + scale.x = scaleX; + scale.y = scaleY; + scale.z = scaleZ; + + + float rn; + rn = 1.0F / scaleX; + xAxis.x *= rn; + xAxis.y *= rn; + xAxis.z *= rn; + + rn = 1.0F / scaleY; + yAxis.x *= rn; + yAxis.y *= rn; + yAxis.z *= rn; + + rn = 1.0F / scaleZ; + zAxis.x *= rn; + zAxis.y *= rn; + zAxis.z *= rn; + + float trace = xAxis.x + yAxis.y + zAxis.z; + if (trace > 0.0F) { + float s = 0.5F / std::sqrt(trace + 1.0F); + quat.w = 0.25F / s; + quat.x = (yAxis.z - zAxis.y) * s; + quat.y = (zAxis.x - xAxis.z) * s; + quat.z = (xAxis.y - yAxis.x) * s; + } else { + if (xAxis.x > yAxis.y && xAxis.x > zAxis.z) { + float s = 0.5F / std::sqrt(1.0F + xAxis.x - yAxis.y - zAxis.z); + quat.w = (yAxis.z - zAxis.y) * s; + quat.x = 0.25F / s; + quat.y = (yAxis.x + xAxis.y) * s; + quat.z = (zAxis.x + xAxis.z) * s; + } else if (yAxis.y > zAxis.z) { + float s = 0.5F / std::sqrt(1.0F + yAxis.y - xAxis.x - zAxis.z); + quat.w = (zAxis.x - xAxis.z) * s; + quat.x = (yAxis.x + xAxis.y) * s; + quat.y = 0.25F / s; + quat.z = (zAxis.y + yAxis.z) * s; + } else { + float s = 0.5F / std::sqrt(1.0F + zAxis.z - xAxis.x - yAxis.y); + quat.w = (xAxis.y - yAxis.x) * s; + quat.x = (zAxis.x + xAxis.z) * s; + quat.y = (zAxis.y + yAxis.z) * s; + quat.z = 0.25F / s; + } + } + } + inline Vector2 Min(const Vector2 &lhs, const Vector2 &rhs) { Vector2 ret; @@ -159,8 +251,13 @@ namespace sky { }; } - inline uint32_t Ceil(uint32_t v0, uint32_t v1) { + constexpr inline uint32_t Ceil(uint32_t v0, uint32_t v1) { return (v0 + v1 - 1) / v1; } + constexpr inline float FloatSelect(float comp, float ge, float lt) + { + return comp >= 0.f ? ge : lt; + } + } // namespace sky diff --git a/core/include/core/math/Matrix3.h b/runtime/core/include/core/math/Matrix3.h similarity index 100% rename from core/include/core/math/Matrix3.h rename to runtime/core/include/core/math/Matrix3.h diff --git a/core/include/core/math/Matrix3.inl b/runtime/core/include/core/math/Matrix3.inl similarity index 100% rename from core/include/core/math/Matrix3.inl rename to runtime/core/include/core/math/Matrix3.inl diff --git a/core/include/core/math/Matrix4.h b/runtime/core/include/core/math/Matrix4.h similarity index 97% rename from core/include/core/math/Matrix4.h rename to runtime/core/include/core/math/Matrix4.h index 2d23c95b..39584918 100644 --- a/core/include/core/math/Matrix4.h +++ b/runtime/core/include/core/math/Matrix4.h @@ -27,6 +27,7 @@ namespace sky { inline void Translate(const Vector3 &rhs); inline Matrix4 Inverse() const; inline Matrix4 InverseTranspose() const; + inline float Determinant() const; inline Matrix4 operator+(const Matrix4& rhs) const; inline Matrix4 operator-(const Matrix4& rhs) const; diff --git a/core/include/core/math/Matrix4.inl b/runtime/core/include/core/math/Matrix4.inl similarity index 88% rename from core/include/core/math/Matrix4.inl rename to runtime/core/include/core/math/Matrix4.inl index 963a270f..8d179025 100644 --- a/core/include/core/math/Matrix4.inl +++ b/runtime/core/include/core/math/Matrix4.inl @@ -117,6 +117,26 @@ namespace sky { m[3] = m[0] * rhs.v[0] + m[1] * rhs.v[1] + m[2] * rhs.v[2] + m[3]; } + inline float Matrix4::Determinant() const + { + float SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + float SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + float SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + float SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + float SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + float SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + Vector4 DetCof( + + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + return + m[0][0] * DetCof[0] + m[0][1] * DetCof[1] + + m[0][2] * DetCof[2] + m[0][3] * DetCof[3]; + } + inline Matrix4 Matrix4::Inverse() const { float c00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; diff --git a/core/include/core/math/Quaternion.h b/runtime/core/include/core/math/Quaternion.h similarity index 91% rename from core/include/core/math/Quaternion.h rename to runtime/core/include/core/math/Quaternion.h index 13926a60..baa2d7d3 100644 --- a/core/include/core/math/Quaternion.h +++ b/runtime/core/include/core/math/Quaternion.h @@ -6,6 +6,7 @@ #include #include +#include namespace sky { @@ -24,6 +25,7 @@ namespace sky { inline Quaternion(float w, float x, float y, float z); inline Quaternion(float angle, const Vector3 &axis); + inline float Dot(const Quaternion &rhs) const; inline void Normalize(); inline Quaternion Conjugate() const; diff --git a/core/include/core/math/Quaternion.inl b/runtime/core/include/core/math/Quaternion.inl similarity index 93% rename from core/include/core/math/Quaternion.inl rename to runtime/core/include/core/math/Quaternion.inl index 69b703ef..6b9a3f86 100644 --- a/core/include/core/math/Quaternion.inl +++ b/runtime/core/include/core/math/Quaternion.inl @@ -26,6 +26,11 @@ namespace sky { tmp.Normalize(); } + inline float Quaternion::Dot(const Quaternion &rhs) const + { + return x * rhs.x + y * rhs.y + z * rhs.z + w * rhs.w; + } + inline void Quaternion::Normalize() { float n = w * w + x * x + y * y + z * z; @@ -89,14 +94,16 @@ namespace sky { float sx = std::sin(euler.x); float cx = std::cos(euler.x); float sy = std::sin(euler.y); - float cy = std::cos(y); - float sz = std::sin(z); - float cz = std::cos(z); + float cy = std::cos(euler.y); + float sz = std::sin(euler.z); + float cz = std::cos(euler.z); x = sx * cy * cz + cx * sy * sz; y = cx * sy * cz + sx * cy * sz; z = cx * cy * sz - sx * sy * cz; w = cx * cy * cz - sx * sy * sz; + + Normalize(); } inline Vector3 Quaternion::ToEulerYZX() const diff --git a/core/include/core/math/Random.h b/runtime/core/include/core/math/Random.h similarity index 100% rename from core/include/core/math/Random.h rename to runtime/core/include/core/math/Random.h diff --git a/core/include/core/math/Sfmt.h b/runtime/core/include/core/math/Sfmt.h similarity index 100% rename from core/include/core/math/Sfmt.h rename to runtime/core/include/core/math/Sfmt.h diff --git a/core/include/core/math/Transform.h b/runtime/core/include/core/math/Transform.h similarity index 84% rename from core/include/core/math/Transform.h rename to runtime/core/include/core/math/Transform.h index 196c2c8a..c7d39780 100644 --- a/core/include/core/math/Transform.h +++ b/runtime/core/include/core/math/Transform.h @@ -56,16 +56,6 @@ namespace sky { return matR; } -// static Transform FromMatrix(const Matrix4 &matrix) -// { -// Transform result; -// glm::vec3 skew; -// glm::vec4 perspective; -// glm::decompose(matrix, result.scale, result.rotation, result.translation, skew, perspective); -// return result; -// return {}; -// } - static const Transform &GetIdentity() { static Transform transform; diff --git a/core/include/core/math/Util.h b/runtime/core/include/core/math/Util.h similarity index 100% rename from core/include/core/math/Util.h rename to runtime/core/include/core/math/Util.h diff --git a/core/include/core/math/Vector2.h b/runtime/core/include/core/math/Vector2.h similarity index 79% rename from core/include/core/math/Vector2.h rename to runtime/core/include/core/math/Vector2.h index b5e1f2f8..1dc15592 100644 --- a/core/include/core/math/Vector2.h +++ b/runtime/core/include/core/math/Vector2.h @@ -18,9 +18,9 @@ namespace sky { }; }; - inline Vector2(); - inline explicit Vector2(float v); - inline Vector2(float x_, float y_); + inline constexpr Vector2(); + inline constexpr explicit Vector2(float v); + inline constexpr Vector2(float x_, float y_); inline float Dot(const Vector2 &rhs) const; inline float Length() const; @@ -49,4 +49,9 @@ namespace sky { }; } -#include "core/math/Vector2.inl" \ No newline at end of file +#include "core/math/Vector2.inl" + +namespace sky { + static constexpr Vector2 VEC2_ZERO = Vector2(); + static constexpr Vector2 VEC2_ONE = Vector2(1, 1); +} // namespace sky \ No newline at end of file diff --git a/core/include/core/math/Vector2.inl b/runtime/core/include/core/math/Vector2.inl similarity index 91% rename from core/include/core/math/Vector2.inl rename to runtime/core/include/core/math/Vector2.inl index 5beab65a..71e52ebe 100644 --- a/core/include/core/math/Vector2.inl +++ b/runtime/core/include/core/math/Vector2.inl @@ -4,15 +4,15 @@ namespace sky { - inline Vector2::Vector2() : Vector2(0, 0) + inline constexpr Vector2::Vector2() : Vector2(0, 0) { } - inline Vector2::Vector2(float v) : Vector2(v, v) + inline constexpr Vector2::Vector2(float v) : Vector2(v, v) { } - inline Vector2::Vector2(float x_, float y_) : x(x_), y(y_) + inline constexpr Vector2::Vector2(float x_, float y_) : x(x_), y(y_) { } diff --git a/core/include/core/math/Vector3.h b/runtime/core/include/core/math/Vector3.h similarity index 100% rename from core/include/core/math/Vector3.h rename to runtime/core/include/core/math/Vector3.h diff --git a/core/include/core/math/Vector3.inl b/runtime/core/include/core/math/Vector3.inl similarity index 100% rename from core/include/core/math/Vector3.inl rename to runtime/core/include/core/math/Vector3.inl diff --git a/core/include/core/math/Vector4.h b/runtime/core/include/core/math/Vector4.h similarity index 96% rename from core/include/core/math/Vector4.h rename to runtime/core/include/core/math/Vector4.h index 86696be6..0f9452ca 100644 --- a/core/include/core/math/Vector4.h +++ b/runtime/core/include/core/math/Vector4.h @@ -21,7 +21,7 @@ namespace sky { }; inline constexpr Vector4(); - inline constexpr Vector4(float v); + inline constexpr Vector4(float v); // NOLINT inline constexpr Vector4(float x_, float y_, float z_, float w_); inline void Normalize(); diff --git a/core/include/core/math/Vector4.inl b/runtime/core/include/core/math/Vector4.inl similarity index 100% rename from core/include/core/math/Vector4.inl rename to runtime/core/include/core/math/Vector4.inl diff --git a/runtime/core/include/core/memory/Allocator.h b/runtime/core/include/core/memory/Allocator.h new file mode 100644 index 00000000..e338c8db --- /dev/null +++ b/runtime/core/include/core/memory/Allocator.h @@ -0,0 +1,46 @@ +// +// Created by blues on 2024/4/6. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + static constexpr size_t DEFAULT_ALLOC_ALIGNMENT = 8; + + class IAllocator { + public: + IAllocator() = default; + virtual ~IAllocator() = default; + + virtual void *Allocate(size_t size, size_t alignment) = 0; + virtual void Deallocate(void *ptr) = 0; + }; + + class SystemAllocator : public Singleton { + public: + SystemAllocator(); + ~SystemAllocator() override = default; + + void *Allocate(size_t size, size_t alignment); + void Deallocate(void *ptr); + + private: + std::unique_ptr impl; + }; + + +#define SKY_ALLOCATOR(Name, Allocator) \ + inline void* operator new(size_t size) \ + { \ + return Allocator::Get()->Allocate(size, alignof(Name)); \ + } \ + inline void operator delete(void* ptr, size_t size) \ + { \ + if (ptr) Allocator::Get()->Deallocate(ptr); \ + } +} // namespace sky \ No newline at end of file diff --git a/core/include/core/memory/LinearStorage.h b/runtime/core/include/core/memory/LinearStorage.h similarity index 100% rename from core/include/core/memory/LinearStorage.h rename to runtime/core/include/core/memory/LinearStorage.h diff --git a/runtime/core/include/core/memory/LinkedStorage.h b/runtime/core/include/core/memory/LinkedStorage.h new file mode 100644 index 00000000..64e9c186 --- /dev/null +++ b/runtime/core/include/core/memory/LinkedStorage.h @@ -0,0 +1,52 @@ +// +// Created by blues on 2024/4/6. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + template + class LinkedStorage { + public: + explicit LinkedStorage(uint32_t blockSize_) : blockSize(blockSize_) {} + ~LinkedStorage() = default; + + uint8_t *Allocate(uint32_t size, uint32_t alignment) + { + if (storages.empty()) { + NewStorage(); + return AllocateImpl(size, alignment); + } + + uint8_t *ptr = AllocateImpl(size, alignment); + if (ptr == nullptr) { + NewStorage(); + ptr = AllocateImpl(size, alignment); + } + return ptr; + } + + void NewStorage() + { + storages.emplace_back(std::make_unique(blockSize)); + } + + private: + uint8_t *AllocateImpl(uint32_t size, uint32_t alignment) + { + auto &storage = storages.back(); + return storage->Allocate(Align(size, alignment)); + } + + using StoragePtr = std::unique_ptr; + std::list storages; + + uint32_t blockSize = 16; + }; + +} // namespace sky \ No newline at end of file diff --git a/core/include/core/memory/TLSFAllocator.h b/runtime/core/include/core/memory/TLSFAllocator.h similarity index 100% rename from core/include/core/memory/TLSFAllocator.h rename to runtime/core/include/core/memory/TLSFAllocator.h diff --git a/core/include/core/platform/Platform.h b/runtime/core/include/core/platform/Platform.h similarity index 95% rename from core/include/core/platform/Platform.h rename to runtime/core/include/core/platform/Platform.h index 36e594de..a965fac7 100644 --- a/core/include/core/platform/Platform.h +++ b/runtime/core/include/core/platform/Platform.h @@ -8,7 +8,7 @@ #include #define SKY_ASSERT(val) assert(val); #else -#define SKY_ASSERT(val) +#define SKY_ASSERT(val) (val) #endif #ifdef _DEBUG diff --git a/runtime/core/include/core/profile/Profiler.h b/runtime/core/include/core/profile/Profiler.h new file mode 100644 index 00000000..3c8a2b14 --- /dev/null +++ b/runtime/core/include/core/profile/Profiler.h @@ -0,0 +1,16 @@ +// +// Created by blues on 2024/3/1. +// + +#pragma once + +#ifdef TRACY_ENABLE +#include +#define SKY_PROFILE_FRAME FrameMark +#define SKY_PROFILE_SCOPE ZoneScoped +#define SKY_PROFILE_NAME(name) ZoneScopedN(name) +#else +#define SKY_PROFILE_FRAME +#define SKY_PROFILE_SCOPE +#define SKY_PROFILE_NAME(name) +#endif \ No newline at end of file diff --git a/runtime/core/include/core/shapes/AABB.h b/runtime/core/include/core/shapes/AABB.h new file mode 100644 index 00000000..aee89949 --- /dev/null +++ b/runtime/core/include/core/shapes/AABB.h @@ -0,0 +1,26 @@ +// +// Created by Zach Lee on 2023/8/29. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + struct AABB { + Vector3 min; + Vector3 max; + + inline constexpr AABB() : min(VEC3_ZERO), max(VEC3_ZERO) {} + inline constexpr AABB(Vector3 min_, Vector3 max_) : min(min_), max(max_) {} + + static AABB Transform(const AABB& box, const Matrix4 &matrix); + }; + + void Merge(const AABB &a, const AABB &b, AABB &out); + + static constexpr AABB AABB_MAX = AABB(Vector3(std::numeric_limits::min()), Vector3(std::numeric_limits::max())); +} // namespace sky diff --git a/core/include/core/shapes/Base.h b/runtime/core/include/core/shapes/Base.h similarity index 50% rename from core/include/core/shapes/Base.h rename to runtime/core/include/core/shapes/Base.h index 6193ed1e..d5736463 100644 --- a/core/include/core/shapes/Base.h +++ b/runtime/core/include/core/shapes/Base.h @@ -4,7 +4,9 @@ #pragma once +#include #include +#include namespace sky { @@ -14,16 +16,31 @@ namespace sky { }; struct Triangle { - std::array v; + std::array v; }; struct Quad { std::array v; }; + struct Rect { + Vector2 offset = VEC2_ZERO; + Vector2 ext = VEC2_ZERO; + }; + struct Plane { Vector3 normal = VEC3_Y; float distance = 0; }; + struct Sphere { + Vector3 center = VEC3_ZERO; + float radius = 1.f; + }; + + struct Capsule { + float halfHeight = 1.f; + float radius = 1.f; + }; + } // namespace sky \ No newline at end of file diff --git a/core/include/core/shapes/Frustum.h b/runtime/core/include/core/shapes/Frustum.h similarity index 100% rename from core/include/core/shapes/Frustum.h rename to runtime/core/include/core/shapes/Frustum.h diff --git a/core/include/core/shapes/Shapes.h b/runtime/core/include/core/shapes/Shapes.h similarity index 100% rename from core/include/core/shapes/Shapes.h rename to runtime/core/include/core/shapes/Shapes.h diff --git a/core/include/core/std/Container.h b/runtime/core/include/core/std/Container.h similarity index 100% rename from core/include/core/std/Container.h rename to runtime/core/include/core/std/Container.h diff --git a/core/include/core/template/Cast.h b/runtime/core/include/core/template/Cast.h similarity index 100% rename from core/include/core/template/Cast.h rename to runtime/core/include/core/template/Cast.h diff --git a/core/include/core/template/FixedChunkArray.h b/runtime/core/include/core/template/FixedChunkArray.h similarity index 100% rename from core/include/core/template/FixedChunkArray.h rename to runtime/core/include/core/template/FixedChunkArray.h diff --git a/core/include/core/template/Flags.h b/runtime/core/include/core/template/Flags.h similarity index 82% rename from core/include/core/template/Flags.h rename to runtime/core/include/core/template/Flags.h index 1b91d6ba..24ed0000 100644 --- a/core/include/core/template/Flags.h +++ b/runtime/core/include/core/template/Flags.h @@ -11,7 +11,7 @@ namespace sky { template class Flags { public: - using ValueType = typename std::make_unsigned>::type ; + using ValueType = std::make_unsigned_t> ; static constexpr ValueType AllFlagBits() { @@ -89,7 +89,12 @@ namespace sky { return *this; } - explicit constexpr operator bool() const noexcept + constexpr bool TestBit(T val) noexcept + { + return operator&(val) == val; + } + + constexpr operator bool() const noexcept { return value != 0; } @@ -120,6 +125,20 @@ namespace sky { return flags.operator^( bit ); } +#define ENABLE_FLAG_BIT_OPERATOR(Type) \ + constexpr Flags operator&(Type const& lhs, Type const& rhs) noexcept \ + { \ + return Flags(lhs) & rhs; \ + } \ + constexpr Flags operator|(Type const& lhs, Type const& rhs) noexcept \ + { \ + return Flags(lhs) | rhs; \ + } \ + constexpr Flags operator^(Type const& lhs, Type const& rhs) noexcept \ + { \ + return Flags(lhs) ^ rhs; \ + } + } // namespace sky namespace std { diff --git a/core/include/core/template/ObjectPool.h b/runtime/core/include/core/template/ObjectPool.h similarity index 100% rename from core/include/core/template/ObjectPool.h rename to runtime/core/include/core/template/ObjectPool.h diff --git a/core/include/core/template/Overloaded.h b/runtime/core/include/core/template/Overloaded.h similarity index 100% rename from core/include/core/template/Overloaded.h rename to runtime/core/include/core/template/Overloaded.h diff --git a/runtime/core/include/core/template/ReferenceObject.h b/runtime/core/include/core/template/ReferenceObject.h new file mode 100644 index 00000000..660d1d66 --- /dev/null +++ b/runtime/core/include/core/template/ReferenceObject.h @@ -0,0 +1,166 @@ +// +// Created by Zach Lee on 2021/12/19. +// + +#pragma once + +#include +#include + +namespace sky { + + class RefObject { + public: + RefObject() = default; + virtual ~RefObject() = default; + + void AddRef() noexcept + { + counter.fetch_add(1); + } + + void RemoveRef() noexcept + { + auto prev = counter.fetch_sub(1); + SKY_ASSERT(prev >= 1); + if (prev == 1) { + OnExpire(); + } + } + + uint32_t GetRef() const + { + return counter.load(); + } + + protected: + virtual void OnExpire() noexcept + { + delete this; + } + + std::atomic_uint32_t counter; + }; + + template + class CounterPtr { + public: + CounterPtr() : ptr(nullptr) {} + + CounterPtr(T *p) // NOLINT + { + Reset(p); + } + + CounterPtr(const CounterPtr &p) : CounterPtr(p.Get()) + { + } + + CounterPtr(CounterPtr &&p) noexcept + { + if (ptr != nullptr) { + ptr->RemoveRef(); + } + ptr = p.Release(); + } + + template + CounterPtr(const CounterPtr &p) : CounterPtr(static_cast(p.Get())) // NOLINT + { + } + + CounterPtr &operator=(const CounterPtr &p) noexcept + { + Reset(p.ptr); + return *this; + } + + template + CounterPtr &operator=(U *p) + { + static_assert(std::is_base_of_v); + Reset(static_cast(p)); + return *this; + } + + template + CounterPtr &operator=(const CounterPtr &p) + { + static_assert(std::is_base_of_v); + Reset(static_cast(p.Get())); + return *this; + } + + template + CounterPtr &operator=(CounterPtr &&p) + { + static_assert(std::is_base_of_v); + if (ptr != nullptr) { + ptr->RemoveRef(); + } + ptr = static_cast(p.Release()); + return *this; + } + + virtual ~CounterPtr() + { + if (ptr != nullptr) { + ptr->RemoveRef(); + } + } + + void Reset(T *p) noexcept + { + if (ptr != nullptr) { + ptr->RemoveRef(); + } + ptr = p; + if (ptr != nullptr) { + ptr->AddRef(); + } + } + + T* Release() + { + T* ret = ptr; + ptr = nullptr; + return ret; + } + + T *Get() const { return ptr; } + T &operator*() const { return *ptr; } + T *operator->() const { return ptr; } + explicit operator bool() const { return ptr != nullptr; } + + protected: + template + friend class CounterPtr; + + T *ptr = nullptr; + }; + + template< class T > + bool operator==(const CounterPtr& p, std::nullptr_t) noexcept + { + return p.Get() == nullptr; + } + + template< class T > + bool operator!=(const CounterPtr& p, std::nullptr_t) noexcept + { + return p.Get() != nullptr; + } + + template< class T > + bool operator==(std::nullptr_t, const CounterPtr& p) noexcept + { + return p.Get() == nullptr; + } + + template< class T > + bool operator!=(std::nullptr_t, const CounterPtr& p) noexcept + { + return p.Get() != nullptr; + } + +} // namespace sky \ No newline at end of file diff --git a/core/include/core/template/Result.h b/runtime/core/include/core/template/Result.h similarity index 100% rename from core/include/core/template/Result.h rename to runtime/core/include/core/template/Result.h diff --git a/runtime/core/include/core/type/Rtti.h b/runtime/core/include/core/type/Rtti.h new file mode 100644 index 00000000..3efd0368 --- /dev/null +++ b/runtime/core/include/core/type/Rtti.h @@ -0,0 +1,136 @@ +// +// Created by Zach Lee on 2021/12/3. +// + +#pragma once + +#include +#include +#include +#include + +#ifdef _MSC_VER +#define PRETTY_FUNC __FUNCSIG__ +#else +#define PRETTY_FUNC __PRETTY_FUNCTION__ +#endif + +namespace sky { + + template + constexpr std::string_view PrettyFunc() + { + return PRETTY_FUNC; + } + + + constexpr std::string_view GetClassNameFromPrettyFunc(std::string_view prettyFunc) + { +#ifdef _MSC_VER + auto t1 = prettyFunc.find_first_of(' ', prettyFunc.find("PrettyFunc<")) + 1; + return prettyFunc.substr(t1, prettyFunc.find_last_of('>') - t1); +#else + auto t1 = prettyFunc.find_first_not_of(' ', prettyFunc.find_first_of('=') + 1); + return prettyFunc.substr(t1, prettyFunc.find_first_of("];", t1) - t1); +#endif + } + + template + constexpr std::string_view GetClassNameWithNameSpace() + { + static_assert(!std::is_fundamental_v); + return GetClassNameFromPrettyFunc(PrettyFunc()); + } + + struct StaticTypeInfo { + const size_t rank; + const size_t size; + const bool isFundamental; + const bool isVoid; + const bool isNullptr; + const bool isArithmetic; + const bool isFloatingPoint; + const bool isInteger; + const bool isCompound; + const bool isPointer; + const bool isMemberObjectPointer; + const bool isMemberFunctionPointer; + const bool isArray; + const bool isEnum; + const bool isUnion; + const bool isClass; + const bool isTrivial; + }; + + using DestructorDelete = void (*)(void *ptr); + using Destructor = void (*)(void *ptr); + using ConstructorNew = void* (*)(); + using ConstructorPlace = void (*)(void *ptr); + using CopyFn = void (*)(const void *src, void *dst); + + struct TypeInfoRT { + std::string_view name; + Uuid registeredId; + Uuid underlyingTypeId; + const StaticTypeInfo* staticInfo = nullptr; + ConstructorNew newFunc = nullptr; // default constructor + ConstructorPlace placeFunc = nullptr; // default constructor + DestructorDelete deleteFunc = nullptr; // default destructor + Destructor destructor = nullptr; // default destructor + CopyFn copy = nullptr; // default copy constructor + }; + + // There may be different values on different platforms, limited to runtime and not persistent. + template + static constexpr uint32_t RuntimeTypeId() + { + return Fnv1a32(PrettyFunc()); + } + + template + struct TypeAllocate { + static constexpr bool CTOR = std::is_default_constructible_v; + static constexpr bool DTOR = std::is_destructible_v; + static constexpr bool COPY = std::is_copy_constructible_v; + + static void Construct(void *ptr) + { + if constexpr (CTOR) { + new (ptr) T{}; + } + } + + static void Destruct(void *ptr) + { + if constexpr (DTOR) { + if (T *p = static_cast(ptr); p != nullptr) { + p->~T(); + } + } + } + + static void* New() + { + if constexpr (CTOR) { + return new T(); + } + return nullptr; + } + + static void Delete(void *ptr) + { + if constexpr (DTOR) { + if (T *p = static_cast(ptr); p != nullptr) { + delete p; + } + } + } + + static void Copy(const void *src, void *dst) + { + if constexpr (COPY) { + new(dst) T{*((T *) src)}; + } + } + }; +} // namespace sky diff --git a/runtime/core/include/core/type/Type.h b/runtime/core/include/core/type/Type.h new file mode 100644 index 00000000..3a017010 --- /dev/null +++ b/runtime/core/include/core/type/Type.h @@ -0,0 +1,84 @@ +// +// Created by Zach Lee on 2021/12/9. +// + +#pragma once +#include + +namespace sky { + + template + const StaticTypeInfo &TypeInfoStatic() + { + static const StaticTypeInfo info = { + std::rank_v, // rank + sizeof(T), // size + std::is_fundamental_v, // isFundamental + std::is_void_v, // isVoid + std::is_null_pointer_v, // isNullptr + std::is_arithmetic_v, // isArithmetic + std::is_floating_point_v, // isFloatingPoint + std::is_integral_v, // isInteger + std::is_compound_v, // isCompound + std::is_pointer_v, // isPointer + std::is_member_pointer_v, // isMemberObjectPointer + std::is_member_function_pointer_v, // isMemberFunctionPointer + std::is_array_v, // isArray; + std::is_enum_v, // isEnum; + std::is_union_v, // isUnion; + std::is_class_v, // isClass; + std::is_trivial_v, // isTrivial; + }; + return info; + } + +#define IF_CONSTEXPR_FUNDAMENTAL(NAME) if constexpr(std::is_same_v()) return #NAME; + + template + std::string_view GetArithmeticName() + { + static_assert(std::is_arithmetic_v); + static_assert(!std::is_same_v()); + static_assert(!std::is_same_v()); + + IF_CONSTEXPR_FUNDAMENTAL(int8_t) + else IF_CONSTEXPR_FUNDAMENTAL(uint8_t) + else IF_CONSTEXPR_FUNDAMENTAL(int16_t) + else IF_CONSTEXPR_FUNDAMENTAL(uint16_t) + else IF_CONSTEXPR_FUNDAMENTAL(int32_t) + else IF_CONSTEXPR_FUNDAMENTAL(uint32_t) + else IF_CONSTEXPR_FUNDAMENTAL(int64_t) + else IF_CONSTEXPR_FUNDAMENTAL(uint64_t) + else IF_CONSTEXPR_FUNDAMENTAL(float) + else IF_CONSTEXPR_FUNDAMENTAL(double) + } + + + template + struct FuncTraits { + static constexpr bool CONST = false; + }; + + template + struct FuncTraits { + using CLASS_TYPE = Cls; + using RET_TYPE = Ret; + using ARGS_TYPE = std::tuple; + static constexpr bool CONST = false; + }; + + template + struct FuncTraits { + using CLASS_TYPE = Cls; + using RET_TYPE = Ret; + using ARGS_TYPE = std::tuple; + static constexpr bool CONST = true; + }; + + template + struct FuncTraits { + using RET_TYPE = Ret; + using ARGS_TYPE = std::tuple; + }; + +} // namespace sky diff --git a/runtime/core/include/core/type/TypeInfo.h b/runtime/core/include/core/type/TypeInfo.h new file mode 100644 index 00000000..c4e6a2cb --- /dev/null +++ b/runtime/core/include/core/type/TypeInfo.h @@ -0,0 +1,19 @@ +// +// Created by blues on 2024/5/5. +// + +#pragma once + +#include + +namespace sky { + + template + struct TypeInfo { + static const Uuid &RegisteredId() + { + return TypeInfoObj::Get()->RtInfo()->registeredId; + } + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/core/include/core/type/TypeInfoObj.h b/runtime/core/include/core/type/TypeInfoObj.h new file mode 100644 index 00000000..9c65c99e --- /dev/null +++ b/runtime/core/include/core/type/TypeInfoObj.h @@ -0,0 +1,61 @@ +// +// Created by blues on 2024/5/5. +// + +#pragma once +#include +#include +#include +#include + +namespace sky { + + template + class TypeInfoObj : public Singleton> { + public: + const TypeInfoRT *Register(std::string_view name, const Uuid &uuid, const Uuid &underlyingId = {}) + { + std::lock_guard lock(mutex); + if (info == nullptr) { + info = new TypeInfoRT { + name, + uuid, + underlyingId, + &TypeInfoStatic(), + TypeAllocate::CTOR ? &TypeAllocate::New : nullptr, + TypeAllocate::CTOR ? &TypeAllocate::Construct : nullptr, + TypeAllocate::DTOR ? &TypeAllocate::Delete : nullptr, + TypeAllocate::DTOR ? &TypeAllocate::Destruct : nullptr, + TypeAllocate::COPY ? &TypeAllocate::Copy : nullptr + }; + } else { + info->name = name; + info->registeredId = uuid; + } + return info; + } + + const TypeInfoRT *RtInfo() + { + if (info == nullptr) { + info = new TypeInfoRT { + "", + {}, + {}, + &TypeInfoStatic(), + TypeAllocate::CTOR ? &TypeAllocate::New : nullptr, + TypeAllocate::CTOR ? &TypeAllocate::Construct : nullptr, + TypeAllocate::DTOR ? &TypeAllocate::Delete : nullptr, + TypeAllocate::DTOR ? &TypeAllocate::Destruct : nullptr, + TypeAllocate::COPY ? &TypeAllocate::Copy : nullptr + }; + } + return info; + } + + private: + std::mutex mutex; + TypeInfoRT *info = nullptr; + }; + +} // namespace sky \ No newline at end of file diff --git a/core/include/core/util/ArrayBitFlag.h b/runtime/core/include/core/util/ArrayBitFlag.h similarity index 69% rename from core/include/core/util/ArrayBitFlag.h rename to runtime/core/include/core/util/ArrayBitFlag.h index 9107f4a8..efeda2fc 100644 --- a/core/include/core/util/ArrayBitFlag.h +++ b/runtime/core/include/core/util/ArrayBitFlag.h @@ -6,6 +6,7 @@ #include #include +#include namespace sky { @@ -46,7 +47,7 @@ namespace sky { void SetBit(const T &v) noexcept { - auto val = static_cast>(v); + auto val = static_cast(v); uint32_t index = val / STEP; uint32_t offset = val % STEP; values[index] |= (1 << offset); @@ -54,7 +55,7 @@ namespace sky { void ResetBit(const T &v) noexcept { - auto val = static_cast>(v); + auto val = static_cast(v); uint32_t index = val / STEP; uint32_t offset = val % STEP; values[index] &= ~(1 << offset); @@ -62,7 +63,7 @@ namespace sky { bool CheckBit(const T &v) noexcept { - auto val = static_cast>(v); + auto val = static_cast(v); uint32_t index = val / STEP; uint32_t offset = val % STEP; return (values[index] & (1 << offset)) != 0; @@ -76,17 +77,40 @@ namespace sky { return *this; } + ArrayBit operator&(const ArrayBit &val) noexcept + { + return ArrayBit(*this) &= val; + } + + bool operator==(const ArrayBit& val) const noexcept { return memcmp(&values[0], &val.values[0], sizeof(values)) == 0; } - private: + std::array values; }; +} - template - ArrayBit operator&(const ArrayBit &lhs, const ArrayBit &rhs) +namespace std { + + template + struct hash> { + size_t operator()(const sky::ArrayBit &flags) const noexcept { - ArrayBit res = lhs; - return res &= rhs; + uint32_t hash = 0; + for (const auto &val : flags.values) { + sky::HashCombine32(hash, val); + } + return hash; } -} +}; + +template +struct equal_to> { + bool operator()(const sky::ArrayBit &x, const sky::ArrayBit &y) const noexcept + { + return x == y; + } +}; + +} // namespace std diff --git a/core/include/core/util/DynamicModule.h b/runtime/core/include/core/util/DynamicModule.h similarity index 100% rename from core/include/core/util/DynamicModule.h rename to runtime/core/include/core/util/DynamicModule.h diff --git a/core/include/core/util/Macros.h b/runtime/core/include/core/util/Macros.h similarity index 100% rename from core/include/core/util/Macros.h rename to runtime/core/include/core/util/Macros.h diff --git a/core/include/core/util/Memory.h b/runtime/core/include/core/util/Memory.h similarity index 100% rename from core/include/core/util/Memory.h rename to runtime/core/include/core/util/Memory.h diff --git a/runtime/core/include/core/util/Name.h b/runtime/core/include/core/util/Name.h new file mode 100644 index 00000000..910e65b3 --- /dev/null +++ b/runtime/core/include/core/util/Name.h @@ -0,0 +1,13 @@ +// +// Created by blues on 2024/8/1. +// + +#pragma once + +#include + +namespace sky { + + using Name = std::string; + +} // namespace \ No newline at end of file diff --git a/core/include/core/util/Overloaded.h b/runtime/core/include/core/util/Overloaded.h similarity index 100% rename from core/include/core/util/Overloaded.h rename to runtime/core/include/core/util/Overloaded.h diff --git a/core/include/core/util/String.h b/runtime/core/include/core/util/String.h similarity index 60% rename from core/include/core/util/String.h rename to runtime/core/include/core/util/String.h index ce243226..60dd5bdf 100644 --- a/core/include/core/util/String.h +++ b/runtime/core/include/core/util/String.h @@ -8,5 +8,11 @@ #include namespace sky { + namespace String { + const std::string &GetEmpty(); + } + std::vector Split(const std::string& s, const char *separator); + + std::wstring Utf8ToUtf16(const std::string &path); } \ No newline at end of file diff --git a/core/include/core/util/Uuid.h b/runtime/core/include/core/util/Uuid.h similarity index 96% rename from core/include/core/util/Uuid.h rename to runtime/core/include/core/util/Uuid.h index 8353e213..9c42bf6a 100644 --- a/core/include/core/util/Uuid.h +++ b/runtime/core/include/core/util/Uuid.h @@ -36,6 +36,8 @@ namespace sky { ~Uuid() = default; + static const Uuid &GetEmpty(); + static Uuid Create(); static Uuid CreateWithSeed(uint32_t); @@ -69,6 +71,7 @@ namespace sky { } std::string ToString() const; + void FromString(const std::string & string); explicit operator bool() const { diff --git a/core/platform/macos/async/Semaphore.cpp b/runtime/core/platform/macos/async/Semaphore.cpp similarity index 100% rename from core/platform/macos/async/Semaphore.cpp rename to runtime/core/platform/macos/async/Semaphore.cpp diff --git a/core/platform/unix/async/Semaphore.cpp b/runtime/core/platform/unix/async/Semaphore.cpp similarity index 100% rename from core/platform/unix/async/Semaphore.cpp rename to runtime/core/platform/unix/async/Semaphore.cpp diff --git a/core/platform/windows/async/Semaphore.cpp b/runtime/core/platform/windows/async/Semaphore.cpp similarity index 100% rename from core/platform/windows/async/Semaphore.cpp rename to runtime/core/platform/windows/async/Semaphore.cpp diff --git a/runtime/core/src/archive/FileArchive.cpp b/runtime/core/src/archive/FileArchive.cpp new file mode 100644 index 00000000..64cc59dd --- /dev/null +++ b/runtime/core/src/archive/FileArchive.cpp @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/2/7. +// + +#include + +namespace sky { + + IFileArchive::IFileArchive(const FilePath &path, std::ios::openmode mode) + : stream(path.OpenFStream(mode | std::ios::in)) + , IStreamArchive(stream) + { + } + + OFileArchive::OFileArchive(const FilePath &path, std::ios::openmode mode) + : stream(path.OpenFStream(mode | std::ios::out)) + , OStreamArchive(stream) + { + } + +} // namespace sky diff --git a/runtime/core/src/archive/MemoryAchive.cpp b/runtime/core/src/archive/MemoryAchive.cpp new file mode 100644 index 00000000..8181bbdb --- /dev/null +++ b/runtime/core/src/archive/MemoryAchive.cpp @@ -0,0 +1,10 @@ +// +// Created by blues on 2024/1/14. +// + +#include + +namespace sky { + + +} // namespace sky \ No newline at end of file diff --git a/runtime/core/src/archive/StreamArchive.cpp b/runtime/core/src/archive/StreamArchive.cpp new file mode 100644 index 00000000..f9c1c0be --- /dev/null +++ b/runtime/core/src/archive/StreamArchive.cpp @@ -0,0 +1,73 @@ +// +// Created by blues on 2023/10/11. +// + +#include "core/archive/StreamArchive.h" + +namespace sky { + + int StreamArchive::Peek() + { + return stream.peek(); + } + + int StreamArchive::Get() + { + return stream.get(); + } + + size_t StreamArchive::Tell() const + { + return stream.tellg(); + } + + void StreamArchive::Put(char ch) + { + stream.rdbuf()->sputc(ch); + } + + bool StreamArchive::LoadRaw(char *data, size_t size) + { + return stream.rdbuf()->sgetn(data, static_cast(size)) == size; + } + + bool StreamArchive::SaveRaw(const char *data, size_t size) + { + return stream.rdbuf()->sputn(data, static_cast(size)) == size; + } + + bool IStreamArchive::LoadRaw(char *data, size_t size) + { + return stream.rdbuf()->sgetn(data, static_cast(size)) == size; + } + + int IStreamArchive::Peek() + { + return stream.peek(); + } + + int IStreamArchive::Get() + { + return stream.get(); + } + + size_t IStreamArchive::Tell() const + { + return static_cast(stream.tellg()); + } + + bool OStreamArchive::SaveRaw(const char *data, size_t size) + { + return stream.rdbuf()->sputn(data, static_cast(size)) == size; + } + + void OStreamArchive::Put(char ch) + { + stream.put(ch); + } + + void OStreamArchive::Flush() + { + stream.flush(); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/core/src/async/Task.cpp b/runtime/core/src/async/Task.cpp new file mode 100644 index 00000000..0818aa53 --- /dev/null +++ b/runtime/core/src/async/Task.cpp @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/9/6. +// + +#include + +namespace sky { + + void TaskExecutor::ExecuteTask(const TaskPtr &task) + { + executor.dependent_async([task]() { + bool result = task->DoWork(); + task->OnComplete(result); + }); + } + + void TaskExecutor::WaitForAll() + { + executor.wait_for_all(); + } +} // namespace sky \ No newline at end of file diff --git a/core/src/environment/Environment.cpp b/runtime/core/src/environment/Environment.cpp similarity index 100% rename from core/src/environment/Environment.cpp rename to runtime/core/src/environment/Environment.cpp diff --git a/core/src/file/FileIO.cpp b/runtime/core/src/file/FileIO.cpp similarity index 59% rename from core/src/file/FileIO.cpp rename to runtime/core/src/file/FileIO.cpp index 80435624..5163554b 100644 --- a/core/src/file/FileIO.cpp +++ b/runtime/core/src/file/FileIO.cpp @@ -8,27 +8,27 @@ namespace sky { - void WriteBin(const std::string &path, const char *data, size_t size) + void WriteBin(const FilePath &path, const char *data, size_t size) { - std::ofstream file(path, std::ios::binary | std::ios::trunc); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::trunc | std::ios::out)); if (!file.is_open()) { return; } file.write(data, size); } - void WriteString(const std::string &path, const std::string &out) + void WriteString(const FilePath &path, const std::string &out) { - std::ofstream file(path, std::ios::binary | std::ios::trunc); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::trunc | std::ios::out)); if (!file.is_open()) { return; } file.write(out.data(), out.size() + 1); } - bool ReadBin(const std::string &path, uint8_t *&out, uint32_t &size) + bool ReadBin(const FilePath &path, uint8_t *&out, uint32_t &size) { - std::ifstream file(path, std::ios::ate | std::ios::binary); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::ate | std::ios::in)); if (!file.is_open()) { return false; } @@ -40,9 +40,9 @@ namespace sky { return true; } - bool ReadBin(const std::string &path, std::vector &out) + bool ReadBin(const FilePath &path, std::vector &out) { - std::ifstream file(path, std::ios::ate | std::ios::binary); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::ate | std::ios::in)); if (!file.is_open()) { return false; } @@ -54,9 +54,9 @@ namespace sky { return true; } - bool ReadBin(const std::string &path, std::vector &out) + bool ReadBin(const FilePath &path, std::vector &out) { - std::ifstream file(path, std::ios::ate | std::ios::binary); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::ate | std::ios::in)); if (!file.is_open()) { return false; } @@ -68,9 +68,9 @@ namespace sky { return true; } - bool ReadString(const std::string &path, std::string &out) + bool ReadString(const FilePath &path, std::string &out) { - std::ifstream file(path, std::ios::binary); + std::fstream file(path.OpenFStream(std::ios::binary | std::ios::in)); if (!file.is_open()) { return false; } diff --git a/runtime/core/src/file/FileSystem.cpp b/runtime/core/src/file/FileSystem.cpp new file mode 100644 index 00000000..aaea2d6e --- /dev/null +++ b/runtime/core/src/file/FileSystem.cpp @@ -0,0 +1,191 @@ +// +// Created by blues on 2024/4/1. +// + +#include +#include +#include +#include +#include + +namespace sky { + + FilePath::FilePath() : FilePath("") + { + } + + FilePath::FilePath(const char *filePath_) : FilePath(std::string(filePath_)) + { + } + + FilePath::FilePath(const std::filesystem::path &filePath_) : filePath(filePath_) // NOLINT + { + } + + FilePath::FilePath(const std::string &filePath_) +#ifdef SKY_FS_USE_WCHAR + : filePath(Utf8ToUtf16(filePath_)) // NOLINT +#else + : filePath(filePath_) // NOLINT +#endif + { + filePath.make_preferred(); + } + + void FilePath::MakeDirectory() const + { + if (!std::filesystem::exists(filePath)) { + std::filesystem::create_directories(filePath); + } + } + + bool FilePath::Exist() const + { + return std::filesystem::exists(filePath); + } + + FilePath FilePath::Parent() const + { + return FilePath{filePath.parent_path()}; + } + + std::string FilePath::FileName() const + { + return filePath.filename().string(); + } + + std::string FilePath::FileNameWithoutExt() const + { + return filePath.stem().string(); + } + + std::string FilePath::Extension() const + { + return filePath.extension().string(); + } + + std::fstream FilePath::OpenFStream(std::ios_base::openmode mode) const + { + return std::fstream(filePath, mode); + } + + FilePath& FilePath::operator/=(const FilePath& sub) + { + filePath /= sub.filePath; + return *this; + } + + FilePath FilePath::operator/(const FilePath& sub) const + { + return FilePath(filePath) /= sub; + } + + std::string FilePath::GetStr() const + { + return filePath.string(); + } + + IStreamArchivePtr NativeFile::ReadAsArchive() + { + return new IFileArchive(filePath); + } + + OStreamArchivePtr NativeFile::WriteAsArchive() + { + return new OFileArchive(filePath); + } + + std::string NativeFile::GetPath() const + { + return filePath.GetStr(); + } + + bool NativeFile::ReadBin(std::vector &out) + { + return sky::ReadBin(filePath, out); + } + + bool NativeFile::ReadString(std::string &out) + { + return sky::ReadString(filePath, out); + } + + void NativeFile::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + std::fstream stream = filePath.OpenFStream(std::ios::in | std::ios::binary); + if (!stream.is_open()) { + return; + } + + stream.seekg(static_cast(offset), std::ios::beg); + stream.read(reinterpret_cast(out), static_cast(size)); + } + + void RawBufferView::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + } + + bool RawBufferView::ReadBin(std::vector &out) + { + return true; + } + + bool RawBufferView::ReadString(std::string &out) + { + return true; + } + + IStreamArchivePtr RawBufferView::ReadAsArchive() + { + return {}; + } + + OStreamArchivePtr RawBufferView::WriteAsArchive() + { + return {}; + } + + bool NativeFileSystem::FileExist(const FilePath &path) const + { + FilePath res = fsRoot; + res /= path; + return res.Exist(); + } + + FilePtr NativeFileSystem::OpenFile(const FilePath &path) + { + FilePath res = fsRoot; + res /= path; + return res.Exist() ? new NativeFile(res) : nullptr; + } + + FilePtr NativeFileSystem::CreateOrOpenFile(const FilePath &path) + { + FilePath res = fsRoot; + res /= path; + + return new NativeFile(res); + } + + void NativeFileSystem::Copy(const FilePath &from, const FilePath &to) const + { + auto fromPath = from.filePath.is_absolute() ? from.filePath : (fsRoot / from).filePath; + auto toPath = to.filePath.is_absolute() ? to.filePath : (fsRoot / to).filePath; + + std::filesystem::copy(fromPath, toPath, std::filesystem::copy_options::overwrite_existing); + } + + bool NativeFileSystem::IsSubDir(const std::string &path) const + { + return path.find(fsRoot.GetStr()) != std::string::npos; + } + + NativeFileSystemPtr NativeFileSystem::CreateSubSystem(const std::string &path, bool createDir) + { + auto subDir = FilePath(fsRoot.GetStr() + "/" + path); + if (createDir) { + subDir.MakeDirectory(); + } + return new NativeFileSystem(subDir); + } +} // namespace sky \ No newline at end of file diff --git a/core/src/file/FileUtil.cpp b/runtime/core/src/file/FileUtil.cpp similarity index 100% rename from core/src/file/FileUtil.cpp rename to runtime/core/src/file/FileUtil.cpp diff --git a/core/src/hash/Crc32.cpp b/runtime/core/src/hash/Crc32.cpp similarity index 100% rename from core/src/hash/Crc32.cpp rename to runtime/core/src/hash/Crc32.cpp diff --git a/core/src/logger/Logger.cpp b/runtime/core/src/logger/Logger.cpp similarity index 100% rename from core/src/logger/Logger.cpp rename to runtime/core/src/logger/Logger.cpp diff --git a/core/src/math/Color.cpp b/runtime/core/src/math/Color.cpp similarity index 100% rename from core/src/math/Color.cpp rename to runtime/core/src/math/Color.cpp diff --git a/core/src/math/MathUtil.cpp b/runtime/core/src/math/MathUtil.cpp similarity index 100% rename from core/src/math/MathUtil.cpp rename to runtime/core/src/math/MathUtil.cpp diff --git a/core/src/math/Random.cpp b/runtime/core/src/math/Random.cpp similarity index 100% rename from core/src/math/Random.cpp rename to runtime/core/src/math/Random.cpp diff --git a/core/src/math/Sfmt.cpp b/runtime/core/src/math/Sfmt.cpp similarity index 100% rename from core/src/math/Sfmt.cpp rename to runtime/core/src/math/Sfmt.cpp diff --git a/runtime/core/src/memory/Allocator.cpp b/runtime/core/src/memory/Allocator.cpp new file mode 100644 index 00000000..05c56208 --- /dev/null +++ b/runtime/core/src/memory/Allocator.cpp @@ -0,0 +1,43 @@ +// +// Created by blues on 2024/4/19. +// + +#include +//#include +#include + +namespace sky { + +// class MiMallocAllocator : public IAllocator { +// public: +// MiMallocAllocator() = default; +// ~MiMallocAllocator() override = default; +// +// void *Allocate(size_t size, size_t alignment) override +// { +// alignment = std::max(DEFAULT_ALLOC_ALIGNMENT, alignment); +// return mi_malloc_aligned(size, alignment); +// } +// +// void Deallocate(void *ptr) override +// { +// mi_free(ptr); +// } +// +// }; + + SystemAllocator::SystemAllocator() +// : impl(std::make_unique()) + { + } + + void *SystemAllocator::Allocate(size_t size, size_t alignment) + { + return impl->Allocate(size, alignment); + } + + void SystemAllocator::Deallocate(void *ptr) + { + impl->Deallocate(ptr); + } +} // namespace sky \ No newline at end of file diff --git a/core/src/memory/LinearStorage.cpp b/runtime/core/src/memory/LinearStorage.cpp similarity index 100% rename from core/src/memory/LinearStorage.cpp rename to runtime/core/src/memory/LinearStorage.cpp diff --git a/runtime/core/src/memory/LinkedStorage.cpp b/runtime/core/src/memory/LinkedStorage.cpp new file mode 100644 index 00000000..8009707f --- /dev/null +++ b/runtime/core/src/memory/LinkedStorage.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/4/6. +// + +#include + +namespace sky { + +} // namespace sky \ No newline at end of file diff --git a/core/src/memory/TLSFAllocator.cpp b/runtime/core/src/memory/TLSFAllocator.cpp similarity index 100% rename from core/src/memory/TLSFAllocator.cpp rename to runtime/core/src/memory/TLSFAllocator.cpp diff --git a/runtime/core/src/shapes/AABB.cpp b/runtime/core/src/shapes/AABB.cpp new file mode 100644 index 00000000..81f747b9 --- /dev/null +++ b/runtime/core/src/shapes/AABB.cpp @@ -0,0 +1,39 @@ +// +// Created by Zach Lee on 2023/8/29. +// + +#include +#include + +namespace sky { + + void Merge(const AABB &a, const AABB &b, AABB &out) + { + out.min = Min(a.min, b.min); + out.max = Max(a.max, b.max); + } + + // https://gist.github.com/cmf028/81e8d3907035640ee0e3fdd69ada543f + AABB AABB::Transform(const AABB& box, const Matrix4 &mtx) + { + // compute column multiplies for the AABB min + Vector3 min_c1 = Cast(mtx.m[0]) * box.min.x; + Vector3 min_c2 = Cast(mtx.m[1]) * box.min.y; + Vector3 min_c3 = Cast(mtx.m[2]) * box.min.z + Cast(mtx.m[3]); // place 4th column add here for free add (MAD) + + // compute column multiplies for the AABB max + Vector3 max_c1 = Cast(mtx.m[0]) * box.max.x; + Vector3 max_c2 = Cast(mtx.m[1]) * box.max.y; + Vector3 max_c3 = Cast(mtx.m[2]) * box.max.z + Cast(mtx.m[3]); // place 4th column add here for free add (MAD) + + // minimize and maximize the resulting transforms + Vector3 tMin = Min(min_c1,max_c1) + Min(min_c2, max_c2) + Min(min_c3, max_c3); + Vector3 tMax = Max(min_c1,max_c1) + Max(min_c2, max_c2) + Max(min_c3, max_c3); + + AABB res; + res.min = tMin; + res.max = tMax; + return res; + } + +} // namespace sky diff --git a/core/src/shapes/Frustum.cpp b/runtime/core/src/shapes/Frustum.cpp similarity index 100% rename from core/src/shapes/Frustum.cpp rename to runtime/core/src/shapes/Frustum.cpp diff --git a/core/src/shapes/Shapes.cpp b/runtime/core/src/shapes/Shapes.cpp similarity index 100% rename from core/src/shapes/Shapes.cpp rename to runtime/core/src/shapes/Shapes.cpp diff --git a/core/src/std/Std.cpp b/runtime/core/src/std/Std.cpp similarity index 100% rename from core/src/std/Std.cpp rename to runtime/core/src/std/Std.cpp diff --git a/core/src/util/DynamicModule.cpp b/runtime/core/src/util/DynamicModule.cpp similarity index 98% rename from core/src/util/DynamicModule.cpp rename to runtime/core/src/util/DynamicModule.cpp index 7f75cfed..8bc37ff1 100644 --- a/core/src/util/DynamicModule.cpp +++ b/runtime/core/src/util/DynamicModule.cpp @@ -13,7 +13,7 @@ #ifdef __APPLE__ static const std::string DYN_PREFIX = "lib"; static const std::string DYN_SUFFIX = ".dylib"; -#elif defined(ANDROID) +#elif defined(__ANDROID__) static const std::string DYN_PREFIX = "lib"; static const std::string DYN_SUFFIX = ".so"; #endif diff --git a/core/src/util/String.cpp b/runtime/core/src/util/String.cpp similarity index 69% rename from core/src/util/String.cpp rename to runtime/core/src/util/String.cpp index c7f117bd..88d9b29c 100644 --- a/core/src/util/String.cpp +++ b/runtime/core/src/util/String.cpp @@ -3,9 +3,16 @@ // #include +#include namespace sky { + const std::string &GetEmpty() + { + static std::string empty; + return empty; + } + std::vector Split(const std::string &s, const char *separator) { std::vector output; @@ -24,4 +31,10 @@ namespace sky { return output; } + + std::wstring Utf8ToUtf16(const std::string &str) + { + std::wstring_convert> converter; + return converter.from_bytes(str); + } } \ No newline at end of file diff --git a/core/src/util/Uuid.cpp b/runtime/core/src/util/Uuid.cpp similarity index 76% rename from core/src/util/Uuid.cpp rename to runtime/core/src/util/Uuid.cpp index fe58cf00..a0a13095 100644 --- a/core/src/util/Uuid.cpp +++ b/runtime/core/src/util/Uuid.cpp @@ -8,6 +8,12 @@ namespace sky { + const Uuid &Uuid::GetEmpty() + { + static Uuid empty; + return empty; + } + Uuid Uuid::Create() { Uuid res; @@ -24,9 +30,9 @@ namespace sky { { Uuid res; SFMTRandom random(seed); - uint64_t *lPtr = reinterpret_cast(&res); - lPtr[0] = random.GenU64(); - lPtr[1] = random.GenU64(); + auto *lPtr = reinterpret_cast(&res); + lPtr[0] = random.GenU64(); + lPtr[1] = random.GenU64(); res.data[8] &= 0xBF; res.data[8] |= 0x80; @@ -51,4 +57,9 @@ namespace sky { return res; } + void Uuid::FromString(const std::string &str) + { + *this = Uuid::CreateFromString(str); + } + } // namespace sky \ No newline at end of file diff --git a/framework/CMakeLists.txt b/runtime/framework/CMakeLists.txt similarity index 97% rename from framework/CMakeLists.txt rename to runtime/framework/CMakeLists.txt index 190ebe78..58579739 100644 --- a/framework/CMakeLists.txt +++ b/runtime/framework/CMakeLists.txt @@ -20,6 +20,8 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") file(GLOB_RECURSE PLATFORM_SRC platform/android/*) set(FM_EXT_LIB + log + android game-activity::game-activity) endif () diff --git a/framework/include/framework/application/Application.h b/runtime/framework/include/framework/application/Application.h similarity index 92% rename from framework/include/framework/application/Application.h rename to runtime/framework/include/framework/application/Application.h index 7715b6ee..92376b5f 100644 --- a/framework/include/framework/application/Application.h +++ b/runtime/framework/include/framework/application/Application.h @@ -19,16 +19,14 @@ namespace sky { class Application : public ISystemNotify { public: Application(); - ~Application() override = default; + ~Application() override; Application(const Application &) = delete; Application &operator=(const Application &) = delete; virtual bool Init(int argc, char **argv); - virtual void Shutdown(); - - virtual void PreTick() {}; + virtual void PreTick() {} void Mainloop(); diff --git a/framework/include/framework/application/GameApplication.h b/runtime/framework/include/framework/application/GameApplication.h similarity index 87% rename from framework/include/framework/application/GameApplication.h rename to runtime/framework/include/framework/application/GameApplication.h index b122335d..cb58a6b2 100644 --- a/framework/include/framework/application/GameApplication.h +++ b/runtime/framework/include/framework/application/GameApplication.h @@ -6,6 +6,7 @@ #include #include +#include namespace sky { @@ -18,17 +19,15 @@ namespace sky { void PreInit() override; void PostInit() override; - void Shutdown() override; void PreTick() override; - - const NativeWindow *GetViewport() const override; - private: void LoadConfigs() override; std::unique_ptr nativeWindow; uint32_t width = 1024; uint32_t height = 1024; + + FileSystemPtr workFs; }; } diff --git a/framework/include/framework/application/ModuleManager.h b/runtime/framework/include/framework/application/ModuleManager.h similarity index 100% rename from framework/include/framework/application/ModuleManager.h rename to runtime/framework/include/framework/application/ModuleManager.h diff --git a/framework/include/framework/application/SettingRegistry.h b/runtime/framework/include/framework/application/SettingRegistry.h similarity index 100% rename from framework/include/framework/application/SettingRegistry.h rename to runtime/framework/include/framework/application/SettingRegistry.h diff --git a/framework/include/framework/application/ToolApplicationBase.h b/runtime/framework/include/framework/application/ToolApplicationBase.h similarity index 100% rename from framework/include/framework/application/ToolApplicationBase.h rename to runtime/framework/include/framework/application/ToolApplicationBase.h diff --git a/runtime/framework/include/framework/application/XRApplication.h b/runtime/framework/include/framework/application/XRApplication.h new file mode 100644 index 00000000..03b7d66b --- /dev/null +++ b/runtime/framework/include/framework/application/XRApplication.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/3/13. +// + +#pragma once + +#include +#include + +namespace sky { + + class XRApplication : public Application { + public: + XRApplication() = default; + ~XRApplication() override = default; + + bool Init(int argc, char **argv) override; + private: + void LoadConfigs() override; + + std::unique_ptr nativeWindow; + uint32_t width = 1024; + uint32_t height = 1024; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/Asset.h b/runtime/framework/include/framework/asset/Asset.h new file mode 100644 index 00000000..1a99e933 --- /dev/null +++ b/runtime/framework/include/framework/asset/Asset.h @@ -0,0 +1,163 @@ +// +// Created by Zach on 2022/8/8. +// + +#pragma once + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace sky { + + class AssetBase; + using AssetPtr = std::shared_ptr; + + using AsyncTask = std::pair>; + + class AssetBase { + public: + AssetBase() = default; + + virtual ~AssetBase() = default; + + enum class Status : uint32_t { INITIAL, LOADING, LOADED, FAILED }; + + void SetUuid(const Uuid &id) { uuid = id; } + const Uuid &GetUuid() const { return uuid; } + + void SetType(const std::string &val) { type = val; } + const std::string &GetType() const { return type; } + + Status GetStatus() const { return status.load(); } + bool IsLoaded() const { return status.load() == Status::LOADED; } + + void AddDependencies(const Uuid &id); + void ResetDependencies(); + void BlockUntilLoaded() const; + + virtual const uint8_t *GetData() const = 0; + + const AsyncTask &GetAsyncTask() const { return asyncTask; } + protected: + friend class AssetManager; + friend class AssetManager; + + Uuid uuid; + std::string type; + std::vector dependencies; + std::vector depAssets; + + std::atomic status = Status::INITIAL; + AsyncTask asyncTask; + }; + + enum class SerializeType : uint8_t { JSON, BIN }; + + template + struct AssetTraits { + using DataType = std::vector; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::JSON; + }; + + template + class Asset : public AssetBase { + public: + Asset() = default; + + ~Asset() override = default; + + using DataType = typename AssetTraits::DataType; + + const DataType &Data() const + { + return data; + } + DataType &Data() + { + return data; + } + + const uint8_t *GetData() const override { return reinterpret_cast(&data); } + private: + friend class AssetManager; + + DataType data; + }; + + class AssetHandlerBase { + public: + AssetHandlerBase() = default; + + virtual ~AssetHandlerBase() = default; + + SKY_DISABLE_COPY(AssetHandlerBase) + + virtual std::shared_ptr CreateAsset() = 0; + + virtual bool Load(IStreamArchive &archive, const std::shared_ptr &asset) = 0; + + virtual void Save(OStreamArchive &archive, const std::shared_ptr &data) = 0; + }; + + template + class AssetHandler : public AssetHandlerBase { + public: + AssetHandler() = default; + + ~AssetHandler() override = default; + + using DataType = typename AssetTraits::DataType; + + static constexpr SerializeType SERIALIZE_TYPE = AssetTraits::SERIALIZE_TYPE; + + std::shared_ptr CreateAsset() override + { + return std::make_shared>(); + } + + bool Load(IStreamArchive &archive, const std::shared_ptr &assetBase) override + { + auto asset = std::static_pointer_cast>(assetBase); + DataType &assetData = asset->Data(); + if (SERIALIZE_TYPE == SerializeType::JSON) { + JsonInputArchive jArchive(archive); + jArchive.LoadValueById(&assetData, TypeInfo::RegisteredId()); + } else if (SERIALIZE_TYPE == SerializeType::BIN) { + BinaryInputArchive bArchive(archive); + bArchive.LoadObject(&assetData, TypeInfo::RegisteredId()); + } + return true; + } + + void Save(OStreamArchive &archive, const std::shared_ptr &assetBase) override + { + auto asset = std::static_pointer_cast>(assetBase); + auto &assetData = asset->Data(); + + if (SERIALIZE_TYPE == SerializeType::JSON) { +// JsonOutputArchive archive(file); +// archive.SaveValueObject(assetBase->GetData(), TypeInfo::RegisteredId()); + } else if (SERIALIZE_TYPE == SerializeType::BIN) { + BinaryOutputArchive bArchive(archive); + bArchive.SaveObject(assetBase->GetData(), TypeInfo::RegisteredId()); + } + } + + protected: + virtual void LoadBinary(BinaryInputArchive &archive) {} + virtual void SaveBinary(BinaryOutputArchive &archive) {} + + virtual void LoadJson(JsonInputArchive &archive) {} + virtual void SaveJson(JsonOutputArchive &archive) {} + }; +} // names \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetBuilder.h b/runtime/framework/include/framework/asset/AssetBuilder.h new file mode 100644 index 00000000..bcb84377 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetBuilder.h @@ -0,0 +1,32 @@ +// +// Created by Zach Lee on 2023/2/20. +// + +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + class AssetBuilder { + public: + AssetBuilder() = default; + virtual ~AssetBuilder() = default; + + virtual const std::vector &GetExtensions() const = 0; + + virtual void Import(const AssetImportRequest &request) const {} + + virtual void Request(const AssetBuildRequest &request, AssetBuildResult &result) {} + + virtual std::string_view QueryType(const std::string &ext) const { return ""; } + + virtual void LoadConfig(const FileSystemPtr &cfg) {} + }; +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetBuilderConfig.h b/runtime/framework/include/framework/asset/AssetBuilderConfig.h new file mode 100644 index 00000000..986742c9 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetBuilderConfig.h @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/7/21. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky { + + struct AssetBuilderConfig { + std::vector bundles; + std::map> presets; + + void LoadJson(JsonInputArchive &archive); + void SaveJson(JsonOutputArchive &archive); + }; + +} // namespace sky diff --git a/runtime/framework/include/framework/asset/AssetBuilderManager.h b/runtime/framework/include/framework/asset/AssetBuilderManager.h new file mode 100644 index 00000000..fad4852d --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetBuilderManager.h @@ -0,0 +1,48 @@ +// +// Created by blues on 2024/6/21. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + class AssetBuilderManager : public Singleton { + public: + AssetBuilderManager() = default; + ~AssetBuilderManager() override = default; + + void SetWorkSpaceFs(const NativeFileSystemPtr &fs); + void SetEngineFs(const NativeFileSystemPtr &fs); + + const NativeFileSystemPtr &GetEngineFs() const { return engineFs; } + const NativeFileSystemPtr &GetWorkSpaceFs() const { return workSpaceFs; } + + void RegisterBuilder(AssetBuilder *builder); + void UnRegisterBuilder(AssetBuilder *builder); + + void LoadBuildConfigs(const FileSystemPtr &fs); + + void ImportAsset(const AssetImportRequest &request); + + void BuildRequest(const AssetBuildRequest &request); + void BuildRequest(const Uuid &uuid, const std::string &target); + + AssetBuilder *QueryBuilder(const std::string &ext) const; + + private: + std::vector> assetBuilders; + std::unordered_map assetBuilderMap; + + NativeFileSystemPtr engineFs; + NativeFileSystemPtr workSpaceFs; + AssetBuilderConfig config; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetCommon.h b/runtime/framework/include/framework/asset/AssetCommon.h new file mode 100644 index 00000000..938fe9e6 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetCommon.h @@ -0,0 +1,88 @@ +// +// Created by blues on 2024/6/16. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + enum class SourceAssetBundle : uint32_t { + INVALID, + ENGINE, + WORKSPACE, + CUSTOM_BEGIN = WORKSPACE + 1 + }; + + struct AssetSourcePath { + SourceAssetBundle bundle; // asset bundle + FilePath path; // relative path to bundle + }; + + // asset source info + struct AssetSourceInfo : public RefObject { + AssetSourcePath path; // asset path + std::string name; // marked name used to load by name, can be empty + std::string ext; // file extension + std::string category; // asset category + Uuid uuid; // uuid of the asset + std::vector dependencies; // dependent assets + }; + using AssetSourcePtr = CounterPtr; + + enum class AssetBuildRetCode : uint32_t { + SUCCESS, + FAILED, + }; + + struct AssetImportRequest { + FilePath filePath; + }; + + using ProductBundleKey = std::string; + struct AssetBuildRequest { + FilePtr file; + AssetSourcePtr assetInfo; + ProductBundleKey target; + }; + + struct AssetBuildResult { + AssetBuildRetCode retCode; + }; + + struct AssetRawData { + std::vector storage; + }; +} // namespace sky + +namespace std { + + template <> + struct hash { + size_t operator()(const sky::AssetSourcePath &path) const noexcept + { + auto hash = static_cast(path.bundle); + sky::HashCombine32(hash, sky::Fnv1a32(path.path.GetStr())); + return hash; + } + }; + + template <> + struct equal_to { + bool operator()(const sky::AssetSourcePath &x, const sky::AssetSourcePath &y) const noexcept + { + return x.bundle == y.bundle && x.path == y.path; + } + }; + +} // namespace std \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetDataBase.h b/runtime/framework/include/framework/asset/AssetDataBase.h new file mode 100644 index 00000000..544dfd91 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetDataBase.h @@ -0,0 +1,63 @@ +// +// Created by blues on 2024/6/16. +// + +#pragma once + +#include +#include + +#include +#include + +#include +#include +#include + +namespace sky { + + class AssetDataBase : public Singleton { + public: + AssetDataBase() = default; + ~AssetDataBase() override = default; + + void SetEngineFs(const NativeFileSystemPtr &fs); + void SetWorkSpaceFs(const NativeFileSystemPtr &fs); + + const NativeFileSystemPtr &GetEngineFs() const { return engineFs; } + const NativeFileSystemPtr &GetWorkSpaceFs() const { return workSpaceFs; } + + AssetSourcePtr RegisterAsset(const AssetSourcePath &path); + AssetSourcePtr RegisterAsset(const std::string &path); + AssetSourcePath QuerySource(const std::string &path); // engine->workspace->custom + + AssetSourcePtr FindAsset(const Uuid &id); + AssetSourcePtr FindAsset(const std::string &path); + void RemoveAsset(const Uuid &id); + + FilePtr OpenFile(const AssetSourcePtr &src); + FilePtr CreateOrOpenFile(const AssetSourcePath &path); + + void SetMarkedName(const Uuid& id, const std::string &name); + + void Load(); + void Save(); + void Reset(); + + void Dump(std::ostream &stream); + + const std::unordered_map &GetSources() const { return idMap; } + + private: + const NativeFileSystemPtr &GetFileSystemBySourcePath(const AssetSourcePath &path); + + NativeFileSystemPtr engineFs; + NativeFileSystemPtr workSpaceFs; + std::unordered_map pluginFs; + + std::recursive_mutex assetMutex; + std::unordered_map pathMap; + std::unordered_map idMap; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetEvent.h b/runtime/framework/include/framework/asset/AssetEvent.h new file mode 100644 index 00000000..a918c397 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetEvent.h @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/7/23. +// + +#pragma once + +#include +#include + +namespace sky { + + struct AssetBuildResult; + + class IAssetEvent : public EventTraits { + public: + IAssetEvent() = default; + virtual ~IAssetEvent() = default; + + using KeyType = Uuid; + using MutexType = std::mutex; + + virtual void OnAssetBuildFinished(const AssetBuildResult &result) {} + virtual void OnAssetLoaded() {} + }; + using AsseEvent = Event; + +} // namespace sky diff --git a/runtime/framework/include/framework/asset/AssetExecutor.h b/runtime/framework/include/framework/asset/AssetExecutor.h new file mode 100644 index 00000000..219e5aeb --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetExecutor.h @@ -0,0 +1,75 @@ +// +// Created by blues on 2024/6/29. +// + +#pragma once + +#include +#include +#include + +#include + +#include + +namespace sky { + + struct SavingTask { + FilePtr file; + tf::AsyncTask asyncTask; + }; + + class AssetExecutor : public Singleton { + public: + AssetExecutor() = default; + ~AssetExecutor() override = default; + + template + auto DependentAsync(Func &&func, Tasks &&...tasks) + { + return executor.dependent_async(std::forward(func), std::forward(tasks)...); + } + + template + auto DependentAsyncRange(Func &&func, Iter begin, Iter last) + { + return executor.dependent_async(std::forward(func), begin, last); + } + + template + void PushSavingTask(const FilePtr &file, Func &&func, Tasks &&...tasks) + { + std::lock_guard lock(mutex); + auto iter = std::find_if(savingTasks.begin(), savingTasks.end(), [file](const auto &v) { + return v.file->GetPath() == file->GetPath(); + }); + + if (iter == savingTasks.end()) { + SavingTask task = { + file, + executor.silent_dependent_async([fn = std::forward(func), file, this]() { + fn(); + std::lock_guard lock(mutex); + auto iter = std::find_if(savingTasks.begin(), savingTasks.end(), [file](const auto &v) { + return v.file.Get() == file.Get(); + }); + if (iter != savingTasks.end()) { + savingTasks.erase(iter); + } + }, std::forward(tasks)...) + }; + + savingTasks.emplace_back(std::move(task)); + } + } + + void WaitForAll(); + + private: + tf::Executor executor; + + mutable std::mutex mutex; + std::list savingTasks; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetManager.h b/runtime/framework/include/framework/asset/AssetManager.h new file mode 100644 index 00000000..d7cec752 --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetManager.h @@ -0,0 +1,80 @@ +// +// Created by blues on 2024/6/16. +// + +#pragma once + +#include +#include + +#include +#include +#include + +#include + +namespace sky { + + class AssetManager : public Singleton { + public: + AssetManager() = default; + ~AssetManager() override = default; + + void SetWorkFileSystem(const FileSystemPtr &fs); + void AddAssetProductBundle(AssetProductBundle *bundle); + + AssetPtr FindAsset(const Uuid &uuid) const; + AssetPtr FindOrCreateAsset(const Uuid &uuid, const std::string &type); + + AssetPtr LoadAsset(const Uuid &uuid); + void SaveAsset(const AssetPtr &asset, const ProductBundleKey &bundleKey); + + AssetPtr LoadAssetFromPath(const std::string &path); + + const FileSystemPtr &GetWorkSpaceFS() const { return workSpace; } + + template + std::shared_ptr> LoadAssetFromPath(const std::string &path) + { + return std::static_pointer_cast>(LoadAssetFromPath(path)); + } + + template + std::shared_ptr> LoadAsset(const Uuid &uuid) + { + return std::static_pointer_cast>(LoadAsset(uuid)); + } + + template + std::shared_ptr> FindAsset(const Uuid &uuid) + { + return std::static_pointer_cast>(FindAsset(uuid)); + } + + template + std::shared_ptr> FindOrCreateAsset(const Uuid &uuid) + { + return std::static_pointer_cast>(FindOrCreateAsset(uuid, std::string(AssetTraits::ASSET_TYPE))); + } + + FilePtr OpenFile(const Uuid &uuid) const; + + void RegisterAssetHandler(const std::string_view &type, AssetHandlerBase *handler); + template + void RegisterAssetHandler() + { + RegisterAssetHandler(AssetTraits::ASSET_TYPE, new AssetHandler()); + } + private: + FileSystemPtr workSpace; + AssetPtr CreateAssetByHeader(const Uuid &uuid, const IStreamArchivePtr &archive); + AssetProductBundle *GetBundle(const ProductBundleKey &key) const; + + std::unordered_map> assetHandlers; + std::vector> bundles; + + mutable std::recursive_mutex mutex; + std::unordered_map> assets; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/asset/AssetProductBundle.h b/runtime/framework/include/framework/asset/AssetProductBundle.h new file mode 100644 index 00000000..f529d36c --- /dev/null +++ b/runtime/framework/include/framework/asset/AssetProductBundle.h @@ -0,0 +1,52 @@ +// +// Created by blues on 2024/6/26. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class AssetProductBundle { + public: + explicit AssetProductBundle(const FileSystemPtr &fs_, const ProductBundleKey &key_) // NOLINT + : fs(fs_), key(key_) + { + } + virtual ~AssetProductBundle() = default; + + virtual FilePtr OpenFile(const Uuid &uuid) const = 0; + virtual FilePtr CreateOrOpenFile(const Uuid &uuid) const = 0; + + const ProductBundleKey &GetKey() const { return key; } + virtual bool IsPacked() const { return false; } + + protected: + FileSystemPtr fs; + ProductBundleKey key; + }; + + class HashedAssetBundle : public AssetProductBundle { + public: + explicit HashedAssetBundle(const NativeFileSystemPtr &fs, const ProductBundleKey &key) : AssetProductBundle(fs, key) {} + ~HashedAssetBundle() override = default; + + protected: + FilePtr OpenFile(const Uuid &uuid) const override; + FilePtr CreateOrOpenFile(const Uuid &uuid) const override; + }; + + class PackageAssetBundle : public AssetProductBundle { + public: + explicit PackageAssetBundle(const FileSystemPtr &fs, const ProductBundleKey &key) : AssetProductBundle(fs, key) {} + ~PackageAssetBundle() override = default; + + bool IsPacked() const override { return true; } + protected: + FilePtr OpenFile(const Uuid &uuid) const override { return {}; } + FilePtr CreateOrOpenFile(const Uuid &uuid) const override { return {}; } + }; +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/controller/SimpleController.h b/runtime/framework/include/framework/controller/SimpleController.h new file mode 100644 index 00000000..fb4f4a9c --- /dev/null +++ b/runtime/framework/include/framework/controller/SimpleController.h @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/5/19. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class FirstPersonController : public IMouseEvent, public IKeyboardEvent { + public: + FirstPersonController(); + ~FirstPersonController() override = default; + + void BindWindow(const NativeWindow *window); + Transform Resolve(float time, const Transform &trans); + + private: + void OnMouseButtonDown(const MouseButtonEvent &event) override; + void OnMouseButtonUp(const MouseButtonEvent &event) override; + void OnMouseMotion(const MouseMotionEvent &event) override; + void OnMouseWheel(const MouseWheelEvent &event) override; + + void OnKeyUp(const KeyboardEvent &event) override; + void OnKeyDown(const KeyboardEvent &event) override; + + bool FilterWindowID(WindowID id); + + EventBinder keyBinder; + EventBinder mouseBinder; + + std::unordered_map mouseButtons; + std::unordered_map keyButtons; + int32_t startX = 0; + int32_t startY = 0; + + int32_t currentX = 0; + int32_t currentY = 0; + + float moveSpeed = 3.f; + + const NativeWindow *window = nullptr; + }; + +} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/database/DBManager.h b/runtime/framework/include/framework/database/DBManager.h similarity index 100% rename from framework/include/framework/database/DBManager.h rename to runtime/framework/include/framework/database/DBManager.h diff --git a/framework/include/framework/database/DataBase.h b/runtime/framework/include/framework/database/DataBase.h similarity index 100% rename from framework/include/framework/database/DataBase.h rename to runtime/framework/include/framework/database/DataBase.h diff --git a/framework/include/framework/interface/IBuilder.h b/runtime/framework/include/framework/interface/IBuilder.h similarity index 100% rename from framework/include/framework/interface/IBuilder.h rename to runtime/framework/include/framework/interface/IBuilder.h diff --git a/runtime/framework/include/framework/interface/IGizmo.h b/runtime/framework/include/framework/interface/IGizmo.h new file mode 100644 index 00000000..61362a29 --- /dev/null +++ b/runtime/framework/include/framework/interface/IGizmo.h @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/7/31. +// + +#pragma once + +namespace sky { + class World; + class NativeWindow; + + class IGizmo { + public: + IGizmo() = default; + virtual ~IGizmo() = default; + + virtual void Init(World &world, NativeWindow* window) = 0; + }; + + class IGizmoFactory { + public: + IGizmoFactory() = default; + virtual ~IGizmoFactory() = default; + + virtual IGizmo* CreateGizmo() = 0; + }; + +} // namespace sky diff --git a/framework/include/framework/interface/IModule.h b/runtime/framework/include/framework/interface/IModule.h similarity index 93% rename from framework/include/framework/interface/IModule.h rename to runtime/framework/include/framework/interface/IModule.h index 092aa0af..0d070713 100644 --- a/framework/include/framework/interface/IModule.h +++ b/runtime/framework/include/framework/interface/IModule.h @@ -27,7 +27,9 @@ namespace sky { virtual void Shutdown() {} virtual void Start() {} - virtual void Tick(float delta) = 0; + virtual void PreTick(float delta) {}; + virtual void Tick(float delta) {}; + virtual void PostTick(float delta) {}; }; } // namespace sky diff --git a/runtime/framework/include/framework/interface/ISelectEvent.h b/runtime/framework/include/framework/interface/ISelectEvent.h new file mode 100644 index 00000000..659ce621 --- /dev/null +++ b/runtime/framework/include/framework/interface/ISelectEvent.h @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/7/31. +// + +#pragma once + +#include + +namespace sky { + class Actor; + + class ISelectEvent : public EventTraits { + public: + ISelectEvent() = default; + virtual ~ISelectEvent() = default; + + virtual void OnActorSelected(Actor *actor) = 0; + }; + using SelectEvent = Event; + +} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/interface/ISystem.h b/runtime/framework/include/framework/interface/ISystem.h similarity index 57% rename from framework/include/framework/interface/ISystem.h rename to runtime/framework/include/framework/interface/ISystem.h index 2dc9a62a..b49f2668 100644 --- a/framework/include/framework/interface/ISystem.h +++ b/runtime/framework/include/framework/interface/ISystem.h @@ -4,20 +4,29 @@ #pragma once +#include + namespace sky { - class SettingRegistry; class NativeWindow; class ModuleManager; + class ISystemNotify { public: ISystemNotify() = default; virtual ~ISystemNotify() = default; - virtual void SetExit() = 0; - virtual const NativeWindow *GetViewport() const { return nullptr; } virtual ModuleManager* GetModuleManager() const { return nullptr; } }; + class ISystemEvent : public EventTraits { + public: + ISystemEvent() = default; + virtual ~ISystemEvent() = default; + + virtual void OnMainWindowCreated(NativeWindow *window) = 0; + }; + using SystemEvent = Event; + } // namespace sky diff --git a/runtime/framework/include/framework/interface/ITickEvent.h b/runtime/framework/include/framework/interface/ITickEvent.h new file mode 100644 index 00000000..57d12b1e --- /dev/null +++ b/runtime/framework/include/framework/interface/ITickEvent.h @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/7/28. +// + +#pragma once + +#include + +namespace sky { + + class ITickEvent : public EventTraits { + public: + ITickEvent() = default; + virtual ~ITickEvent() = default; + + using KeyType = void; + using MutexType = void; + + virtual void Tick(float time) = 0; + }; + using TickEvent = Event; + +} // namespace sky diff --git a/framework/include/framework/interface/Interface.h b/runtime/framework/include/framework/interface/Interface.h similarity index 100% rename from framework/include/framework/interface/Interface.h rename to runtime/framework/include/framework/interface/Interface.h diff --git a/framework/include/framework/performance/AdaptivePerfManager.h b/runtime/framework/include/framework/performance/AdaptivePerfManager.h similarity index 100% rename from framework/include/framework/performance/AdaptivePerfManager.h rename to runtime/framework/include/framework/performance/AdaptivePerfManager.h diff --git a/framework/include/framework/platform/PlatformBase.h b/runtime/framework/include/framework/platform/PlatformBase.h similarity index 66% rename from framework/include/framework/platform/PlatformBase.h rename to runtime/framework/include/framework/platform/PlatformBase.h index 9912bb4b..2a36de85 100644 --- a/framework/include/framework/platform/PlatformBase.h +++ b/runtime/framework/include/framework/platform/PlatformBase.h @@ -10,7 +10,7 @@ #include #include #include - +#include #include namespace sky { @@ -30,11 +30,18 @@ namespace sky { virtual uint64_t GetPerformanceFrequency() const = 0; virtual uint64_t GetPerformanceCounter() const = 0; virtual std::string GetInternalPath() const = 0; + virtual std::string GetBundlePath() const = 0; virtual void *GetMainWinHandle() const { return nullptr; }; virtual void *GetNativeApp() const { return nullptr; } + virtual std::string GetEnvVariable(const std::string &env) const { return ""; } virtual AdaptivePerfManager *GetPerformanceManager() const { return nullptr; } virtual bool RunCmd(const std::string &str, std::string &out) const { return true; } virtual PlatformType GetType() const { return PlatformType::UNDEFINED; } + virtual FileSystemPtr GetBundleFileSystem() { return nullptr; } + virtual char* GetClipBoardText() { return nullptr; } + virtual void FreeClipBoardText(char* text) {} + virtual void SetClipBoardText(const std::string &text) {} + virtual void PollEvent(bool &exit) {} void setLaunchCallback(LaunchCallback &&cb) { launchCallback = std::move(cb); } protected: LaunchCallback launchCallback; @@ -45,22 +52,35 @@ namespace sky { bool Init(const PlatformInfo&); void Shutdown(); + static std::string GetPlatformNameByType(PlatformType type); + static PlatformType GetPlatformTypeByName(const std::string &name); + uint64_t GetPerformanceFrequency() const; uint64_t GetPerformanceCounter() const; std::string GetInternalPath() const; + std::string GetBundlePath() const; + void *GetMainWinHandle() const; void *GetNativeApp() const; AdaptivePerfManager *GetPerformanceManager() const; + std::string GetEnvVariable(const std::string &env) const; + FileSystemPtr GetBundleFileSystem() const; + + char* GetClipBoardText() const; + void FreeClipBoardText(char* text); + void SetClipBoardText(const std::string &text); bool RunCmd(const std::string &str, std::string &out) const; PlatformType GetType() const; + void PoolEvent(bool &exit); + template void setLaunchCallback(T &&cb) { platform->setLaunchCallback(std::forward(cb)); } private: - std::unique_ptr platform; + std::unique_ptr platform; }; } diff --git a/core/include/core/type/Any.h b/runtime/framework/include/framework/serialization/Any.h similarity index 73% rename from core/include/core/type/Any.h rename to runtime/framework/include/framework/serialization/Any.h index 524fee23..2d67159a 100644 --- a/core/include/core/type/Any.h +++ b/runtime/framework/include/framework/serialization/Any.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include namespace sky { @@ -18,19 +18,19 @@ namespace sky { } template - Any(std::in_place_type_t, Args &&...args) : data{0}, info(TypeInfoObj::Get()->RtInfo()) + explicit Any(std::in_place_type_t, Args &&...args) : data{0}, info(TypeInfoObj::Get()->RtInfo()) { CheckMemory(); new (Data()) T{std::forward(args)...}; } - template - Any(std::reference_wrapper ref) : Any(std::in_place_type, &ref.get()) - { - } +// template +// explicit Any(std::reference_wrapper ref) : Any(std::in_place_type, &ref.get()) +// { +// } template - Any(const T &t) : Any(std::in_place_type, t) + explicit Any(const T &t) : Any(std::in_place_type, t) { } @@ -54,14 +54,14 @@ namespace sky { return *this; } - Any(Any &&any) + Any(Any &&any) noexcept { info = any.info; CheckMemory(); Move(any); } - Any &operator=(Any &&any) + Any &operator=(Any &&any) noexcept { info = any.info; CheckMemory(); @@ -82,7 +82,9 @@ namespace sky { template const T *GetAsConst() const { - if (info != nullptr && TypeInfo::Hash() == info->typeId) { + if (info != nullptr && + (TypeInfo::RegisteredId() == info->registeredId || + info->staticInfo->isEnum)) { return static_cast(Data()); } return nullptr; @@ -93,26 +95,21 @@ namespace sky { return info; } - operator bool() const + explicit operator bool() const { return Data() != nullptr; } private: void CheckMemory(); - - void Construct(); - void Destructor(); - void Move(Any &any); - void Copy(const Any &any); union { uint8_t data[BLOCK_SIZE]; void *ptr; }; - TypeInfoRT *info = nullptr; + const TypeInfoRT *info = nullptr; }; } // namespace sky \ No newline at end of file diff --git a/framework/include/framework/serialization/BinaryArchive.h b/runtime/framework/include/framework/serialization/BinaryArchive.h similarity index 68% rename from framework/include/framework/serialization/BinaryArchive.h rename to runtime/framework/include/framework/serialization/BinaryArchive.h index 10ee0bb7..eaac6c3d 100644 --- a/framework/include/framework/serialization/BinaryArchive.h +++ b/runtime/framework/include/framework/serialization/BinaryArchive.h @@ -5,14 +5,16 @@ #pragma once #include +#include +#include #include -#include +#include namespace sky { class BinaryInputArchive { public: - explicit BinaryInputArchive(std::istream &s) : stream(s) + explicit BinaryInputArchive(IStreamArchive &arc) : archive(arc) { } @@ -20,8 +22,7 @@ namespace sky { void LoadValue(char* data, uint32_t size) { - auto const writtenSize = stream.rdbuf()->sgetn(data, size); - SKY_ASSERT(writtenSize == size); + archive.LoadRaw(data, size); } template || std::is_enum_v>> @@ -38,22 +39,23 @@ namespace sky { LoadValue(v.data(), length); } - void LoadObject(void *ptr, uint32_t id); + void LoadObject(void *ptr, const Uuid &id); + + const IStreamArchive &GetStream() const { return archive; } protected: - std::istream &stream; + IStreamArchive &archive; }; class BinaryOutputArchive { public: - explicit BinaryOutputArchive(std::ostream &s) : stream(s) + explicit BinaryOutputArchive(OStreamArchive &arc) : archive(arc) { } ~BinaryOutputArchive() = default; void SaveValue(const char* data, uint32_t size) { - auto const writtenSize = stream.rdbuf()->sputn(data, size); - SKY_ASSERT(writtenSize == size); + archive.SaveRaw(data, size); } template || std::is_enum_v>> @@ -68,8 +70,11 @@ namespace sky { SaveValue(v.data(), static_cast(v.length())); } - void SaveObject(const void* data, uint32_t id); + + void SaveObject(const void* data, const Uuid &id); + + const OStreamArchive &GetStream() const { return archive; } protected: - std::ostream &stream; + OStreamArchive &archive; }; } diff --git a/framework/include/framework/serialization/CoreReflection.h b/runtime/framework/include/framework/serialization/CoreReflection.h similarity index 51% rename from framework/include/framework/serialization/CoreReflection.h rename to runtime/framework/include/framework/serialization/CoreReflection.h index 46f033dd..61195eeb 100644 --- a/framework/include/framework/serialization/CoreReflection.h +++ b/runtime/framework/include/framework/serialization/CoreReflection.h @@ -5,7 +5,8 @@ #pragma once namespace sky { + class SerializationContext; - void CoreReflection(); + void CoreReflection(SerializationContext *context); } // namespace sky \ No newline at end of file diff --git a/framework/include/framework/serialization/JsonArchive.h b/runtime/framework/include/framework/serialization/JsonArchive.h similarity index 69% rename from framework/include/framework/serialization/JsonArchive.h rename to runtime/framework/include/framework/serialization/JsonArchive.h index 7118176d..c62f9110 100644 --- a/framework/include/framework/serialization/JsonArchive.h +++ b/runtime/framework/include/framework/serialization/JsonArchive.h @@ -7,8 +7,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -16,11 +17,10 @@ namespace sky { namespace impl { - template class InputStreamWrapper { public: - using Ch = typename StreamType::char_type; - InputStreamWrapper(StreamType &s) : stream(s) + using Ch = std::istream::char_type; + explicit InputStreamWrapper(IInputArchive &s) : stream(s) { } @@ -29,36 +29,34 @@ namespace sky { Ch Peek() const { - int c = stream.peek(); + int c = stream.Peek(); return c == std::char_traits::eof() ? '\0' : static_cast(c); } Ch Take() { - int c = stream.get(); + int c = stream.Get(); return c == std::char_traits::eof() ? '\0' : static_cast(c); } size_t Tell() const { - return static_cast(stream.tellg()); + return static_cast(stream.Tell()); } - Ch *PutBegin() { SKY_ASSERT(false); return 0; } - void Put(Ch) { SKY_ASSERT(false); } - void Flush() { SKY_ASSERT(false); } - size_t PutEnd(Ch *) { SKY_ASSERT(false); return 0; } + Ch *PutBegin() { SKY_ASSERT(false); return nullptr; } // NOLINT + void Put(Ch) { SKY_ASSERT(false); } // NOLINT + void Flush() { SKY_ASSERT(false); } // NOLINT + size_t PutEnd(Ch *) { SKY_ASSERT(false); return 0; } // NOLINT private: - StreamType &stream; + IInputArchive &stream; }; - - template class OutputStreamWrapper { public: - using Ch = typename StreamType::char_type; - OutputStreamWrapper(StreamType &s) : stream(s) + using Ch = std::istream::char_type; + explicit OutputStreamWrapper(IOutputArchive &s) : stream(s) { } @@ -67,25 +65,25 @@ namespace sky { void Put(Ch c) { - stream.put(c); + stream.Put(c); } void Flush() { - stream.flush(); + stream.Flush(); } private: - StreamType &stream; + IOutputArchive &stream; }; } class JsonInputArchive { public: using Value = rapidjson::GenericValue>; - using Stream = impl::InputStreamWrapper; + using Stream = impl::InputStreamWrapper; - JsonInputArchive(std::istream &s) : stream(s) + explicit JsonInputArchive(IInputArchive &archive) : stream(archive) { document.ParseStream(stream); stack.emplace_back(&document); @@ -95,7 +93,7 @@ namespace sky { bool Start(const std::string &name) { - auto &parent = *stack.back(); + const auto &parent = *stack.back(); auto iter = parent.FindMember(name.c_str()); if (iter == parent.MemberEnd()) { return false; @@ -110,7 +108,7 @@ namespace sky { uint32_t StartArray(const std::string &name) { - auto &parent = *stack.back(); + const auto &parent = *stack.back(); auto iter = parent.FindMember(name.c_str()); if (iter != parent.MemberEnd() && iter->value.IsArray()) { auto array = iter->value.GetArray(); @@ -120,6 +118,22 @@ namespace sky { return 0; } + template + void ForEachMember(Func &&func) + { + const auto &parent = *stack.back(); + for (auto iter = parent.MemberBegin(); iter != parent.MemberEnd(); ++iter) + { + const auto &member = *iter; + + if constexpr (std::is_invocable_v) { + func(member.name.GetString()); + } else { + func(member.name.GetString(), member.value); + } + } + } + void End() { if (!stack.empty()) { @@ -138,7 +152,7 @@ namespace sky { template void LoadArrayElement(T &value) { - LoadValueById(&value, TypeInfo::Hash()); + LoadValueById(&value, TypeInfo::RegisteredId()); stack.back()++; } @@ -147,13 +161,13 @@ namespace sky { stack.back()++; } - Any LoadValueById(uint32_t typeId); - void LoadValueById(void *ptr, uint32_t typeId); + Any LoadValueById(const Uuid & typeId); + void LoadValueById(void *ptr, const Uuid &typeId); template void LoadValueObject(T &value) { - LoadValueById(&value, TypeInfo::Hash()); + LoadValueById(&value, TypeInfo::RegisteredId()); } template @@ -180,10 +194,10 @@ namespace sky { class JsonOutputArchive { public: - using Stream = impl::OutputStreamWrapper; + using Stream = impl::OutputStreamWrapper; using Writter = rapidjson::PrettyWriter; - JsonOutputArchive(std::ostream &s) : stream(s), writer(stream) {} + explicit JsonOutputArchive(IOutputArchive &s) : stream(s), writer(stream) {} ~JsonOutputArchive() = default; void StartObject() { writer.StartObject(); } @@ -192,6 +206,13 @@ namespace sky { void StartArray() { writer.StartArray(); } void EndArray() { writer.EndArray(); } + template + void SaveEnum(const T &v) + { + static_assert(std::is_enum_v); + SaveValue(static_cast>(v)); + } + void SaveValue(bool v) { writer.Bool(v); } void SaveValue(uint32_t v) { writer.Uint(v); } void SaveValue(int32_t v) { writer.Int(v); } @@ -204,11 +225,11 @@ namespace sky { void SaveValue(std::nullptr_t) { writer.Null(); } void SaveValueObject(const Any &any); - void SaveValueObject(const void *ptr, uint32_t id); + void SaveValueObject(const void *ptr, const Uuid &id); template , void>> void SaveValueObject(const T& value) { - SaveValueObject(&value, TypeInfo::Hash()); + SaveValueObject(&value, TypeInfo::RegisteredId()); } template diff --git a/runtime/framework/include/framework/serialization/PropertyCommon.h b/runtime/framework/include/framework/serialization/PropertyCommon.h new file mode 100644 index 00000000..b2a8989e --- /dev/null +++ b/runtime/framework/include/framework/serialization/PropertyCommon.h @@ -0,0 +1,16 @@ +// +// Created by Zach Lee on 2021/12/16. +// + +#pragma once + +namespace sky { + + enum class CommonPropertyKey : uint32_t { + VISIBLE, + LABEL_VISIBLE, + LABEL_COLOR, + ASSET_TYPE + }; + +} diff --git a/runtime/framework/include/framework/serialization/SerializationContext.h b/runtime/framework/include/framework/serialization/SerializationContext.h new file mode 100644 index 00000000..1e59c731 --- /dev/null +++ b/runtime/framework/include/framework/serialization/SerializationContext.h @@ -0,0 +1,130 @@ +// +// Created by Zach Lee on 2021/12/9. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class SerializationContext : public Singleton { + public: + template + auto Register(std::string_view name, const Uuid &uuid) + { + auto underlyingTypeId = uuid; + if constexpr (std::is_enum_v) { + using UnderlyingType = std::underlying_type_t; + underlyingTypeId = TypeInfoObj::Get()->RtInfo()->registeredId; + } + + const auto *info = TypeInfoObj::Get()->Register(name, uuid, underlyingTypeId); + SKY_ASSERT(!types.count(info->registeredId)) + auto &type = types[info->registeredId]; + type.info = info; + if constexpr (std::is_default_constructible_v) { + type.constructList.emplace_back( + ConstructNode{0, + [](Any *args) { return true; }, + [](Any *args) -> Any { return Any(std::in_place_type); }}); + } + + SKY_ASSERT(lookupTable.emplace(info->name, &type).second) + return TypeFactory(type); + } + + template + auto Register(std::string_view name) + { + return Register(name, Uuid::CreateWithSeed(Fnv1a32(name))); + } + + TypeNode *FindType(const std::string &key); + TypeNode *FindTypeById(const Uuid &id); + + private: + friend class Singleton; + + SerializationContext(); + ~SerializationContext() override = default; + + std::unordered_map types; + std::unordered_map lookupTable; + }; + + template + Any MakeAny(const Uuid &typeId, Args &&...args) + { + auto *context = SerializationContext::Get(); + TypeNode *node = context->FindTypeById(typeId); + if (node == nullptr || node->constructList.empty()) { + return {}; + } + for (auto &ctr : node->constructList) { + std::array anyArgs{Any(std::in_place_type, std::forward(args))...}; + if (ctr.argsNum == sizeof...(Args) && ctr.checkFn(anyArgs.data())) { + return ctr.constructFn(anyArgs.data()); + } + } + + return {}; + } + + template + inline Any MakeAny(Args &&...args) + { + return MakeAny(TypeInfo::RegisteredId(), std::forward(args)...); + } + + inline const TypeNode *GetTypeNode(const Uuid &typeId) + { + auto *context = SerializationContext::Get(); + return context->FindTypeById(typeId); + } + + inline const TypeNode *GetTypeNode(const Any &any) + { + const auto *rtInfo = any.Info(); + if (rtInfo == nullptr) { + return nullptr; + } + auto *context = SerializationContext::Get(); + return context->FindTypeById(rtInfo->registeredId); + } + + inline const TypeNode *GetTypeNode(const TypeInfoRT *rtInfo) + { + if (rtInfo == nullptr) { + return nullptr; + } + auto *context = SerializationContext::Get(); + return context->FindTypeById(rtInfo->registeredId); + } + + inline TypeMemberNode *GetTypeMember(const std::string_view &member, const Uuid &typeId) + { + auto *context = SerializationContext::Get(); + auto *node = context->FindTypeById(typeId); + if (node == nullptr) { + return nullptr; + } + + auto it = node->members.find(member); + if (it == node->members.end()) { + return nullptr; + } + + return &it->second; + } + + enum class SerializeOption : uint8_t { BIN, JSON }; + +} // namespace sky + +#define REGISTER_BEGIN(NAME, context) context->Register(#NAME) +#define REGISTER_MEMBER(NAME, Setter, Getter) .Member<&MY_CLASS::Setter, &MY_CLASS::Getter>(#NAME) + diff --git a/framework/include/framework/serialization/SerializationFactory.h b/runtime/framework/include/framework/serialization/SerializationFactory.h similarity index 85% rename from framework/include/framework/serialization/SerializationFactory.h rename to runtime/framework/include/framework/serialization/SerializationFactory.h index 44300b29..4b275954 100644 --- a/framework/include/framework/serialization/SerializationFactory.h +++ b/runtime/framework/include/framework/serialization/SerializationFactory.h @@ -4,7 +4,7 @@ #pragma once -#include +#include #include #include #include @@ -19,8 +19,8 @@ namespace sky { using PropertyMap = std::unordered_map; using SetterFn = bool (*)(void *ptr, const void *); - using GetterFn = void *(*)(void *ptr); - using GetterConstFn = const void*(*)(const void *ptr); + using GetterFn = Any (*)(void *ptr); + using GetterConstFn = Any (*)(const void *ptr); using ConstructibleFn = bool (*)(Any *); using ConstructFn = Any (*)(Any *); using JsonInFn = void (*)(void *p, JsonInputArchive& archive); @@ -29,7 +29,7 @@ namespace sky { using BinaryOutFn = void (*)(const void *p, BinaryOutputArchive& archive); struct TypeMemberNode { - TypeInfoRT *info = nullptr; + const TypeInfoRT *info = nullptr; const bool isConst; const bool isStatic; SetterFn setterFn = nullptr; @@ -52,11 +52,13 @@ namespace sky { }; using MemberMap = std::unordered_map; + using EnumMap = std::unordered_map; using ConstructList = std::list; struct TypeNode { - TypeInfoRT *base = nullptr; - TypeInfoRT *info = nullptr; + const TypeInfoRT *base = nullptr; + const TypeInfoRT *info = nullptr; MemberMap members; + EnumMap enums; PropertyMap properties; ConstructList constructList; SerializationNode serialization; @@ -104,42 +106,41 @@ namespace sky { } } - template + template bool Setter(void *p, const void *value) noexcept { if constexpr (std::is_member_object_pointer_v) { - using ValType = std::remove_reference_t().*D)>; - - if constexpr (!std::is_const_v) { + if constexpr (!std::is_const_v) { if (auto ptr = static_cast(p); ptr != nullptr) { - std::invoke(D, *ptr) = *static_cast(value); + std::invoke(D, *ptr) = *static_cast(value); return true; } } + } else if constexpr (std::is_member_function_pointer_v) { + std::invoke(D, static_cast(p), *static_cast(value)); + return true; } return false; } template - void* Getter(void *p) noexcept + Any Getter(void *p) noexcept { - if constexpr (std::is_member_object_pointer_v) { - if (auto ptr = static_cast(p); ptr != nullptr) { - return reinterpret_cast(std::addressof(std::invoke(D, *ptr))); - } + if constexpr (std::is_member_object_pointer_v || std::is_member_function_pointer_v) { + return Any(std::invoke(D, static_cast(p))); } - return nullptr; + return Any{}; } template - const void *GetterConst(const void *p) noexcept + Any GetterConst(const void *p) noexcept { - if constexpr (std::is_member_object_pointer_v) { - if (auto ptr = static_cast(p); ptr != nullptr) { - return reinterpret_cast(std::addressof(std::invoke(D, *ptr))); + if constexpr (std::is_member_object_pointer_v || std::is_member_function_pointer_v) { + if constexpr (std::is_invocable_v) { + return Any(std::invoke(D, static_cast(p))); } } - return nullptr; + return Any{}; } template @@ -193,7 +194,7 @@ namespace sky { } else { using Type = std::remove_pointer_t; auto it = type.members.emplace(key, TypeMemberNode{ - TypeInfoObj::Get()->RtInfo(), + TypeInfoObj>::Get()->RtInfo(), std::is_const_v, std::is_member_object_pointer_v, }); @@ -207,20 +208,20 @@ namespace sky { using Type = std::remove_reference_t>; if constexpr (std::is_const_v) { auto it = type.members.emplace(key, TypeMemberNode{ - TypeInfoObj::Get()->RtInfo(), + TypeInfoObj>::Get()->RtInfo(), std::is_const_v, !std::is_member_object_pointer_v, - &Setter, + &Setter, nullptr, &GetterConst, }); return TypeFactory, std::integral_constant>(type, it.first->second.properties); } else { auto it = type.members.emplace(key, TypeMemberNode{ - TypeInfoObj::Get()->RtInfo(), + TypeInfoObj>::Get()->RtInfo(), std::is_const_v, !std::is_member_object_pointer_v, - &Setter, + &Setter, &Getter, &GetterConst, }); @@ -228,6 +229,14 @@ namespace sky { } } + template + TypeFactory &Enum(E val, const std::string_view &name) + { + static_assert(std::is_integral_v>, "T must be integral type"); + type.enums.emplace(static_cast(val), name); + return *this; + } + template auto JsonLoad() { diff --git a/runtime/framework/include/framework/serialization/SerializationUtil.h b/runtime/framework/include/framework/serialization/SerializationUtil.h new file mode 100644 index 00000000..6ac511af --- /dev/null +++ b/runtime/framework/include/framework/serialization/SerializationUtil.h @@ -0,0 +1,42 @@ +// +// Created by Zach Lee on 2023/2/19. +// + +#pragma once + +#include +#include + +namespace sky { + + Any GetValueRaw(void *ptr, const Uuid &typeId, const std::string_view &memberName); + Any GetValueRawConst(const void *ptr, const Uuid &typeId, const std::string_view &memberName); + + template + Any GetValue(T &ptr, const std::string_view &memberName) + { + return GetValueRaw(static_cast(std::addressof(ptr)), TypeInfo::RegisteredId(), memberName); + } + + template + Any GetValueConst(T &ptr, const std::string_view &memberName) + { + return GetValueRawConst(static_cast(std::addressof(ptr)), TypeInfo::RegisteredId(), memberName); + } + + bool SetValueRaw(void* ptr, const Uuid &typeId, const std::string_view &memberName, const void* data); + + template + bool SetValue(void* ptr, const Uuid &typeId, const std::string_view &memberName, const M& data) + { + return SetValueRaw(ptr, typeId, memberName, &data); + } + + template + bool SetValue(T &ptr, const std::string_view &memberName, const M &data) + { + return SetValueRaw(static_cast(std::addressof(ptr)), TypeInfo::RegisteredId(), memberName, static_cast(std::addressof(data))); + } + + const Any &GetTypeProperty(const Uuid &typeId, uint32_t key); +} \ No newline at end of file diff --git a/framework/include/framework/window/IWindow.h b/runtime/framework/include/framework/window/IWindow.h similarity index 100% rename from framework/include/framework/window/IWindow.h rename to runtime/framework/include/framework/window/IWindow.h diff --git a/runtime/framework/include/framework/window/IWindowEvent.h b/runtime/framework/include/framework/window/IWindowEvent.h new file mode 100644 index 00000000..6e78364f --- /dev/null +++ b/runtime/framework/include/framework/window/IWindowEvent.h @@ -0,0 +1,198 @@ +// +// Created by Zach Lee on 2022/1/3. +// + +#pragma once + +#include +#include + +namespace sky { + class NativeWindow; + + using WindowID = uint32_t; + static const WindowID INVALID_WIN_ID = 0; + + enum class MouseButtonType : uint32_t { + LEFT, + RIGHT, + MIDDLE + }; + + struct MouseButtonEvent { + WindowID winID; + MouseButtonType button; + uint32_t clicks; + int32_t x; + int32_t y; + }; + + struct MouseMotionEvent { + WindowID winID; + int32_t x; + int32_t y; + int32_t relX; + int32_t relY; + }; + + struct MouseWheelEvent { + WindowID winID; + int32_t x; + int32_t y; + }; + + class IMouseEvent : public EventTraits { + public: + IMouseEvent() = default; + virtual ~IMouseEvent() = default; + + virtual void OnMouseButtonDown(const MouseButtonEvent &event) {} + virtual void OnMouseButtonUp(const MouseButtonEvent &event) {} + virtual void OnMouseMotion(const MouseMotionEvent &event) {} + virtual void OnMouseWheel(const MouseWheelEvent &event) {} + }; + + enum class ScanCode : uint32_t { + KEY_A = 4, + KEY_B = 5, + KEY_C = 6, + KEY_D = 7, + KEY_E = 8, + KEY_F = 9, + KEY_G = 10, + KEY_H = 11, + KEY_I = 12, + KEY_J = 13, + KEY_K = 14, + KEY_L = 15, + KEY_M = 16, + KEY_N = 17, + KEY_O = 18, + KEY_P = 19, + KEY_Q = 20, + KEY_R = 21, + KEY_S = 22, + KEY_T = 23, + KEY_U = 24, + KEY_V = 25, + KEY_W = 26, + KEY_X = 27, + KEY_Y = 28, + KEY_Z = 29, + KEY_1 = 30, + KEY_2 = 31, + KEY_3 = 32, + KEY_4 = 33, + KEY_5 = 34, + KEY_6 = 35, + KEY_7 = 36, + KEY_8 = 37, + KEY_9 = 38, + KEY_0 = 39, + KEY_RETURN = 40, + KEY_ESCAPE = 41, + KEY_BACKSPACE = 42, + KEY_TAB = 43, + KEY_SPACE = 44, + KEY_MINUS = 45, + KEY_EQUALS = 46, + KEY_LEFTBRACKET = 47, + KEY_RIGHTBRACKET = 48, + KEY_BACKSLASH = 49, + KEY_NONUSHASH = 50, + KEY_SEMICOLON = 51, + KEY_APOSTROPHE = 52, + KEY_GRAVE = 53, + KEY_COMMA = 54, + KEY_PERIOD = 55, + KEY_SLASH = 56, + KEY_CAPSLOCK = 57, + KEY_F1 = 58, + KEY_F2 = 59, + KEY_F3 = 60, + KEY_F4 = 61, + KEY_F5 = 62, + KEY_F6 = 63, + KEY_F7 = 64, + KEY_F8 = 65, + KEY_F9 = 66, + KEY_F10 = 67, + KEY_F11 = 68, + KEY_F12 = 69, + KEY_PRINTSCREEN = 70, + KEY_SCROLLLOCK = 71, + KEY_PAUSE = 72, + KEY_INSERT = 73, + KEY_HOME = 74, + KEY_PAGEUP = 75, + KEY_DELETE = 76, + KEY_END = 77, + KEY_PAGEDOWN = 78, + KEY_RIGHT = 79, + KEY_LEFT = 80, + KEY_DOWN = 81, + KEY_UP = 82, + KEY_NUMLOCKCLEAR = 83, + KEY_KP_DIVIDE = 84, + KEY_KP_MULTIPLY = 85, + KEY_KP_MINUS = 86, + KEY_KP_PLUS = 87, + KEY_KP_ENTER = 88, + KEY_KP_1 = 89, + KEY_KP_2 = 90, + KEY_KP_3 = 91, + KEY_KP_4 = 92, + KEY_KP_5 = 93, + KEY_KP_6 = 94, + KEY_KP_7 = 95, + KEY_KP_8 = 96, + KEY_KP_9 = 97, + KEY_KP_0 = 98, + KEY_KP_PERIOD = 99, + }; + + enum class KeyMod : uint32_t { + NONE = 0x0000, + LEFT_SHIFT = 0x0001, + RIGHT_SHIFT = 0x0002, + LEFT_CTRL = 0x0040, + RIGHT_CTRL = 0x0080, + LEFT_ALT = 0x0100, + RIGHT_ALT = 0x0200, + LEFT_GUI = 0x0400, + RIGHT_GUI = 0x0800, + NUM = 0x1000, + CAPS = 0x2000, + + SHIFT = LEFT_SHIFT | RIGHT_SHIFT, + CTRL = LEFT_CTRL | RIGHT_CTRL, + ALT = LEFT_ALT | RIGHT_ALT, + GUI = LEFT_GUI | RIGHT_GUI + }; + using KeyModFlags = Flags; + + struct KeyboardEvent { + WindowID winID; + ScanCode scanCode; + KeyModFlags mod; + }; + + class IKeyboardEvent : public EventTraits { + public: + virtual void OnKeyUp(const KeyboardEvent &event) {} + virtual void OnKeyDown(const KeyboardEvent &event) {} + virtual void OnTextInput(WindowID windID, const char *text) {} + }; + + class IWindowEvent : public EventTraits { + public: + using KeyType = const NativeWindow*; + + IWindowEvent() = default; + virtual ~IWindowEvent() = default; + + virtual void OnWindowResize(uint32_t width, uint32_t height) {} + virtual void OnFocusChanged(bool focus) {} + }; + +} // namespace sky \ No newline at end of file diff --git a/framework/include/framework/window/NativeWindow.h b/runtime/framework/include/framework/window/NativeWindow.h similarity index 73% rename from framework/include/framework/window/NativeWindow.h rename to runtime/framework/include/framework/window/NativeWindow.h index 7aaacca6..403ed7c6 100644 --- a/framework/include/framework/window/NativeWindow.h +++ b/runtime/framework/include/framework/window/NativeWindow.h @@ -6,6 +6,7 @@ #include #include +#include //struct SDL_Window; //union SDL_Event; @@ -24,22 +25,26 @@ namespace sky { uint32_t height = 768; std::string className; std::string titleName; - void *nativeHandle = nullptr; + void *handle = nullptr; }; static NativeWindow *Create(const Descriptor &); void *GetNativeHandle() const override; - virtual void PollEvent(bool &quit) = 0; - - virtual bool Init(const Descriptor &desc) = 0; + virtual bool Init(const Descriptor &desc) { return true; } uint32_t GetWidth() const { return descriptor.width; } uint32_t GetHeight() const { return descriptor.height; } + WindowID GetWinId() const { return winID; } protected: + friend class NativeWindowManager; + + void SetID(WindowID id); + void *winHandle = nullptr; + WindowID winID = INVALID_WIN_ID; Descriptor descriptor; }; } // namespace sky diff --git a/runtime/framework/include/framework/window/NativeWindowManager.h b/runtime/framework/include/framework/window/NativeWindowManager.h new file mode 100644 index 00000000..2476a718 --- /dev/null +++ b/runtime/framework/include/framework/window/NativeWindowManager.h @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/6/14. +// + +#pragma once + +#include +#include + +namespace sky { + + class NativeWindowManager : public Singleton { + public: + NativeWindowManager() = default; + ~NativeWindowManager() override = default; + + void Register(NativeWindow *window); + void UnRegister(NativeWindow *window); + NativeWindow* GetWindowByID(WindowID id) const; + private: + std::unordered_map windowLut; + }; + +} // namespace sky diff --git a/runtime/framework/include/framework/world/Actor.h b/runtime/framework/include/framework/world/Actor.h new file mode 100644 index 00000000..709dddb5 --- /dev/null +++ b/runtime/framework/include/framework/world/Actor.h @@ -0,0 +1,99 @@ +// +// Created by blues on 2024/5/14. +// + +#pragma once + +#include + +#include +#include + +#include +#include +#include + +namespace sky { + + class Actor; + class World; + + using ActorPtr = std::shared_ptr; + using ActorWeakPtr = std::weak_ptr; + + class Actor { + public: + Actor() = default; + explicit Actor(Uuid id) : uuid(id), name("Actor") {} + ~Actor(); + + using ComponentPtr = std::unique_ptr; + + template + T* AddComponent(Args &&...args) + { + static_assert(std::is_base_of_v); + const auto &id = TypeInfoObj::Get()->RtInfo()->registeredId; + SKY_ASSERT(static_cast(id)); + + auto *component = new T(std::forward(args)...); + if (!EmplaceComponent(id, component)) { + delete component; + component = nullptr; + } + return component; + } + + template + T* GetComponent() + { + static_assert(std::is_base_of_v); + const auto &id = TypeInfoObj::Get()->RtInfo()->registeredId; + SKY_ASSERT(static_cast(id)); + + return static_cast(GetComponent(id)); + } + + template + void RemoveComponent() + { + static_assert(std::is_base_of_v); + const auto &id = TypeInfoObj::Get()->RtInfo()->registeredId; + SKY_ASSERT(static_cast(id)); + + RemoveComponent(id); + } + + ComponentBase *GetComponent(const Uuid &typeId); + ComponentBase *AddComponent(const Uuid &typeId); + void RemoveComponent(const Uuid &typeId); + + void SaveJson(JsonOutputArchive &archive); + void LoadJson(JsonInputArchive &archive); + + void SetParent(const ActorPtr &actor); + + void Tick(float time); + + const Uuid &GetUuid() const { return uuid; } + const std::string &GetName() const { return name; } + void SetName(const std::string &name_) { name = name_; } + World *GetWorld() const { return world; } + + const std::unordered_map &GetComponents() const { return storage; } + + void AttachToWorld(World *world); + void DetachFromWorld(); + private: + friend class World; + bool EmplaceComponent(const Uuid &typeId, ComponentBase* component); + + std::unordered_map storage; + + Uuid uuid; + std::string name; + + World *world = nullptr; + }; + +} // namespace sky diff --git a/runtime/framework/include/framework/world/Component.h b/runtime/framework/include/framework/world/Component.h new file mode 100644 index 00000000..454d9d2f --- /dev/null +++ b/runtime/framework/include/framework/world/Component.h @@ -0,0 +1,68 @@ +// +// Created by Zach Lee on 2021/11/13. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class Actor; + class World; + class JsonOutputArchive; + class JsonInputArchive; + + class ComponentBase { + public: + ComponentBase() = default; + virtual ~ComponentBase() = default; + + virtual void Tick(float time) {} + + virtual void SaveJson(JsonOutputArchive &archive) const {} + virtual void LoadJson(JsonInputArchive &archive) {} + + virtual void SaveBin(BinaryOutputArchive &archive) const {} + virtual void LoadBin(BinaryInputArchive &archive) {} + + virtual const Uuid &GetTypeId() const = 0; + + virtual void OnAttachToWorld() {} + virtual void OnDetachFromWorld() {} + + Actor* GetActor() const { return actor; } + protected: + friend class Actor; + Actor *actor = nullptr; + }; + + template + class ComponentAdaptor : public ComponentBase { + public: + ComponentAdaptor() = default; + ~ComponentAdaptor() override = default; + + void SaveJson(JsonOutputArchive &archive) const override + { + archive.SaveValueObject(data); + } + + void LoadJson(JsonInputArchive &archive) override + { + archive.LoadValueObject(data); + } + + const Data &GetData() const { return data; } + + protected: + Data data = {}; + }; + + +#define COMPONENT_RUNTIME_INFO(NAME) \ + using MY_CLASS = NAME; \ + const Uuid &GetTypeId() const override { return TypeInfoObj::Get()->RtInfo()->registeredId; } +} // namespace sky diff --git a/runtime/framework/include/framework/world/ComponentFactory.h b/runtime/framework/include/framework/world/ComponentFactory.h new file mode 100644 index 00000000..21504726 --- /dev/null +++ b/runtime/framework/include/framework/world/ComponentFactory.h @@ -0,0 +1,44 @@ +// +// Created by blues on 2024/4/19. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class ComponentFactory : public Singleton { + public: + ComponentFactory() = default; + ~ComponentFactory() override = default; + + struct ComponentInfo { + Uuid typeId; + std::string_view name; + }; + + template + void RegisterComponent(const std::string &group) + { + static_assert(std::is_base_of_v); + + const auto *info = TypeInfoObj::Get()->RtInfo(); + + RegisterComponent(info->registeredId, info->name, group); + } + + const std::unordered_map> &GetTypes() const { return componentTypes; } + + private: + void RegisterComponent(const Uuid &uuid, const std::string_view &name, const std::string &group) + { + componentTypes[group].emplace_back(uuid, name); + } + + std::unordered_map> componentTypes; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/include/framework/world/Entity.h b/runtime/framework/include/framework/world/Entity.h new file mode 100644 index 00000000..8c16b315 --- /dev/null +++ b/runtime/framework/include/framework/world/Entity.h @@ -0,0 +1,59 @@ +// +// Created by blues on 2024/4/19. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + struct EntityValues { + uint64_t valid : 1; + uint64_t id : 63; + }; + static_assert(sizeof(EntityValues) == 8); + + using EntityId = uint64_t; + struct Entity { + union { + EntityValues value; + EntityId id; + }; + }; + + class EntityManager : Singleton { + public: + EntityManager() = default; + ~EntityManager() override = default; + + template + T* AddComponent(EntityId entity, Args&&... args) + { + return nullptr; + } + + template + T* GetComponent(EntityId entity) + { + return nullptr; + } + + template + void RemoveComponent(EntityId entity) + { + } + + EntityId CreateEntity(); + void DestroyEntity(EntityId entity); + private: + std::vector entities; + std::vector freeList; + + using Storage = std::vector; + std::unordered_map storages; + }; + +} // namespace sky diff --git a/runtime/framework/include/framework/world/TransformComponent.h b/runtime/framework/include/framework/world/TransformComponent.h new file mode 100644 index 00000000..a601a074 --- /dev/null +++ b/runtime/framework/include/framework/world/TransformComponent.h @@ -0,0 +1,59 @@ +// +// Created by Zach Lee on 2021/11/13. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + struct TransformData { + Transform local; + Transform global; + Uuid parent; + }; + + class TransformComponent : public ComponentAdaptor { + public: + TransformComponent() = default; + ~TransformComponent() override; + + static void Reflect(SerializationContext *context); + + COMPONENT_RUNTIME_INFO(TransformComponent) + + void SetParent(TransformComponent *parent); + TransformComponent *GetParent() const { return parent; } + void OnTransformChanged(); + + Matrix4 GetWorldMatrix() const; + + void SetWorldTranslation(const Vector3 &translation); + void SetWorldRotation(const Quaternion &rotation); + void SetWorldScale(const Vector3 &scale); + + void SetLocalTransform(const Transform &trans); + void SetLocalTranslation(const Vector3 &translation); + void SetLocalRotationEuler(const Vector3 &euler); + void SetLocalRotation(const Quaternion &rotation); + void SetLocalScale(const Vector3 &scale); + + const Transform& GetLocalTransform() const { return data.local; } + + Vector3 GetLocalRotationEuler() const; + const Quaternion &GetLocalRotation() const; + const Vector3 &GetLocalTranslation() const; + const Vector3 &GetLocalScale() const; + + private: + void UpdateLocal(); + void UpdateGlobal(); + + TransformComponent* parent = nullptr; + std::vector children; + }; + +} // namespace sky diff --git a/runtime/framework/include/framework/world/World.h b/runtime/framework/include/framework/world/World.h new file mode 100644 index 00000000..8f4607c5 --- /dev/null +++ b/runtime/framework/include/framework/world/World.h @@ -0,0 +1,96 @@ +// +// Created by Zach Lee on 2021/11/12. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace sky { + + class World; + using WorldPtr = CounterPtr; + + class IWorldEvent { + public: + IWorldEvent() = default; + ~IWorldEvent() = default; + + using KeyType = void; + using MutexType = void; + + virtual void OnCreateWorld(World& world) = 0; + }; + using WorldEvent = Event; + + class IWorldSubSystem { + public: + IWorldSubSystem() = default; + virtual ~IWorldSubSystem() = default; + + virtual void OnAttachToWorld(World &world) {} + virtual void OnDetachFromWorld(World &world) {} + + virtual void Tick(float time) {} + }; + + class World : public RefObject { + public: + ~World() override; + + static World *CreateWorld(); + + World(const World &) = delete; + World &operator=(const World &) = delete; + + static void Reflect(SerializationContext *context); + + void Init(std::vector&& systems); + void Tick(float time); + + void SaveJson(JsonOutputArchive &archive); + void LoadJson(JsonInputArchive &archive); + + ActorPtr CreateActor(bool withTrans = true); + ActorPtr CreateActor(const char *name, bool withTrans = true); + ActorPtr CreateActor(const std::string &name, bool withTrans = true); + ActorPtr CreateActor(const Uuid &id, bool withTrans = true); + ActorPtr GetActorByUuid(const Uuid &id); + const std::vector &GetActors() const { return actors; } + + void AttachToWorld(const ActorPtr &); + void DetachFromWorld(const ActorPtr &); + void Reset(); + + bool CheckSystem(const Name &name) const; + void AddSubSystem(const Name &name, IWorldSubSystem*); + IWorldSubSystem* GetSubSystem(const Name &name) const; + + void RegisterConfiguration(const std::string& name, const Any& any); + const Any& GetConfigByName(const std::string &name) const; + + private: + World() = default; + + std::vector actors; + + std::vector subSystemRegistry; + std::unordered_map> subSystems; + + std::unordered_map worldConfigs; + uint32_t version = 0; + }; +} // namespace sky diff --git a/framework/platform/android/AndridAssetStream.cpp b/runtime/framework/platform/android/AndridAssetStream.cpp similarity index 100% rename from framework/platform/android/AndridAssetStream.cpp rename to runtime/framework/platform/android/AndridAssetStream.cpp diff --git a/runtime/framework/platform/android/AndroidAssetArchive.cpp b/runtime/framework/platform/android/AndroidAssetArchive.cpp new file mode 100644 index 00000000..0f8ab368 --- /dev/null +++ b/runtime/framework/platform/android/AndroidAssetArchive.cpp @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/5/16. +// + +#include "AndroidAssetArchive.h" +#include +#include +#include + +namespace sky { + + AndroidAssetArchive::~AndroidAssetArchive() + { + AAsset_close(assetFile); + } + + AndroidAssetArchive::AndroidAssetArchive(AAsset *asset) : assetFile(asset) + { + } + + bool AndroidAssetArchive::LoadRaw(char *out, size_t size) + { + return AAsset_read(assetFile, out, size) == size; + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/platform/android/AndroidAssetArchive.h b/runtime/framework/platform/android/AndroidAssetArchive.h new file mode 100644 index 00000000..db8f8d67 --- /dev/null +++ b/runtime/framework/platform/android/AndroidAssetArchive.h @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/5/16. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class AndroidAssetArchive : public IInputArchive { + public: + explicit AndroidAssetArchive(AAsset *asset); + ~AndroidAssetArchive() override; + + bool LoadRaw(char *data, size_t size) override; + private: + AAsset *assetFile; + }; + +} \ No newline at end of file diff --git a/runtime/framework/platform/android/AndroidBundleFileSystem.cpp b/runtime/framework/platform/android/AndroidBundleFileSystem.cpp new file mode 100644 index 00000000..815c6d9b --- /dev/null +++ b/runtime/framework/platform/android/AndroidBundleFileSystem.cpp @@ -0,0 +1,75 @@ +// +// Created by blues on 2024/5/16. +// + +#include "AndroidBundleFileSystem.h" +#include "AndroidAssetArchive.h" + +#include +#include + +namespace sky { + + bool AndroidBundleFileSystem::FileExist(const std::string &path) + { + auto *am = static_cast(Platform::Get()->GetNativeApp())->activity->assetManager; + AAsset* assetFile = AAssetManager_open(am, path.c_str(), AASSET_MODE_UNKNOWN); + if (assetFile == nullptr) { + return false; + } + AAsset_close(assetFile); + return true; + } + + IArchivePtr AndroidBundleFileSystem::ReadAsArchive(const std::string &path) + { + auto *am = static_cast(Platform::Get()->GetNativeApp())->activity->assetManager; + AAsset* assetFile = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER); + if (assetFile != nullptr) { + return std::make_shared(assetFile); + } + return {}; + } + + OArchivePtr AndroidBundleFileSystem::WriteAsArchive(const std::string &path) + { + return {}; + } + + FilePtr AndroidBundleFileSystem::OpenFile(const std::string &name) + { + return std::make_shared(name); + } + + bool AndroidBundleFileSystem::ReadString(const std::string &path, std::string &out) + { + auto *am = static_cast(Platform::Get()->GetNativeApp())->activity->assetManager; + AAsset* assetFile = AAssetManager_open(am, path.c_str(), AASSET_MODE_BUFFER); + if (assetFile == nullptr) { + return false; + } + + size_t assetLength = AAsset_getLength(assetFile); + out.resize(assetLength); + AAsset_read(assetFile, out.data(), assetLength); + AAsset_close(assetFile); + return true; + } + + void AndroidAssetFile::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + auto *am = static_cast(Platform::Get()->GetNativeApp())->activity->assetManager; + AAsset* assetFile = AAssetManager_open(am, path.c_str(), AASSET_MODE_RANDOM); + if (assetFile == nullptr) { + return; + } + + size_t assetLength = AAsset_getLength(assetFile); + if (offset + size <= assetLength) { + AAsset_seek64(assetFile, offset, SEEK_SET); + AAsset_read(assetFile, out, size); + } + AAsset_close(assetFile); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/platform/android/AndroidBundleFileSystem.h b/runtime/framework/platform/android/AndroidBundleFileSystem.h new file mode 100644 index 00000000..4d68f346 --- /dev/null +++ b/runtime/framework/platform/android/AndroidBundleFileSystem.h @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/5/16. +// + +#pragma once + +#include + +namespace sky { + + class AndroidAssetFile : public IFile { + public: + explicit AndroidAssetFile(const std::string &name) : path(name) {} + ~AndroidAssetFile() = default; + + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + private: + std::string path; + }; + + class AndroidBundleFileSystem : public IFileSystem { + public: + AndroidBundleFileSystem() = default; + ~AndroidBundleFileSystem() override = default; + + bool FileExist(const std::string &path) override; + IArchivePtr ReadAsArchive(const std::string &path) override; + OArchivePtr WriteAsArchive(const std::string &path) override; + FilePtr OpenFile(const std::string &name) override; + bool ReadString(const std::string &path, std::string &out) override; + }; + +} // namespace sky diff --git a/framework/platform/android/AndroidPerfManager.cpp b/runtime/framework/platform/android/AndroidPerfManager.cpp similarity index 100% rename from framework/platform/android/AndroidPerfManager.cpp rename to runtime/framework/platform/android/AndroidPerfManager.cpp diff --git a/framework/platform/android/AndroidPerfManager.h b/runtime/framework/platform/android/AndroidPerfManager.h similarity index 100% rename from framework/platform/android/AndroidPerfManager.h rename to runtime/framework/platform/android/AndroidPerfManager.h diff --git a/framework/platform/android/AndroidPlatform.cpp b/runtime/framework/platform/android/AndroidPlatform.cpp similarity index 91% rename from framework/platform/android/AndroidPlatform.cpp rename to runtime/framework/platform/android/AndroidPlatform.cpp index 4f1fde80..393048ce 100644 --- a/framework/platform/android/AndroidPlatform.cpp +++ b/runtime/framework/platform/android/AndroidPlatform.cpp @@ -100,6 +100,11 @@ namespace sky { return app->activity->internalDataPath; } + std::string AndroidPlatform::GetBundlePath() const + { + return ""; + } + void *AndroidPlatform::GetMainWinHandle() const { return mainWindow; @@ -115,6 +120,14 @@ namespace sky { return perfManager.get(); } + FileSystemPtr AndroidPlatform::GetBundleFileSystem() + { + if (!assetFs) { + assetFs = std::make_shared(); + } + return assetFs; + } + bool Platform::Init(const PlatformInfo& info) { platform = std::make_unique(); diff --git a/framework/platform/android/AndroidPlatform.h b/runtime/framework/platform/android/AndroidPlatform.h similarity index 83% rename from framework/platform/android/AndroidPlatform.h rename to runtime/framework/platform/android/AndroidPlatform.h index c37e3af2..b57bbb3f 100644 --- a/framework/platform/android/AndroidPlatform.h +++ b/runtime/framework/platform/android/AndroidPlatform.h @@ -7,6 +7,7 @@ #include #include #include "AndroidPerfManager.h" +#include "AndroidBundleFileSystem.h" namespace sky { @@ -25,13 +26,16 @@ namespace sky { uint64_t GetPerformanceFrequency() const override; uint64_t GetPerformanceCounter() const override; std::string GetInternalPath() const override; + std::string GetBundlePath() const override; void *GetMainWinHandle() const override; void *GetNativeApp() const override; AdaptivePerfManager *GetPerformanceManager() const override; + FileSystemPtr GetBundleFileSystem() override; android_app *app = nullptr; ANativeWindow *mainWindow = nullptr; bool launched = false; std::unique_ptr perfManager; + std::shared_ptr assetFs; }; } diff --git a/runtime/framework/platform/android/AndroidWindow.cpp b/runtime/framework/platform/android/AndroidWindow.cpp new file mode 100644 index 00000000..82791fc1 --- /dev/null +++ b/runtime/framework/platform/android/AndroidWindow.cpp @@ -0,0 +1,94 @@ +// +// Created by Zach Lee on 2022/9/26. +// + +#include "AndroidWindow.h" +#include +#include +#include +#include "core/event/Event.h" +#include + +namespace sky { + + bool AndroidWindow::Init(const Descriptor &desc) + { + descriptor = desc; + if (descriptor.nativeHandle != nullptr) { + winHandle = descriptor.nativeHandle; + descriptor.width = ANativeWindow_getWidth(static_cast(winHandle)); + descriptor.height = ANativeWindow_getHeight(static_cast(winHandle)); + } + return winHandle != nullptr; + } + + void AndroidWindow::PollEvent(bool &quit) + { + android_app *app = static_cast(Platform::Get()->GetNativeApp()); +// android_input_buffer* inputBuffer = android_app_swap_input_buffers(app); +// +// if (inputBuffer == nullptr) { +// return; +// } +// +// if (inputBuffer->keyEventsCount != 0) { +// for (uint64_t i = 0; i < inputBuffer->keyEventsCount; ++i) { +// GameActivityKeyEvent *keyEvent = &inputBuffer->keyEvents[i]; +// // process key event +// } +// android_app_clear_key_events(inputBuffer); +// } +// +// +// if (inputBuffer && inputBuffer->motionEventsCount) { +// for (uint64_t i = 0; i < inputBuffer->motionEventsCount; ++i) { +// GameActivityMotionEvent* motionEvent = &inputBuffer->motionEvents[i]; +// +// if (motionEvent->pointerCount > 0) { +// const int action = motionEvent->action; +// const int actionMasked = action & AMOTION_EVENT_ACTION_MASK; +// const int button = motionEvent->buttonState; +// +// auto mouseX = static_cast(GameActivityPointerAxes_getX(&motionEvent->pointers[0])); +// auto mouseY = static_cast(GameActivityPointerAxes_getY(&motionEvent->pointers[0])); +// +// switch (button) { +// case AMOTION_EVENT_BUTTON_PRIMARY: +// break; +// case AMOTION_EVENT_BUTTON_SECONDARY: +// break; +// case AMOTION_EVENT_BUTTON_TERTIARY: +// break; +// case AMOTION_EVENT_BUTTON_BACK: +// break; +// case AMOTION_EVENT_BUTTON_FORWARD: +// break; +// default: +// break; +// } +// +// if (actionMasked == AMOTION_EVENT_ACTION_DOWN || actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) { +// Event::BroadCast(this, &IWindowEvent::OnMouseButtonDown, 1); +// } else if (actionMasked == AMOTION_EVENT_ACTION_UP || actionMasked == AMOTION_EVENT_ACTION_POINTER_UP) { +// Event::BroadCast(this, &IWindowEvent::OnMouseButtonUp, 1); +// } else if (actionMasked == AMOTION_EVENT_ACTION_SCROLL) { +// Event::BroadCast(this, &IWindowEvent::OnMouseWheel, mouseX, mouseY); +// } else if (actionMasked == AMOTION_EVENT_ACTION_MOVE) { +// Event::BroadCast(this, &IWindowEvent::OnMouseMove, mouseX, mouseY); +// } +// } +// } +// android_app_clear_motion_events(inputBuffer); +// } + } + + NativeWindow *NativeWindow::Create(const Descriptor &des) + { + NativeWindow *window = new AndroidWindow(); + if (!window->Init(des)) { + delete window; + window = nullptr; + } + return window; + } +} diff --git a/framework/platform/android/AndroidWindow.h b/runtime/framework/platform/android/AndroidWindow.h similarity index 100% rename from framework/platform/android/AndroidWindow.h rename to runtime/framework/platform/android/AndroidWindow.h diff --git a/framework/platform/genetic/GeneticPerfManager.cpp b/runtime/framework/platform/genetic/GeneticPerfManager.cpp similarity index 100% rename from framework/platform/genetic/GeneticPerfManager.cpp rename to runtime/framework/platform/genetic/GeneticPerfManager.cpp diff --git a/framework/platform/genetic/GeneticPerfManager.h b/runtime/framework/platform/genetic/GeneticPerfManager.h similarity index 100% rename from framework/platform/genetic/GeneticPerfManager.h rename to runtime/framework/platform/genetic/GeneticPerfManager.h diff --git a/runtime/framework/platform/genetic/SDLPlatform.cpp b/runtime/framework/platform/genetic/SDLPlatform.cpp new file mode 100644 index 00000000..58cae377 --- /dev/null +++ b/runtime/framework/platform/genetic/SDLPlatform.cpp @@ -0,0 +1,147 @@ +// +// Created by Zach Lee on 2022/9/25. +// + +#include "SDLPlatform.h" +#include +#include +#include +#include + +#include "SDLWindow.h" + +static const char* TAG = "SDLPlatform"; + +namespace sky { + + SDLPlatform::~SDLPlatform() + { + SDL_Quit(); + } + + bool SDLPlatform::Init(const PlatformInfo &desc) + { + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { + LOG_E(TAG, "SDL could not be initialized! Error: %s", SDL_GetError()); + return false; + } + return true; + } + + uint64_t SDLPlatform::GetPerformanceFrequency() const + { + return SDL_GetPerformanceFrequency(); + } + + uint64_t SDLPlatform::GetPerformanceCounter() const + { + return SDL_GetPerformanceCounter(); + } + + char* SDLPlatform::GetClipBoardText() + { + return SDL_GetClipboardText(); + } + + void SDLPlatform::FreeClipBoardText(char* text) + { + SDL_free(text); + } + + void SDLPlatform::SetClipBoardText(const std::string &text) + { + SDL_SetClipboardText(text.data()); + } + + void SDLPlatform::PollEvent(bool &exit) + { + SDL_Event sdlEvent; + while (SDL_PollEvent(&sdlEvent) != 0) { + Dispatch(sdlEvent, exit); + } + } + + void SDLPlatform::DispatchWindowEvent(const SDL_Event &sdlEvent) + { + const auto& winEvent = sdlEvent.window; + auto *nativeWindow = NativeWindowManager::Get()->GetWindowByID(winEvent.windowID); + if (nativeWindow != nullptr) { + static_cast(nativeWindow)->Dispatch(winEvent); + } + } + + void SDLPlatform::Dispatch(const SDL_Event &sdlEvent, bool &quit) + { + switch (sdlEvent.type) { + case SDL_QUIT: { + quit = true; + break; + } + case SDL_WINDOWEVENT: + DispatchWindowEvent(sdlEvent); + break; + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: { + const SDL_MouseButtonEvent &event = sdlEvent.button; + MouseButtonEvent mEvent = {}; + mEvent.winID = event.windowID; + mEvent.x = event.x; + mEvent.y = event.y; + mEvent.clicks = event.clicks; + if (event.button == SDL_BUTTON_LEFT) { mEvent.button = MouseButtonType::LEFT; } + else if (event.button == SDL_BUTTON_RIGHT) { mEvent.button = MouseButtonType::RIGHT; } + else if (event.button == SDL_BUTTON_MIDDLE) { mEvent.button = MouseButtonType::MIDDLE; } + if (sdlEvent.type == SDL_MOUSEBUTTONUP) { + Event::BroadCast(&IMouseEvent::OnMouseButtonUp, mEvent); + } else { + Event::BroadCast(&IMouseEvent::OnMouseButtonDown, mEvent); + } + break; + } + case SDL_MOUSEMOTION: { + const SDL_MouseMotionEvent &event = sdlEvent.motion; + MouseMotionEvent mEvent = {}; + mEvent.winID = event.windowID; + mEvent.x = event.x; + mEvent.y = event.y; + mEvent.relX = event.xrel; + mEvent.relY = event.yrel; + Event::BroadCast(&IMouseEvent::OnMouseMotion, mEvent); + break; + } + case SDL_MOUSEWHEEL: { + const SDL_MouseWheelEvent &event = sdlEvent.wheel; + MouseWheelEvent mEvent = {}; + mEvent.winID = event.windowID; + mEvent.x = event.x; + mEvent.y = event.y; + Event::BroadCast(&IMouseEvent::OnMouseWheel, mEvent); + break; + } + case SDL_KEYUP: + case SDL_KEYDOWN: { + const SDL_KeyboardEvent &event = sdlEvent.key; + KeyboardEvent kEvent = {}; + kEvent.winID = event.windowID; + kEvent.scanCode = static_cast(event.keysym.scancode); + kEvent.mod = KeyModFlags(event.keysym.mod); + if (sdlEvent.type == SDL_KEYUP) { + Event::BroadCast(&IKeyboardEvent::OnKeyUp, kEvent); + } else { + Event::BroadCast(&IKeyboardEvent::OnKeyDown, kEvent); + } + break; + } + case SDL_TEXTINPUT: { + const SDL_TextInputEvent &event = sdlEvent.text; + Event::BroadCast(&IKeyboardEvent::OnTextInput, event.windowID, event.text); + } + default: break; + } + } + +// std::string SDLPlatform::GetBundlePath() const +// { +// return SDL_GetBasePath(); +// } +} // namespace sky \ No newline at end of file diff --git a/framework/platform/genetic/SDLPlatform.h b/runtime/framework/platform/genetic/SDLPlatform.h similarity index 57% rename from framework/platform/genetic/SDLPlatform.h rename to runtime/framework/platform/genetic/SDLPlatform.h index 0cbc7cea..1b1e4939 100644 --- a/framework/platform/genetic/SDLPlatform.h +++ b/runtime/framework/platform/genetic/SDLPlatform.h @@ -7,6 +7,8 @@ #include #include +union SDL_Event; + namespace sky { class SDLPlatform : public PlatformBase { @@ -19,5 +21,13 @@ namespace sky { uint64_t GetPerformanceFrequency() const override; uint64_t GetPerformanceCounter() const override; + + void PollEvent(bool &exit) override; + void Dispatch(const SDL_Event &sdlEvent, bool &quit); + void DispatchWindowEvent(const SDL_Event &sdlEvent); + + char* GetClipBoardText() override; + void FreeClipBoardText(char* text) override; + void SetClipBoardText(const std::string &text) override; }; } // namespace sky diff --git a/runtime/framework/platform/genetic/SDLWindow.cpp b/runtime/framework/platform/genetic/SDLWindow.cpp new file mode 100644 index 00000000..befd7c18 --- /dev/null +++ b/runtime/framework/platform/genetic/SDLWindow.cpp @@ -0,0 +1,57 @@ +// +// Created by Zach Lee on 2022/9/25. +// + +#include "SDLWindow.h" +#include +#include +#include + +namespace sky { + + SDLWindow::~SDLWindow() + { + SDL_DestroyWindow(window); + } + + bool SDLWindow::Init(const Descriptor &desc) + { + descriptor = desc; + window = SDL_CreateWindow(desc.titleName.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, desc.width, desc.height, + SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MOUSE_CAPTURE | + SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_VULKAN); + + if (window != nullptr) { + winID = SDL_GetWindowID(window); + NativeWindowManager::Get()->Register(this); + } + return window != nullptr; + } + + void SDLWindow::Dispatch(const SDL_WindowEvent &event) { + switch (event.event) { + case SDL_WINDOWEVENT_SHOWN: + case SDL_WINDOWEVENT_RESTORED: + break; +// case SDL_WINDOWEVENT_SIZE_CHANGED: + case SDL_WINDOWEVENT_RESIZED: { + UpdateWindow(); + Event::BroadCast(this, &IWindowEvent::OnWindowResize, + static_cast(event.data1), + static_cast(event.data2)); + break; + } + case SDL_WINDOWEVENT_FOCUS_GAINED: + case SDL_WINDOWEVENT_FOCUS_LOST: { + Event::BroadCast(this, &IWindowEvent::OnFocusChanged, event.event == SDL_WINDOWEVENT_FOCUS_GAINED); + break; + } + case SDL_WINDOWEVENT_HIDDEN: + case SDL_WINDOWEVENT_MINIMIZED: + case SDL_WINDOWEVENT_ENTER: + case SDL_WINDOWEVENT_CLOSE: { + break; + } + } + } +} \ No newline at end of file diff --git a/framework/platform/genetic/SDLWindow.h b/runtime/framework/platform/genetic/SDLWindow.h similarity index 81% rename from framework/platform/genetic/SDLWindow.h rename to runtime/framework/platform/genetic/SDLWindow.h index 689e87cd..02ff25ae 100644 --- a/framework/platform/genetic/SDLWindow.h +++ b/runtime/framework/platform/genetic/SDLWindow.h @@ -14,15 +14,11 @@ namespace sky { SDLWindow() = default; ~SDLWindow() override; - void PollEvent(bool &quit) override; - bool Init(const Descriptor &desc) override; virtual void UpdateWindow() {} - protected: void Dispatch(const SDL_WindowEvent &event); - void Dispatch(const SDL_Event &sdlEvent, bool &quit); - + protected: SDL_Window *window = nullptr; }; diff --git a/framework/platform/macos/MacosPlatform.h b/runtime/framework/platform/macos/MacosPlatform.h similarity index 70% rename from framework/platform/macos/MacosPlatform.h rename to runtime/framework/platform/macos/MacosPlatform.h index 9d6d41e1..79ddd7a4 100644 --- a/framework/platform/macos/MacosPlatform.h +++ b/runtime/framework/platform/macos/MacosPlatform.h @@ -14,5 +14,8 @@ namespace sky { ~MacosPlatform() = default; std::string GetInternalPath() const override; + std::string GetBundlePath() const override; + + PlatformType GetType() const override { return PlatformType::MacOS; } }; } diff --git a/framework/platform/macos/MacosPlatform.mm b/runtime/framework/platform/macos/MacosPlatform.mm similarity index 73% rename from framework/platform/macos/MacosPlatform.mm rename to runtime/framework/platform/macos/MacosPlatform.mm index 93b1d750..d55d968c 100644 --- a/framework/platform/macos/MacosPlatform.mm +++ b/runtime/framework/platform/macos/MacosPlatform.mm @@ -19,8 +19,12 @@ { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; - std::string strRet = [documentsDirectory UTF8String]; - strRet.append("/"); - return strRet; + return [documentsDirectory UTF8String]; + } + + std::string MacosPlatform::GetBundlePath() const + { + auto *path = [[NSBundle mainBundle] bundlePath]; + return [path UTF8String]; } } diff --git a/framework/platform/macos/MacosWindow.cpp b/runtime/framework/platform/macos/MacosWindow.cpp similarity index 100% rename from framework/platform/macos/MacosWindow.cpp rename to runtime/framework/platform/macos/MacosWindow.cpp diff --git a/framework/platform/macos/MacosWindow.h b/runtime/framework/platform/macos/MacosWindow.h similarity index 100% rename from framework/platform/macos/MacosWindow.h rename to runtime/framework/platform/macos/MacosWindow.h diff --git a/framework/platform/windows/Win32Platform.cpp b/runtime/framework/platform/windows/Win32Platform.cpp similarity index 56% rename from framework/platform/windows/Win32Platform.cpp rename to runtime/framework/platform/windows/Win32Platform.cpp index b504e670..bb656522 100644 --- a/framework/platform/windows/Win32Platform.cpp +++ b/runtime/framework/platform/windows/Win32Platform.cpp @@ -14,17 +14,48 @@ static const char* TAG = "Win32Platform"; namespace sky { - std::string StringWideCharToUtf8(const std::wstring_view &strWideChar) + static std::wstring UTF8ToWide(const std::string& utf8Text) { - std::string ret; - if (!strWideChar.empty()) { - int num = WideCharToMultiByte(CP_UTF8, 0, strWideChar.data(), -1, nullptr, 0, nullptr, FALSE); - if (num != 0) { - ret.resize(num + 1, 0); - num = WideCharToMultiByte(CP_UTF8, 0, strWideChar.data(), -1, ret.data(), num + 1, nullptr, FALSE); - } + if (utf8Text.empty()) { + return {}; + } + + std::wstring wideText; + const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0); + if (wideLength == 0) { + return {}; } - return ret; + + wideText.resize(wideLength, 0); + auto* wideString = const_cast(wideText.data()); + const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength); + if (length != wideLength) { + return {}; + } + + return wideText; + } + + static std::string WideToUTF8(const std::wstring& wideText) + { + if (wideText.empty()) { + return {}; + } + + std::string narrowText; + int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr); + if (narrowLength == 0) { + return {}; + } + + narrowText.resize(narrowLength, 0); + char* narrowString = const_cast(narrowText.data()); + const int length = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr); + if (length != narrowLength) { + return {}; + } + + return narrowText; } struct Pipe { @@ -85,7 +116,28 @@ namespace sky { wchar_t fullPath[MAX_WRITABLE_PATH + 1]; ::GetModuleFileNameW(nullptr, fullPath, MAX_WRITABLE_PATH + 1); - return std::filesystem::path(StringWideCharToUtf8(fullPath)).parent_path().string(); + return std::filesystem::path(WideToUTF8(fullPath)).parent_path().string(); + } + + std::string Win32Platform::GetBundlePath() const + { + return GetInternalPath(); // TODO + } + + std::string Win32Platform::GetEnvVariable(const std::string &name) const + { + const std::wstring envKey = UTF8ToWide(name); + const DWORD size = ::GetEnvironmentVariableW(envKey.c_str(), nullptr, 0); + if (size == 0 || size == 1) { + return {}; + } + std::wstring envValue(size, 0); + const DWORD length = ::GetEnvironmentVariableW(envKey.data(), envValue.data(), (DWORD)envValue.size()); + if ((length == 0) || (length >= envValue.size())) { + return {}; + } + envValue.resize(length); + return WideToUTF8(envValue); } bool Win32Platform::RunCmd(const std::string &cmd, std::string &out) const diff --git a/framework/platform/windows/Win32Platform.h b/runtime/framework/platform/windows/Win32Platform.h similarity index 79% rename from framework/platform/windows/Win32Platform.h rename to runtime/framework/platform/windows/Win32Platform.h index 9baf41c9..8a39eed6 100644 --- a/framework/platform/windows/Win32Platform.h +++ b/runtime/framework/platform/windows/Win32Platform.h @@ -15,6 +15,8 @@ namespace sky { private: std::string GetInternalPath() const override; + std::string GetBundlePath() const override; + std::string GetEnvVariable(const std::string &env) const; bool RunCmd(const std::string &str, std::string &out) const override; PlatformType GetType() const override; }; diff --git a/framework/platform/windows/Win32Window.cpp b/runtime/framework/platform/windows/Win32Window.cpp similarity index 100% rename from framework/platform/windows/Win32Window.cpp rename to runtime/framework/platform/windows/Win32Window.cpp diff --git a/framework/platform/windows/Win32Window.h b/runtime/framework/platform/windows/Win32Window.h similarity index 100% rename from framework/platform/windows/Win32Window.h rename to runtime/framework/platform/windows/Win32Window.h diff --git a/framework/src/application/Application.cpp b/runtime/framework/src/application/Application.cpp similarity index 86% rename from framework/src/application/Application.cpp rename to runtime/framework/src/application/Application.cpp index 73c89732..f9e25958 100644 --- a/framework/src/application/Application.cpp +++ b/runtime/framework/src/application/Application.cpp @@ -4,8 +4,7 @@ #include -// 3rd -#include +#include // std #include @@ -17,7 +16,8 @@ #include #include #include -#include +#include +#include static const char *TAG = "Application"; @@ -27,6 +27,21 @@ namespace sky { { } + Application::~Application() + { + if (moduleManager) { + moduleManager->UnLoadModules(); + } + + Interface::Get()->UnRegister(); + + AssetManager::Destroy(); + DBManager::Destroy(); + + sky::Platform* platform = sky::Platform::Get(); + platform->Shutdown(); + } + void Application::SaveArgs(int argc, char **argv) { for (int i = 0; i < argc; ++i) { @@ -59,7 +74,8 @@ namespace sky { DBManager::Get()->Init(); Interface::Get()->Register(*this); - CoreReflection(); + auto *context = SerializationContext::Get(); + World::Reflect(context); PreInit(); @@ -76,17 +92,6 @@ namespace sky { return true; } - void Application::Shutdown() - { - Interface::Get()->UnRegister(); - - AssetManager::Destroy(); - DBManager::Destroy(); - - sky::Platform* platform = sky::Platform::Get(); - platform->Shutdown(); - } - void Application::SetExit() { exit = true; @@ -94,6 +99,11 @@ namespace sky { void Application::Loop() { + SKY_PROFILE_FRAME; + + // pool events + Platform::Get()->PoolEvent(exit); + PreTick(); uint64_t frequency = Platform::Get()->GetPerformanceFrequency(); diff --git a/framework/src/application/GameApplication.cpp b/runtime/framework/src/application/GameApplication.cpp similarity index 71% rename from framework/src/application/GameApplication.cpp rename to runtime/framework/src/application/GameApplication.cpp index bfa332c4..a0aabab3 100644 --- a/framework/src/application/GameApplication.cpp +++ b/runtime/framework/src/application/GameApplication.cpp @@ -17,7 +17,11 @@ #include static const char *TAG = "Application"; -static const char *CONFIG_PATH = "/config/modules_game.json"; +#ifdef SKY_EDITOR +static const char *CONFIG_PATH = "config/modules_game.json"; +#else +static const char *CONFIG_PATH = "config/modules_game.json"; +#endif namespace sky { @@ -30,10 +34,23 @@ namespace sky { options.add_options()("p,project", "Project Directory", cxxopts::value()); auto result = options.parse(argc, argv); if (result.count("project") != 0u) { - AssetManager::Get()->SetProjectPath(result["project"].as()); + std::string projectPath = result["project"].as(); + workFs = new NativeFileSystem(projectPath); + AssetManager::Get()->SetWorkFileSystem(workFs); + } else { + std::string workPath = Platform::Get()->GetBundlePath(); + workFs = new NativeFileSystem(workPath); + AssetManager::Get()->SetWorkFileSystem(workFs); } +#elif __ANDROID__ + workFs = Platform::Get()->GetBundleFileSystem(); +// workFs = std::make_shared(Platform::Get()->GetInternalPath()); + AssetManager::Get()->SetWorkPath(workFs); #else AssetManager::Get()->SetWorkPath(Platform::Get()->GetInternalPath()); + auto fs = std::make_shared(); + fs->AddPath(Platform::Get()->GetInternalPath()); + workFs = fs; #endif if (!Application::Init(argc, argv)) { @@ -43,34 +60,15 @@ namespace sky { return true; } - void GameApplication::Shutdown() - { - Application::Shutdown(); - nativeWindow.reset(); - } - void GameApplication::PreTick() { - if (nativeWindow) { - nativeWindow->PollEvent(exit); - } - } - - const NativeWindow *GameApplication::GetViewport() const - { - return nativeWindow.get(); } void GameApplication::LoadConfigs() { -#ifdef SKY_EDITOR - auto configPath = AssetManager::Get()->GetProjectPath() + CONFIG_PATH; -#else - auto configPath = Platform::Get()->GetInternalPath() + CONFIG_PATH; -#endif - std::string json; - if (!ReadString(configPath, json)) { + auto file = workFs->OpenFile(CONFIG_PATH); + if (!file || file->ReadString(json)) { LOG_W(TAG, "Load Config Failed"); return; } @@ -111,11 +109,11 @@ namespace sky { void GameApplication::PreInit() { - auto handle = Platform::Get()->GetMainWinHandle(); + auto *handle = Platform::Get()->GetMainWinHandle(); nativeWindow.reset(NativeWindow::Create(NativeWindow::Descriptor{width, height, "SkyGame", "SkyGame", handle})); } void GameApplication::PostInit() { } -} \ No newline at end of file +} diff --git a/framework/src/application/ModuleManager.cpp b/runtime/framework/src/application/ModuleManager.cpp similarity index 86% rename from framework/src/application/ModuleManager.cpp rename to runtime/framework/src/application/ModuleManager.cpp index ca77c558..b6e3fb4d 100644 --- a/framework/src/application/ModuleManager.cpp +++ b/runtime/framework/src/application/ModuleManager.cpp @@ -46,9 +46,17 @@ namespace sky { void ModuleManager::Tick(float time) { + WalkModules([this, time](const std::string &moduleName) { + modules[moduleName]->PreTick(time); + }, sortedContainer); + WalkModules([this, time](const std::string &moduleName) { modules[moduleName]->Tick(time); }, sortedContainer); + + WalkModules([this, time](const std::string &moduleName) { + modules[moduleName]->PostTick(time); + }, sortedContainer); } void ModuleManager::LoadModules(const StartArguments &args) @@ -69,8 +77,10 @@ namespace sky { modules.emplace(moduleName, std::unique_ptr(module)); dynLibs.emplace(moduleName, std::move(dynModule)); + LOG_I(TAG, "Load Module : %s success", moduleName.c_str()); + } else { + LOG_E(TAG, "Load Module : %s Failed", moduleName.c_str()); } - LOG_I(TAG, "Load Module : %s success", moduleName.c_str()); }, sortedContainer); } diff --git a/framework/src/application/SettingRegistry.cpp b/runtime/framework/src/application/SettingRegistry.cpp similarity index 100% rename from framework/src/application/SettingRegistry.cpp rename to runtime/framework/src/application/SettingRegistry.cpp diff --git a/framework/src/application/ToolApplicationBase.cpp b/runtime/framework/src/application/ToolApplicationBase.cpp similarity index 96% rename from framework/src/application/ToolApplicationBase.cpp rename to runtime/framework/src/application/ToolApplicationBase.cpp index 12a089af..68b03d64 100644 --- a/framework/src/application/ToolApplicationBase.cpp +++ b/runtime/framework/src/application/ToolApplicationBase.cpp @@ -41,7 +41,7 @@ namespace sky { } } - AssetManager::Get()->SetProjectPath(projectPath); + AssetManager::Get()->SetWorkFileSystem(new NativeFileSystem(projectPath)); } void ToolApplicationBase::LoadConfigs() diff --git a/runtime/framework/src/application/XRApplication.cpp b/runtime/framework/src/application/XRApplication.cpp new file mode 100644 index 00000000..97de4b3d --- /dev/null +++ b/runtime/framework/src/application/XRApplication.cpp @@ -0,0 +1,86 @@ +// +// Created by blues on 2024/3/13. +// + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +static const char *TAG = "Application"; +static const char *CONFIG_PATH = "/config/modules_game.json"; + +namespace sky { + + bool XRApplication::Init(int argc, char **argv) + { +#ifdef SKY_EDITOR + cxxopts::Options options("GameApplication Launcher", "SkyEngine Launcher"); + options.allow_unrecognised_options(); + + options.add_options()("p,project", "Project Directory", cxxopts::value()); + auto result = options.parse(argc, argv); + if (result.count("project") != 0u) { + AssetManager::Get()->SetWorkFileSystem(new NativeFileSystem(result["project"].as())); + } else { + AssetManager::Get()->SetWorkFileSystem(new NativeFileSystem(Platform::Get()->GetBundlePath())); + } +#else + AssetManager::Get()->SetWorkPath(Platform::Get()->GetBundleFileSystem()); +#endif + + if (!Application::Init(argc, argv)) { + return false; + } + + return true; + } + + void XRApplication::LoadConfigs() + { +//#ifdef SKY_EDITOR +// auto configPath = AssetManager::Get()->GetProjectPath() + CONFIG_PATH; +//#else +// auto configPath = Platform::Get()->GetInternalPath() + CONFIG_PATH; +//#endif +// +// std::string json; +// if (!ReadString(configPath, json)) { +// LOG_W(TAG, "Load Config Failed"); +// return; +// } +// +// rapidjson::Document document; +// document.Parse(json.c_str()); +// +// if (document.HasMember("modules")) { +// auto array = document["modules"].GetArray(); +// for (auto &module : array) { +// if (!module.HasMember("name")) { +// continue; +// } +// +// ModuleInfo info; +// info.name = module["name"].GetString(); +// +// if (module.HasMember("dependencies")) { +// auto depArray = module["dependencies"].GetArray(); +// for (auto &dep : depArray) { +// info.dependencies.emplace_back(dep.GetString()); +// } +// } +// moduleManager->RegisterModule(info); +// } +// } + } + + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/Asset.cpp b/runtime/framework/src/asset/Asset.cpp new file mode 100644 index 00000000..f8881938 --- /dev/null +++ b/runtime/framework/src/asset/Asset.cpp @@ -0,0 +1,26 @@ +// +// Created by Zach on 2022/8/8. +// + +#include + +namespace sky { + + void AssetBase::AddDependencies(const Uuid &id) + { + dependencies.emplace_back(id); + } + + void AssetBase::ResetDependencies() + { + dependencies.clear(); + } + + void AssetBase::BlockUntilLoaded() const + { + if (asyncTask.second.valid()) { + asyncTask.second.wait(); + } + } + +} // namespace sky \ No newline at end of file diff --git a/framework/src/asset/AssetBuilder.cpp b/runtime/framework/src/asset/AssetBuilder.cpp similarity index 100% rename from framework/src/asset/AssetBuilder.cpp rename to runtime/framework/src/asset/AssetBuilder.cpp diff --git a/runtime/framework/src/asset/AssetBuilderConfig.cpp b/runtime/framework/src/asset/AssetBuilderConfig.cpp new file mode 100644 index 00000000..fd9066af --- /dev/null +++ b/runtime/framework/src/asset/AssetBuilderConfig.cpp @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/7/21. +// + +#include + +namespace sky { + + void AssetBuilderConfig::LoadJson(JsonInputArchive &json) + { + uint32_t count = json.StartArray("bundles"); + for (uint32_t i = 0; i < count; ++i) { + bundles.emplace_back(json.LoadString()); + json.NextArrayElement(); + } + json.End(); + + json.Start("presets"); + json.ForEachMember([&json, this](const std::string &key) { + uint32_t count = json.StartArray(key); + auto &preset = presets[key]; + for (uint32_t i = 0; i < count; ++i) { + preset.emplace_back(json.LoadString()); + json.NextArrayElement(); + } + + json.End(); + }); + + json.End(); + } + + void AssetBuilderConfig::SaveJson(JsonOutputArchive &archive) + { + + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/AssetBuilderManager.cpp b/runtime/framework/src/asset/AssetBuilderManager.cpp new file mode 100644 index 00000000..41ba27a3 --- /dev/null +++ b/runtime/framework/src/asset/AssetBuilderManager.cpp @@ -0,0 +1,125 @@ +// +// Created by blues on 2024/6/21. +// + +#include +#include +#include +#include +#include +#include + +namespace sky { + AssetBuilder *AssetBuilderManager::QueryBuilder(const std::string &ext) const + { + auto iter = assetBuilderMap.find(ext); + return iter == assetBuilderMap.end() ? nullptr : iter->second; + } + + void AssetBuilderManager::SetEngineFs(const NativeFileSystemPtr &fs) + { + engineFs = fs; + } + + void AssetBuilderManager::SetWorkSpaceFs(const NativeFileSystemPtr &fs) + { + workSpaceFs = fs; + + // create products directory + auto productFs = workSpaceFs->CreateSubSystem("products", true); + auto configFs = workSpaceFs->CreateSubSystem("configs", false); + + auto *am = AssetManager::Get(); + // load configs + auto file = configFs->OpenFile("asset_build_presets.json"); + if (file) { + auto archive = file->ReadAsArchive(); + JsonInputArchive json(*archive); + config.LoadJson(json); + + if (config.bundles.empty()) { + config.bundles.emplace_back("common"); + } + for (auto &bundle :config.bundles) { + auto bundleFs = productFs->CreateSubSystem(bundle, true); + am->AddAssetProductBundle(new HashedAssetBundle(bundleFs, bundle)); + } + } + } + + void AssetBuilderManager::RegisterBuilder(AssetBuilder *builder) + { + assetBuilders.emplace_back(builder); + const auto &extensions = builder->GetExtensions(); + for (const auto &ext : extensions) { + assetBuilderMap[ext] = assetBuilders.back().get(); + } + } + + void AssetBuilderManager::LoadBuildConfigs(const FileSystemPtr &fs) + { + for (auto &builder : assetBuilders) { + builder->LoadConfig(fs); + } + } + + void AssetBuilderManager::UnRegisterBuilder(AssetBuilder *builder) + { + { + auto iter = std::find_if(assetBuilders.begin(), assetBuilders.end(), + [builder](const auto &val) { + return builder == val.get(); + }); + if (iter != assetBuilders.end()) { + assetBuilders.erase(iter); + } + } + + { + for (auto iter = assetBuilderMap.begin(); iter != assetBuilderMap.end();) { + if (iter->second == builder) { + iter = assetBuilderMap.erase(iter); + } else { + ++iter; + } + } + } + } + + void AssetBuilderManager::BuildRequest(const Uuid &uuid, const std::string &target) + { + auto srcAsset = AssetDataBase::Get()->FindAsset(uuid); + if (srcAsset) { + AssetBuildRequest request = {}; + request.assetInfo = srcAsset; + request.file = AssetDataBase::Get()->OpenFile(srcAsset); + request.target = target; + + BuildRequest(request); + } + } + + void AssetBuilderManager::BuildRequest(const AssetBuildRequest &request) + { + AssetExecutor::Get()->PushSavingTask(request.file, [this, request]() { + auto *builder = QueryBuilder(request.assetInfo->ext); + request.assetInfo->dependencies.clear(); + + AssetBuildResult result = {}; + builder->Request(request, result); + + AsseEvent::BroadCast(request.assetInfo->uuid, &IAssetEvent::OnAssetBuildFinished, result); + }); + } + + void AssetBuilderManager::ImportAsset(const AssetImportRequest &request) + { + AssetExecutor::Get()->DependentAsync([this, request]() { + auto ext = request.filePath.Extension(); + + auto *builder = QueryBuilder(ext); + builder->Import(request); + }); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/AssetDataBase.cpp b/runtime/framework/src/asset/AssetDataBase.cpp new file mode 100644 index 00000000..be0009f2 --- /dev/null +++ b/runtime/framework/src/asset/AssetDataBase.cpp @@ -0,0 +1,308 @@ +// +// Created by blues on 2024/6/16. +// + +#include +#include +#include +#include +#include +#include + +static const char* TAG = "AssetDataBase"; + +namespace sky { + + static uint32_t CalculateHash(const AssetSourcePath &path) + { + uint32_t res = 0; + HashCombine32(res, static_cast(path.bundle)); + HashCombine32(res, std::hash()(path.path.GetStr())); + return res; + } + + void AssetDataBase::SetEngineFs(const NativeFileSystemPtr &fs) + { + engineFs = fs->CreateSubSystem("assets", true); + + AssetBuilderManager::Get()->SetEngineFs(engineFs); + } + + void AssetDataBase::SetWorkSpaceFs(const NativeFileSystemPtr &fs) + { + workSpaceFs = fs->CreateSubSystem("assets", true); + + AssetBuilderManager::Get()->SetWorkSpaceFs(fs); + } + + AssetSourcePtr AssetDataBase::FindAsset(const Uuid &id) + { + std::lock_guard lock(assetMutex); + auto iter = idMap.find(id); + return iter != idMap.end() ? iter->second : nullptr; + } + + AssetSourcePtr AssetDataBase::FindAsset(const std::string &path) + { + std::lock_guard lock(assetMutex); + const SourceAssetBundle bundles[] = { + SourceAssetBundle::WORKSPACE, + SourceAssetBundle::ENGINE + }; + for (const auto &bundle : bundles) { + auto iter = pathMap.find({bundle, path}); + if (iter != pathMap.end()) { + return FindAsset(iter->second); + } + } + return {}; + } + + AssetSourcePtr AssetDataBase::RegisterAsset(const AssetSourcePath &path) + { + const auto &fs = GetFileSystemBySourcePath(path); + if (!fs->FileExist(path.path)) { + LOG_E(TAG, "File not Exist %s", path.path.GetStr().c_str()); + return nullptr; + } + + AssetSourcePtr info = nullptr; + { + std::lock_guard lock(assetMutex); + auto iter = pathMap.find(path); + if (iter != pathMap.end()) { + info = idMap.at(iter->second); + } + } + + if (info == nullptr) { + // query builder + auto ext = path.path.Extension(); + auto *builder = AssetBuilderManager::Get()->QueryBuilder(ext); + if (builder == nullptr) { + LOG_E(TAG, "Builder not found for asset %s", ext.c_str()); + return nullptr; + } + + AssetSourcePtr srcInfo = new AssetSourceInfo(); + auto uuid = Uuid::CreateWithSeed(CalculateHash(path)); + srcInfo->path = path; + srcInfo->uuid = uuid; + srcInfo->ext = ext; + srcInfo->category = builder->QueryType(ext); + + // new asset + { + std::lock_guard lock(assetMutex); + pathMap.emplace(path, uuid); + info = idMap.emplace(uuid, std::move(srcInfo)).first->second; + } + } + + AssetBuildRequest request = {}; + request.file = fs->OpenFile(path.path); + request.assetInfo = info; + AssetBuilderManager::Get()->BuildRequest(request); + + // request builder + return info; + } + + AssetSourcePtr AssetDataBase::RegisterAsset(const std::string &path) + { + auto querySource = QuerySource(path); + if (querySource.bundle == SourceAssetBundle::INVALID) { + return nullptr; + } + + return RegisterAsset(querySource); + } + + void AssetDataBase::RemoveAsset(const Uuid &id) + { + std::lock_guard lock(assetMutex); + SKY_ASSERT(idMap.count(id)); + auto &src = idMap[id]; + pathMap.erase(src->path); + idMap.erase(id); + } + + FilePtr AssetDataBase::OpenFile(const AssetSourcePtr &src) + { + const auto &fs = GetFileSystemBySourcePath(src->path); + return fs->OpenFile(src->path.path); + } + + FilePtr AssetDataBase::CreateOrOpenFile(const AssetSourcePath &path) + { + const auto &fs = GetFileSystemBySourcePath(path); + return fs->CreateOrOpenFile(path.path); + } + + void AssetDataBase::SetMarkedName(const Uuid& id, const std::string &name) + { + auto iter = idMap.find(id); + if (iter == idMap.end()) { + return; + } + + iter->second->name = name; + } + + void AssetDataBase::Load() + { + auto file = workSpaceFs->OpenFile("assets.db"); + if (!file) { + return; + } + + auto archive = file->ReadAsArchive(); + JsonInputArchive json(*archive); + + { + uint32_t count = json.StartArray("assets"); + for (uint32_t i = 0; i < count; ++i) { + auto *pInfo = new AssetSourceInfo(); + auto &info = *pInfo; + + json.Start("uuid"); + info.uuid = Uuid::CreateFromString(json.LoadString()); + json.End(); + + json.Start("markedName"); + info.name = json.LoadString(); + json.End(); + + json.Start("ext"); + info.ext = json.LoadString(); + json.End(); + + json.Start("type"); + info.category = json.LoadString(); + json.End(); + + json.Start("bundle"); + info.path.bundle = static_cast(json.LoadUint()); + json.End(); + + json.Start("path"); + info.path.path = json.LoadString(); + json.End(); + + uint32_t depCount = json.StartArray("dependencies"); + for (uint32_t j = 0; j < depCount; ++j) { + info.dependencies.emplace_back(Uuid::CreateFromString(json.LoadString())); + json.NextArrayElement(); + } + json.End(); + + json.NextArrayElement(); + + { + std::lock_guard lock(assetMutex); + pathMap.emplace(info.path, info.uuid); + idMap.emplace(info.uuid, pInfo); + } + } + + json.End(); + } + } + + void AssetDataBase::Save() + { + AssetExecutor::Get()->WaitForAll(); + + auto file = workSpaceFs->CreateOrOpenFile("assets.db"); + auto archive = file->WriteAsArchive(); + JsonOutputArchive json(*archive); + + { + std::lock_guard lock(assetMutex); + + json.StartObject(); + json.Key("assets"); + json.StartArray(); + for (auto &[id, pInfo] : idMap) { + auto &info = *pInfo; + json.StartObject(); + + // info + json.Key("uuid"); + json.SaveValue(info.uuid.ToString()); + + json.Key("markedName"); + json.SaveValue(info.name); + + json.Key("ext"); + json.SaveValue(info.ext); + + json.Key("type"); + json.SaveValue(info.category); + + json.Key("bundle"); + json.SaveEnum(info.path.bundle); + + json.Key("path"); + json.SaveValue(info.path.path.GetStr()); + + json.Key("dependencies"); + json.StartArray(); + + for (auto &dep : info.dependencies) { + json.SaveValue(dep.ToString()); + } + json.EndArray(); + json.EndObject(); + } + json.EndArray(); + json.EndObject(); + } + } + + void AssetDataBase::Reset() + { + std::lock_guard lock(assetMutex); + pathMap.clear(); + idMap.clear(); + } + + void AssetDataBase::Dump(std::ostream &stream) + { + std::lock_guard lock(assetMutex); + for (auto &[id, info] : idMap) { + stream << id.ToString() << "\t" + << info->category << "\t" + << info->name << "\t" + << "@" << static_cast(info->path.bundle) << "@" << info->path.path.GetStr() << "\n"; + } + } + + AssetSourcePath AssetDataBase::QuerySource(const std::string &path) + { + if (workSpaceFs->FileExist(FilePath(path))) { + return {SourceAssetBundle::WORKSPACE, path}; + } + + if (engineFs->FileExist(FilePath(path))) { + return {SourceAssetBundle::ENGINE, path}; + } + + return {SourceAssetBundle::INVALID}; + } + + const NativeFileSystemPtr &AssetDataBase::GetFileSystemBySourcePath(const AssetSourcePath &path) + { + static NativeFileSystemPtr empty; + switch (path.bundle) { + case SourceAssetBundle::ENGINE: + return engineFs; + case SourceAssetBundle::WORKSPACE: + return workSpaceFs; + case SourceAssetBundle::INVALID: + case SourceAssetBundle::CUSTOM_BEGIN: + break; + } + return empty; + } +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/AssetExecutor.cpp b/runtime/framework/src/asset/AssetExecutor.cpp new file mode 100644 index 00000000..b098bd35 --- /dev/null +++ b/runtime/framework/src/asset/AssetExecutor.cpp @@ -0,0 +1,16 @@ +// +// Created by blues on 2024/6/29. +// + +#include + +namespace sky { + + void AssetExecutor::WaitForAll() + { + executor.wait_for_all(); + std::lock_guard lock(mutex); + SKY_ASSERT(savingTasks.empty()); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/AssetManager.cpp b/runtime/framework/src/asset/AssetManager.cpp new file mode 100644 index 00000000..ccf93d00 --- /dev/null +++ b/runtime/framework/src/asset/AssetManager.cpp @@ -0,0 +1,216 @@ +// +// Created by blues on 2024/6/16. +// + +#include +#include +#include +#include +#include +#include + +static const char* TAG = "AssetManager"; + +namespace sky { + void AssetManager::SetWorkFileSystem(const FileSystemPtr &fs) + { + workSpace = fs; + } + + void AssetManager::AddAssetProductBundle(AssetProductBundle *bundle) + { + bundles.emplace_back(bundle); + } + + AssetPtr AssetManager::FindAsset(const Uuid &uuid) const + { + // check asset exists + std::lock_guard lock(mutex); + auto iter = assets.find(uuid); + if (iter != assets.end()) { + if (auto res = iter->second.lock(); res) { + return res; + } + } + return {}; + } + + AssetPtr AssetManager::FindOrCreateAsset(const Uuid &uuid, const std::string &type) + { + auto hIter = assetHandlers.find(type); + if (hIter == assetHandlers.end()) { + LOG_E(TAG, "Asset handler not registered asset %s, type %s", uuid.ToString().c_str(), type.c_str()); + return {}; + } + + std::shared_ptr asset; + { + std::lock_guard lock(mutex); + auto &ref = assets[uuid]; + if (auto res = ref.lock(); res) { + return res; + } + ref = asset = hIter->second->CreateAsset(); + } + asset->SetUuid(uuid); + asset->SetType(type); + return asset; + } + + AssetPtr AssetManager::CreateAssetByHeader(const Uuid &uuid, const IStreamArchivePtr &archive) + { + // get asset type + std::string type; + archive->Load(type); + + // try to find again + auto asset = FindOrCreateAsset(uuid, type); + if (asset) { + uint32_t depCount = 0; + archive->Load(depCount); + + asset->dependencies.resize(depCount); + for (uint32_t i = 0; i < depCount; ++i) { + auto &dep = asset->dependencies[i]; + archive->Load(dep.word[0]); + archive->Load(dep.word[1]); + } + } + return asset; + } + + AssetPtr AssetManager::LoadAsset(const Uuid &uuid) // NOLINT + { + auto asset = FindAsset(uuid); + + // check loaded + if (asset && asset->IsLoaded()) { + return asset; + } + + auto file = OpenFile(uuid); + if (!file) { + LOG_E(TAG, "Asset file missing %s", uuid.ToString().c_str()); + return {}; + } + + auto archive = file->ReadAsArchive(); + asset = CreateAssetByHeader(uuid, archive); + if (!asset) { + return {}; + } + + // avoid release dep asset + std::vector holder; + std::vector asyncTasks; + holder.reserve(asset->dependencies.size()); + + for (auto &dep : asset->dependencies) { + auto depAsset = LoadAsset(dep); + if (!depAsset) { + return {}; + } + + holder.emplace_back(depAsset); + asyncTasks.emplace_back(depAsset->asyncTask.first); + } + + asset->status.store(AssetBase::Status::LOADING); + asset->asyncTask = AssetExecutor::Get()->DependentAsyncRange( + [this, uuid, archive, deps = std::move(holder)]() mutable { + bool success = true; + for (const auto &dep : deps) { + SKY_ASSERT(dep->status.load() >= AssetBase::Status::LOADED) + success &= dep->IsLoaded(); + } + + if (!success) { + return; + } + + auto asset = FindAsset(uuid); + SKY_ASSERT(asset) + asset->depAssets.swap(deps); + auto res = assetHandlers[asset->type]->Load(*archive, asset); + asset->status.store(res ? AssetBase::Status::LOADED : AssetBase::Status::FAILED); + + AsseEvent::BroadCast(uuid, &IAssetEvent::OnAssetLoaded); + }, asyncTasks.begin(), asyncTasks.end()); + + return asset; + } + + AssetProductBundle *AssetManager::GetBundle(const ProductBundleKey &target) const + { + if (bundles.empty()) { + return nullptr; + } + + if (target.empty()) { + return bundles[0].get(); + } + + for (const auto &bundle : bundles) { + if (bundle->GetKey() != target) { + return bundle.get(); + } + } + return nullptr; + } + + AssetPtr AssetManager::LoadAssetFromPath(const std::string &path) + { + auto src = AssetDataBase::Get()->FindAsset(path); + return src ? LoadAsset(src->uuid) : AssetPtr{}; + } + + void AssetManager::SaveAsset(const AssetPtr &asset, const ProductBundleKey &target) + { + auto hIter = assetHandlers.find(asset->GetType()); + if (hIter == assetHandlers.end()) { + return; + } + + // flush load operation + asset->BlockUntilLoaded(); + + auto *pBundle = GetBundle(target); + if (pBundle == nullptr) { + return; + } + + FilePtr file = pBundle->CreateOrOpenFile(asset->GetUuid()); + if (!file) { + LOG_E(TAG, "Save Asset %s Failed. Can not create file.", asset->GetUuid().ToString().c_str()); + return; + } + + auto archive = file->WriteAsArchive(); + + archive->Save(asset->type); + archive->Save(static_cast(asset->dependencies.size())); + for (auto &dep : asset->dependencies) { + archive->Save(dep.word[0]); + archive->Save(dep.word[1]); + } + + asset->status.store(AssetBase::Status::LOADED); + hIter->second->Save(*archive, asset); + } + + FilePtr AssetManager::OpenFile(const Uuid &uuid) const + { + for (const auto &bundle : bundles) { + if (auto file = bundle->OpenFile(uuid); file) { + return file; + } + } + return {}; + } + + void AssetManager::RegisterAssetHandler(const std::string_view &type, AssetHandlerBase *handler) + { + assetHandlers[type.data()].reset(handler); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/asset/AssetProductBundle.cpp b/runtime/framework/src/asset/AssetProductBundle.cpp new file mode 100644 index 00000000..3e3b01d1 --- /dev/null +++ b/runtime/framework/src/asset/AssetProductBundle.cpp @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/6/26. +// + +#include + +namespace sky { + + FilePtr HashedAssetBundle::OpenFile(const Uuid &uuid) const + { + auto strUuid = uuid.ToString(); + auto sub = strUuid.substr(0, 2); + auto subFs = static_cast(fs.Get())->CreateSubSystem(sub, false); + return subFs->OpenFile(strUuid + ".bin"); + } + + FilePtr HashedAssetBundle::CreateOrOpenFile(const Uuid &uuid) const + { + auto strUuid = uuid.ToString(); + auto sub = strUuid.substr(0, 2); + auto subFs = static_cast(fs.Get())->CreateSubSystem(sub, true); + return subFs->CreateOrOpenFile(strUuid + ".bin"); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/controller/SimpleController.cpp b/runtime/framework/src/controller/SimpleController.cpp new file mode 100644 index 00000000..4703c59e --- /dev/null +++ b/runtime/framework/src/controller/SimpleController.cpp @@ -0,0 +1,123 @@ +// +// Created by blues on 2024/5/19. +// + +#include +#include +#include + +namespace sky { + + FirstPersonController::FirstPersonController() = default; + + Transform FirstPersonController::Resolve(float time, const Transform &trans) + { + Transform res = trans; + + auto euler = trans.rotation.ToEulerYZX(); + if (mouseButtons[MouseButtonType::RIGHT]) { + float diffX = static_cast(currentX - startX) / static_cast(window->GetWidth()); + float diffY = static_cast(currentY - startY) / static_cast(window->GetHeight()); + + startX = currentX; + startY = currentY; + + euler.y -= diffX * 20000.0f * time; + euler.x -= diffY * 20000.0f * time; + res.rotation.FromEulerYZX(euler); + } + + auto forward = trans.rotation * (-VEC3_Z); + auto up = trans.rotation * (VEC3_Y); + auto right = forward.Cross(up); + + if (keyButtons[ScanCode::KEY_UP] || keyButtons[ScanCode::KEY_W]) { + res.translation += forward * time * moveSpeed; + } + if (keyButtons[ScanCode::KEY_DOWN] || keyButtons[ScanCode::KEY_S]) { + res.translation -= forward * time * moveSpeed; + } + if (keyButtons[ScanCode::KEY_LEFT] || keyButtons[ScanCode::KEY_A]) { + res.translation -= right * time * moveSpeed; + } + if (keyButtons[ScanCode::KEY_RIGHT] || keyButtons[ScanCode::KEY_D]) { + res.translation += right * time * moveSpeed; + } + + return res; + } + + void FirstPersonController::BindWindow(const NativeWindow *window_) + { + keyBinder.Bind(this); + mouseBinder.Bind(this); + + window = window_; + } + + bool FirstPersonController::FilterWindowID(WindowID id) + { + return window != nullptr && window->GetWinId() == id; + } + + void FirstPersonController::OnMouseMotion(const MouseMotionEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + currentX = event.x; + currentY = event.y; + } + + void FirstPersonController::OnMouseButtonDown(const MouseButtonEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + mouseButtons[event.button] = true; + + if (event.button == MouseButtonType::RIGHT) { + startX = currentX; + startY = currentY; + } + } + + void FirstPersonController::OnMouseButtonUp(const MouseButtonEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + mouseButtons[event.button] = false; + } + + void FirstPersonController::OnMouseWheel(const MouseWheelEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + moveSpeed += static_cast(event.y); + moveSpeed = std::clamp(moveSpeed, 0.1f, 100.f); + } + + void FirstPersonController::OnKeyUp(const KeyboardEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + keyButtons[event.scanCode] = false; + } + + void FirstPersonController::OnKeyDown(const KeyboardEvent &event) + { + if (!FilterWindowID(event.winID)) { + return; + } + + keyButtons[event.scanCode] = true; + } +} // namespace sky \ No newline at end of file diff --git a/framework/src/database/DBManager.cpp b/runtime/framework/src/database/DBManager.cpp similarity index 100% rename from framework/src/database/DBManager.cpp rename to runtime/framework/src/database/DBManager.cpp diff --git a/framework/src/database/DataBase.cpp b/runtime/framework/src/database/DataBase.cpp similarity index 100% rename from framework/src/database/DataBase.cpp rename to runtime/framework/src/database/DataBase.cpp diff --git a/runtime/framework/src/platform/PlatformBase.cpp b/runtime/framework/src/platform/PlatformBase.cpp new file mode 100644 index 00000000..c3eec43c --- /dev/null +++ b/runtime/framework/src/platform/PlatformBase.cpp @@ -0,0 +1,128 @@ +// +// Created by bluesky on 2023/4/15. +// + +#include + +namespace sky { + + std::string Platform::GetPlatformNameByType(PlatformType type) + { + switch (type) { + case PlatformType::Windows: + return "Windows"; + case PlatformType::MacOS: + return "MacOS"; + case PlatformType::Linux: + return "Linux"; + case PlatformType::Android: + return "Android"; + case PlatformType::IOS: + return "iOS"; + case PlatformType::Default: + case PlatformType::UNDEFINED: + break; + } + return {}; + } + + PlatformType Platform::GetPlatformTypeByName(const std::string &name) + { + if (name == "Windows") { + return PlatformType::Windows; + } + if (name == "Linux") { + return PlatformType::Linux; + } + if (name == "MacOS") { + return PlatformType::MacOS; + } + if (name == "Android") { + return PlatformType::Android; + } + if (name == "iOS") { + return PlatformType::IOS; + } + return PlatformType::UNDEFINED; + } + + void Platform::Shutdown() + { + platform = nullptr; + } + + uint64_t Platform::GetPerformanceFrequency() const + { + return platform->GetPerformanceFrequency(); + } + + uint64_t Platform::GetPerformanceCounter() const + { + return platform->GetPerformanceCounter(); + } + + std::string Platform::GetInternalPath() const + { + return platform->GetInternalPath(); + } + + std::string Platform::GetBundlePath() const + { + return platform->GetBundlePath(); + } + + void *Platform::GetMainWinHandle() const + { + return platform->GetMainWinHandle(); + } + + void *Platform::GetNativeApp() const + { + return platform->GetNativeApp(); + } + + AdaptivePerfManager *Platform::GetPerformanceManager() const + { + return platform->GetPerformanceManager(); + } + + std::string Platform::GetEnvVariable(const std::string &env) const + { + return platform->GetEnvVariable(env); + } + + FileSystemPtr Platform::GetBundleFileSystem() const + { + return platform->GetBundleFileSystem(); + } + + bool Platform::RunCmd(const std::string &str, std::string &out) const + { + return platform->RunCmd(str, out); + } + + PlatformType Platform::GetType() const + { + return platform->GetType(); + } + + char* Platform::GetClipBoardText() const + { + return platform->GetClipBoardText(); + } + + void Platform::FreeClipBoardText(char* text) + { + platform->FreeClipBoardText(text); + } + + void Platform::SetClipBoardText(const std::string &text) + { + platform->SetClipBoardText(text); + } + + void Platform::PoolEvent(bool &exit) + { + platform->PollEvent(exit); + } +} diff --git a/core/src/type/Any.cpp b/runtime/framework/src/serialization/Any.cpp similarity index 67% rename from core/src/type/Any.cpp rename to runtime/framework/src/serialization/Any.cpp index 0efbc2d4..d33d3202 100644 --- a/core/src/type/Any.cpp +++ b/runtime/framework/src/serialization/Any.cpp @@ -2,7 +2,7 @@ // Created by Zach Lee on 2021/12/9. // -#include +#include namespace sky { @@ -11,7 +11,7 @@ namespace sky { if (info == nullptr) { return nullptr; } - return info->size > BLOCK_SIZE ? ptr : &data[0]; + return info->staticInfo->size > BLOCK_SIZE ? ptr : &data[0]; } const void *Any::Data() const @@ -19,26 +19,19 @@ namespace sky { if (info == nullptr) { return nullptr; } - return info->size > BLOCK_SIZE ? ptr : &data[0]; + return info->staticInfo->size > BLOCK_SIZE ? ptr : &data[0]; } void Any::CheckMemory() { - if (info->size > BLOCK_SIZE) { - ptr = malloc(info->size); - } - } - - void Any::Construct() - { - if (info->constructor != nullptr) { - info->constructor(ptr); + if (info->staticInfo->size > BLOCK_SIZE) { + ptr = malloc(info->staticInfo->size); } } void Any::Destructor() { - auto instance = Data(); + auto *instance = Data(); if (info == nullptr || instance == nullptr) { return; } @@ -47,7 +40,7 @@ namespace sky { info->destructor(instance); } - if (info->size > BLOCK_SIZE && ptr != nullptr) { + if (info->staticInfo->size > BLOCK_SIZE && ptr != nullptr) { free(ptr); } memset(data, 0, BLOCK_SIZE); @@ -62,7 +55,7 @@ namespace sky { void Any::Move(Any &any) { - if (info->size > BLOCK_SIZE) { + if (info->staticInfo->size > BLOCK_SIZE) { ptr = any.ptr; any.ptr = nullptr; } else { diff --git a/framework/src/serialization/BinaryArchive.cpp b/runtime/framework/src/serialization/BinaryArchive.cpp similarity index 55% rename from framework/src/serialization/BinaryArchive.cpp rename to runtime/framework/src/serialization/BinaryArchive.cpp index c39202f5..e550446a 100644 --- a/framework/src/serialization/BinaryArchive.cpp +++ b/runtime/framework/src/serialization/BinaryArchive.cpp @@ -8,31 +8,31 @@ namespace sky { - void BinaryInputArchive::LoadObject(void *ptr, uint32_t typeId) + void BinaryInputArchive::LoadObject(void *ptr, const Uuid &typeId) { - if (typeId == TypeInfo::Hash()) { + if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { LoadValue(*static_cast(ptr)); } else { const auto *node = GetTypeNode(typeId); @@ -47,37 +47,38 @@ namespace sky { } for (const auto &member : node->members) { std::string memberName = member.first.data(); - void *memPtr = GetValue(ptr, typeId, memberName); - LoadObject(memPtr, member.second.info->typeId); + Any value = GetValueRaw(ptr, typeId, memberName); + LoadObject(value.Data(), member.second.info->registeredId); + SetValueRaw(ptr, typeId, memberName, value.Data()); } } } - void BinaryOutputArchive::SaveObject(const void* ptr, uint32_t typeId) + void BinaryOutputArchive::SaveObject(const void* ptr, const Uuid &typeId) { - if (typeId == TypeInfo::Hash()) { + if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); } else { const auto *node = GetTypeNode(typeId); @@ -93,8 +94,8 @@ namespace sky { for (const auto &member : node->members) { std::string memberName = member.first.data(); - const void *memPtr = GetValueConst(ptr, typeId, memberName); - SaveObject(memPtr, member.second.info->typeId); + Any value = GetValueRawConst(ptr, typeId, memberName); + SaveObject(value.Data(), member.second.info->registeredId); } } } diff --git a/framework/src/serialization/CoreReflection.cpp b/runtime/framework/src/serialization/CoreReflection.cpp similarity index 72% rename from framework/src/serialization/CoreReflection.cpp rename to runtime/framework/src/serialization/CoreReflection.cpp index ce866951..e7fe8ef9 100644 --- a/framework/src/serialization/CoreReflection.cpp +++ b/runtime/framework/src/serialization/CoreReflection.cpp @@ -47,26 +47,36 @@ namespace sky { void JsonSaveVec4(const Vector4 &val, JsonOutputArchive &ar) { SaveN<4>(val.v, ar); } void JsonSaveQuat(const Quaternion &val, JsonOutputArchive &ar) { SaveN<4>(val.v, ar); } + void JsonSaveUuid(const Uuid &uuid, JsonOutputArchive &ar) { ar.SaveValue(uuid.ToString()); } + void JsonLoadUuid(Uuid &uuid, JsonInputArchive &ar) { uuid = Uuid::CreateFromString(ar.LoadString()); } - void CoreReflection() + void BinarySaveUuid(const Uuid &uuid, BinaryOutputArchive &ar) { - SerializationContext::Get() - ->Register("Vector2") + ar.SaveValue(uuid.word[0]); + ar.SaveValue(uuid.word[1]); + } + void BinaryLoadUuid(Uuid &uuid, BinaryInputArchive &ar) + { + ar.LoadValue(uuid.word[0]); + ar.LoadValue(uuid.word[1]); + } + + void CoreReflection(SerializationContext *context) + { + context->Register("Vector2") .Member<&Vector2::x>("x") .Member<&Vector2::y>("y") .JsonSave<&JsonSaveVec2>() .JsonLoad<&JsonLoadVec2>(); - SerializationContext::Get() - ->Register("Vector3") + context->Register("Vector3") .Member<&Vector3::x>("x") .Member<&Vector3::y>("y") .Member<&Vector3::z>("z") .JsonSave<&JsonSaveVec3>() .JsonLoad<&JsonLoadVec3>(); - SerializationContext::Get() - ->Register("Vector4") + context->Register("Vector4") .Member<&Vector4::x>("x") .Member<&Vector4::y>("y") .Member<&Vector4::z>("z") @@ -74,8 +84,7 @@ namespace sky { .JsonSave<&JsonSaveVec4>() .JsonLoad<&JsonLoadVec4>(); - SerializationContext::Get() - ->Register("Quaternion") + context->Register("Quaternion") .Member<&Quaternion::x>("x") .Member<&Quaternion::y>("y") .Member<&Quaternion::z>("z") @@ -83,17 +92,22 @@ namespace sky { .JsonSave<&JsonSaveQuat>() .JsonLoad<&JsonLoadQuat>(); - SerializationContext::Get() - ->Register("Transform") + context->Register("Transform") .Member<&Transform::translation>("translation") .Member<&Transform::scale>("scale") .Member<&Transform::rotation>("rotation"); - SerializationContext::Get() - ->Register("Color") + context->Register("Color") .Member<&Color::r>("r") .Member<&Color::g>("g") .Member<&Color::b>("b") .Member<&Color::b>("a"); + + context->Register("Uuid") + .Member<&Uuid::FromString, &Uuid::ToString>("id") + .JsonSave<&JsonSaveUuid>() + .JsonLoad<&JsonLoadUuid>() + .BinLoad<&BinaryLoadUuid>() + .BinSave<&BinarySaveUuid>(); } } // namespace sky \ No newline at end of file diff --git a/framework/src/serialization/JsonArchive.cpp b/runtime/framework/src/serialization/JsonArchive.cpp similarity index 51% rename from framework/src/serialization/JsonArchive.cpp rename to runtime/framework/src/serialization/JsonArchive.cpp index 88b06f65..73fc81d0 100644 --- a/framework/src/serialization/JsonArchive.cpp +++ b/runtime/framework/src/serialization/JsonArchive.cpp @@ -10,34 +10,34 @@ namespace sky { void JsonOutputArchive::SaveValueObject(const Any &any) { - SaveValueObject(any.Data(), any.Info()->typeId); + SaveValueObject(any.Data(), any.Info()->registeredId); } - void JsonOutputArchive::SaveValueObject(const void *ptr, uint32_t typeId) + void JsonOutputArchive::SaveValueObject(const void *ptr, const Uuid &typeId) { - if (typeId == TypeInfo::Hash()) { + if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { SaveValue(*static_cast(ptr)); } else { auto *context = SerializationContext::Get(); @@ -51,54 +51,58 @@ namespace sky { return; } - StartObject(); - Key("classId"); - SaveValue(typeId); - - Key("elements"); - StartObject(); - for (auto &member : node->members) { - std::string memberName = member.first.data(); - Key(memberName.c_str()); - auto memberValue = GetValueConst(ptr, typeId, memberName); - SaveValueObject(memberValue, member.second.info->typeId); + if (node->info->staticInfo->isEnum) { + SaveValueObject(ptr, node->info->underlyingTypeId); + } else { + StartObject(); + Key("classId"); + SaveValue(typeId.ToString()); + + Key("elements"); + StartObject(); + for (auto &member: node->members) { + std::string memberName = member.first.data(); + Key(memberName.c_str()); + Any value = GetValueRawConst(ptr, typeId, memberName); + SaveValueObject(value.Data(), member.second.info->registeredId); + } + EndObject(); + EndObject(); } - EndObject(); - EndObject(); } } - void JsonInputArchive::LoadValueById(void *ptr, uint32_t typeId) + void JsonInputArchive::LoadValueById(void *ptr, const Uuid &typeId) { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); - if (typeId == TypeInfo::Hash()) { + if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetBool()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetUint64()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetUint()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetUint()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetUint()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetInt64()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetInt()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetInt()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetInt()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetDouble()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = static_cast(value->GetDouble()); - } else if (typeId == TypeInfo::Hash()) { + } else if (typeId == TypeInfo::RegisteredId()) { *static_cast(ptr) = std::string(value->GetString()); } else { - auto node = GetTypeNode(typeId); + const auto *node = GetTypeNode(typeId); SKY_ASSERT(node != nullptr && "type not registered"); if (node == nullptr) { return; @@ -108,26 +112,37 @@ namespace sky { node->serialization.jsonLoad(ptr, *this); return; } - SKY_ASSERT(value != nullptr && value->IsObject()); - SKY_ASSERT(Start("classId")); - uint32_t id = LoadUint(); - SKY_ASSERT(id == typeId); - End(); - - SKY_ASSERT(Start("elements")); - for (auto &member : node->members) { - std::string memberName = member.first.data(); - SKY_ASSERT(Start(memberName)); - auto *memberAddress = GetValue(ptr, typeId, memberName); - LoadValueById(memberAddress, member.second.info->typeId); + + if (node->info->staticInfo->isEnum) { + LoadValueById(ptr, node->info->underlyingTypeId); + } else { + SKY_ASSERT(value != nullptr && value->IsObject()); + SKY_ASSERT(Start("classId")); + auto id = Uuid::CreateFromString(LoadString()); + End(); + SKY_ASSERT(id == typeId); + + SKY_ASSERT(Start("elements")); + for (const auto &member : node->members) { + std::string memberName = member.first.data(); + auto *memberNode = GetTypeMember(memberName, typeId); + if (memberNode == nullptr) { + continue; + } + + if(Start(memberName)) { + Any any = GetValueRawConst(ptr, typeId, memberName); + LoadValueById(any.Data(), member.second.info->registeredId); + SetValueRaw(ptr, typeId, memberName, any.Data()); + End(); + } + } End(); } - - End(); } } - Any JsonInputArchive::LoadValueById(uint32_t typeId) + Any JsonInputArchive::LoadValueById(const Uuid &typeId) { auto res = MakeAny(typeId); LoadValueById(res.Data(), typeId); @@ -137,7 +152,7 @@ namespace sky { bool JsonInputArchive::LoadBool() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsBool()); return value->GetBool(); } @@ -145,7 +160,7 @@ namespace sky { int32_t JsonInputArchive::LoadInt() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsInt()); return value->GetInt(); @@ -154,7 +169,7 @@ namespace sky { uint32_t JsonInputArchive::LoadUint() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsUint()); return value->GetUint(); @@ -163,7 +178,7 @@ namespace sky { int64_t JsonInputArchive::LoadInt64() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsInt64()); return value->GetInt64(); @@ -172,7 +187,7 @@ namespace sky { uint64_t JsonInputArchive::LoadUint64() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsUint64()); return value->GetUint64(); @@ -181,7 +196,7 @@ namespace sky { double JsonInputArchive::LoadDouble() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsDouble()); return value->GetDouble(); @@ -190,7 +205,7 @@ namespace sky { std::string JsonInputArchive::LoadString() { SKY_ASSERT(!stack.empty()); - auto value = stack.back(); + const auto *value = stack.back(); SKY_ASSERT(value != nullptr && value->IsString()); return value->GetString(); diff --git a/framework/src/serialization/SerializationContext.cpp b/runtime/framework/src/serialization/SerializationContext.cpp similarity index 62% rename from framework/src/serialization/SerializationContext.cpp rename to runtime/framework/src/serialization/SerializationContext.cpp index 8a84c350..dd652f03 100644 --- a/framework/src/serialization/SerializationContext.cpp +++ b/runtime/framework/src/serialization/SerializationContext.cpp @@ -3,8 +3,20 @@ // #include - +#include +#include namespace sky { + + void JsonLoad(std::string &str, JsonInputArchive &archive) + { + str = archive.LoadString(); + } + + void JsonStore(const std::string &str, JsonOutputArchive &archive) + { + archive.SaveValue(str); + } + SerializationContext::SerializationContext() { Register("uint64_t"); @@ -18,7 +30,12 @@ namespace sky { Register("bool"); Register("float"); Register("double"); - Register("string"); + + Register("String") + .JsonLoad<&JsonLoad>() + .JsonSave<&JsonStore>(); + + CoreReflection(this); } TypeNode *SerializationContext::FindType(const std::string &key) @@ -27,7 +44,7 @@ namespace sky { return iter == lookupTable.end() ? nullptr : iter->second; } - TypeNode *SerializationContext::FindTypeById(uint32_t id) + TypeNode *SerializationContext::FindTypeById(const Uuid &id) { auto iter = types.find(id); return iter == types.end() ? nullptr : &iter->second; diff --git a/runtime/framework/src/serialization/SerializationUtil.cpp b/runtime/framework/src/serialization/SerializationUtil.cpp new file mode 100644 index 00000000..538dac19 --- /dev/null +++ b/runtime/framework/src/serialization/SerializationUtil.cpp @@ -0,0 +1,50 @@ +// +// Created by Zach Lee on 2023/2/19. +// + +#include + +namespace sky { + + Any GetValueRaw(void *ptr, const Uuid &typeId, const std::string_view &memberName) + { + auto *node = GetTypeMember(memberName, typeId); + if (node != nullptr && node->getterFn != nullptr) { + return node->getterFn(const_cast(ptr)); + } + return Any{}; + } + + Any GetValueRawConst(const void *ptr, const Uuid &typeId, const std::string_view &memberName) + { + auto *node = GetTypeMember(memberName, typeId); + if (node != nullptr && node->getterConstFn != nullptr) { + return node->getterConstFn(const_cast(ptr)); + } + return Any{}; + } + + bool SetValueRaw(void* ptr, const Uuid &typeId, const std::string_view &memberName, const void* data) + { + auto *node = GetTypeMember(memberName, typeId); + if (node != nullptr && node->setterFn != nullptr) { + return node->setterFn(ptr, data); + } + return false; + } + + const Any &GetTypeProperty(const Uuid &typeId, uint32_t key) + { + static const Any Empty; + + const auto *node = GetTypeNode(typeId); + if (node != nullptr) { + auto iter = node->properties.find(key); + if (iter != node->properties.end()) { + return iter->second; + } + } + return Empty; + } + +} \ No newline at end of file diff --git a/framework/src/window/NativeWindow.cpp b/runtime/framework/src/window/NativeWindow.cpp similarity index 53% rename from framework/src/window/NativeWindow.cpp rename to runtime/framework/src/window/NativeWindow.cpp index 08e3ce3e..f43a2b1e 100644 --- a/framework/src/window/NativeWindow.cpp +++ b/runtime/framework/src/window/NativeWindow.cpp @@ -4,6 +4,8 @@ #include +#include +#include namespace sky { @@ -13,6 +15,7 @@ namespace sky { NativeWindow::~NativeWindow() { + NativeWindowManager::Get()->UnRegister(this); } void *NativeWindow::GetNativeHandle() const @@ -20,4 +23,10 @@ namespace sky { return winHandle; } + void NativeWindow::SetID(WindowID id) + { + SKY_ASSERT(winID == INVALID_WIN_ID); + winID = id; + } + } // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/window/NativeWindowManager.cpp b/runtime/framework/src/window/NativeWindowManager.cpp new file mode 100644 index 00000000..b3c90060 --- /dev/null +++ b/runtime/framework/src/window/NativeWindowManager.cpp @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/6/14. +// + +#include + +namespace sky { + + void NativeWindowManager::Register(NativeWindow *window) + { + windowLut.emplace(window->GetWinId(), window); + } + + void NativeWindowManager::UnRegister(NativeWindow *window) + { + windowLut.erase(window->GetWinId()); + } + + NativeWindow* NativeWindowManager::GetWindowByID(WindowID id) const + { + auto iter = windowLut.find(id); + return iter == windowLut.end() ? nullptr : iter->second; + } +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/world/Actor.cpp b/runtime/framework/src/world/Actor.cpp new file mode 100644 index 00000000..0c5040a0 --- /dev/null +++ b/runtime/framework/src/world/Actor.cpp @@ -0,0 +1,129 @@ +// +// Created by blues on 2024/5/14. +// + +#include +#include +#include + +namespace sky { + + Actor::~Actor() + { + storage.clear(); + } + + ComponentBase *Actor::GetComponent(const Uuid &typeId) + { + auto iter = storage.find(typeId); + return iter != storage.end() ? iter->second.get() : nullptr; + } + + bool Actor::EmplaceComponent(const Uuid &typeId, ComponentBase* component) + { + component->actor = this; + auto res = storage.emplace(typeId, component); + return res.second; + } + + ComponentBase *Actor::AddComponent(const Uuid &typeId) + { + auto *component = static_cast(SerializationContext::Get()->FindTypeById(typeId)->info->newFunc()); + if (!EmplaceComponent(typeId, component)) { + delete component; + component = nullptr; + } + return component; + } + + void Actor::RemoveComponent(const Uuid &typeId) + { + storage.erase(typeId); + } + + void Actor::SaveJson(JsonOutputArchive &archive) + { + archive.StartObject(); + archive.Key("uuid"); + archive.SaveValue(uuid.ToString()); + archive.Key("name"); + archive.SaveValue(name); + + archive.Key("components"); + archive.StartArray(); + for (auto &[id, component] : storage) { + archive.StartObject(); + archive.Key("type"); + archive.SaveValue(id.ToString()); + archive.Key("data"); + component->SaveJson(archive); + archive.EndObject(); + } + archive.EndArray(); + archive.EndObject(); + } + + void Actor::LoadJson(JsonInputArchive &archive) + { + archive.Start("uuid"); + uuid = Uuid::CreateFromString(archive.LoadString()); + archive.End(); + + archive.Start("name"); + name = archive.LoadString(); + archive.End(); + + auto componentCount = archive.StartArray("components"); + + auto *context = SerializationContext::Get(); + + for (uint32_t i = 0; i < componentCount; ++i) { + + archive.Start("type"); + auto typeId = Uuid::CreateFromString(archive.LoadString()); + archive.End(); + + archive.Start("data"); + auto *tmp = static_cast(context->FindTypeById(typeId)->info->newFunc()); + tmp->LoadJson(archive); + tmp->actor = this; + EmplaceComponent(typeId, tmp); + archive.End(); + + archive.NextArrayElement(); + } + archive.End(); + } + + void Actor::SetParent(const ActorPtr &parent) + { + auto* trans = GetComponent(); + auto* parentTrans = parent ? parent->GetComponent() : nullptr; + if (trans != nullptr) { + trans->SetParent(parentTrans); + } + } + + void Actor::Tick(float time) + { + for (auto &[id, component] : storage) { + component->Tick(time); + } + } + + void Actor::AttachToWorld(World *world_) + { + world = world_; + for (auto &[id, component] : storage) { + component->OnAttachToWorld(); + } + } + + void Actor::DetachFromWorld() + { + for (auto &[id, component] : storage) { + component->OnDetachFromWorld(); + } + world = nullptr; + } +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/world/Entity.cpp b/runtime/framework/src/world/Entity.cpp new file mode 100644 index 00000000..08482e8d --- /dev/null +++ b/runtime/framework/src/world/Entity.cpp @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/4/19. +// + +#include + +namespace sky { + + EntityId EntityManager::CreateEntity() + { + if (freeList.empty()) { + Entity entity = {}; + entity.value.valid = true; + entity.value.id = static_cast(entities.size()); + entities.emplace_back(entity); + return entity.id; + } + + auto back = freeList.back(); + entities[back].value.valid = true; + freeList.pop_back(); + return back; + } + + void EntityManager::DestroyEntity(EntityId entity) + { + entities[entity].value.valid = false; + freeList.emplace_back(entity); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/framework/src/world/TransformComponent.cpp b/runtime/framework/src/world/TransformComponent.cpp new file mode 100644 index 00000000..07bcb87f --- /dev/null +++ b/runtime/framework/src/world/TransformComponent.cpp @@ -0,0 +1,143 @@ +// +// Created by Zach Lee on 2021/11/13. +// + +#include +#include +#include +#include + +namespace sky { + + static const char *TAG = "TransformComponent"; + + void TransformComponent::Reflect(SerializationContext *context) + { + context->Register("TransformData") + .Member<&TransformData::local>("data") + .Member<&TransformData::parent>("parent"); + + REGISTER_BEGIN(TransformComponent, context) + REGISTER_MEMBER(translation, SetLocalTranslation, GetLocalTranslation) + REGISTER_MEMBER(rotation, SetLocalRotationEuler, GetLocalRotationEuler) + REGISTER_MEMBER(scale, SetLocalScale, GetLocalScale); + + ComponentFactory::Get()->RegisterComponent("Base"); + } + + TransformComponent::~TransformComponent() + { + SetParent(nullptr); + for (auto &child : children) { + child->parent = nullptr; + } + } + + Matrix4 TransformComponent::GetWorldMatrix() const + { + return data.local.ToMatrix(); + } + + void TransformComponent::SetParent(TransformComponent *parent_) + { + if (parent_ == parent || parent_ == this) { + return; + } + + if (parent != nullptr) { + parent->children.erase(std::remove(parent->children.begin(), parent->children.end(), this), parent->children.end()); + } + + parent = parent_; + data.parent = parent != nullptr ? parent->actor->GetUuid() : Uuid::GetEmpty(); + UpdateLocal(); + + if (parent != nullptr) { + parent->children.emplace_back(this); + } + } + + void TransformComponent::OnTransformChanged() // NOLINT + { + for (auto *child : children) { + child->OnTransformChanged(); + } + } + + void TransformComponent::SetWorldTranslation(const Vector3 &translation) + { + data.global.translation = translation; + UpdateLocal(); + OnTransformChanged(); + } + void TransformComponent::SetWorldRotation(const Quaternion &rotation) + { + data.global.rotation = rotation; + UpdateLocal(); + OnTransformChanged(); + } + void TransformComponent::SetWorldScale(const Vector3 &scale) + { + data.global.scale = scale; + UpdateLocal(); + OnTransformChanged(); + } + void TransformComponent::SetLocalTransform(const Transform &trans) + { + data.local = trans; + UpdateGlobal(); + OnTransformChanged(); + } + void TransformComponent::SetLocalTranslation(const Vector3 &translation) + { + data.local.translation = translation; + UpdateGlobal(); + OnTransformChanged(); + } + void TransformComponent::SetLocalRotationEuler(const Vector3 &euler) + { + data.local.rotation.FromEulerYZX(euler); + UpdateGlobal(); + OnTransformChanged(); + } + void TransformComponent::SetLocalRotation(const Quaternion &rotation) + { + data.local.rotation = rotation; + UpdateGlobal(); + OnTransformChanged(); + } + void TransformComponent::SetLocalScale(const Vector3 &scale) + { + data.local.scale = scale; + UpdateGlobal(); + OnTransformChanged(); + } + + Vector3 TransformComponent::GetLocalRotationEuler() const + { + return data.local.rotation.ToEulerYZX(); + } + + const Quaternion &TransformComponent::GetLocalRotation() const + { + return data.local.rotation; + } + const Vector3 &TransformComponent::GetLocalTranslation() const + { + return data.local.translation; + } + const Vector3 &TransformComponent::GetLocalScale() const + { + return data.local.scale; + } + + void TransformComponent::UpdateLocal() + { + data.local = parent != nullptr ? parent->data.global.GetInverse() * data.global : data.global; + } + + void TransformComponent::UpdateGlobal() + { + data.global = parent != nullptr ? parent->data.global * data.local * data.global : data.local; + } +} // namespace sky diff --git a/runtime/framework/src/world/World.cpp b/runtime/framework/src/world/World.cpp new file mode 100644 index 00000000..e7db34ea --- /dev/null +++ b/runtime/framework/src/world/World.cpp @@ -0,0 +1,189 @@ +// +// Created by Zach Lee on 2021/11/13. +// + +#include +#include +#include +#include + +#include +#include +#include + +namespace sky { + + World::~World() + { + for (auto &actor : actors) { + actor->DetachFromWorld(); + } + actors.clear(); + + for (auto &sub : subSystems) { + sub.second->OnDetachFromWorld(*this); + } + } + + void World::Reflect(SerializationContext *context) + { + TransformComponent::Reflect(context); + } + + World *World::CreateWorld() + { + auto *world = new World(); + return world; + } + + void World::Init(std::vector&& systems) + { + subSystemRegistry.swap(systems); + WorldEvent::BroadCast(&IWorldEvent::OnCreateWorld, *this); + } + + void World::Tick(float time) + { + for (auto &actor : actors) { + actor->Tick(time); + } + + for (auto &sys : subSystems) { + sys.second->Tick(time); + } + } + + void World::SaveJson(JsonOutputArchive &archive) + { + archive.StartObject(); + + archive.Key("actors"); + archive.StartArray(); + + for (auto &actor : actors) { + actor->SaveJson(archive); + } + + archive.EndArray(); + + archive.EndObject(); + } + + void World::LoadJson(JsonInputArchive &archive) + { + auto num = archive.StartArray("actors"); + for (uint32_t i = 0; i < num; ++i) { + auto actor = std::make_shared(); + actor->LoadJson(archive); + AttachToWorld(actor); + archive.NextArrayElement(); + } + archive.End(); + + // resolve hierarchy + for (auto &actor : actors) { + auto *trans = actor->GetComponent(); + if (trans != nullptr) { + auto parentActor = GetActorByUuid(trans->GetData().parent); + + if (parentActor != nullptr) { + auto *parentTrans = parentActor->GetComponent(); + SKY_ASSERT(parentTrans); + trans->SetParent(parentTrans); + } + } + } + } + + ActorPtr World::CreateActor(const char *name, bool withTrans) + { + auto actor = CreateActor(Uuid::Create(), withTrans); + actor->SetName(name); + return actor; + } + + ActorPtr World::CreateActor(const std::string &name, bool withTrans) + { + auto actor = CreateActor(Uuid::Create(), withTrans); + actor->SetName(name); + return actor; + } + + ActorPtr World::CreateActor(bool withTrans) + { + return CreateActor("Actor", withTrans); + } + + ActorPtr World::CreateActor(const Uuid &id, bool withTrans) + { + actors.emplace_back(std::make_shared(id)); + actors.back()->world = this; + if (withTrans) { + actors.back()->AddComponent(); + } + return actors.back(); + } + + ActorPtr World::GetActorByUuid(const Uuid &id) + { + auto iter = std::find_if(actors.begin(), actors.end(), [&id](const auto &v) { + return id == v->GetUuid(); + }); + return iter != actors.end() ? *iter : ActorPtr{}; + } + + void World::AttachToWorld(const sky::ActorPtr &actor) + { + if (actor->world != nullptr && actor->world != this) { + actor->world->DetachFromWorld(actor); + } + actor->world = this; + actors.emplace_back(actor); + actor->AttachToWorld(this); + } + + void World::DetachFromWorld(const ActorPtr &actor) + { + actor->DetachFromWorld(); + auto iter = std::find_if(actors.begin(), actors.end(), + [&actor](const auto &v) { return actor == v; }); + + if (iter != actors.end()) { + actors.erase(iter); + } + } + + void World::Reset() + { + actors.clear(); + } + + bool World::CheckSystem(const Name &name) const + { + return std::find(subSystemRegistry.begin(), subSystemRegistry.end(), name) != subSystemRegistry.end(); + } + + void World::AddSubSystem(const Name &name, IWorldSubSystem* sys) + { + SKY_ASSERT(subSystems.emplace(name, sys).second); + sys->OnAttachToWorld(*this); + } + + IWorldSubSystem* World::GetSubSystem(const Name &name) const + { + auto iter = subSystems.find(name); + return iter != subSystems.end() ? iter->second.get() : nullptr; + } + + void World::RegisterConfiguration(const std::string& name, const Any& any) + { + SKY_ASSERT(worldConfigs.emplace(name, any).second); + } + + const Any& World::GetConfigByName(const std::string &name) const + { + static Any EMPTY; + auto iter = worldConfigs.find(name); + return iter != worldConfigs.end() ? iter->second : EMPTY; + } +} // namespace sky diff --git a/engine/CMakeLists.txt b/runtime/navigation/CMakeLists.txt similarity index 79% rename from engine/CMakeLists.txt rename to runtime/navigation/CMakeLists.txt index f5140ae6..07e31143 100644 --- a/engine/CMakeLists.txt +++ b/runtime/navigation/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE SRC_FILES src/*) file(GLOB_RECURSE INC_FILES include/*) -sky_add_library(TARGET SkyEngine STATIC +sky_add_library(TARGET Navigation STATIC SOURCES ${SRC_FILES} ${INC_FILES} @@ -10,6 +10,5 @@ sky_add_library(TARGET SkyEngine STATIC PUBLIC_INC include LINK_LIBS - Core Framework - ) \ No newline at end of file +) \ No newline at end of file diff --git a/runtime/navigation/include/navigation/NaviMap.h b/runtime/navigation/include/navigation/NaviMap.h new file mode 100644 index 00000000..4682c2a2 --- /dev/null +++ b/runtime/navigation/include/navigation/NaviMap.h @@ -0,0 +1,42 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include + +namespace sky::ai { + + class NaviMapData { + public: + NaviMapData() = default; + virtual ~NaviMapData() = default; + }; + + class NaviMap { + public: + NaviMap() = default; + virtual ~NaviMap() = default; + }; + + class NaviMapFactory : public Singleton { + public: + NaviMapFactory() = default; + ~NaviMapFactory() override = default; + + NaviMap* CreateNaviMap(); + + class Impl { + public: + Impl() = default; + virtual ~Impl() = default; + + virtual NaviMap* CreateNaviMap() = 0; + }; + + private: + std::unique_ptr factory; + }; + +} // namespace sky::ai diff --git a/runtime/navigation/include/navigation/NavigationSystem.h b/runtime/navigation/include/navigation/NavigationSystem.h new file mode 100644 index 00000000..86f9b5a2 --- /dev/null +++ b/runtime/navigation/include/navigation/NavigationSystem.h @@ -0,0 +1,22 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include + +namespace sky::ai { + + class NavigationSystem : public IWorldSubSystem { + public: + NavigationSystem() = default; + ~NavigationSystem() override = default; + + private: + std::unique_ptr naviMap; + }; + +} // namespace sky::ai diff --git a/runtime/navigation/src/NaviMap.cpp b/runtime/navigation/src/NaviMap.cpp new file mode 100644 index 00000000..5f1d2808 --- /dev/null +++ b/runtime/navigation/src/NaviMap.cpp @@ -0,0 +1,14 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::ai { + + NaviMap* NaviMapFactory::CreateNaviMap() + { + return factory ? factory->CreateNaviMap() : nullptr; + } + +} // namespace sky::ai \ No newline at end of file diff --git a/runtime/navigation/src/NavigationSystem.cpp b/runtime/navigation/src/NavigationSystem.cpp new file mode 100644 index 00000000..3d0cc087 --- /dev/null +++ b/runtime/navigation/src/NavigationSystem.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::ai { + +} // namespace sky::ai \ No newline at end of file diff --git a/render/adaptor/CMakeLists.txt b/runtime/physics/CMakeLists.txt similarity index 74% rename from render/adaptor/CMakeLists.txt rename to runtime/physics/CMakeLists.txt index ba768a98..e51d0245 100644 --- a/render/adaptor/CMakeLists.txt +++ b/runtime/physics/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE SRC_FILES src/*) file(GLOB_RECURSE INC_FILES include/*) -sky_add_library(TARGET SkyRenderAdaptor STATIC +sky_add_library(TARGET Physics STATIC SOURCES ${SRC_FILES} ${INC_FILES} @@ -10,6 +10,5 @@ sky_add_library(TARGET SkyRenderAdaptor STATIC PUBLIC_INC include LINK_LIBS - SkyRenderCore Framework - ) \ No newline at end of file +) \ No newline at end of file diff --git a/runtime/physics/include/physics/CharacterController.h b/runtime/physics/include/physics/CharacterController.h new file mode 100644 index 00000000..1f0f2a57 --- /dev/null +++ b/runtime/physics/include/physics/CharacterController.h @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +namespace sky::phy { + + class CharacterController { + public: + CharacterController() = default; + virtual ~CharacterController() = default; + }; + +} // namespace sky::phy diff --git a/runtime/physics/include/physics/PhysicsDebugDraw.h b/runtime/physics/include/physics/PhysicsDebugDraw.h new file mode 100644 index 00000000..05739f60 --- /dev/null +++ b/runtime/physics/include/physics/PhysicsDebugDraw.h @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +namespace sky::phy { + + class PhysicsDebugDraw { + public: + PhysicsDebugDraw() = default; + virtual ~PhysicsDebugDraw() = default; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/include/physics/PhysicsMaterial.h b/runtime/physics/include/physics/PhysicsMaterial.h new file mode 100644 index 00000000..b2098eab --- /dev/null +++ b/runtime/physics/include/physics/PhysicsMaterial.h @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +namespace sky::phy { + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/include/physics/PhysicsRegistry.h b/runtime/physics/include/physics/PhysicsRegistry.h new file mode 100644 index 00000000..59a732ee --- /dev/null +++ b/runtime/physics/include/physics/PhysicsRegistry.h @@ -0,0 +1,41 @@ +// +// Created by blues on 2024/9/2. +// + +#pragma once + +#include + +namespace sky::phy { + class PhysicsWorld; + class RigidBody; + class CharacterController; + class PhysicsShape; + + class PhysicsRegistry : public Singleton { + public: + PhysicsRegistry() = default; + ~PhysicsRegistry() override = default; + + class Impl { + public: + Impl() = default; + virtual ~Impl() = default; + + virtual PhysicsWorld* CreatePhysicsWorld() = 0; + virtual RigidBody* CreateRigidBody() = 0; + virtual CharacterController* CreateCharacterController() = 0; + }; + + PhysicsWorld* CreatePhysicsWorld(); + RigidBody* CreateRigidBody(); + CharacterController* CreateCharacterController(); + + void Register(Impl* factory); + void UnRegister(); + + private: + std::unique_ptr factory; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/include/physics/PhysicsShape.h b/runtime/physics/include/physics/PhysicsShape.h new file mode 100644 index 00000000..4792da05 --- /dev/null +++ b/runtime/physics/include/physics/PhysicsShape.h @@ -0,0 +1,17 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include + +namespace sky::phy { + + class PhysicsShape { + public: + PhysicsShape() = default; + ~PhysicsShape() = default; + }; + +} // namespace sky::phy diff --git a/runtime/physics/include/physics/PhysicsWorld.h b/runtime/physics/include/physics/PhysicsWorld.h new file mode 100644 index 00000000..7d840b4a --- /dev/null +++ b/runtime/physics/include/physics/PhysicsWorld.h @@ -0,0 +1,40 @@ +// +// Created by blues on 2024/9/1. +// + +#include +#include +#include +#include +#include + +namespace sky::phy { + class PhysicsWorld : public IWorldSubSystem { + public: + PhysicsWorld() = default; + ~PhysicsWorld() override = default; + + static constexpr std::string_view NAME = "PhysicsWorld"; + + void AddRigidBody(RigidBody *rb); + void RemoveRigidBody(RigidBody *rb); + + void AddCharacterController(CharacterController *rb); + void RemoveCharacterController(CharacterController *rb); + + virtual void SetSimulationEnable(bool en) {} + virtual void SetDebugDrawEnable(bool en) {} + + virtual void SetGravity(const Vector3 &gravity) {} + + protected: + virtual void AddRigidBodyImpl(RigidBody *rb) = 0; + virtual void RemoveRigidBodyImpl(RigidBody *rb) = 0; + virtual void AddCharacterControllerImpl(CharacterController *rb) = 0; + virtual void RemoveCharacterControllerImpl(CharacterController *rb) = 0; + + std::list> rigidBodies; + std::list> characterControllers; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/include/physics/RigidBody.h b/runtime/physics/include/physics/RigidBody.h new file mode 100644 index 00000000..6eb72b3c --- /dev/null +++ b/runtime/physics/include/physics/RigidBody.h @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky::phy { + + enum class CollisionFlag : uint32_t { + DYNAMIC, + STATIC, + KINEMATIC + }; + + class RigidBody { + public: + RigidBody() = default; + virtual ~RigidBody() = default; + + void AddShape(PhysicsShape* shape); + void SetMass(float m); + void SetFlag(CollisionFlag m); + void SetGroup(int32_t group_); + void SetMask(int32_t mask_); + + int32_t GetGroup() const { return group; } + int32_t GetMask() const { return mask; } + + protected: + virtual void OnMassChanged() = 0; + virtual void OnShapeChanged() = 0; + virtual void OnFlagChanged() = 0; + virtual void OnGroupMaskChanged() = 0; + + float mass = 1.f; + int32_t group = 0; + int32_t mask = 0; + CollisionFlag collisionFlag = CollisionFlag::STATIC; + + std::vector> shapes; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/include/physics/components/RigidBodyComponent.h b/runtime/physics/include/physics/components/RigidBodyComponent.h new file mode 100644 index 00000000..a2801eea --- /dev/null +++ b/runtime/physics/include/physics/components/RigidBodyComponent.h @@ -0,0 +1,48 @@ +// +// Created by blues on 2024/9/25. +// + +#pragma once + +#include +#include + +namespace sky { + class SerializationContext; +} // namespace sky + +namespace sky::phy { + + class PhysicsWorld; + + struct RigidBodyData { + float mass = 1.f; + CollisionFlag flag = CollisionFlag::STATIC; + }; + + class RigidBodyComponent : public ComponentAdaptor { + public: + RigidBodyComponent() = default; + ~RigidBodyComponent() override = default; + + static void Reflect(SerializationContext *context); + COMPONENT_RUNTIME_INFO(RigidBodyComponent) + + void SetMass(float mass); + float GetMass() const { return data.mass; } + + void SetFlag(CollisionFlag flag); + CollisionFlag GetFlag() const { return data.flag; } + + private: + void OnAttachToWorld() override; + void OnDetachFromWorld() override; + void Tick(float time) override; + + PhysicsWorld* GetWorld() const; + void SetRigidBody(); + + RigidBody* rigidBody = nullptr; + }; + +} // namespace sky::phy diff --git a/runtime/physics/src/CharacterController.cpp b/runtime/physics/src/CharacterController.cpp new file mode 100644 index 00000000..75dbe2c8 --- /dev/null +++ b/runtime/physics/src/CharacterController.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/src/PhysicsRegistry.cpp b/runtime/physics/src/PhysicsRegistry.cpp new file mode 100644 index 00000000..90bca3a7 --- /dev/null +++ b/runtime/physics/src/PhysicsRegistry.cpp @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/9/2. +// + +#include + +namespace sky::phy { + + PhysicsWorld* PhysicsRegistry::CreatePhysicsWorld() + { + return factory ? factory->CreatePhysicsWorld() : nullptr; + } + + CharacterController* PhysicsRegistry::CreateCharacterController() + { + return factory ? factory->CreateCharacterController() : nullptr; + } + + RigidBody* PhysicsRegistry::CreateRigidBody() + { + return factory ? factory->CreateRigidBody() : nullptr; + } + + void PhysicsRegistry::Register(Impl* impl) + { + factory.reset(impl); + } + + void PhysicsRegistry::UnRegister() + { + factory.reset(); + } +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/src/PhysicsShape.cpp b/runtime/physics/src/PhysicsShape.cpp new file mode 100644 index 00000000..93b3e234 --- /dev/null +++ b/runtime/physics/src/PhysicsShape.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/src/PhysicsWorld.cpp b/runtime/physics/src/PhysicsWorld.cpp new file mode 100644 index 00000000..22953a06 --- /dev/null +++ b/runtime/physics/src/PhysicsWorld.cpp @@ -0,0 +1,42 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + + void PhysicsWorld::AddRigidBody(RigidBody *rb) + { + AddRigidBodyImpl(rb); + rigidBodies.emplace_back(rb); + } + + void PhysicsWorld::RemoveRigidBody(RigidBody *rb) + { + auto iter = std::find_if(rigidBodies.begin(), rigidBodies.end(), [rb](const auto &val) { + return rb == val.get(); + }); + if (iter != rigidBodies.end()) { + RemoveRigidBodyImpl(rb); + rigidBodies.erase(iter); + } + } + + void PhysicsWorld::AddCharacterController(CharacterController *ch) + { + AddCharacterControllerImpl(ch); + characterControllers.emplace_back(ch); + } + + void PhysicsWorld::RemoveCharacterController(CharacterController *ch) + { + auto iter = std::find_if(characterControllers.begin(), characterControllers.end(), [ch](const auto &val) { + return ch == val.get(); + }); + if (iter != characterControllers.end()) { + RemoveCharacterControllerImpl(ch); + characterControllers.erase(iter); + } + } +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/src/RigidBody.cpp b/runtime/physics/src/RigidBody.cpp new file mode 100644 index 00000000..1f2a3f43 --- /dev/null +++ b/runtime/physics/src/RigidBody.cpp @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + + void RigidBody::AddShape(PhysicsShape* shape) + { + shapes.emplace_back(shape); + OnShapeChanged(); + } + + void RigidBody::SetFlag(CollisionFlag flag) + { + collisionFlag = flag; + OnFlagChanged(); + } + + void RigidBody::SetMass(float m) + { + mass = m; + OnMassChanged(); + } + + void RigidBody::SetGroup(int32_t group_) + { + group = group_; + OnGroupMaskChanged(); + } + + void RigidBody::SetMask(int32_t mask_) + { + mask = mask_; + OnGroupMaskChanged(); + } +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/physics/src/components/RigidBodyComponent.cpp b/runtime/physics/src/components/RigidBodyComponent.cpp new file mode 100644 index 00000000..ced5df7f --- /dev/null +++ b/runtime/physics/src/components/RigidBodyComponent.cpp @@ -0,0 +1,77 @@ +// +// Created by blues on 2024/9/25. +// + +#include +#include +#include +#include +#include +#include + +namespace sky::phy { + + void RigidBodyComponent::Reflect(SerializationContext *context) + { + context->Register("CollisionFlag") + .Enum(CollisionFlag::DYNAMIC, "Dynamic") + .Enum(CollisionFlag::STATIC, "Static") + .Enum(CollisionFlag::KINEMATIC, "Kinematic"); + + context->Register("RigidBodyData") + .Member<&RigidBodyData::mass>("mass") + .Member<&RigidBodyData::flag>("flag"); + + REGISTER_BEGIN(RigidBodyComponent, context) + REGISTER_MEMBER(mass, SetMass, GetMass) + REGISTER_MEMBER(flag, SetFlag, GetFlag); + + ComponentFactory::Get()->RegisterComponent("Physics"); + } + + void RigidBodyComponent::SetMass(float mass) + { + if (rigidBody != nullptr) { + rigidBody->SetMass(mass); + } + data.mass = mass; + } + + void RigidBodyComponent::SetFlag(CollisionFlag flag) + { + data.flag = flag; + } + + PhysicsWorld* RigidBodyComponent::GetWorld() const + { + return static_cast(actor->GetWorld()->GetSubSystem(PhysicsWorld::NAME.data())); + } + + void RigidBodyComponent::SetRigidBody() + { + rigidBody->SetMass(data.mass); + } + + void RigidBodyComponent::OnAttachToWorld() + { + auto *world = GetWorld(); + if (world != nullptr) { + rigidBody = PhysicsRegistry::Get()->CreateRigidBody(); + SetRigidBody(); + world->AddRigidBody(rigidBody); + } + } + + void RigidBodyComponent::OnDetachFromWorld() + { + auto *world = GetWorld(); + if (world != nullptr && rigidBody != nullptr) { + world->RemoveRigidBody(rigidBody); + } + } + + void RigidBodyComponent::Tick(float time) + { + + } +} // namespace sky::phy diff --git a/runtime/plugins/CMakeLists.txt b/runtime/plugins/CMakeLists.txt new file mode 100644 index 00000000..f1500f66 --- /dev/null +++ b/runtime/plugins/CMakeLists.txt @@ -0,0 +1,23 @@ +if (SKY_EDITOR) + add_subdirectory(guizmo) +endif () + +if (SKY_BUILD_PYTHON) + add_subdirectory(python) +endif () + +if (SKY_BUILD_XR) + add_subdirectory(xr) +endif () + +if (SKY_BUILD_BULLET) + add_subdirectory(bullet) +endif () + +if (SKY_BUILD_RECAST) + add_subdirectory(recast) +endif () + +if (SKY_BUILD_FREETYPE) + add_subdirectory(freetype) +endif () \ No newline at end of file diff --git a/runtime/plugins/bullet/BulletModule.cpp b/runtime/plugins/bullet/BulletModule.cpp new file mode 100644 index 00000000..ef9d4445 --- /dev/null +++ b/runtime/plugins/bullet/BulletModule.cpp @@ -0,0 +1,74 @@ +// +// Created by Zach on 2024/3/17. +// + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + + +namespace sky::phy { + + class BulletFactory : public PhysicsRegistry::Impl { + public: + BulletFactory() = default; + ~BulletFactory() override = default; + + PhysicsWorld* CreatePhysicsWorld() override + { + return new BulletPhysicsWorld(); + } + + RigidBody* CreateRigidBody() override + { + return new BulletRigidBody(); + } + + CharacterController* CreateCharacterController() override + { + return new BulletCharacterController(); + } + }; + + class BulletPhysicsModule : public IModule, public IWorldEvent { + public: + BulletPhysicsModule() = default; + ~BulletPhysicsModule() override = default; + + void OnCreateWorld(World& world) override + { + if (world.CheckSystem(PhysicsWorld::NAME.data())) { + world.AddSubSystem(phy::PhysicsWorld::NAME.data(), new BulletPhysicsWorld()); + } + } + + bool Init(const StartArguments &args) override + { + worldEvent.Bind(this); + return true; + } + + void Start() override + { + PhysicsRegistry::Get()->Register(new BulletFactory()); + + RigidBodyComponent::Reflect(SerializationContext::Get()); + } + + void Shutdown() override + { + PhysicsRegistry::Get()->UnRegister(); + } + + EventBinder worldEvent; + }; +} // namespace sky::phy +REGISTER_MODULE(sky::phy::BulletPhysicsModule) \ No newline at end of file diff --git a/runtime/plugins/bullet/CMakeLists.txt b/runtime/plugins/bullet/CMakeLists.txt new file mode 100644 index 00000000..cbdc2314 --- /dev/null +++ b/runtime/plugins/bullet/CMakeLists.txt @@ -0,0 +1,20 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET BulletPhysicsModule SHARED + SOURCES + ${SRC_FILES} + ${INC_FILES} + BulletModule.cpp + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Framework + Physics + RenderCore + 3rdParty::bullet3 +) + +sky_add_dependency(TARGET BulletPhysicsModule DEPENDENCIES Launcher Editor) \ No newline at end of file diff --git a/runtime/plugins/bullet/include/bullet/BulletCharacterController.h b/runtime/plugins/bullet/include/bullet/BulletCharacterController.h new file mode 100644 index 00000000..c3e3abee --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/BulletCharacterController.h @@ -0,0 +1,22 @@ +// +// Created by blues on 2024/9/2. +// + +#pragma once + +#include +#include +#include + +namespace sky::phy { + + class BulletCharacterController : public CharacterController { + public: + BulletCharacterController() = default; + ~BulletCharacterController() override = default; + + private: + std::unique_ptr controller; + }; + +} // namespace sky::phy diff --git a/runtime/plugins/bullet/include/bullet/BulletConversion.h b/runtime/plugins/bullet/include/bullet/BulletConversion.h new file mode 100644 index 00000000..0b24fbfa --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/BulletConversion.h @@ -0,0 +1,14 @@ +// +// Created by blues on 2024/9/25. +// + +#pragma once + +#include +#include + +namespace sky::phy { + + btVector3 ToBullet(const Vector3& vec); + +} // namespace sky::phy diff --git a/runtime/plugins/bullet/include/bullet/BulletPhysicsWorld.h b/runtime/plugins/bullet/include/bullet/BulletPhysicsWorld.h new file mode 100644 index 00000000..3eab75a0 --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/BulletPhysicsWorld.h @@ -0,0 +1,42 @@ +// +// Created by blues on 2024/9/1. +// + +#include +#include +#include +#include +#include +#include + +namespace sky::phy { + + class BulletPhysicsWorld : public PhysicsWorld { + public: + BulletPhysicsWorld(); + ~BulletPhysicsWorld() override; + + btDiscreteDynamicsWorld *GetWorld() const { return dynamicWorld.get(); } + private: + void Tick(float delta) override; + void SetSimulationEnable(bool en) override; + void SetDebugDrawEnable(bool en) override; + void SetGravity(const Vector3 &gravity) override; + + void AddRigidBodyImpl(RigidBody *rb) override; + void RemoveRigidBodyImpl(RigidBody *rb) override; + void AddCharacterControllerImpl(CharacterController *rb) override; + void RemoveCharacterControllerImpl(CharacterController *rb) override; + + std::unique_ptr configuration; + std::unique_ptr dispatcher; + std::unique_ptr broadPhase; + std::unique_ptr solver; + std::unique_ptr dynamicWorld; + + bool enableSimulation = true; + bool enableDebugDraw = true; + std::unique_ptr debugDraw; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/include/bullet/BulletRigidBody.h b/runtime/plugins/bullet/include/bullet/BulletRigidBody.h new file mode 100644 index 00000000..b791bed6 --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/BulletRigidBody.h @@ -0,0 +1,43 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky::phy { + class BulletPhysicsWorld; + + class BulletRigidBody : public RigidBody, public btMotionState { + public: + BulletRigidBody() = default; + ~BulletRigidBody() override = default; + + btRigidBody *BuildRigidBody(); + btRigidBody *GetRigidBody() const { return rigidBody.get(); } + + void SetPhysicsWorld(BulletPhysicsWorld *wd); + + private: + void getWorldTransform(btTransform& worldTrans) const override; + void setWorldTransform(const btTransform& worldTrans) override; + + void OnMassChanged() override; + void OnShapeChanged() override; + void OnFlagChanged() override; + void OnGroupMaskChanged() override; + + void SetFlags(); + + BulletPhysicsWorld *world = nullptr; + std::unique_ptr collisionShape; + std::unique_ptr rigidBody; + + btVector3 localInertia = btVector3{0, 0, 0}; + }; + +} // namespace sky::phy diff --git a/runtime/plugins/bullet/include/bullet/BulletShapes.h b/runtime/plugins/bullet/include/bullet/BulletShapes.h new file mode 100644 index 00000000..c49b7cd7 --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/BulletShapes.h @@ -0,0 +1,13 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include + +namespace sky::phy { + + + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/include/bullet/debug/BulletDebugDraw.h b/runtime/plugins/bullet/include/bullet/debug/BulletDebugDraw.h new file mode 100644 index 00000000..df280b14 --- /dev/null +++ b/runtime/plugins/bullet/include/bullet/debug/BulletDebugDraw.h @@ -0,0 +1,36 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky::phy { + + class BulletDebugDraw : public PhysicsDebugDraw, public btIDebugDraw { + public: + BulletDebugDraw(); + ~BulletDebugDraw() override = default; + + private: + void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override; + void drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override; + void reportErrorWarning(const char* warningString) override; + void draw3dText(const btVector3& location, const char* textString) override; + void setDebugMode(int debugMode_) override { debugMode = debugMode_; } + int getDebugMode() const override { return debugMode; } + + void clearLines() override; + void flushLines() override; + + int32_t debugMode = 0; + + std::unique_ptr debugRenderer; + }; + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/BulletCharacterController.cpp b/runtime/plugins/bullet/src/BulletCharacterController.cpp new file mode 100644 index 00000000..c7f88d27 --- /dev/null +++ b/runtime/plugins/bullet/src/BulletCharacterController.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/2. +// + +#include + +namespace sky::phy { + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/BulletConversion.cpp b/runtime/plugins/bullet/src/BulletConversion.cpp new file mode 100644 index 00000000..9f13d121 --- /dev/null +++ b/runtime/plugins/bullet/src/BulletConversion.cpp @@ -0,0 +1,14 @@ +// +// Created by blues on 2024/9/25. +// + +#include + +namespace sky::phy { + + btVector3 ToBullet(const Vector3& vec) + { + return btVector3{vec.x, vec.y, vec.z}; + } + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/BulletPhysicsWorld.cpp b/runtime/plugins/bullet/src/BulletPhysicsWorld.cpp new file mode 100644 index 00000000..de66d5b5 --- /dev/null +++ b/runtime/plugins/bullet/src/BulletPhysicsWorld.cpp @@ -0,0 +1,91 @@ +// +// Created by blues on 2024/9/1. +// + +#include +#include +#include + +#include +namespace sky::phy { + + BulletPhysicsWorld::~BulletPhysicsWorld() + { + dynamicWorld = nullptr; + solver = nullptr; + broadPhase = nullptr; + dispatcher = nullptr; + configuration = nullptr; + } + + BulletPhysicsWorld::BulletPhysicsWorld() + { + configuration = std::make_unique(); + dispatcher = std::make_unique(configuration.get()); + broadPhase = std::make_unique(); + solver = std::make_unique(); + + dynamicWorld = std::make_unique(dispatcher.get(), + broadPhase.get(), solver.get(), configuration.get()); + } + + void BulletPhysicsWorld::Tick(float delta) + { + if (dynamicWorld && enableSimulation) { + dynamicWorld->stepSimulation(delta); + } + } + + void BulletPhysicsWorld::SetSimulationEnable(bool en) + { + enableSimulation = en; + } + + void BulletPhysicsWorld::SetDebugDrawEnable(bool en) + { + enableDebugDraw = en; + + if (!debugDraw && enableDebugDraw) { + debugDraw = std::make_unique(); + } + + btIDebugDraw* bulletDebugDraw = enableDebugDraw ? static_cast(debugDraw.get()) : nullptr; + dynamicWorld->setDebugDrawer(bulletDebugDraw); + } + + void BulletPhysicsWorld::SetGravity(const Vector3 &gravity) + { + if (dynamicWorld) { + dynamicWorld->setGravity(ToBullet(gravity)); + } + } + + void BulletPhysicsWorld::AddRigidBodyImpl(RigidBody *rb) + { + auto *rigidBody = static_cast(rb); + auto *btRb = rigidBody->GetRigidBody(); + if (btRb != nullptr) { + dynamicWorld->addRigidBody(btRb, rb->GetGroup(), rb->GetMask()); + } + rigidBody->SetPhysicsWorld(this); + } + + void BulletPhysicsWorld::RemoveRigidBodyImpl(RigidBody *rb) + { + auto *rigidBody = static_cast(rb); + auto *btRb = rigidBody->GetRigidBody(); + if (btRb != nullptr) { + dynamicWorld->removeRigidBody(btRb); + } + } + + void BulletPhysicsWorld::AddCharacterControllerImpl(CharacterController *rb) + { + + } + + void BulletPhysicsWorld::RemoveCharacterControllerImpl(CharacterController *rb) + { + + } +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/BulletRigidBody.cpp b/runtime/plugins/bullet/src/BulletRigidBody.cpp new file mode 100644 index 00000000..4e9e1e11 --- /dev/null +++ b/runtime/plugins/bullet/src/BulletRigidBody.cpp @@ -0,0 +1,83 @@ +// +// Created by blues on 2024/9/1. +// + +#include +#include +#include + +namespace sky::phy { + btRigidBody *BulletRigidBody::BuildRigidBody() + { + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, this, collisionShape.get(), localInertia); + rigidBody = std::make_unique(rbInfo); + SetFlags(); + return rigidBody.get(); + } + + void BulletRigidBody::SetFlags() + { + int flags = 0; + switch (collisionFlag) { + case CollisionFlag::STATIC: + flags |= btCollisionObject::CF_STATIC_OBJECT; + break; + case CollisionFlag::DYNAMIC: + flags |= btCollisionObject::CF_DYNAMIC_OBJECT; + break; + case CollisionFlag::KINEMATIC: + flags |= btCollisionObject::CF_KINEMATIC_OBJECT; + break; + } + rigidBody->setCollisionFlags(flags); + } + + void BulletRigidBody::SetPhysicsWorld(BulletPhysicsWorld *wd) + { + world = wd; + } + + void BulletRigidBody::OnMassChanged() + { + if (rigidBody) { + rigidBody->setMassProps(mass, localInertia); + } + } + + void BulletRigidBody::OnShapeChanged() + { + if (world != nullptr && rigidBody) { + world->GetWorld()->removeRigidBody(rigidBody.get()); + } + BuildRigidBody(); + if (world != nullptr && rigidBody) { + world->GetWorld()->addRigidBody(rigidBody.get(), group, mask); + } + } + + void BulletRigidBody::OnFlagChanged() + { + if (rigidBody) { + SetFlags(); + } + } + + void BulletRigidBody::OnGroupMaskChanged() + { + if (world != nullptr && rigidBody) { + world->GetWorld()->removeRigidBody(rigidBody.get()); + world->GetWorld()->addRigidBody(rigidBody.get(), group, mask); + } + } + + void BulletRigidBody::getWorldTransform(btTransform& worldTrans) const + { + + } + + void BulletRigidBody::setWorldTransform(const btTransform& worldTrans) + { + + } + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/BulletShapes.cpp b/runtime/plugins/bullet/src/BulletShapes.cpp new file mode 100644 index 00000000..3fc334fc --- /dev/null +++ b/runtime/plugins/bullet/src/BulletShapes.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/bullet/src/debug/BulletDebugDraw.cpp b/runtime/plugins/bullet/src/debug/BulletDebugDraw.cpp new file mode 100644 index 00000000..0e5a313a --- /dev/null +++ b/runtime/plugins/bullet/src/debug/BulletDebugDraw.cpp @@ -0,0 +1,55 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::phy { + + static Vector3 FromBullet(const btVector3 &vec) + { + return Vector3{vec.x(), vec.y(), vec.z()}; + } + + static constexpr int32_t DEFAULT_DEBUG_DRAW_FLAG = + btIDebugDraw::DBG_DrawWireframe | + btIDebugDraw::DBG_DrawAabb | + btIDebugDraw::DBG_DrawContactPoints | + btIDebugDraw::DBG_NoDeactivation | + btIDebugDraw::DBG_DrawConstraints; + + BulletDebugDraw::BulletDebugDraw() + : debugMode(DEFAULT_DEBUG_DRAW_FLAG) + , debugRenderer(std::make_unique()) + { + } + + void BulletDebugDraw::drawLine(const btVector3& from, const btVector3& to, const btVector3& color) + { + debugRenderer->SetColor(Color{color.x(), color.y(), color.z(), 1.f}); + debugRenderer->DrawLine(FromBullet(from), FromBullet(to)); + } + + void BulletDebugDraw::drawContactPoint(const btVector3& pointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) + { + drawLine(pointOnB, pointOnB + normalOnB * distance, color); + drawLine(pointOnB, pointOnB + normalOnB * 0.01f, btVector3{0, 0, 0}); + } + + void BulletDebugDraw::reportErrorWarning(const char* warningString) + { + } + + void BulletDebugDraw::draw3dText(const btVector3& location, const char* textString) + { + } + + void BulletDebugDraw::clearLines() + { + debugRenderer->Reset(); + } + + void BulletDebugDraw::flushLines() + { + } +} // namespace sky::phy \ No newline at end of file diff --git a/runtime/plugins/freetype/CMakeLists.txt b/runtime/plugins/freetype/CMakeLists.txt new file mode 100644 index 00000000..94cb7e54 --- /dev/null +++ b/runtime/plugins/freetype/CMakeLists.txt @@ -0,0 +1,19 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET FreeTypeModule SHARED + SOURCES + ${SRC_FILES} + ${INC_FILES} + FreeTypeModule.cpp + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Framework + RenderCore + 3rdParty::freetype +) + +sky_add_dependency(TARGET FreeTypeModule DEPENDENCIES Launcher Editor) \ No newline at end of file diff --git a/runtime/plugins/freetype/FreeTypeModule.cpp b/runtime/plugins/freetype/FreeTypeModule.cpp new file mode 100644 index 00000000..76aa0278 --- /dev/null +++ b/runtime/plugins/freetype/FreeTypeModule.cpp @@ -0,0 +1,34 @@ +// +// Created by blues on 2024/9/11. +// +// +// Created by Zach on 2024/3/17. +// + +#include +#include +#include +#include +#include + +namespace sky { + + class FreeTypeModule : public IModule { + public: + FreeTypeModule() = default; + ~FreeTypeModule() override = default; + + void Start() override + { + FreeTypeLibrary::Get()->Init(); + TextRegistry::Get()->Register(new FreeTypeFactory()); + } + + void Shutdown() override + { + TextRegistry::Get()->UnRegister(); + FreeTypeLibrary::Destroy(); + } + }; +} // namespace sky +REGISTER_MODULE(sky::FreeTypeModule) \ No newline at end of file diff --git a/runtime/plugins/freetype/include/freetype/FreeTypeFactory.h b/runtime/plugins/freetype/include/freetype/FreeTypeFactory.h new file mode 100644 index 00000000..bc43c307 --- /dev/null +++ b/runtime/plugins/freetype/include/freetype/FreeTypeFactory.h @@ -0,0 +1,20 @@ +// +// Created by blues on 2024/9/13. +// + +#pragma once + +#include + +namespace sky { + + class FreeTypeFactory : public TextRegistry::Impl { + public: + FreeTypeFactory() = default; + ~FreeTypeFactory() override = default; + + FontPtr LoadFont(const FileSystemPtr &fs, const std::string &name) override; + Text* CreateText(const FontPtr &font) override; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/freetype/include/freetype/FreeTypeFont.h b/runtime/plugins/freetype/include/freetype/FreeTypeFont.h new file mode 100644 index 00000000..bcdf753c --- /dev/null +++ b/runtime/plugins/freetype/include/freetype/FreeTypeFont.h @@ -0,0 +1,59 @@ +// +// Created by blues on 2024/9/11. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + struct FreeTypeGlyph { + uint32_t width = 0; + uint32_t height = 0; + int32_t bearingX = 0; + int32_t bearingY = 0; + int32_t advanceX = 0; + + uint32_t x = 0; + uint32_t y = 0; + uint32_t index = 0; + }; + + class FreeTypeFont : public Font { + public: + explicit FreeTypeFont(const std::string &name) : Font(name) {} + ~FreeTypeFont() override; + + void Load(const FilePtr &file) override; + bool Init(uint32_t fontSize, uint32_t fontWidth, uint32_t fontHeight); + + FreeTypeGlyph* Query(uint32_t code); + FreeTypeGlyph* Allocate(uint32_t code); + + uint32_t GetLineHeight() const { return lineHeight; } + uint32_t GetFontTexWidth() const { return fontWidth; } + uint32_t GetFontTexHeight() const { return fontHeight; } + + RDTexture2DPtr GetTextureByIndex(uint32_t index); + private: + bool IsReady() const override; + + void EmplaceTexture(); + + FT_Face face; + uint32_t lineHeight = 0; + uint32_t fontWidth = 512; + uint32_t fontHeight = 512; + + std::vector textures; + std::unordered_map glyphLut; + std::vector rawData; + }; + +} // namespace sky diff --git a/runtime/plugins/freetype/include/freetype/FreeTypeLibrary.h b/runtime/plugins/freetype/include/freetype/FreeTypeLibrary.h new file mode 100644 index 00000000..a3f665dc --- /dev/null +++ b/runtime/plugins/freetype/include/freetype/FreeTypeLibrary.h @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/9/11. +// + +#include +#include +#include + +namespace sky { + + class FreeTypeLibrary : public Singleton { + public: + FreeTypeLibrary() = default; + ~FreeTypeLibrary() override; + + void Init(); + + FT_Library GetLibrary() const { return library; } + + private: + FT_Library library = nullptr; + }; + +} // namespace sky diff --git a/runtime/plugins/freetype/include/freetype/FreeTypeText.h b/runtime/plugins/freetype/include/freetype/FreeTypeText.h new file mode 100644 index 00000000..f38b6567 --- /dev/null +++ b/runtime/plugins/freetype/include/freetype/FreeTypeText.h @@ -0,0 +1,55 @@ +// +// Created by blues on 2024/9/11. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + struct TextVertex { + Vector2 pos; + Vector2 uv; + Color col; + }; + + struct TextBatch : public RefObject { + void Init(const RDGfxTechPtr &tech, const RDTexturePtr &tex, const RDDynamicUniformBufferPtr &ubo); + void Flush(); + void AddQuad(const Rect& rect, const Rect &uv, const Color &color); + + rhi::CmdDrawLinear args; + std::unique_ptr primitive; + std::vector vertices; + }; + using TextBatchPtr = CounterPtr; + + class FreeTypeText : public Text { + public: + explicit FreeTypeText(const FontPtr &font_) : Text(font_) {} + ~FreeTypeText() override = default; + + private: + bool Init(const TextDesc &desc) override; + void SetDisplaySize(float w, float h) override; + + void Reset(RenderScene& scene) override; + void Finalize(RenderScene& scene) override; + + void AddText(const std::string &text, const Vector2& pos, const TextInfo &info) override; + + static TextFlags ValidateFlags(const TextFlags &flags) ; + std::unordered_map batches; + RDDynamicUniformBufferPtr ubo; + }; + +} // namespace sky diff --git a/runtime/plugins/freetype/src/FreeTypeFactory.cpp b/runtime/plugins/freetype/src/FreeTypeFactory.cpp new file mode 100644 index 00000000..79b5ce04 --- /dev/null +++ b/runtime/plugins/freetype/src/FreeTypeFactory.cpp @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/9/13. +// + +#include +#include +#include + +namespace sky { + + FontPtr FreeTypeFactory::LoadFont(const FileSystemPtr &fs, const std::string &name) + { + auto *font = new FreeTypeFont(name); + auto file = fs->OpenFile(name); + if (!file) { + return nullptr; + } + + font->Load(file); + return font; + } + + Text* FreeTypeFactory::CreateText(const FontPtr &font) + { + return new FreeTypeText(font); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/freetype/src/FreeTypeFont.cpp b/runtime/plugins/freetype/src/FreeTypeFont.cpp new file mode 100644 index 00000000..4e72ae3d --- /dev/null +++ b/runtime/plugins/freetype/src/FreeTypeFont.cpp @@ -0,0 +1,119 @@ +// +// Created by blues on 2024/9/11. +// + +#include +#include +#include +#include +#include +static const char* TAG = "FreeType"; + +namespace sky { + + FreeTypeFont::~FreeTypeFont() + { + if (face != nullptr) { + FT_Done_Face(face); + face = nullptr; + } + } + + void FreeTypeFont::Load(const FilePtr &file) + { + auto *library = FreeTypeLibrary::Get()->GetLibrary(); + file->ReadBin(rawData); + FT_Error error = FT_New_Memory_Face(library, rawData.data(), static_cast(rawData.size()), 0, &face); + if (error != 0) { + LOG_E(TAG, "New Memory Face failed : %d.", error); + } + } + + bool FreeTypeFont::Init(uint32_t fontSize, uint32_t w, uint32_t h) + { + FT_Error error = FT_Set_Pixel_Sizes(face, 0, fontSize); + if (error != 0) { + LOG_E(TAG, "Set Font Size failed : %d.", error); + return false; + } + + fontWidth = w; + fontHeight = h; + lineHeight = static_cast(face->size->metrics.height >> 6); + return true; + } + + FreeTypeGlyph* FreeTypeFont::Query(uint32_t code) + { + auto iter = glyphLut.find(code); + if (iter != glyphLut.end()) { + return &iter->second; + } + + return Allocate(code); + } + + RDTexture2DPtr FreeTypeFont::GetTextureByIndex(uint32_t index) + { + return textures[index]; + } + + FreeTypeGlyph* FreeTypeFont::Allocate(uint32_t code) + { + FT_Error error = FT_Load_Char(face, code, FT_LOAD_RENDER); + if (error != 0) { + return nullptr; + } + + FreeTypeGlyph glyph; + glyph.width = face->glyph->bitmap.width; + glyph.height = face->glyph->bitmap.rows; + glyph.bearingX = face->glyph->bitmap_left; + glyph.bearingY = face->glyph->bitmap_top; + glyph.advanceX = static_cast(face->glyph->advance.x >> 6); + + if (textures.empty()) { + EmplaceTexture(); + } + + if (glyph.width > 0 && glyph.height > 0) { + // try allocate + auto res = textures.back()->Allocate(glyph.width, glyph.height); + if (!res.first) { + EmplaceTexture(); + // try again + res = textures.back()->Allocate(glyph.width, glyph.height); + } + + if (!res.first) { + return nullptr; + } + + glyph.x = res.second.x; + glyph.y = res.second.y; + glyph.index = static_cast(textures.size()) - 1; + + uint32_t dataSize = static_cast(std::abs(face->glyph->bitmap.pitch)) * face->glyph->bitmap.rows; + std::vector data(dataSize); + memcpy(data.data(), face->glyph->bitmap.buffer, dataSize); + textures[glyph.index]->Upload(res.second, *RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER), std::move(data)); + } + + auto it = glyphLut.emplace(code, glyph); + return &it.first->second; + } + + bool FreeTypeFont::IsReady() const + { + return face != nullptr; + } + + void FreeTypeFont::EmplaceTexture() + { + auto *tex = new Texture2DAtlas(); + tex->Init(rhi::PixelFormat::R8_UNORM, fontWidth, fontHeight); + + textures.emplace_back(tex); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/freetype/src/FreeTypeLibrary.cpp b/runtime/plugins/freetype/src/FreeTypeLibrary.cpp new file mode 100644 index 00000000..f7c85525 --- /dev/null +++ b/runtime/plugins/freetype/src/FreeTypeLibrary.cpp @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/11. +// + +#include +#include + +namespace sky { + + void FreeTypeLibrary::Init() + { + FT_Error error = FT_Init_FreeType(&library); + if (error != 0) { + LOG_E("FreeType", "Freetype init failed, %d", error); + } + } + + FreeTypeLibrary::~FreeTypeLibrary() + { + if (library != nullptr) { + FT_Done_FreeType(library); + library = nullptr; + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/freetype/src/FreeTypeText.cpp b/runtime/plugins/freetype/src/FreeTypeText.cpp new file mode 100644 index 00000000..f0293881 --- /dev/null +++ b/runtime/plugins/freetype/src/FreeTypeText.cpp @@ -0,0 +1,189 @@ +// +// Created by blues on 2024/9/11. +// + +#include +#include +#include +#include + +namespace sky { + + struct TextTransform { + Vector2 scale; + Vector2 translate; + }; + + static std::vector TEXT_ATTRIBUTES = { + VertexAttribute{VertexSemanticFlagBit::POSITION, 0, OFFSET_OF(TextVertex, pos), rhi::Format::F_RG32}, + VertexAttribute{VertexSemanticFlagBit::UV, 0, OFFSET_OF(TextVertex, uv), rhi::Format::F_RG32}, + VertexAttribute{VertexSemanticFlagBit::COLOR, 0, OFFSET_OF(TextVertex, col), rhi::Format::F_RGBA32}, + }; + + static VertexSemanticFlags TEXT_VTX_SEMANTICS = VertexSemanticFlagBit::POSITION | + VertexSemanticFlagBit::UV | + VertexSemanticFlagBit::COLOR; + + void TextBatch::Init(const RDGfxTechPtr &tech, const RDTexturePtr &tex, const RDDynamicUniformBufferPtr &ubo) + { + primitive = std::make_unique(); + + primitive->isReady = true; + primitive->batchSet = TextFeature::Get()->RequestResourceGroup(); + primitive->batchSet->BindTexture("FontTexture", tex->GetImageView(), 0); + primitive->batchSet->BindDynamicUBO("Constants", ubo, 0); + primitive->batchSet->Update(); + + primitive->techniques.emplace_back(TechniqueInstance{tech}); + } + + void TextBatch::Flush() + { + primitive->geometry = new RenderGeometry(); + primitive->geometry->vertexAttributes = TEXT_ATTRIBUTES; + primitive->geometry->attributeSemantics = TEXT_VTX_SEMANTICS; + primitive->geometry->version++; + primitive->args.clear(); + primitive->args.emplace_back(args); + + auto *buffer = new Buffer(); + buffer->Init(vertices.size() * sizeof(TextVertex), rhi::BufferUsageFlagBit::VERTEX, rhi::MemoryType::CPU_TO_GPU); + auto *ptr = buffer->GetRHIBuffer()->Map(); + memcpy(ptr, vertices.data(), buffer->GetSize()); + + primitive->geometry->vertexBuffers.emplace_back(VertexBuffer{ + buffer, 0, buffer->GetSize(), sizeof(TextVertex) + }); + } + + void TextBatch::AddQuad(const Rect &rect, const Rect &uv, const Color &color) + { + TextVertex quad[4] = { + {{rect.offset.x , rect.offset.y }, {uv.offset.x , uv.offset.y }, color}, + {{rect.offset.x + rect.ext.x, rect.offset.y }, {uv.offset.x + uv.ext.x, uv.offset.y }, color}, + {{rect.offset.x , rect.offset.y + rect.ext.y}, {uv.offset.x , uv.offset.y + uv.ext.y}, color}, + {{rect.offset.x + rect.ext.x, rect.offset.y + rect.ext.y}, {uv.offset.x + uv.ext.x, uv.offset.y + uv.ext.y}, color}, + }; + + vertices.emplace_back(quad[0]); + vertices.emplace_back(quad[1]); + vertices.emplace_back(quad[2]); + + vertices.emplace_back(quad[3]); + vertices.emplace_back(quad[2]); + vertices.emplace_back(quad[1]); + + args.vertexCount += 6; + } + + void FreeTypeText::Reset(RenderScene& scene) + { + for (auto &batch : batches) { + scene.RemovePrimitive(batch.second->primitive.get()); + } + batches.clear(); + } + + void FreeTypeText::Finalize(RenderScene& scene) + { + for (auto &[key, batch] : batches) { + batch->Flush(); + scene.AddPrimitive(batch->primitive.get()); + } + } + + bool FreeTypeText::Init(const TextDesc &desc) + { + ubo = new DynamicUniformBuffer(); + ubo->Init(static_cast(sizeof(TextTransform))); + + return static_cast(font.Get())->Init(desc.fontSize, desc.texWidth, desc.texHeight); + } + + TextFlags FreeTypeText::ValidateFlags(const TextFlags &flags) + { + return flags & TextFlags(0x11); + } + + void FreeTypeText::SetDisplaySize(float w, float h) + { + TextTransform transform = {}; + transform.scale.x = 2.0f / w; + transform.scale.y = 2.0f / h; + transform.translate.x = -1.0f; + transform.translate.y = -1.0f; + ubo->WriteT(0, transform); + ubo->Upload(); + } + + void FreeTypeText::AddText(const std::string &text, const Vector2& pos, const TextInfo &info) + { + if (text.empty()) { + return; + } + + auto *ftFont = static_cast(font.Get()); + + auto offsetX = pos.x; + auto offsetY = pos.y; + auto lingHeight = static_cast(ftFont->GetLineHeight()) * info.scale; + + for (const auto &ch : text) { + if (ch == '\n') { + offsetX = pos.x; + offsetY += lingHeight; + continue; + } + + auto *glyph = ftFont->Query(ch); + if (glyph == nullptr) { + continue; + } + + Rect position = { + Vector2{ + offsetX + static_cast(glyph->bearingX) * info.scale, + offsetY + static_cast(-glyph->bearingY) * info.scale, + }, + Vector2{ + static_cast(glyph->width) * info.scale, + static_cast(glyph->height) * info.scale, + } + }; + + float invTexWidth = 1.f / static_cast(ftFont->GetFontTexWidth()); + float invTexHeight = 1.f / static_cast(ftFont->GetFontTexHeight()); + Rect uv = { + Vector2{ + static_cast(glyph->x) * invTexWidth, + static_cast(glyph->y) * invTexHeight, + }, + Vector2{ + static_cast(glyph->width) * invTexWidth, + static_cast(glyph->height) * invTexHeight, + } + }; + + auto &batch = batches[BatchKey{ValidateFlags(info.flags), glyph->index}]; + if (!batch) { + batch = new TextBatch(); + batch->Init(TextFeature::Get()->GetTechnique(), ftFont->GetTextureByIndex(glyph->index), ubo); + } + + if (info.flags & TextFlagBit::SHADOW) { + for (uint32_t i = 1; i <= info.shadowThickness; ++i) { + for (uint32_t j = 1; j <= info.shadowThickness; ++j) { + Rect shadowPos = position; + shadowPos.offset.x += static_cast(i); + shadowPos.offset.y += static_cast(j); + batch->AddQuad(shadowPos, uv, info.shadowColor); + } + } + } + batch->AddQuad(position, uv, info.color); + + offsetX += static_cast(glyph->advanceX) * info.scale; + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/guizmo/CMakeLists.txt b/runtime/plugins/guizmo/CMakeLists.txt new file mode 100644 index 00000000..ce555500 --- /dev/null +++ b/runtime/plugins/guizmo/CMakeLists.txt @@ -0,0 +1,20 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET ImGuizmoModule SHARED + SOURCES + ${SRC_FILES} + ${INC_FILES} + ImGuizmoModule.cpp + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Framework + ImGuiRender + RenderAdaptor + 3rdParty::ImGuizmo +) + +sky_add_dependency(TARGET ImGuizmoModule DEPENDENCIES Launcher Editor) \ No newline at end of file diff --git a/runtime/plugins/guizmo/ImGuizmoModule.cpp b/runtime/plugins/guizmo/ImGuizmoModule.cpp new file mode 100644 index 00000000..14d15b1a --- /dev/null +++ b/runtime/plugins/guizmo/ImGuizmoModule.cpp @@ -0,0 +1,30 @@ +// +// Created by Zach on 2024/3/17. +// + +#include +#include +#include +#include + +namespace sky::editor { + + class ImGuizmoModule : public IModule, public IGizmoFactory { + public: + ImGuizmoModule() + { + Interface::Get()->Register(*this); + } + + ~ImGuizmoModule() override + { + Interface::Get()->UnRegister(); + } + + IGizmo* CreateGizmo() override + { + return new EditorGuiInstance(); + } + }; +} // namespace sky +REGISTER_MODULE(sky::editor::ImGuizmoModule) \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/EditorGuiInstance.h b/runtime/plugins/guizmo/include/editor/EditorGuiInstance.h new file mode 100644 index 00000000..a191f37c --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/EditorGuiInstance.h @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/3/17. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky::editor { + + class EditorGuiInstance : public IGizmo { + public: + EditorGuiInstance() = default; + ~EditorGuiInstance() override; + + void Init(World &world, NativeWindow* window) override; + private: + void Init(); + + std::unique_ptr wm; + std::unique_ptr gui; + ImGuiInstance* guiInstance = nullptr; + RenderScene* renderScene = nullptr; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/WidgetManager.h b/runtime/plugins/guizmo/include/editor/WidgetManager.h new file mode 100644 index 00000000..9e420b7f --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/WidgetManager.h @@ -0,0 +1,26 @@ +// +// Created by Zach on 2024/3/17. +// + +#pragma once + +#include +#include + +namespace sky::editor { + + class WidgetManager : public ImWidget { + public: + WidgetManager() : ImWidget("parent") {} + ~WidgetManager() override = default; + + void RegisterWidget(ImWidget*); + void RemoveWidget(const std::string &key); + + void Execute(ImContext &context) override; + + private: + std::unordered_map> widgets; + }; + +} // namespace sky::editor diff --git a/runtime/plugins/guizmo/include/editor/event/Event.h b/runtime/plugins/guizmo/include/editor/event/Event.h new file mode 100644 index 00000000..9e25ebac --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/event/Event.h @@ -0,0 +1,48 @@ +// +// Created by blues on 2024/3/29. +// + +#pragma once + +#include +#include +#include + +namespace sky::editor { + + class IToggleEvent { + public: + IToggleEvent() = default; + virtual ~IToggleEvent() = default; + + using KeyType = EventID; + using MutexType = void; + + virtual void OnToggle(bool val) = 0; + }; + using ToogleEvent = Event; + + class IButtonEvent { + public: + IButtonEvent() = default; + virtual ~IButtonEvent() = default; + + using KeyType = EventID; + using MutexType = void; + + virtual void OnClicked() = 0; + }; + using ButtonEvent = Event; + + class IAssetViewEvent { + public: + IAssetViewEvent() = default; + virtual ~IAssetViewEvent() = default; + + using KeyType = Uuid; + using MutexType = void; + + virtual void OnClicked(const Uuid& type, void *data) = 0; + }; + using AssetViewEvent = Event; +} // sky::editor diff --git a/runtime/plugins/guizmo/include/editor/event/EventId.h b/runtime/plugins/guizmo/include/editor/event/EventId.h new file mode 100644 index 00000000..7f6d7be4 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/event/EventId.h @@ -0,0 +1,18 @@ +// +// Created by blues on 2024/3/29. +// + +#pragma once + +namespace sky::editor { + +using EventID = uint32_t; + +static constexpr uint32_t BTN_MENU_FILE_IMPORT = 0x01; + +static constexpr uint32_t BTN_MENU_VIEW_SHOW_ASSETS = 0x10; +static constexpr uint32_t BTN_MENU_VIEW_SHOW_WORLD = 0x11; +static constexpr uint32_t BTN_MENU_VIEW_SHOW_DEMO = 0x13; + + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/AssetInspector.h b/runtime/plugins/guizmo/include/editor/widgets/AssetInspector.h new file mode 100644 index 00000000..c4cf240e --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/AssetInspector.h @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/4/6. +// + +#pragma once + +#include +#include + +namespace sky::editor { + + class AssetInspector : public ImWidget, public IAssetViewEvent { + public: + AssetInspector() : ImWidget("Asset Inspector") {} + ~AssetInspector() override = default; + + void Execute(ImContext &context) override; + + private: + void OnClicked(const Uuid& type, void *data) override; + + bool show = false; + Uuid currentType; + void *currentData = nullptr; + }; + +} // sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/DemoWidget.h b/runtime/plugins/guizmo/include/editor/widgets/DemoWidget.h new file mode 100644 index 00000000..d5c1930c --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/DemoWidget.h @@ -0,0 +1,28 @@ +// +// Created by blues on 2024/3/29. +// + +#pragma once + +#include +#include + +namespace sky::editor { + + class DemoWidget : public ImWidget, public IToggleEvent { + public: + DemoWidget() : ImWidget("DemoWidget") {} + ~DemoWidget() override = default; + + void Execute(ImContext &context) override; + void BindEvent(EventID id); + + void OnToggle(bool val) override { show = val; } + + private: + bool show = false; + + EventBinder binder; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/Guizmo.h b/runtime/plugins/guizmo/include/editor/widgets/Guizmo.h new file mode 100644 index 00000000..17deb710 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/Guizmo.h @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/5/21. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class RenderScene; +} // namespace sky + +namespace sky::editor { + class GuiZmoWidget : public ImWidget, public ISelectEvent { + public: + GuiZmoWidget(); + ~GuiZmoWidget() override; + + void Execute(ImContext &context) override; + void AttachScene(RenderScene *scn) { renderScene = scn; } + private: + void OnActorSelected(Actor *actor_) override; + + Actor *actor = nullptr; + RenderScene* renderScene = nullptr; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/InspectorWidget.h b/runtime/plugins/guizmo/include/editor/widgets/InspectorWidget.h new file mode 100644 index 00000000..bb21a159 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/InspectorWidget.h @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/5/19. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky::editor { + + class InspectorWidget : public ImWidget, public IToggleEvent, public ISelectEvent { + public: + InspectorWidget(); + ~InspectorWidget() override; + + void BindEvent(EventID id); + private: + void Execute(ImContext &context) override; + void OnToggle(bool val) override { show = val; } + void OnActorSelected(Actor *actor_) override { actor = actor_; } + void ShowDetails(); + static bool ShowComponent(const Uuid &id, ComponentBase *comp); + + bool show = false; + Actor *actor = nullptr; + EventBinder binder; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/Menu.h b/runtime/plugins/guizmo/include/editor/widgets/Menu.h new file mode 100644 index 00000000..c4c2a842 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/Menu.h @@ -0,0 +1,65 @@ +// +// Created by Zach on 2024/3/17. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky::editor { + + class MenuItem : public ImWidget { + public: + explicit MenuItem(const std::string &name, EventID id_, bool isBtn_) : ImWidget(name), isBtn(isBtn_), id(id_) {} + ~MenuItem() override = default; + + void Execute(ImContext &context) override; + + private: + bool isBtn = true; + bool selected = false; + bool enable = true; + + EventID id; + }; + + class Menu : public ImWidget { + public: + explicit Menu(const std::string &name) : ImWidget(name) {} + ~Menu() override = default; + + MenuItem *AddItem(const std::string &name, EventID id, bool isBtn = true); + + void Execute(ImContext &context) override; + + private: + std::list> items; + }; + + class MenuBar : public ImWidget { + public: + MenuBar() : ImWidget("MenuBar") {} + ~MenuBar() override = default; + + Menu *AddMenu(const std::string &name); + void RemoveMenu(Menu *); + + void Execute(ImContext &context) override; + + protected: + std::list> menus; + }; + + class MainMenuBar : public MenuBar { + public: + MainMenuBar() = default; + ~MainMenuBar() override = default; + + void Execute(ImContext &context) override; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/RenderStats.h b/runtime/plugins/guizmo/include/editor/widgets/RenderStats.h new file mode 100644 index 00000000..24445d41 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/RenderStats.h @@ -0,0 +1,19 @@ +// +// Created by blues on 2024/3/30. +// + +#pragma once + +#include + +namespace sky::editor { + + class RenderStats : public ImWidget { + public: + RenderStats() : ImWidget("Statistics") {} + ~RenderStats() override = default; + + void Execute(ImContext &context) override; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/include/editor/widgets/WorldWidget.h b/runtime/plugins/guizmo/include/editor/widgets/WorldWidget.h new file mode 100644 index 00000000..32ba9333 --- /dev/null +++ b/runtime/plugins/guizmo/include/editor/widgets/WorldWidget.h @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/3/31. +// + +#pragma once + +#include +#include +#include + +namespace sky::editor { + class WorldWidget : public ImWidget, public IToggleEvent { + public: + WorldWidget() : ImWidget("World") {} + ~WorldWidget() override = default; + + void SetWorld(const WorldPtr &world_) { world = world_; } + void BindEvent(EventID id); + + private: + void Execute(ImContext &context) override; + void ShowActors(); + void OnToggle(bool val) override { show = val; } + + bool show = false; + WorldPtr world = nullptr; + + EventBinder binder; + }; + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/EditorGuiInstance.cpp b/runtime/plugins/guizmo/src/EditorGuiInstance.cpp new file mode 100644 index 00000000..88d1489c --- /dev/null +++ b/runtime/plugins/guizmo/src/EditorGuiInstance.cpp @@ -0,0 +1,72 @@ +// +// Created by blues on 2024/3/17. +// + +#include +#include +#include +#include +//#include +//#include +//#include + +namespace sky::editor { + + EditorGuiInstance::~EditorGuiInstance() = default; + + void EditorGuiInstance::Init(World &world, NativeWindow* window) + { + renderScene = static_cast(world.GetSubSystem("RenderScene"))->GetRenderScene(); + auto *imguiFeature = renderScene->GetFeature(); + if (imguiFeature != nullptr) { + guiInstance = imguiFeature->CreateImGuiInstance(); + guiInstance->BindNativeWindow(window); + renderScene->AddPrimitive(guiInstance->GetPrimitive()); + Init(); + } + } + + void EditorGuiInstance::Init() + { +// wm = std::make_unique(); + +// menuBar = new MainMenuBar(); +// wm->RegisterWidget(menuBar); + + // menu +// auto *fileMenu = menuBar->AddMenu("File"); +// fileMenu->AddItem("Import", BTN_MENU_FILE_IMPORT); +// +// auto *viewMenu = menuBar->AddMenu("View"); +// viewMenu->AddItem("Assets", BTN_MENU_VIEW_SHOW_ASSETS, false); +// viewMenu->AddItem("Demo", BTN_MENU_VIEW_SHOW_DEMO, false); +// viewMenu->AddItem("World", BTN_MENU_VIEW_SHOW_WORLD, false); +// +// auto *demoWidget = new DemoWidget(); +// demoWidget->BindEvent(BTN_MENU_VIEW_SHOW_DEMO); +// +// auto *assetWidget = new AssetWidget(); +// assetWidget->BindEvent(BTN_MENU_VIEW_SHOW_ASSETS); +// +// worldWidget = new WorldWidget(); +// worldWidget->BindEvent(BTN_MENU_VIEW_SHOW_WORLD); +// +// auto *inspect = new InspectorWidget(); +// inspect->BindEvent(BTN_MENU_VIEW_SHOW_WORLD); + +// auto *dirWidget = new DirectoryBrowser(); +// dirWidget->AddPath(AssetManager::Get()->GetProjectAssetPath()); +// dirWidget->AddPath(AssetManager::Get()->GetEngineAssetPath()); +// dirWidget->BindEvent(BTN_MENU_FILE_IMPORT); +// +// wm->RegisterWidget(demoWidget); +// wm->RegisterWidget(worldWidget); +// wm->RegisterWidget(inspect); + + gui = std::make_unique(); + gui->AttachScene(renderScene); + +// instance->AddWidget(wm.get()); + guiInstance->AddWidget(gui.get()); + } +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/WidgetManager.cpp b/runtime/plugins/guizmo/src/WidgetManager.cpp new file mode 100644 index 00000000..44dbc89a --- /dev/null +++ b/runtime/plugins/guizmo/src/WidgetManager.cpp @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/3/17. +// + +#include +#include + +namespace sky::editor { + + void WidgetManager::Execute(ImContext &context) + { + context.MakeCurrent(); + for (auto &widget : widgets) { + widget.second->Execute(context); + } + } + + void WidgetManager::RegisterWidget(ImWidget* widget) + { + widgets.emplace(widget->GetName(), widget); + } + + void WidgetManager::RemoveWidget(const std::string &key) + { + widgets.erase(key); + } +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/AssetInspector.cpp b/runtime/plugins/guizmo/src/widgets/AssetInspector.cpp new file mode 100644 index 00000000..f90c893c --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/AssetInspector.cpp @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/4/6. +// + +#include +#include + +namespace sky::editor { + + void AssetInspector::Execute(ImContext &context) + { + if (!show) { + currentType = Uuid(); + currentData = nullptr; + return; + } + + if (ImGui::Begin(name.c_str(), &show)) { + ImGui::Text("Type %s", currentType.ToString().c_str()); + } + ImGui::End(); + } + + void AssetInspector::OnClicked(const Uuid& type, void *data) + { + currentType = type; + currentData = data; + show = true; + } + +} // sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/DemoWidgets.cpp b/runtime/plugins/guizmo/src/widgets/DemoWidgets.cpp new file mode 100644 index 00000000..123a50bd --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/DemoWidgets.cpp @@ -0,0 +1,22 @@ +// +// Created by blues on 2024/3/29. +// + +#include + +namespace sky::editor { + + void DemoWidget::Execute(ImContext &context) + { + if (show) { + ImGui::ShowDemoWindow(nullptr); +// ImPlot::ShowDemoWindow(nullptr); + } + } + + void DemoWidget::BindEvent(EventID id) + { + binder.Bind(this, id); + } + +} // sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/Guizmo.cpp b/runtime/plugins/guizmo/src/widgets/Guizmo.cpp new file mode 100644 index 00000000..a8a08b5c --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/Guizmo.cpp @@ -0,0 +1,64 @@ +// +// Created by blues on 2024/5/21. +// + +#include +#include +#include +#include +#include + +namespace sky::editor { + + GuiZmoWidget::GuiZmoWidget() : ImWidget("GuiZmoWidget") + { + SelectEvent::Connect(this); + } + + GuiZmoWidget::~GuiZmoWidget() + { + SelectEvent::DisConnect(this); + } + + void GuiZmoWidget::OnActorSelected(Actor *actor_) + { + actor = actor_; + + if (actor != nullptr) { + auto *world = actor->GetWorld(); + renderScene = static_cast(world->GetSubSystem("RenderScene"))->GetRenderScene(); + } + } + + void GuiZmoWidget::Execute(ImContext &context) + { + static const auto &identity = Matrix4::Identity(); + ImGuizmo::BeginFrame(); + ImGuiIO& io = ImGui::GetIO(); + ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y); + + if (renderScene == nullptr) { + return; + } + auto *sceneView = renderScene->GetSceneViews()[0].get(); + SKY_ASSERT(sceneView != nullptr); + const auto &proj = sceneView->GetProject(); + auto view = sceneView->GetView(); + + ImGuizmo::DrawGrid(view.v, proj.v, identity.v, 500.f); + auto offsetX = io.DisplaySize.x - 256; + + ImGuizmo::ViewManipulate(view.v, 8.f, ImVec2(offsetX, 0), ImVec2(256, 266), 0x10101010); + + if (actor != nullptr) { + auto *transComp = actor->GetComponent(); + auto matrix = transComp->GetLocalTransform().ToMatrix(); + ImGuizmo::Manipulate(view.v, proj.v, ImGuizmo::UNIVERSAL, ImGuizmo::LOCAL, matrix.v, + nullptr, nullptr, nullptr, nullptr); + Transform res = {}; + Decompose(matrix, res.translation, res.rotation, res.scale); + transComp->SetLocalTransform(res); + } + } + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/InspectorWidget.cpp b/runtime/plugins/guizmo/src/widgets/InspectorWidget.cpp new file mode 100644 index 00000000..cdde4c0c --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/InspectorWidget.cpp @@ -0,0 +1,141 @@ +// +// Created by blues on 2024/5/19. +// + +#include +#include +#include +#include +#include + +namespace sky::editor { + + InspectorWidget::InspectorWidget() : ImWidget("Inspector") + { + SelectEvent::Connect(this); + } + + InspectorWidget::~InspectorWidget() + { + SelectEvent::DisConnect(this); + } + + void InspectorWidget::Execute(ImContext &context) + { + if (!show) { + return; + } + + if (ImGui::Begin("Details")) { + ShowDetails(); + ImGui::End(); + } + } + + void InspectorWidget::ShowDetails() + { + if (actor == nullptr) { + return; + } + + Uuid delId; + const auto &components = actor->GetComponents(); + for (const auto &[id, component] : components) { + ImGui::Separator(); + ImGui::BeginGroup(); + if (ShowComponent(id, component.get())) { + delId = id; + } + ImGui::EndGroup(); + } + if (static_cast(delId)) { + actor->RemoveComponent(delId); + } + +// if (ImGui::BeginPopupContextItem(0, ImGuiPopupFlags_AnyPopup)) { +// if (ImGui::MenuItem("Delete")) {} +// ImGui::EndPopup(); +// } + } + + bool InspectorWidget::ShowComponent(const Uuid &id, ComponentBase *comp) + { + const auto *node = GetTypeNode(id); + ImGui::Text("%s", node->info->name.data()); + ImGui::SameLine(); + if (ImGui::Button("x")) { + return true; + } + + for (const auto &member : node->members) { + auto data = GetValueRawConst(comp, id, member.first.data()); + if (member.second.info->staticInfo->isEnum) { + auto *v = data.GetAs(); + const auto *enumInfo = GetTypeNode(member.second.info->registeredId); + auto enumText = enumInfo->enums.at(*v); + if (ImGui::BeginCombo(member.first.data(), enumText.data())) { + for (const auto &[val, key] : enumInfo->enums) { + bool isSelect = false; + ImGui::Selectable(key.data(), &isSelect); + + if (isSelect) { + SetValueRaw(comp, id, member.first.data(), &val); + } + } + ImGui::EndCombo(); + } + } else { + const char *fFormat = "%.3f"; + const auto fRules = ImGuiInputTextFlags_EnterReturnsTrue; + float step = 0.05f; + float stepFast = 0.1f; + + if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + if (ImGui::InputScalarN(member.first.data(), ImGuiDataType_Float, v, 1, &step, &stepFast, fFormat, fRules)) { + SetValueRaw(comp, id, member.first.data(), v); + } + } + else if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + if (ImGui::InputScalarN(member.first.data(), ImGuiDataType_Float, v, 2, &step, &stepFast, fFormat, fRules)) { + SetValueRaw(comp, id, member.first.data(), v); + } + } + else if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + if (ImGui::InputScalarN(member.first.data(), ImGuiDataType_Float, v, 3, &step, &stepFast, fFormat, fRules)) { + SetValueRaw(comp, id, member.first.data(), v); + } + } + else if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + if (ImGui::InputScalarN(member.first.data(), ImGuiDataType_Float, v, 4, &step, &stepFast, fFormat, fRules)) { + SetValueRaw(comp, id, member.first.data(), v); + } + } + else if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + if (ImGui::Checkbox(member.first.data(), v)) { + SetValueRaw(comp, id, member.first.data(), v); + } + } + else if (member.second.info->registeredId == TypeInfo::RegisteredId()) { + auto *v = reinterpret_cast(data.GetAs()); + auto uuid = v->ToString(); + if (ImGui::InputText(member.first.data(), uuid.data(), uuid.length() + 1)) { + auto assetId = Uuid::CreateFromString(uuid); + SetValueRaw(comp, id, member.first.data(), &assetId); + } + } + } + } + return false; + } + + void InspectorWidget::BindEvent(EventID id) + { + binder.Bind(this, id); + } + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/Menu.cpp b/runtime/plugins/guizmo/src/widgets/Menu.cpp new file mode 100644 index 00000000..9ef1c6f9 --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/Menu.cpp @@ -0,0 +1,74 @@ +// +// Created by blues on 2024/3/17. +// + +#include +#include + +namespace sky::editor { + + void MenuItem::Execute(ImContext &context) + { + if (isBtn) { + if (ImGui::MenuItem(name.c_str(), nullptr, false, enable)) { + ButtonEvent::BroadCast(id, &IButtonEvent::OnClicked); + } + } else { + if (ImGui::MenuItem(name.c_str(), nullptr, &selected, enable)) { + ToogleEvent::BroadCast(id, &IToggleEvent::OnToggle, selected); + } + } + } + + void Menu::Execute(ImContext &context) + { + if (ImGui::BeginMenu(name.c_str())) { + for (auto &item: items) { + item->Execute(context); + } + + ImGui::EndMenu(); + } + } + + MenuItem *Menu::AddItem(const std::string &name, EventID id, bool isBtn) + { + items.emplace_back(std::make_unique(name, id, isBtn)); + return items.back().get(); + } + + void MenuBar::Execute(ImContext &context) + { + if (ImGui::BeginMenuBar()) + { + for (auto &menu : menus) { + menu->Execute(context); + } + ImGui::EndMenuBar(); + } + } + + void MainMenuBar::Execute(ImContext &context) + { + if (ImGui::BeginMainMenuBar()) + { + for (auto &menu : menus) { + menu->Execute(context); + } + ImGui::EndMainMenuBar(); + } + } + + Menu *MenuBar::AddMenu(const std::string &name) + { + menus.emplace_back(std::make_unique(name)); + return menus.back().get(); + } + + void MenuBar::RemoveMenu(Menu *menu) + { + menus.remove_if([menu](const auto &v) { + return menu == v.get(); + }); + } +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/RenderStats.cpp b/runtime/plugins/guizmo/src/widgets/RenderStats.cpp new file mode 100644 index 00000000..f283a883 --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/RenderStats.cpp @@ -0,0 +1,18 @@ +// +// Created by blues on 2024/3/30. +// + +#include +#include + +namespace sky::editor { + + void RenderStats::Execute(ImContext &context) + { + if (ImGui::Begin(name.c_str())) { +// ImGui::Text("%.2f ms/frame (%.1d fps)", (1000.0f / lastFPS), lastFPS); + } + ImGui::End(); + } + +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/guizmo/src/widgets/WorldWidget.cpp b/runtime/plugins/guizmo/src/widgets/WorldWidget.cpp new file mode 100644 index 00000000..87ba2bb5 --- /dev/null +++ b/runtime/plugins/guizmo/src/widgets/WorldWidget.cpp @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/3/31. +// + +#include +#include +#include + +namespace sky::editor { + + void WorldWidget::Execute(ImContext &context) + { + if (!show) { + return; + } + + if (ImGui::Begin("WorldInfo")) { + ShowActors(); + ImGui::End(); + } + } + + void WorldWidget::ShowActors() + { + if (world == nullptr) { + return; + } + const auto &actors = world->GetActors(); + + if (ImGui::TreeNode("World")) { + + for (const auto &actor: actors) { + if (ImGui::TreeNodeEx(actor->GetName().c_str(), ImGuiTreeNodeFlags_Leaf)) { + if (ImGui::IsItemClicked()) { + SelectEvent::BroadCast(&ISelectEvent::OnActorSelected, actor.get()); + } + ImGui::TreePop(); + } + } + + ImGui::TreePop(); + } + } + + void WorldWidget::BindEvent(EventID id) + { + binder.Bind(this, id); + } +} // namespace sky::editor \ No newline at end of file diff --git a/runtime/plugins/python/CMakeLists.txt b/runtime/plugins/python/CMakeLists.txt new file mode 100644 index 00000000..00aa94f8 --- /dev/null +++ b/runtime/plugins/python/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET PythonModule SHARED + SOURCES + ${SRC_FILES} + ${INC_FILES} + PythonModule.cpp + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Framework + 3rdParty::cpython +) + +sky_add_dependency(TARGET PythonModule DEPENDENCIES Launcher Editor) \ No newline at end of file diff --git a/runtime/plugins/python/PythonModule.cpp b/runtime/plugins/python/PythonModule.cpp new file mode 100644 index 00000000..c747fd1f --- /dev/null +++ b/runtime/plugins/python/PythonModule.cpp @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/6/2. +// + +#include +#include + +namespace sky::py { + + class PythonModule : public IModule { + public: + PythonModule() = default; + ~PythonModule() override = default; + + bool Init(const StartArguments &args) override; + void Tick(float delta) override; + void Shutdown() override; + + private: + bool ProcessArgs(const StartArguments &args); + }; + + bool PythonModule::ProcessArgs(const StartArguments &args) + { + return PythonEngine::Get()->Init(); + } + + bool PythonModule::Init(const StartArguments &args) + { + if (!ProcessArgs(args)) { + return false; + } + + return true; + } + + void PythonModule::Tick(float delta) + { + } + + void PythonModule::Shutdown() + { + PythonEngine::Get()->Shutdown(); + PythonEngine::Destroy(); + } + +} // namespace sky::py + +REGISTER_MODULE(sky::py::PythonModule) \ No newline at end of file diff --git a/runtime/plugins/python/include/python/PythonEngine.h b/runtime/plugins/python/include/python/PythonEngine.h new file mode 100644 index 00000000..146b6eef --- /dev/null +++ b/runtime/plugins/python/include/python/PythonEngine.h @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/6/2. +// + +#pragma once + +#include + +namespace sky::py { + + class PythonEngine : public Singleton { + public: + PythonEngine() = default; + ~PythonEngine() override = default; + + bool Init(); + void Shutdown(); + + private: + bool isInited = false; + }; + +} // namespace sky::py \ No newline at end of file diff --git a/runtime/plugins/python/src/PythonEngine.cpp b/runtime/plugins/python/src/PythonEngine.cpp new file mode 100644 index 00000000..be39de81 --- /dev/null +++ b/runtime/plugins/python/src/PythonEngine.cpp @@ -0,0 +1,40 @@ +// +// Created by blues on 2024/6/2. +// + +#include + +#include + +#define PY_SSIZE_T_CLEAN +#include + +static const char* TAG = "PythonEngine"; + +namespace sky::py { + + bool PythonEngine::Init() + { + PyConfig config; + PyConfig_InitPythonConfig(&config); + + PyConfig_SetString(&config, &config.home, L"D:\\Code\\3rd\\cpython"); + + auto status = Py_InitializeFromConfig(&config); + PyConfig_Clear(&config); + if (PyStatus_Exception(status) != 0) { + LOG_E(TAG, "Python Init failed... %s", status.err_msg); + return false; + } + + isInited = (Py_IsInitialized() != 0); + return isInited; + } + + void PythonEngine::Shutdown() + { + Py_Finalize(); + } + + +} // namespace sky::py \ No newline at end of file diff --git a/runtime/plugins/recast/CMakeLists.txt b/runtime/plugins/recast/CMakeLists.txt new file mode 100644 index 00000000..1a0e5658 --- /dev/null +++ b/runtime/plugins/recast/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET RecastModule SHARED + SOURCES + ${SRC_FILES} + ${INC_FILES} + RecastModule.cpp + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Navigation + 3rdParty::recast +) + +sky_add_dependency(TARGET RecastModule DEPENDENCIES Launcher Editor) \ No newline at end of file diff --git a/runtime/plugins/recast/RecastModule.cpp b/runtime/plugins/recast/RecastModule.cpp new file mode 100644 index 00000000..cc4c69a6 --- /dev/null +++ b/runtime/plugins/recast/RecastModule.cpp @@ -0,0 +1,3 @@ +// +// Created by blues on 2024/9/1. +// diff --git a/runtime/plugins/recast/include/recast/RecastNaviMap.h b/runtime/plugins/recast/include/recast/RecastNaviMap.h new file mode 100644 index 00000000..a3fd0aed --- /dev/null +++ b/runtime/plugins/recast/include/recast/RecastNaviMap.h @@ -0,0 +1,44 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include + +namespace sky::ai { + + struct RecastNaviMapConfig { + Vector3 origin = VEC3_ZERO; + float tileWidth = 16; + float tileHeight = 16; + uint32_t maxTiles = 65536; + uint32_t maxPolys = 65536; + }; + + class RecastNaviMap : public NaviMap { + public: + RecastNaviMap() = default; + ~RecastNaviMap() override = default; + + void BuildNavMesh(const RecastNaviMapConfig &config); + private: + void ResetNavMesh(); + + dtNavMesh *navMesh = nullptr; + }; + + class RecastNaviMapFactory : public NaviMapFactory::Impl { + public: + RecastNaviMapFactory() = default; + ~RecastNaviMapFactory() override = default; + + NaviMap* CreateNaviMap() override + { + return new RecastNaviMap(); + } + }; + +} // namespace sky::ai \ No newline at end of file diff --git a/runtime/plugins/recast/include/recast/RecastNaviMapGenerator.h b/runtime/plugins/recast/include/recast/RecastNaviMapGenerator.h new file mode 100644 index 00000000..6f17c59c --- /dev/null +++ b/runtime/plugins/recast/include/recast/RecastNaviMapGenerator.h @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/9/6. +// + +#pragma once + +#include + +namespace sky::ai { + + class RecastNaviMapGenerator : public Task { + public: + RecastNaviMapGenerator() = default; + ~RecastNaviMapGenerator() override = default; + + private: + bool DoWork() override; + void OnComplete(bool result) override; + }; + +} // namespace sky::ai diff --git a/runtime/plugins/recast/src/RecastNaviMap.cpp b/runtime/plugins/recast/src/RecastNaviMap.cpp new file mode 100644 index 00000000..bb71fa33 --- /dev/null +++ b/runtime/plugins/recast/src/RecastNaviMap.cpp @@ -0,0 +1,37 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky::ai { + + static void DebugDetourStatusDetail(dtStatus status) + { + } + + void RecastNaviMap::BuildNavMesh(const RecastNaviMapConfig &config) + { + navMesh = dtAllocNavMesh(); + + dtNavMeshParams params = {}; + params.tileWidth = config.tileWidth; + params.tileHeight = config.tileHeight; + params.maxTiles = config.maxTiles; + params.maxPolys = config.maxPolys; + + auto status = navMesh->init(¶ms); + if (dtStatusFailed(status)) { + DebugDetourStatusDetail(status); + return; + } + } + + void RecastNaviMap::ResetNavMesh() + { + if (navMesh != nullptr) { + dtFreeNavMesh(navMesh); + } + } + +} // namespace sky::ai \ No newline at end of file diff --git a/runtime/plugins/recast/src/RecastnaviMapGenerator.cpp b/runtime/plugins/recast/src/RecastnaviMapGenerator.cpp new file mode 100644 index 00000000..c11dae84 --- /dev/null +++ b/runtime/plugins/recast/src/RecastnaviMapGenerator.cpp @@ -0,0 +1,19 @@ +// +// Created by blues on 2024/9/6. +// + +#include + +namespace sky::ai { + + bool RecastNaviMapGenerator::DoWork() + { + return true; + } + + void RecastNaviMapGenerator::OnComplete(bool result) + { + + } + +} // namespace sky::ai \ No newline at end of file diff --git a/runtime/plugins/xr/CMakeLists.txt b/runtime/plugins/xr/CMakeLists.txt new file mode 100644 index 00000000..4ec6ec80 --- /dev/null +++ b/runtime/plugins/xr/CMakeLists.txt @@ -0,0 +1,36 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + file(GLOB_RECURSE PLATFORM_SRC platform/windows/*) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Android") + file(GLOB_RECURSE PLATFORM_SRC platform/android/*) +endif () + +sky_add_library(TARGET XRModule.Static STATIC + SOURCES + ${SRC_FILES} + ${INC_FILES} + ${PLATFORM_SRC} + PRIVATE_INC + src + rhi + platform + PUBLIC_INC + include + LINK_LIBS + Framework + RenderCore + 3rdParty::OpenXR +) + +sky_add_library(TARGET XRModule SHARED + SOURCES + XRModule.cpp + PRIVATE_INC + PUBLIC_INC + LINK_LIBS + XRModule.Static +) + +sky_add_dependency(TARGET XRModule DEPENDENCIES Launcher) \ No newline at end of file diff --git a/runtime/plugins/xr/XRModule.cpp b/runtime/plugins/xr/XRModule.cpp new file mode 100644 index 00000000..213e6a37 --- /dev/null +++ b/runtime/plugins/xr/XRModule.cpp @@ -0,0 +1,87 @@ +// +// Created by blues on 2024/2/28. +// + +#include +#include + +#include + +#include +#include + +#include + +namespace sky { + + class XRModule : public IModule { + public: + XRModule() = default; + ~XRModule() override = default; + + bool Init(const StartArguments &args) override; + void Tick(float delta) override; + void PreTick(float delta) override; + void PostTick(float delta) override; + + private: + bool ProcessArgs(const StartArguments &args); + + std::unique_ptr instance; + rhi::API api = rhi::API::DEFAULT; + }; + + bool XRModule::ProcessArgs(const StartArguments &args) + { + cxxopts::Options options("SkyEngine XR Plugin", "SkyEngine XR Plugin"); + options.allow_unrecognised_options(); + + options.add_options()("r,rhi", "RHI Type", cxxopts::value()); + options.add_options()("a,app", "App Type", cxxopts::value()); + + if (args.args.empty()) { + return false; + } + + auto result = options.parse(static_cast(args.args.size()), args.args.data()); + + if (result.count("app") == 0u || result["app"].as() != "xr") { + return false; + } + + if (result.count("rhi") != 0u) { + api = rhi::GetApiByString(result["rhi"].as()); + } + + return true; + } + + bool XRModule::Init(const StartArguments &args) + { + if (!ProcessArgs(args)) { + return false; + } + + instance = std::make_unique(); + return instance->Init({api}); + } + + void XRModule::PreTick(float delta) + { + if (instance) { + instance->BeginFrame(); + } + } + + void XRModule::PostTick(float delta) + { + if (instance) { + instance->EndFrame(); + } + } + + void XRModule::Tick(float delta) + { + } +} +REGISTER_MODULE(sky::XRModule) diff --git a/runtime/plugins/xr/include/xr/IXRPlatform.h b/runtime/plugins/xr/include/xr/IXRPlatform.h new file mode 100644 index 00000000..201da2b8 --- /dev/null +++ b/runtime/plugins/xr/include/xr/IXRPlatform.h @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/3/3. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class IXRPlatform { + public: + IXRPlatform() = default; + virtual ~IXRPlatform() = default; + + virtual const XrBaseInStructure *GetInstanceCreateInfo() const { return nullptr; } + }; + + IXRPlatform *CreateXRPlatform(); + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/include/xr/XRCore.h b/runtime/plugins/xr/include/xr/XRCore.h new file mode 100644 index 00000000..a228450b --- /dev/null +++ b/runtime/plugins/xr/include/xr/XRCore.h @@ -0,0 +1,43 @@ +// +// Created by zach on 2024/3/9. +// + +#pragma once + +#include +#include +#include +#include + +#define XR_FAILED(result) ((result) < 0) + +#define XR_CHECK_RESULT(result) \ + { \ + if (XR_FAILED(result)) {\ + LOG_E("XR", "error result: %d", result); \ + SKY_UNEXPECTED; \ + } \ + } + +namespace sky { + + enum class XRSide : uint32_t { + LEFT = 0, + RIGHT = 1, + NUM + }; + + + struct XRInputState { + XrActionSet actionSet{XR_NULL_HANDLE}; + XrAction grabAction{XR_NULL_HANDLE}; + XrAction poseAction{XR_NULL_HANDLE}; + XrAction vibrateAction{XR_NULL_HANDLE}; + XrAction quitAction{XR_NULL_HANDLE}; + std::array(XRSide::NUM)> handSubActionPath; + std::array(XRSide::NUM)> handSpace; + std::array(XRSide::NUM)> handScale = {{1.0f, 1.0f}}; + std::array(XRSide::NUM)> handActive; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/include/xr/XRInstance.h b/runtime/plugins/xr/include/xr/XRInstance.h new file mode 100644 index 00000000..a5c6fb9f --- /dev/null +++ b/runtime/plugins/xr/include/xr/XRInstance.h @@ -0,0 +1,70 @@ +// +// Created by blues on 2024/2/28. +// + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace sky { + + struct XROption { + XrFormFactor formFactor; + XrViewConfigurationType viewCfgType; + XrEnvironmentBlendMode blendMode; + }; + + class XRInstance : public rhi::XRInterface { + public: + XRInstance() = default; + ~XRInstance() override = default; + + struct Desc { + rhi::API api; + }; + + bool Init(const Desc &desc); + + void BeginFrame(); + void EndFrame(); + + XrInstance GetXrInstanceHandle() const override { return instance; } + XrSystemId GetXrSystemId() const override { return systemId; } + rhi::IXRSwapChain* CreateXrSwapChain(const rhi::IXRSwapChain::Descriptor &desc) override; + void DestroyXrSwapChain(rhi::IXRSwapChain *) override; + + const XROption &GetOptions() const { return options; } + private: + void InitFunctions(); + void AddFunctions(const std::string_view &name); + void PollEvents(); + const XrEventDataBaseHeader *FetchEvent(); + + PFN_xrVoidFunction GetFunction(const std::string_view &func) const override; + void SetSessionGraphicsBinding(const void *data) override; + + rhi::API api = rhi::API::VULKAN; + XrInstance instance = XR_NULL_HANDLE; + XrSystemId systemId = XR_NULL_SYSTEM_ID; + + std::unique_ptr platform; + std::unique_ptr session; + + std::unordered_map functionMap; + XrEventDataBuffer eventDataBuffer{XR_TYPE_EVENT_DATA_BUFFER}; + + XROption options; + + std::unique_ptr swapChain; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/include/xr/XRSession.h b/runtime/plugins/xr/include/xr/XRSession.h new file mode 100644 index 00000000..0976694a --- /dev/null +++ b/runtime/plugins/xr/include/xr/XRSession.h @@ -0,0 +1,42 @@ +// +// Created by blues on 2024/3/3. +// +#pragma once + +#include +#include +#include + +namespace sky { + class XRInstance; + + class XRSession { + public: + explicit XRSession(XRInstance &inst) : instance(inst) {} + ~XRSession(); + + bool Init(const void *graphicsBinding); + void SessionStateHandler(const XrEventDataSessionStateChanged& stateChangedEvent); + void PollActions(); + + XrSpace GetSpace() const { return space; } + XrSession GetHandle() const { return session; } + XRInstance &GetInstance() const { return instance; } + bool IsRunning() const { return running; } + + void BeginFrame(); + void EndFrame(const XrFrameEndInfo &endInfo); + + const XrFrameState &FrameState() const { return frameState; } + + private: + XRInstance &instance; + XrSession session = XR_NULL_HANDLE; + XrSpace space = XR_NULL_HANDLE; + XrSessionState sessionState{XR_SESSION_STATE_UNKNOWN}; + bool running = false; + XRInputState inputState; + XrFrameState frameState{XR_TYPE_FRAME_STATE}; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/include/xr/XRSwapchain.h b/runtime/plugins/xr/include/xr/XRSwapchain.h new file mode 100644 index 00000000..a91f9245 --- /dev/null +++ b/runtime/plugins/xr/include/xr/XRSwapchain.h @@ -0,0 +1,45 @@ +// +// Created by blues on 2024/3/11. +// + +#pragma once + +#include +#include + +namespace sky { + class XRSession; + + class XRSwapChain : public rhi::IXRSwapChain { + public: + explicit XRSwapChain(XRSession &session_) : session(session_) {} + ~XRSwapChain() override; + + void Init(const Descriptor &desc); + + uint32_t AcquireNextImage() override; + void Present() override; + + bool RequestViewData(const rhi::XRViewInput &input, std::vector &data) override; + XrSwapchain GetHandle(uint32_t index) const override { return swapChain; } + uint32_t GetWidth() const override { return width; } + uint32_t GetHeight() const override { return height; } + uint32_t GetArrayLayers() const override { return viewCount; } + int64_t GetFormat() const override { return format; } + + const XrCompositionLayerProjection &GetLayerProjection() const { return layer; } + private: + XRSession &session; + XrSwapchain swapChain = XR_NULL_HANDLE; + uint32_t width = 0; + uint32_t height = 0; + uint32_t viewCount = 0; + int64_t format = 0; + + std::vector views; + std::vector layerViews; + XrCompositionLayerProjection layer{XR_TYPE_COMPOSITION_LAYER_PROJECTION}; + }; + + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/platform/android/XRPlatformAndroid.cpp b/runtime/plugins/xr/platform/android/XRPlatformAndroid.cpp new file mode 100644 index 00000000..6f2b01ea --- /dev/null +++ b/runtime/plugins/xr/platform/android/XRPlatformAndroid.cpp @@ -0,0 +1,19 @@ +// +// Created by blues on 2024/3/3. +// + +#include "XRPlatformAndroid.h" + +namespace sky { + + const XrBaseInStructure *XRPlatformAndroid::GetInstanceCreateInfo() const + { + return nullptr; + } + + IXRPlatform *CreateXRPlatform() + { + return new XRPlatformAndroid(); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/platform/android/XRPlatformAndroid.h b/runtime/plugins/xr/platform/android/XRPlatformAndroid.h new file mode 100644 index 00000000..751ab440 --- /dev/null +++ b/runtime/plugins/xr/platform/android/XRPlatformAndroid.h @@ -0,0 +1,20 @@ +// +// Created by blues on 2024/3/3. +// + +#pragma once + +#include + +namespace sky { + + class XRPlatformAndroid : public IXRPlatform { + public: + XRPlatformAndroid() = default; + ~XRPlatformAndroid() override = default; + + private: + const XrBaseInStructure *GetInstanceCreateInfo() const; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/platform/windows/XRPlatformWin32.cpp b/runtime/plugins/xr/platform/windows/XRPlatformWin32.cpp new file mode 100644 index 00000000..5e247cf7 --- /dev/null +++ b/runtime/plugins/xr/platform/windows/XRPlatformWin32.cpp @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/3/3. +// + +#include "XRPlatformWin32.h" +#include + +namespace sky { + + IXRPlatform *CreateXRPlatform() + { + return new XRPlatformWin32(); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/platform/windows/XRPlatformWin32.h b/runtime/plugins/xr/platform/windows/XRPlatformWin32.h new file mode 100644 index 00000000..cb4321de --- /dev/null +++ b/runtime/plugins/xr/platform/windows/XRPlatformWin32.h @@ -0,0 +1,18 @@ +// +// Created by blues on 2024/3/3. +// + +#pragma once + +#include +#include + +namespace sky { + + class XRPlatformWin32 : public IXRPlatform { + public: + XRPlatformWin32() { CoInitializeEx(nullptr, COINIT_MULTITHREADED);} + ~XRPlatformWin32() override = default; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/src/XRInstance.cpp b/runtime/plugins/xr/src/XRInstance.cpp new file mode 100644 index 00000000..492922f9 --- /dev/null +++ b/runtime/plugins/xr/src/XRInstance.cpp @@ -0,0 +1,196 @@ +// +// Created by blues on 2024/2/28. +// + +#include +#include + +#include +#include +#include + +static const char* TAG = "XRInstance"; +namespace sky { + + void XRInstance::AddFunctions(const std::string_view &name) + { + PFN_xrVoidFunction func = nullptr; + xrGetInstanceProcAddr(instance, name.data(), &func); + if (func != nullptr) { + functionMap.emplace(name, func); + } + } + + void XRInstance::InitFunctions() + { + if (api == rhi::API::VULKAN) { + AddFunctions("xrGetVulkanGraphicsRequirementsKHR"); + AddFunctions("xrGetVulkanGraphicsDeviceKHR"); + AddFunctions("xrGetVulkanInstanceExtensionsKHR"); + AddFunctions("xrGetVulkanDeviceExtensionsKHR"); + } + AddFunctions("xrEnumerateSwapchainImages"); + } + + bool XRInstance::Init(const Desc &desc) + { + api = desc.api; + + options.viewCfgType = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO; + options.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY; + options.blendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE; + + std::vector xrInstanceExt; + if (api == rhi::API::VULKAN) { + xrInstanceExt.emplace_back("XR_KHR_vulkan_enable"); + } + + platform.reset(CreateXRPlatform()); + uint32_t count; + XR_CHECK_RESULT(xrEnumerateApiLayerProperties(0, &count, nullptr)); + std::vector layers(count, {XR_TYPE_API_LAYER_PROPERTIES}); + XR_CHECK_RESULT(xrEnumerateApiLayerProperties((uint32_t)layers.size(), &count, layers.data())); + + for (auto &layer : layers) { + LOG_I(TAG, "XR Layer %s\t, %s", layer.layerName, layer.description); + } + + XR_CHECK_RESULT(xrEnumerateInstanceExtensionProperties(nullptr, 0, &count, nullptr)); + std::vector extensions(count, {XR_TYPE_EXTENSION_PROPERTIES}); + XR_CHECK_RESULT(xrEnumerateInstanceExtensionProperties(nullptr, (uint32_t)extensions.size(), &count, extensions.data())); + + XrInstanceCreateInfo createInfo{XR_TYPE_INSTANCE_CREATE_INFO}; + createInfo.next = platform->GetInstanceCreateInfo(); + createInfo.enabledExtensionCount = (uint32_t)xrInstanceExt.size(); + createInfo.enabledExtensionNames = xrInstanceExt.data(); + + createInfo.applicationInfo.apiVersion = XR_CURRENT_API_VERSION; + sprintf(createInfo.applicationInfo.applicationName, "%s", "XRModule"); + sprintf(createInfo.applicationInfo.engineName, "%s", "SkyEngine"); + + XrResult res = xrCreateInstance(&createInfo, &instance); + if (res != XR_SUCCESS) { + return false; + } + + XrSystemGetInfo systemInfo{XR_TYPE_SYSTEM_GET_INFO}; + systemInfo.formFactor = options.formFactor; + + res = xrGetSystem(instance, &systemInfo, &systemId); + if (res != XR_SUCCESS) { + return false; + } + + XR_CHECK_RESULT(xrEnumerateEnvironmentBlendModes(instance, systemId, options.viewCfgType, 0, &count, nullptr)); + std::vector blendModes(count); + XR_CHECK_RESULT(xrEnumerateEnvironmentBlendModes(instance, systemId, options.viewCfgType, count, &count, blendModes.data())); + + XrInstanceProperties instanceProperties{XR_TYPE_INSTANCE_PROPERTIES}; + xrGetInstanceProperties(instance, &instanceProperties); + LOG_I(TAG, "XR instance info. %s, version %llu", instanceProperties.runtimeName, instanceProperties.runtimeVersion); + + InitFunctions(); + + RHI::Get()->SetXRInterface(this); + + LOG_I(TAG, "XR_RUNTIME_JSON: %s", Platform::Get()->GetEnvVariable("XR_RUNTIME_JSON").c_str()); + return true; + } + + const XrEventDataBaseHeader *XRInstance::FetchEvent() + { + auto *baseHeader = reinterpret_cast(&eventDataBuffer); + *baseHeader = {XR_TYPE_EVENT_DATA_BUFFER}; + const XrResult xr = xrPollEvent(instance, &eventDataBuffer); + if (xr == XR_SUCCESS) { + if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) { + const auto* const eventsLost = reinterpret_cast(baseHeader); + LOG_W(TAG, "%d events lost", eventsLost->lostEventCount); + } + return baseHeader; + } + return nullptr; + } + + void XRInstance::PollEvents() + { + while (const auto *event = FetchEvent()) { + switch (event->type) { + case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: { + const auto& instanceLossPending = *reinterpret_cast(event); + LOG_W(TAG, "XrEventDataInstanceLossPending by %lld", instanceLossPending.lossTime); + return; + } + case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: { + auto sessionStateChangedEvent = *reinterpret_cast(event); + session->SessionStateHandler(sessionStateChangedEvent); + break; + } + case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED: + case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING: + default: { + LOG_W(TAG, "Ignoring event type %d", event->type); + break; + } + } + } + } + + void XRInstance::BeginFrame() + { + PollEvents(); + + if (session->IsRunning()) { + session->PollActions(); + session->BeginFrame(); + } + } + + void XRInstance::EndFrame() + { + if (session->IsRunning()) { + std::vector layers; + + if (session->FrameState().shouldRender == XR_TRUE) { + layers.emplace_back(reinterpret_cast(&swapChain->GetLayerProjection())); + } + + XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO}; + frameEndInfo.displayTime = session->FrameState().predictedDisplayTime; + frameEndInfo.environmentBlendMode = options.blendMode; + frameEndInfo.layerCount = static_cast(layers.size()); + frameEndInfo.layers = layers.data(); + + session->EndFrame(frameEndInfo); + } + } + + rhi::IXRSwapChain* XRInstance::CreateXrSwapChain(const rhi::IXRSwapChain::Descriptor &desc) + { + if (!swapChain) { + swapChain = std::make_unique(*session); + swapChain->Init(desc); + } + return swapChain.get(); + } + + void XRInstance::DestroyXrSwapChain(rhi::IXRSwapChain *swc) + { + SKY_ASSERT(swapChain.get() == swc); + swapChain = nullptr; + } + + PFN_xrVoidFunction XRInstance::GetFunction(const std::string_view &func) const + { + auto iter = functionMap.find(func); + return iter != functionMap.end() ? iter->second : nullptr; + } + + void XRInstance::SetSessionGraphicsBinding(const void *data) + { + // init session + session = std::make_unique(*this); + session->Init(data); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/src/XRSession.cpp b/runtime/plugins/xr/src/XRSession.cpp new file mode 100644 index 00000000..8e6db95a --- /dev/null +++ b/runtime/plugins/xr/src/XRSession.cpp @@ -0,0 +1,206 @@ +// +// Created by blues on 2024/3/3. +// + +#include +#include +#include + +static const char* TAG = "XRSession"; + +namespace sky { + XRSession::~XRSession() + { + if (space != XR_NULL_HANDLE) { + xrDestroySpace(space); + } + + if (session != XR_NULL_HANDLE) { + xrDestroySession(session); + } + } + + bool XRSession::Init(const void *graphicsBinding) + { + XrInstance instHandle = instance.GetXrInstanceHandle(); + + XrSessionCreateInfo createInfo{XR_TYPE_SESSION_CREATE_INFO}; + createInfo.next = graphicsBinding; + createInfo.systemId = instance.GetXrSystemId(); + auto result = xrCreateSession(instHandle, &createInfo, &session); + if (result != XR_SUCCESS) { + return false; + } + + uint32_t spaceCount; + XR_CHECK_RESULT(xrEnumerateReferenceSpaces(session, 0, &spaceCount, nullptr)); + std::vector spaces(spaceCount); + XR_CHECK_RESULT(xrEnumerateReferenceSpaces(session, spaceCount, &spaceCount, spaces.data())); + + XrActionSetCreateInfo actionSetInfo{XR_TYPE_ACTION_SET_CREATE_INFO}; + strcpy_s(actionSetInfo.actionSetName, "gameplay"); + strcpy_s(actionSetInfo.localizedActionSetName, "Gameplay"); + actionSetInfo.priority = 0; + result = xrCreateActionSet(instHandle, &actionSetInfo, &inputState.actionSet); + if (result != XR_SUCCESS) { + return false; + } + + XR_CHECK_RESULT(xrStringToPath(instHandle, "/user/hand/left", &inputState.handSubActionPath[static_cast(XRSide::LEFT)])); + XR_CHECK_RESULT(xrStringToPath(instHandle, "/user/hand/right", &inputState.handSubActionPath[static_cast(XRSide::RIGHT)])); + + { + // Create an input action for grabbing objects with the left and right hands. + XrActionCreateInfo actionInfo{XR_TYPE_ACTION_CREATE_INFO}; + actionInfo.actionType = XR_ACTION_TYPE_FLOAT_INPUT; + strcpy_s(actionInfo.actionName, "grab_object"); + strcpy_s(actionInfo.localizedActionName, "Grab Object"); + actionInfo.countSubactionPaths = uint32_t(inputState.handSubActionPath.size()); + actionInfo.subactionPaths = inputState.handSubActionPath.data(); + XR_CHECK_RESULT(xrCreateAction(inputState.actionSet, &actionInfo, &inputState.grabAction)); + + actionInfo.actionType = XR_ACTION_TYPE_POSE_INPUT; + strcpy_s(actionInfo.actionName, "hand_pose"); + strcpy_s(actionInfo.localizedActionName, "Hand Pose"); + actionInfo.countSubactionPaths = uint32_t(inputState.handSubActionPath.size()); + actionInfo.subactionPaths = inputState.handSubActionPath.data(); + XR_CHECK_RESULT(xrCreateAction(inputState.actionSet, &actionInfo, &inputState.poseAction)); + + actionInfo.actionType = XR_ACTION_TYPE_VIBRATION_OUTPUT; + strcpy_s(actionInfo.actionName, "vibrate_hand"); + strcpy_s(actionInfo.localizedActionName, "Vibrate Hand"); + actionInfo.countSubactionPaths = uint32_t(inputState.handSubActionPath.size()); + actionInfo.subactionPaths = inputState.handSubActionPath.data(); + XR_CHECK_RESULT(xrCreateAction(inputState.actionSet, &actionInfo, &inputState.vibrateAction)); + + actionInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT; + strcpy_s(actionInfo.actionName, "quit_session"); + strcpy_s(actionInfo.localizedActionName, "Quit Session"); + actionInfo.countSubactionPaths = 0; + actionInfo.subactionPaths = nullptr; + XR_CHECK_RESULT(xrCreateAction(inputState.actionSet, &actionInfo, &inputState.quitAction)); + } + + + XrActionSpaceCreateInfo actionSpaceInfo{XR_TYPE_ACTION_SPACE_CREATE_INFO}; + actionSpaceInfo.action = inputState.poseAction; + actionSpaceInfo.poseInActionSpace.orientation.w = 1.f; + actionSpaceInfo.subactionPath = inputState.handSubActionPath[static_cast(XRSide::LEFT)]; + XR_CHECK_RESULT(xrCreateActionSpace(session, &actionSpaceInfo, &inputState.handSpace[static_cast(XRSide::LEFT)])); + actionSpaceInfo.subactionPath = inputState.handSubActionPath[static_cast(XRSide::RIGHT)]; + XR_CHECK_RESULT(xrCreateActionSpace(session, &actionSpaceInfo, &inputState.handSpace[static_cast(XRSide::RIGHT)])); + + XrSessionActionSetsAttachInfo attachInfo{XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO}; + attachInfo.countActionSets = 1; + attachInfo.actionSets = &inputState.actionSet; + XR_CHECK_RESULT(xrAttachSessionActionSets(session, &attachInfo)); + + + // action space + XrReferenceSpaceCreateInfo spaceInfo{XR_TYPE_REFERENCE_SPACE_CREATE_INFO}; + spaceInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL; + spaceInfo.poseInReferenceSpace.orientation.w = 1.f; + + result = xrCreateReferenceSpace(session, &spaceInfo, &space); + if (result != XR_SUCCESS) { + return false; + } + + LOG_I(TAG, "Init XR Session Success."); + return true; + } + + void XRSession::SessionStateHandler(const XrEventDataSessionStateChanged& stateChangedEvent) + { + if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session != session)) { + return; + } + + sessionState = stateChangedEvent.state; + switch (sessionState) { + case XR_SESSION_STATE_READY: { + XrSessionBeginInfo sessionBeginInfo{XR_TYPE_SESSION_BEGIN_INFO}; + sessionBeginInfo.primaryViewConfigurationType = instance.GetOptions().viewCfgType; + XR_CHECK_RESULT(xrBeginSession(session, &sessionBeginInfo)); + running = true; + break; + } + case XR_SESSION_STATE_STOPPING: { + XR_CHECK_RESULT(xrEndSession(session)) + running = false; + break; + } + case XR_SESSION_STATE_EXITING: + case XR_SESSION_STATE_LOSS_PENDING: + default: + break; + } + } + + void XRSession::BeginFrame() + { + if (running) { + XrFrameWaitInfo frameWaitInfo{XR_TYPE_FRAME_WAIT_INFO}; + XR_CHECK_RESULT(xrWaitFrame(session, &frameWaitInfo, &frameState)); + + XrFrameBeginInfo frameBeginInfo{XR_TYPE_FRAME_BEGIN_INFO}; + XR_CHECK_RESULT(xrBeginFrame(session, &frameBeginInfo)); + } + } + + void XRSession::EndFrame(const XrFrameEndInfo &endInfo) + { + if (running) { + XR_CHECK_RESULT(xrEndFrame(session, &endInfo)); + } + } + + void XRSession::PollActions() + { + inputState.handActive = {XR_FALSE, XR_FALSE}; + + const XrActiveActionSet activeActionSet{inputState.actionSet, XR_NULL_PATH}; + XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO}; + syncInfo.countActiveActionSets = 1; + syncInfo.activeActionSets = &activeActionSet; + XR_CHECK_RESULT(xrSyncActions(session, &syncInfo)); + + for (auto hand : {XRSide::LEFT, XRSide::RIGHT}) { + auto handIdx = static_cast(hand); + + XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO}; + getInfo.action = inputState.grabAction; + getInfo.subactionPath = inputState.handSubActionPath[handIdx]; + + XrActionStateFloat grabValue{XR_TYPE_ACTION_STATE_FLOAT}; + XR_CHECK_RESULT(xrGetActionStateFloat(session, &getInfo, &grabValue)); + if (grabValue.isActive == XR_TRUE) { + inputState.handScale[handIdx] = 1.0f - 0.5f * grabValue.currentState; + if (grabValue.currentState > 0.9f) { + XrHapticVibration vibration{XR_TYPE_HAPTIC_VIBRATION}; + vibration.amplitude = 0.5; + vibration.duration = XR_MIN_HAPTIC_DURATION; + vibration.frequency = XR_FREQUENCY_UNSPECIFIED; + + XrHapticActionInfo hapticActionInfo{XR_TYPE_HAPTIC_ACTION_INFO}; + hapticActionInfo.action = inputState.vibrateAction; + hapticActionInfo.subactionPath = inputState.handSubActionPath[handIdx]; + XR_CHECK_RESULT(xrApplyHapticFeedback(session, &hapticActionInfo, (XrHapticBaseHeader*)&vibration)); + } + } + + getInfo.action = inputState.poseAction; + XrActionStatePose poseState{XR_TYPE_ACTION_STATE_POSE}; + XR_CHECK_RESULT(xrGetActionStatePose(session, &getInfo, &poseState)); + inputState.handActive[handIdx] = poseState.isActive; + } + + XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO, nullptr, inputState.quitAction, XR_NULL_PATH}; + XrActionStateBoolean quitValue{XR_TYPE_ACTION_STATE_BOOLEAN}; + XR_CHECK_RESULT(xrGetActionStateBoolean(session, &getInfo, &quitValue)); + if ((quitValue.isActive == XR_TRUE) && (quitValue.changedSinceLastSync == XR_TRUE) && (quitValue.currentState == XR_TRUE)) { + XR_CHECK_RESULT(xrRequestExitSession(session)); + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/plugins/xr/src/XRSwapchain.cpp b/runtime/plugins/xr/src/XRSwapchain.cpp new file mode 100644 index 00000000..787d8830 --- /dev/null +++ b/runtime/plugins/xr/src/XRSwapchain.cpp @@ -0,0 +1,127 @@ +// +// Created by blues on 2024/3/11. +// + +#include +#include +#include +#include +#include + +namespace sky { + + XRSwapChain::~XRSwapChain() + { + if (swapChain != XR_NULL_HANDLE) { + XR_CHECK_RESULT(xrDestroySwapchain(swapChain)); + } + } + + void XRSwapChain::Init(const Descriptor &desc) + { + auto &instance = session.GetInstance(); + + XrInstance instHandle = instance.GetXrInstanceHandle(); + XrSystemId systemId = instance.GetXrSystemId(); + XrSession sessionId = session.GetHandle(); + + XR_CHECK_RESULT(xrEnumerateViewConfigurationViews(instHandle, systemId, instance.GetOptions().viewCfgType, 0, &viewCount, nullptr)); + std::vector configViews(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW}); + XR_CHECK_RESULT(xrEnumerateViewConfigurationViews(instHandle, systemId, instance.GetOptions().viewCfgType, viewCount, &viewCount, configViews.data())); + + uint32_t formatCount; + XR_CHECK_RESULT(xrEnumerateSwapchainFormats(sessionId, 0, &formatCount, nullptr)); + std::vector formats(formatCount); + XR_CHECK_RESULT(xrEnumerateSwapchainFormats(sessionId, formatCount, &formatCount, formats.data())); + + auto iter = std::find(formats.begin(), formats.end(), desc.format); + + width = configViews[0].recommendedImageRectWidth; + height = configViews[0].recommendedImageRectHeight; + format = iter != formats.end() ? *iter : formats[0]; + views.resize(viewCount, {XR_TYPE_VIEW}); + + XrSwapchainCreateInfo swcCreateInfo{XR_TYPE_SWAPCHAIN_CREATE_INFO}; + swcCreateInfo.arraySize = viewCount; + swcCreateInfo.format = format; + swcCreateInfo.width = width; + swcCreateInfo.height = height; + swcCreateInfo.mipCount = 1; + swcCreateInfo.faceCount = 1; + swcCreateInfo.sampleCount = 1; + swcCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; + + XR_CHECK_RESULT(xrCreateSwapchain(sessionId, &swcCreateInfo, &swapChain)); + } + + uint32_t XRSwapChain::AcquireNextImage() + { + uint32_t imageIndex = 0; + XrSwapchainImageAcquireInfo acquireInfo = {XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO}; + XR_CHECK_RESULT(xrAcquireSwapchainImage(swapChain, &acquireInfo, &imageIndex)); + + XrSwapchainImageWaitInfo waitInfo{XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO}; + waitInfo.timeout = XR_INFINITE_DURATION; + XR_CHECK_RESULT(xrWaitSwapchainImage(swapChain, &waitInfo)); + + return imageIndex; + } + + bool XRSwapChain::RequestViewData(const rhi::XRViewInput &input, std::vector &data) + { + XrViewState viewState{XR_TYPE_VIEW_STATE}; + uint32_t viewCapacityInput = viewCount; + uint32_t viewCountOutput = 0; + + XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO}; + viewLocateInfo.viewConfigurationType = session.GetInstance().GetOptions().viewCfgType; + viewLocateInfo.displayTime = session.FrameState().predictedDisplayTime; + viewLocateInfo.space = session.GetSpace(); + + if (session.FrameState().shouldRender != XR_TRUE) { + return false; + } + + auto result = xrLocateViews(session.GetHandle(), &viewLocateInfo, &viewState, viewCapacityInput, &viewCountOutput, views.data()); + if (result != XR_SUCCESS) { + return false; + } + + data.resize(viewCount); + layerViews.resize(viewCount, {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW}); + for (uint32_t i = 0; i < viewCount; ++i) { + const auto& pose = views[i].pose; + const auto& fov = views[i].fov; + + auto &proj = reinterpret_cast(data[i].project); + XrMatrix4x4f_CreateProjectionFov(&proj, GRAPHICS_VULKAN, fov, input.vNear, input.vFar); + auto &world = reinterpret_cast(data[i].world); + XrVector3f scale{1.f, 1.f, 1.f}; + XrMatrix4x4f_CreateTranslationRotationScale(&world, &pose.position, &pose.orientation, &scale); + + layerViews[i].pose = pose; + layerViews[i].fov = fov; + layerViews[i].subImage.swapchain = swapChain; + layerViews[i].subImage.imageRect.offset = {0, 0}; + layerViews[i].subImage.imageRect.extent = {static_cast(width), static_cast(height)}; + layerViews[i].subImage.imageArrayIndex = i; + } + + layer.space = viewLocateInfo.space; + layer.layerFlags = + session.GetInstance().GetOptions().blendMode == XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND + ? XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT | XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT + : 0; + layer.viewCount = static_cast(layerViews.size()); + layer.views = layerViews.data(); + + return true; + } + + void XRSwapChain::Present() + { + XrSwapchainImageReleaseInfo releaseInfo{XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO}; + XR_CHECK_RESULT(xrReleaseSwapchainImage(swapChain, &releaseInfo)); + } + +} // namespace sky \ No newline at end of file diff --git a/render/CMakeLists.txt b/runtime/render/CMakeLists.txt similarity index 69% rename from render/CMakeLists.txt rename to runtime/render/CMakeLists.txt index 39bc0a78..8ba80a53 100644 --- a/render/CMakeLists.txt +++ b/runtime/render/CMakeLists.txt @@ -3,7 +3,8 @@ add_subdirectory(shader) add_subdirectory(core) add_subdirectory(adaptor) add_subdirectory(imgui) -if ((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") OR (${CMAKE_SYSTEM_NAME} STREQUAL "Windows")) +add_subdirectory(animation) +if ((SKY_BUILD_TOOL) AND ((${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") OR (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))) add_subdirectory(builder) endif () @@ -13,7 +14,7 @@ sky_add_library(TARGET SkyRender SHARED PRIVATE_INC PUBLIC_INC LINK_LIBS - SkyRenderAdaptor + RenderAdaptor ImGuiRender ) diff --git a/render/RenderModule.cpp b/runtime/render/RenderModule.cpp similarity index 56% rename from render/RenderModule.cpp rename to runtime/render/RenderModule.cpp index cb849c6f..50c18353 100644 --- a/render/RenderModule.cpp +++ b/runtime/render/RenderModule.cpp @@ -8,34 +8,47 @@ #include #include #include +#include +#include +#include #include #include -#include +#include +#include #include +#include +#include -#include -#include #include +#include +#include #include #include -#include - -#include +#include +#include #include namespace sky { static void RegisterComponents() { - LightComponent::Reflect(); - MeshRenderer::Reflect(); - CameraComponent::Reflect(); + auto *context = SerializationContext::Get(); + LightComponent::Reflect(context); + StaticMeshComponent::Reflect(context); + CameraComponent::Reflect(context); + SkeletonMeshComponent::Reflect(context); + + static std::string GROUP = "Render"; + ComponentFactory::Get()->RegisterComponent(GROUP); + ComponentFactory::Get()->RegisterComponent(GROUP); + ComponentFactory::Get()->RegisterComponent(GROUP); + ComponentFactory::Get()->RegisterComponent(GROUP); } - class RenderModule : public IModule { + class RenderModule : public IModule, public IWorldEvent { public: RenderModule() = default; ~RenderModule() override = default; @@ -44,10 +57,20 @@ namespace sky { void Tick(float delta) override; void Shutdown() override; void Start() override; + + void OnCreateWorld(World& world) override + { + if (world.CheckSystem("RenderScene")) { + auto *sceneProxy = new RenderSceneProxy(); + world.AddSubSystem("RenderScene", sceneProxy); + } + } private: void ProcessArgs(const StartArguments &args); + void InitFeatures(); rhi::API api = rhi::API::DEFAULT; + EventBinder worldEvent; }; void RenderModule::ProcessArgs(const StartArguments &args) @@ -72,9 +95,7 @@ namespace sky { auto *serializationContext = SerializationContext::Get(); ReflectRenderAsset(serializationContext); ReflectRHI(serializationContext); - RegisterComponents(); - ProcessArgs(args); rhi::Instance::Descriptor rhiDesc = {}; @@ -89,11 +110,15 @@ namespace sky { // init rhi RHI::Get()->InitInstance(rhiDesc); - RHI::Get()->InitDevice({}); + + rhi::DeviceFeature feature = {}; + RHI::Get()->InitDevice({feature}); // init renderer Renderer::Get()->Init(); Renderer::Get()->SetCacheFolder(Platform::Get()->GetInternalPath()); + + worldEvent.Bind(this); return true; } @@ -103,34 +128,40 @@ namespace sky { auto shaderCompileFunc = mm->GetFunctionFomModule("ShaderCompiler", "CompileBinary"); Renderer::Get()->SetShaderCompiler(shaderCompileFunc); - // init assets + InitFeatures(); + } + + void RenderModule::InitFeatures() // NOLINT + { + MeshFeature::Get()->Init(); + ImGuiFeature::Get()->Init(); + TextFeature::Get()->Init(); + auto *am = AssetManager::Get(); + { + auto guiAsset = am->LoadAssetFromPath("techniques/gui.tech"); + guiAsset->BlockUntilLoaded(); - // init shader compiler -#if SKY_EDITOR - auto *compiler = ShaderCompiler::Get(); - for (const auto &path : am->GetSearchPathList()) { - compiler->AddSearchPath(path.path); + auto tech = CreateTechniqueFromAsset(guiAsset); + ImGuiFeature::Get()->SetTechnique(tech); } -#endif + { + auto guiAsset = am->LoadAssetFromPath("techniques/text.tech"); + guiAsset->BlockUntilLoaded(); - auto vfAsset = AssetManager::Get()->LoadAsset("vertex/vertex_library.vtxlib", false); - if (vfAsset) { - Renderer::Get()->SetVertexDescLibrary(CreateVertexDescLibrary(vfAsset->Data())); + auto tech = CreateTechniqueFromAsset(guiAsset); + TextFeature::Get()->SetTechnique(tech); } -// ImGuiFeature::Get()->Init(AssetManager::Get()->LoadAsset("techniques/gui.tech")->CreateInstanceAs()); -// GeometryFeature::Get()->Init(AssetManager::Get()->LoadAsset("techniques/geometry.tech")->CreateInstanceAs()); - - MeshFeature::Get()->Init(); -// ParticleFeature::Get()->Init(); } void RenderModule::Shutdown() { - GeometryFeature::Destroy(); + Renderer::Get()->StopRender(); + MeshFeature::Destroy(); - ParticleFeature::Destroy(); + ImGuiFeature::Destroy(); + TextFeature::Destroy(); Renderer::Destroy(); RHI::Destroy(); @@ -138,6 +169,7 @@ namespace sky { void RenderModule::Tick(float delta) { + SKY_PROFILE_SCOPE; Renderer::Get()->Tick(delta); } } diff --git a/runtime/render/adaptor/CMakeLists.txt b/runtime/render/adaptor/CMakeLists.txt new file mode 100644 index 00000000..cd006772 --- /dev/null +++ b/runtime/render/adaptor/CMakeLists.txt @@ -0,0 +1,17 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +sky_add_library(TARGET RenderAdaptor STATIC + SOURCES + ${SRC_FILES} + ${INC_FILES} + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + RenderCore + Animation + ImGuiRender + Framework + ) \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/Reflection.h b/runtime/render/adaptor/include/render/adaptor/Reflection.h similarity index 100% rename from render/adaptor/include/render/adaptor/Reflection.h rename to runtime/render/adaptor/include/render/adaptor/Reflection.h diff --git a/render/adaptor/include/render/adaptor/RenderSceneProxy.h b/runtime/render/adaptor/include/render/adaptor/RenderSceneProxy.h similarity index 77% rename from render/adaptor/include/render/adaptor/RenderSceneProxy.h rename to runtime/render/adaptor/include/render/adaptor/RenderSceneProxy.h index 5daf96be..e9e352b5 100644 --- a/render/adaptor/include/render/adaptor/RenderSceneProxy.h +++ b/runtime/render/adaptor/include/render/adaptor/RenderSceneProxy.h @@ -4,12 +4,12 @@ #pragma once -#include +#include #include namespace sky { - class RenderSceneProxy : public IRenderScene { + class RenderSceneProxy : public IWorldSubSystem { public: RenderSceneProxy(); ~RenderSceneProxy() override; diff --git a/runtime/render/adaptor/include/render/adaptor/Util.h b/runtime/render/adaptor/include/render/adaptor/Util.h new file mode 100644 index 00000000..6dba8524 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/Util.h @@ -0,0 +1,31 @@ +// +// Created by Zach Lee on 2023/8/27. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + inline RenderScene *GetRenderSceneFromActor(Actor *actor) + { + return static_cast(actor->GetWorld()->GetSubSystem("RenderScene"))->GetRenderScene(); + } + + template + T *GetFeatureProcessor(const RenderScene *scene) + { + return scene->GetFeature(); + } + + template + T *GetFeatureProcessor(Actor *actor) + { + auto *proxy = static_cast(actor->GetWorld()->GetSubSystem("RenderScene")); + return GetFeatureProcessor(proxy->GetRenderScene()); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/include/render/adaptor/animation/AnimationComponent.h b/runtime/render/adaptor/include/render/adaptor/animation/AnimationComponent.h new file mode 100644 index 00000000..9ebeec25 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/animation/AnimationComponent.h @@ -0,0 +1,28 @@ +// +// Created by blues on 2024/8/30. +// + +#pragma once + +#include +#include + +namespace sky { + class SerializationContext; + + class AnimationComponent : public ComponentBase { + public: + AnimationComponent() = default; + ~AnimationComponent() override = default; + + COMPONENT_RUNTIME_INFO(AnimationComponent) + + static void Reflect(SerializationContext *context); + + void AddAnimation(const AnimationClip &clip); + + private: + std::vector animations; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/include/render/adaptor/assets/AnimationAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/AnimationAsset.h new file mode 100644 index 00000000..e4607946 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/assets/AnimationAsset.h @@ -0,0 +1,35 @@ +// +// Created by blues on 2024/8/2. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + + struct AnimationAssetData { + uint32_t version; + std::string name; + std::vector nodeChannels; + + void Load(BinaryInputArchive &archive); + void Save(BinaryOutputArchive &archive) const; + }; + + template <> + struct AssetTraits { + using DataType = AnimationAssetData; + static constexpr std::string_view ASSET_TYPE = "Animation"; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; + }; + using AnimationAssetPtr = std::shared_ptr>; + + AnimClipPtr CreateAnimationFromAsset(const AnimationAssetPtr &asset); +} // namespace sky \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/BufferAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/BufferAsset.h similarity index 87% rename from render/adaptor/include/render/adaptor/assets/BufferAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/BufferAsset.h index b507de75..4bf912e2 100644 --- a/render/adaptor/include/render/adaptor/assets/BufferAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/BufferAsset.h @@ -28,7 +28,7 @@ namespace sky { template <> struct AssetTraits { using DataType = BufferAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("C0C7D089-9B8B-4B9E-9D61-915C9380705D"); + static constexpr std::string_view ASSET_TYPE = "Buffer"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; }; using BufferAssetPtr = std::shared_ptr>; diff --git a/render/adaptor/include/render/adaptor/assets/ImageAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/ImageAsset.h similarity index 68% rename from render/adaptor/include/render/adaptor/assets/ImageAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/ImageAsset.h index 50d89fb6..007692cf 100644 --- a/render/adaptor/include/render/adaptor/assets/ImageAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/ImageAsset.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -15,7 +16,15 @@ namespace sky { class BinaryInputArchive; class BinaryOutputArchive; + struct ImageSliceHeader { + uint32_t offset = 0; + uint32_t size = 0; + uint32_t mipLevel = 0; + uint32_t layer = 0; + }; + struct ImageAssetHeader { + uint32_t version = 0; rhi::PixelFormat format = rhi::PixelFormat::UNDEFINED; TextureType type = TextureType::TEXTURE_2D; uint32_t width = 1; @@ -23,28 +32,24 @@ namespace sky { uint32_t depth = 1; uint32_t mipLevels = 1; uint32_t arrayLayers = 1; - uint32_t dataSize = 1; + std::vector slices; + uint32_t dataSize; }; struct ImageAssetData : public ImageAssetHeader { - Uuid bufferID; + uint32_t dataOffset; + AssetRawData rawData; void Load(BinaryInputArchive &archive); void Save(BinaryOutputArchive &archive) const; }; - - std::shared_ptr CreateTexture(const ImageAssetData &data); + using ImageAssetPtr = std::shared_ptr>; template <> struct AssetTraits { using DataType = ImageAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("E28E41C7-FC98-47B9-B86E-42CD0541A4BF"); + static constexpr std::string_view ASSET_TYPE = "Texture"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateTexture(data); - } }; - using ImageAssetPtr = std::shared_ptr>; + CounterPtr CreateTextureFromAsset(const ImageAssetPtr &asset); } \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/MaterialAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/MaterialAsset.h similarity index 68% rename from render/adaptor/include/render/adaptor/assets/MaterialAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/MaterialAsset.h index b1ff80b7..42e239b4 100644 --- a/render/adaptor/include/render/adaptor/assets/MaterialAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/MaterialAsset.h @@ -20,9 +20,14 @@ namespace sky { struct MaterialProperties { std::vector images; std::unordered_map valueMap; + std::unordered_map options; + + void LoadJson(JsonInputArchive &archive); + void SaveJson(JsonOutputArchive &archive) const; }; struct MaterialAssetData { + uint32_t version; std::vector techniques; MaterialProperties defaultProperties; @@ -30,41 +35,34 @@ namespace sky { void SaveBin(BinaryOutputArchive &archive) const; }; - std::shared_ptr CreateMaterial(const MaterialAssetData &data); - template <> struct AssetTraits { using DataType = MaterialAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("7A82A577-959A-4735-8175-A14C26D33B6B"); + static constexpr std::string_view ASSET_TYPE = "Material"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateMaterial(data); - } }; using MaterialAssetPtr = std::shared_ptr>; struct MaterialInstanceData { + uint32_t version; Uuid material; MaterialProperties properties; void LoadBin(BinaryInputArchive &archive); void SaveBin(BinaryOutputArchive &archive) const; - }; - std::shared_ptr CreateMaterialInstance(const MaterialInstanceData &data); + void LoadJson(JsonInputArchive &archive); + void SaveJson(JsonOutputArchive &archive) const; + }; template <> struct AssetTraits { using DataType = MaterialInstanceData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("A2223B19-6566-45A4-B9BD-F12A9908BC7C"); + static constexpr std::string_view ASSET_TYPE = "MaterialInstance"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateMaterialInstance(data); - } }; using MaterialInstanceAssetPtr = std::shared_ptr>; + + CounterPtr CreateMaterialFromAsset(const MaterialAssetPtr &asset); + CounterPtr CreateMaterialInstanceFromAsset(const MaterialInstanceAssetPtr &asset); } // namespace sky \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/MeshAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/MeshAsset.h similarity index 58% rename from render/adaptor/include/render/adaptor/assets/MeshAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/MeshAsset.h index 85bb3562..faabf814 100644 --- a/render/adaptor/include/render/adaptor/assets/MeshAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/MeshAsset.h @@ -8,18 +8,32 @@ #include #include +#include #include +#include #include #include #include #include - +#include namespace sky { class BinaryInputArchive; class BinaryOutputArchive; + enum class MeshBufferType : uint32_t { + RAW_DATA = 0, + UUID + }; + + struct MeshBufferView { + uint32_t offset; + uint32_t size; + uint32_t stride; + MeshBufferType type = MeshBufferType::RAW_DATA; + }; + struct SubMeshAssetData { uint32_t firstVertex = 0; uint32_t vertexCount = 0; @@ -29,35 +43,34 @@ namespace sky { AABB aabb; }; - struct BufferViewData { - Uuid buffer; - uint32_t offset; - uint32_t size; - }; + struct MeshDataHeader { + uint32_t version = 0; + Uuid skeleton; - struct MeshAssetData { std::vector subMeshes; - std::vector vertexBuffers; - BufferViewData indexBuffer; + std::vector buffers; + std::vector attributes; + uint32_t indexBuffer; rhi::IndexType indexType = rhi::IndexType::U32; - std::vector vertexDescriptions; + + uint32_t dataSize; + }; + + struct MeshAssetData : MeshDataHeader { + uint32_t dataOffset; + AssetRawData rawData; void Load(BinaryInputArchive &archive); void Save(BinaryOutputArchive &archive) const; }; - std::shared_ptr CreateMesh(const MeshAssetData &data); - template <> struct AssetTraits { using DataType = MeshAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("394AB7FF-FC10-484F-82A6-42D523949DD1"); + static constexpr std::string_view ASSET_TYPE = "Mesh"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateMesh(data); - } }; using MeshAssetPtr = std::shared_ptr>; + + CounterPtr CreateMeshFromAsset(const MeshAssetPtr &asset); } \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/RenderPrefab.h b/runtime/render/adaptor/include/render/adaptor/assets/RenderPrefab.h similarity index 70% rename from render/adaptor/include/render/adaptor/assets/RenderPrefab.h rename to runtime/render/adaptor/include/render/adaptor/assets/RenderPrefab.h index f8efd025..8c695154 100644 --- a/render/adaptor/include/render/adaptor/assets/RenderPrefab.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/RenderPrefab.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include #include @@ -15,16 +16,20 @@ namespace sky { class BinaryOutputArchive; struct RenderPrefabNode { + std::string name; Uuid mesh; uint32_t parentIndex = ~(0u); - Matrix4 localMatrix; + Transform localTransform; }; struct RenderPrefabAssetData { std::vector nodes; - void Load(BinaryInputArchive &archive); - void Save(BinaryOutputArchive &archive) const; + void LoadBin(BinaryInputArchive &archive); + void SaveBin(BinaryOutputArchive &archive) const; + + void LoadJson(JsonInputArchive &archive); + void SaveJson(JsonOutputArchive &archive) const; }; class RenderPrefab { @@ -36,7 +41,7 @@ namespace sky { template <> struct AssetTraits { using DataType = RenderPrefabAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("0339389A-D8BC-46B4-97F2-60B5548A30D7"); + static constexpr std::string_view ASSET_TYPE = "RenderPrefab"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; }; using RenderPrefabAssetPtr = std::shared_ptr>; diff --git a/render/adaptor/include/render/adaptor/assets/ShaderAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/ShaderAsset.h similarity index 67% rename from render/adaptor/include/render/adaptor/assets/ShaderAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/ShaderAsset.h index 271fba51..0ed3ac6b 100644 --- a/render/adaptor/include/render/adaptor/assets/ShaderAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/ShaderAsset.h @@ -20,18 +20,13 @@ namespace sky { void Save(BinaryOutputArchive &archive) const; }; - std::shared_ptr CreateShader(const ShaderAssetData &data); - template <> struct AssetTraits { using DataType = ShaderAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("E71838F5-40F3-470A-883C-401D8796B5FD"); + static constexpr std::string_view ASSET_TYPE = "ShaderCollection"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateShader(data); - } }; using ShaderAssetPtr = std::shared_ptr>; + + CounterPtr CreateShaderFromAsset(const ShaderAssetPtr &asset); } diff --git a/runtime/render/adaptor/include/render/adaptor/assets/SkeletonAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/SkeletonAsset.h new file mode 100644 index 00000000..9efa48ba --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/assets/SkeletonAsset.h @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/8/10. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + struct SkeletonAssetData : public SkeletonData { + uint32_t version = 0; + + uint32_t AdddBone(const std::string &name, const Matrix4 &matrix); + uint32_t FindBoneByName(const Name &name) const; + + void Load(BinaryInputArchive &archive); + void Save(BinaryOutputArchive &archive) const; + }; + + template <> + struct AssetTraits { + using DataType = SkeletonAssetData; + static constexpr std::string_view ASSET_TYPE = "Skeleton"; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; + }; + using SkeletonAssetPtr = std::shared_ptr>; +} // namespace sky \ No newline at end of file diff --git a/render/adaptor/include/render/adaptor/assets/TechniqueAsset.h b/runtime/render/adaptor/include/render/adaptor/assets/TechniqueAsset.h similarity index 68% rename from render/adaptor/include/render/adaptor/assets/TechniqueAsset.h rename to runtime/render/adaptor/include/render/adaptor/assets/TechniqueAsset.h index e8f4126d..993ea852 100644 --- a/render/adaptor/include/render/adaptor/assets/TechniqueAsset.h +++ b/runtime/render/adaptor/include/render/adaptor/assets/TechniqueAsset.h @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -22,38 +23,43 @@ namespace sky { }; struct ShaderRefData { - std::string path; + Uuid shader; std::string objectOrCSMain; std::string vertOrMeshMain; std::string fragmentMain; }; + struct TechniqueVertexFlags { + RenderVertexFlags flag; + std::string macro; + }; + struct TechniqueAssetData { + uint32_t version; ShaderRefData shader; std::string passTag; - std::string vertexDesc; TechAssetType type; rhi::DepthStencil depthStencil; rhi::RasterState rasterState; std::vector blendStates; + // variants + std::vector preDefines; + std::vector vertexFlags; + void Load(BinaryInputArchive &archive); void Save(BinaryOutputArchive &archive) const; }; - std::shared_ptr CreateTechnique(const TechniqueAssetData &data); - template <> struct AssetTraits { using DataType = TechniqueAssetData; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("79F513A7-8BC1-48B4-B086-FB2E78798D60"); + static constexpr std::string_view ASSET_TYPE = "Technique"; static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; - - static std::shared_ptr CreateFromData(const DataType &data) - { - return CreateTechnique(data); - } }; using TechniqueAssetPtr = std::shared_ptr>; + + CounterPtr CreateTechniqueFromAsset(const TechniqueAssetPtr &asset); + CounterPtr GreateGfxTechFromAsset(const TechniqueAssetPtr &asset); } diff --git a/render/adaptor/include/render/adaptor/components/CameraComponent.h b/runtime/render/adaptor/include/render/adaptor/components/CameraComponent.h similarity index 51% rename from render/adaptor/include/render/adaptor/components/CameraComponent.h rename to runtime/render/adaptor/include/render/adaptor/components/CameraComponent.h index 696de943..a1b88859 100644 --- a/render/adaptor/include/render/adaptor/components/CameraComponent.h +++ b/runtime/render/adaptor/include/render/adaptor/components/CameraComponent.h @@ -12,34 +12,40 @@ namespace sky { enum class ProjectType : uint32_t { ORTHOGONAL, PROJECTIVE }; - class CameraComponent : public Component { + class CameraComponent : public ComponentBase { public: CameraComponent() = default; - ~CameraComponent() override = default; + ~CameraComponent() override; - TYPE_RTTI_WITH_VT(CameraComponent) + COMPONENT_RUNTIME_INFO(CameraComponent) - static void Reflect(); + static void Reflect(SerializationContext *context); void Perspective(float near, float far, float fov); - void Otho(float height); + void Otho(float h); void SetAspect(uint32_t width, uint32_t height); - void OnTick(float time) override; - void OnActive() override; - void OnDestroy() override; + void Tick(float time) override; + void OnAttachToWorld() override; + void OnDetachFromWorld() override; - void Save(JsonOutputArchive &ar) const override; - void Load(JsonInputArchive &ar) override; + void SaveJson(JsonOutputArchive &ar) const override; + void LoadJson(JsonInputArchive &ar) override; + const Matrix4 &GetProject() const; + const Matrix4 &GetView() const; private: + void ShutDown(); + // data float near = 0.1f; float far = 100.f; float fov = 60; float aspect = 1.f; - float othoH = 1.f; + float othoH = 25.f; + uint32_t width = 1; + uint32_t height = 1; ProjectType type = ProjectType::PROJECTIVE; // status diff --git a/runtime/render/adaptor/include/render/adaptor/components/LightComponent.h b/runtime/render/adaptor/include/render/adaptor/components/LightComponent.h new file mode 100644 index 00000000..f400f8cf --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/components/LightComponent.h @@ -0,0 +1,39 @@ +// +// Created by Zach Lee on 2023/2/28. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class LightComponent : public ComponentBase { + public: + LightComponent() = default; + ~LightComponent() override = default; + + COMPONENT_RUNTIME_INFO(LightComponent) + + static void Reflect(SerializationContext *context); + + void Tick(float time) override; + void OnAttachToWorld() override; + void OnDetachFromWorld() override; + + void SaveJson(JsonOutputArchive &ar) const override; + void LoadJson(JsonInputArchive &ar) override; + + private: + Color lightColor; + + DirectLight *light = nullptr; + }; + +} // namespace sky + + + + diff --git a/runtime/render/adaptor/include/render/adaptor/components/SkeletonMeshComponent.h b/runtime/render/adaptor/include/render/adaptor/components/SkeletonMeshComponent.h new file mode 100644 index 00000000..94bf9c2b --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/components/SkeletonMeshComponent.h @@ -0,0 +1,48 @@ +// +// Created by blues on 2024/8/11. +// + +#pragma once + + +#include +#include +#include +#include +#include + +namespace sky { + + class SkeletonMeshComponent : public ComponentBase, public IAssetEvent { + public: + SkeletonMeshComponent() = default; + ~SkeletonMeshComponent() override; + + COMPONENT_RUNTIME_INFO(SkeletonMeshComponent) + + static void Reflect(SerializationContext *context); + + void Tick(float time) override; + void OnAttachToWorld() override; + void OnDetachFromWorld() override; + + void SaveJson(JsonOutputArchive &ar) const override; + void LoadJson(JsonInputArchive &ar) override; + + void SetMeshUuid(const Uuid &uuid); + const Uuid& GetMeshUuid() const { return meshAsset ? meshAsset->GetUuid() : Uuid::GetEmpty(); } + private: + void ShutDown(); + void BuildRenderer(); + + void OnAssetLoaded() override; + + MeshAssetPtr meshAsset; + RDMeshPtr meshInstance; + SkeletonMeshRenderer *renderer = nullptr; + + std::atomic_bool dirty = false; + EventBinder binder; + }; + +} // namespace receiveShadow diff --git a/runtime/render/adaptor/include/render/adaptor/components/StaticMeshComponent.h b/runtime/render/adaptor/include/render/adaptor/components/StaticMeshComponent.h new file mode 100644 index 00000000..6e3831e2 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/components/StaticMeshComponent.h @@ -0,0 +1,55 @@ +// +// Created by Zach Lee on 2023/2/28. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky { + + class StaticMeshComponent : public ComponentBase, public IAssetEvent { + public: + StaticMeshComponent() = default; + ~StaticMeshComponent() override; + + COMPONENT_RUNTIME_INFO(StaticMeshComponent) + + static void Reflect(SerializationContext *context); + + void Tick(float time) override; + + void SaveJson(JsonOutputArchive &ar) const override; + void LoadJson(JsonInputArchive &ar) override; + + MeshRenderer *GetRenderer() const { return renderer; } + + void SetMeshUuid(const Uuid &uuid); + const Uuid& GetMeshUuid() const { return meshAsset ? meshAsset->GetUuid() : Uuid::GetEmpty(); } + + void OnAttachToWorld() override; + void OnDetachFromWorld() override; + private: + void ShutDown(); + void BuildRenderer(); + + void OnAssetLoaded() override; + + bool isStatic = true; + bool castShadow = false; + bool receiveShadow = false; + + MeshAssetPtr meshAsset; + RDMeshPtr meshInstance; + MeshRenderer *renderer = nullptr; + + std::atomic_bool dirty = false; + + EventBinder binder; + }; + +} // namespace receiveShadow diff --git a/runtime/render/adaptor/include/render/adaptor/event/ImGuiFeatureEvent.h b/runtime/render/adaptor/include/render/adaptor/event/ImGuiFeatureEvent.h new file mode 100644 index 00000000..19b2fdb1 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/event/ImGuiFeatureEvent.h @@ -0,0 +1,20 @@ +// +// Created by blues on 2024/7/30. +// + +#pragma once + +#include +#include + +namespace sky { + + class ImGuiFeatureEvent : public EventTraits { + public: + ImGuiFeatureEvent() = default; + virtual ~ImGuiFeatureEvent() = default; + + virtual void OnTechniqueReady(RDGfxTechPtr &tech) = 0; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/CustomRenderFlags.h b/runtime/render/adaptor/include/render/adaptor/pipeline/CustomRenderFlags.h new file mode 100644 index 00000000..04258e89 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/CustomRenderFlags.h @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/9/16. +// + +#pragma once + +#include + +namespace sky { + + enum class CustomRenderFlags : uint32_t { + SHADOW, + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultForwardPipeline.h b/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultForwardPipeline.h new file mode 100644 index 00000000..6ab6bc54 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultForwardPipeline.h @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/9/6. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky { + class RenderWindow; + + class DefaultForwardPipeline : public RenderScenePipeline { + public: + explicit DefaultForwardPipeline(RenderScene *scn) : RenderScenePipeline(scn) {} + ~DefaultForwardPipeline() override = default; + + void SetOutput(RenderWindow *wnd); + + private: + void InitPass(); + void Collect(rdg::RenderGraph &rdg) override; + + uint32_t viewMask = 0; + RenderWindow *output = nullptr; + rhi::PixelFormat depthStencilFormat = rhi::PixelFormat::D24_S8; + + RDUniformBufferPtr globalUbo; + + std::unique_ptr forward; + std::unique_ptr postProcess; + std::unique_ptr present; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultPassConstants.h b/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultPassConstants.h new file mode 100644 index 00000000..fee04af6 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/DefaultPassConstants.h @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include + +namespace sky { + + static constexpr std::string_view FWD_CL = "ForwardColor"; + static constexpr std::string_view FWD_DS = "ForwardDepthStencil"; + + static constexpr std::string_view SHADOW_MAP = "ShadowMap"; + + static constexpr std::string_view FWD_MSAA_CL = "ForwardMSAAColor"; + static constexpr std::string_view FWD_MSAA_DS = "ForwardMSAADepthStencil"; + + static constexpr std::string_view SWAP_CHAIN = "SwapChain"; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/ForwardMSAAPass.h b/runtime/render/adaptor/include/render/adaptor/pipeline/ForwardMSAAPass.h new file mode 100644 index 00000000..508b2069 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/ForwardMSAAPass.h @@ -0,0 +1,25 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include +#include + +namespace sky { + + class ForwardMSAAPass : public RasterPass { + public: + ForwardMSAAPass(rhi::PixelFormat color, rhi::PixelFormat ds, rhi::SampleCount samples_); + ~ForwardMSAAPass() override = default; + + private: + void SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) override; + + rhi::PixelFormat colorFormat = rhi::PixelFormat::RGBA8_UNORM; + rhi::PixelFormat depthStenFormat = rhi::PixelFormat::D24_S8; + rhi::SampleCount samples = rhi::SampleCount::X2; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/PostProcessingPass.h b/runtime/render/adaptor/include/render/adaptor/pipeline/PostProcessingPass.h new file mode 100644 index 00000000..5d4bcae1 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/PostProcessingPass.h @@ -0,0 +1,22 @@ +// +// Created by blues on 2024/9/5. +// + +#pragma once + +#include +#include + +namespace sky { + + class PostProcessingPass : public FullScreenPass { + public: + explicit PostProcessingPass(const RDGfxTechPtr &tech); + ~PostProcessingPass() override = default; + + void Setup(rdg::RenderGraph &rdg, RenderScene &scene) override; + + void SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) override; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/PresentPass.h b/runtime/render/adaptor/include/render/adaptor/pipeline/PresentPass.h new file mode 100644 index 00000000..b34be958 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/PresentPass.h @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/9/6. +// + +#pragma once + +#include +#include + +namespace sky { + + class PresentPass : public PassBase { + public: + explicit PresentPass(const rhi::SwapChainPtr &swc); + ~PresentPass() override = default; + + void Prepare(rdg::RenderGraph &rdg, RenderScene &scene) override; + void Setup(rdg::RenderGraph &rdg, RenderScene &scene) override; + + private: + rhi::SwapChainPtr swapChain; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/pipeline/ShadowMapPass.h b/runtime/render/adaptor/include/render/adaptor/pipeline/ShadowMapPass.h new file mode 100644 index 00000000..133b5780 --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/pipeline/ShadowMapPass.h @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/9/6. +// + +#pragma once + +#include +#include + +namespace sky { + + class ShadowMapPass : public RasterPass { + public: + explicit ShadowMapPass(uint32_t width, uint32_t height); + ~ShadowMapPass() override = default; + + private: + void SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) override; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/include/render/adaptor/profile/RenderProfiler.h b/runtime/render/adaptor/include/render/adaptor/profile/RenderProfiler.h new file mode 100644 index 00000000..a53fc27f --- /dev/null +++ b/runtime/render/adaptor/include/render/adaptor/profile/RenderProfiler.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/19. +// + +#pragma once + +#include +#include + +namespace sky { + class RenderScene; + + class RenderProfiler { + public: + explicit RenderProfiler(RenderScene *scn); + ~RenderProfiler(); + + void SetDisplaySize(uint32_t w, uint32_t h); + private: + RenderScene* scene = nullptr; + Text* text = nullptr; + + FontPtr font; + }; + +} // namespace sky diff --git a/runtime/render/adaptor/src/Profile/RenderProfiler.cpp b/runtime/render/adaptor/src/Profile/RenderProfiler.cpp new file mode 100644 index 00000000..3c84fb14 --- /dev/null +++ b/runtime/render/adaptor/src/Profile/RenderProfiler.cpp @@ -0,0 +1,42 @@ +// +// Created by blues on 2024/9/19. +// + +#include +#include +#include +#include +#include +#include + +namespace sky { + + RenderProfiler::RenderProfiler(RenderScene *scn) + : scene(scn) + { + auto fs = AssetDataBase::Get()->GetEngineFs(); + font = TextRegistry::Get()->LoadFont(fs, "fonts/OpenSans-Regular.ttf"); + text = scene->GetFeature()->CreateText(font); + text->Init(TextDesc{20}); + + TextInfo info = {}; + info.color = Color{1.f, 1, 1, 1.f}; + + std::stringstream ss; + ss << RHI::Get()->GetDevice()->GetDeviceInfo() << " <" << RHI::Get()->GetBackendName() << ">" << std::endl; + text->AddText(ss.str(), Vector2{20, 40}, info); + text->Finalize(*scene); + } + + RenderProfiler::~RenderProfiler() + { + if (text != nullptr) { + scene->GetFeature()->RemoveText(text); + } + } + + void RenderProfiler::SetDisplaySize(uint32_t w, uint32_t h) + { + text->SetDisplaySize(static_cast(w), static_cast(h)); + } +} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/Relection.cpp b/runtime/render/adaptor/src/Relection.cpp similarity index 85% rename from render/adaptor/src/Relection.cpp rename to runtime/render/adaptor/src/Relection.cpp index dc9db2e5..9315a314 100644 --- a/render/adaptor/src/Relection.cpp +++ b/runtime/render/adaptor/src/Relection.cpp @@ -11,9 +11,10 @@ #include #include #include -#include #include #include +#include +#include namespace sky { @@ -43,12 +44,10 @@ namespace sky { .BinSave<&MeshAssetData::Save>(); context->Register("RenderPrefabAssetData") - .BinLoad<&RenderPrefabAssetData::Load>() - .BinSave<&RenderPrefabAssetData::Save>(); - - context->Register("VertexDescLibraryAssetData") - .BinLoad<&VertexDescLibraryAssetData::Load>() - .BinSave<&VertexDescLibraryAssetData::Save>(); + .BinLoad<&RenderPrefabAssetData::LoadBin>() + .BinSave<&RenderPrefabAssetData::SaveBin>() + .JsonLoad<&RenderPrefabAssetData::LoadJson>() + .JsonSave<&RenderPrefabAssetData::SaveJson>(); context->Register("BufferAssetData") .BinLoad<&BufferAssetData::Load>() @@ -58,6 +57,14 @@ namespace sky { .BinLoad<&ShaderAssetData::Load>() .BinSave<&ShaderAssetData::Save>(); + context->Register("AnimationAssetData") + .BinLoad<&AnimationAssetData::Load>() + .BinSave<&AnimationAssetData::Save>(); + + context->Register("SkeletonData") + .BinLoad<&SkeletonAssetData::Load>() + .BinSave<&SkeletonAssetData::Save>(); + auto *am = AssetManager::Get(); am->RegisterAssetHandler(); am->RegisterAssetHandler(); @@ -65,9 +72,10 @@ namespace sky { am->RegisterAssetHandler(); am->RegisterAssetHandler(); am->RegisterAssetHandler(); - am->RegisterAssetHandler(); am->RegisterAssetHandler(); am->RegisterAssetHandler(); + am->RegisterAssetHandler(); + am->RegisterAssetHandler(); } void ReflectRHI(SerializationContext *context) diff --git a/render/adaptor/src/RenderSceneProxy.cpp b/runtime/render/adaptor/src/RenderSceneProxy.cpp similarity index 100% rename from render/adaptor/src/RenderSceneProxy.cpp rename to runtime/render/adaptor/src/RenderSceneProxy.cpp diff --git a/runtime/render/adaptor/src/Util.cpp b/runtime/render/adaptor/src/Util.cpp new file mode 100644 index 00000000..51433961 --- /dev/null +++ b/runtime/render/adaptor/src/Util.cpp @@ -0,0 +1,11 @@ +// +// Created by Zach Lee on 2023/8/27. +// + +#include +#include +#include + +namespace sky { + +} // namespace sky diff --git a/runtime/render/adaptor/src/animation/AnimationComponent.cpp b/runtime/render/adaptor/src/animation/AnimationComponent.cpp new file mode 100644 index 00000000..f5adbd72 --- /dev/null +++ b/runtime/render/adaptor/src/animation/AnimationComponent.cpp @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/8/30. +// + +#include +#include + +namespace sky { + + void AnimationComponent::Reflect(SerializationContext *context) + { + context->Register("AnimationComponent"); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/assets/AnimationAsset.cpp b/runtime/render/adaptor/src/assets/AnimationAsset.cpp new file mode 100644 index 00000000..a655e8ab --- /dev/null +++ b/runtime/render/adaptor/src/assets/AnimationAsset.cpp @@ -0,0 +1,92 @@ +// +// Created by blues on 2024/8/2. +// + +#include + +namespace sky { + + void AnimationAssetData::Load(BinaryInputArchive &archive) + { + archive.LoadValue(version); + archive.LoadValue(name); + uint32_t size = 0; + archive.LoadValue(size); + nodeChannels.resize(size); + + for (uint32_t i = 0; i < size; ++i) { + auto &channel = nodeChannels[i]; + archive.LoadValue(channel.name); + uint32_t channelSize = 0; + archive.LoadValue(channelSize); + channel.position.time.resize(channelSize / sizeof(float)); + archive.LoadValue(reinterpret_cast(channel.position.time.data()), channelSize); + + archive.LoadValue(channelSize); + channel.position.keys.resize(channelSize / sizeof(Vector3)); + archive.LoadValue(reinterpret_cast(channel.position.keys.data()), channelSize); + + archive.LoadValue(channelSize); + channel.scale.time.resize(channelSize / sizeof(float)); + archive.LoadValue(reinterpret_cast(channel.scale.time.data()), channelSize); + + archive.LoadValue(channelSize); + channel.scale.keys.resize(channelSize / sizeof(Vector3)); + archive.LoadValue(reinterpret_cast(channel.scale.keys.data()), channelSize); + + archive.LoadValue(channelSize); + channel.rotation.time.resize(channelSize / sizeof(float)); + archive.LoadValue(reinterpret_cast(channel.position.time.data()), channelSize); + + archive.LoadValue(channelSize); + channel.rotation.keys.resize(channelSize / sizeof(Quaternion)); + archive.LoadValue(reinterpret_cast(channel.rotation.keys.data()), channelSize); + } + } + + void AnimationAssetData::Save(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + archive.SaveValue(name); + archive.SaveValue(static_cast(nodeChannels.size())); + for (const auto &channel : nodeChannels) { + archive.SaveValue(channel.name); + auto channelSize = static_cast(channel.position.time.size() * sizeof(float)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.position.time.data()), channelSize); + + channelSize = static_cast(channel.position.keys.size() * sizeof(Vector3)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.position.keys.data()), channelSize); + + channelSize = static_cast(channel.scale.time.size() * sizeof(float)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.scale.time.data()), channelSize); + + channelSize = static_cast(channel.scale.keys.size() * sizeof(Vector3)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.scale.keys.data()), channelSize); + + channelSize = static_cast(channel.rotation.time.size() * sizeof(float)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.rotation.time.data()), channelSize); + + channelSize = static_cast(channel.rotation.keys.size() * sizeof(Quaternion)); + archive.SaveValue(channelSize); + archive.SaveValue(reinterpret_cast(channel.rotation.keys.data()), channelSize); + } + } + + AnimClipPtr CreateAnimationFromAsset(const AnimationAssetPtr &asset) + { + const auto &data = asset->Data(); + + auto *clip = new AnimationClip(data.name); + + for (const auto &nodeChannel : data.nodeChannels) { + clip->AddChannel(new AnimationNodeChannel(nodeChannel)); + } + return clip; + } + +} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/assets/BufferAsset.cpp b/runtime/render/adaptor/src/assets/BufferAsset.cpp similarity index 100% rename from render/adaptor/src/assets/BufferAsset.cpp rename to runtime/render/adaptor/src/assets/BufferAsset.cpp diff --git a/runtime/render/adaptor/src/assets/ImageAsset.cpp b/runtime/render/adaptor/src/assets/ImageAsset.cpp new file mode 100644 index 00000000..b8aa4c3a --- /dev/null +++ b/runtime/render/adaptor/src/assets/ImageAsset.cpp @@ -0,0 +1,103 @@ +// +// Created by Zach Lee on 2023/2/26. +// + +#include +#include +#include + +namespace sky { + void ImageAssetData::Load(BinaryInputArchive &archive) + { + archive.LoadValue(version); + archive.LoadValue(format); + archive.LoadValue(type); + archive.LoadValue(width); + archive.LoadValue(height); + archive.LoadValue(depth); + archive.LoadValue(mipLevels); + archive.LoadValue(arrayLayers); + + uint32_t size = 0; + archive.LoadValue(size); + slices.resize(size); + for (uint32_t i = 0; i < size; ++i) { + auto &slice = slices[i]; + archive.LoadValue(slice.offset); + archive.LoadValue(slice.size); + archive.LoadValue(slice.mipLevel); + archive.LoadValue(slice.layer); + } + + archive.LoadValue(dataSize); + dataOffset = static_cast(archive.GetStream().Tell()); + } + + void ImageAssetData::Save(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + archive.SaveValue(format); + archive.SaveValue(type); + archive.SaveValue(width); + archive.SaveValue(height); + archive.SaveValue(depth); + archive.SaveValue(mipLevels); + archive.SaveValue(arrayLayers); + + archive.SaveValue(static_cast(slices.size())); + for (const auto &slice : slices) { + archive.SaveValue(slice.offset); + archive.SaveValue(slice.size); + archive.SaveValue(slice.mipLevel); + archive.SaveValue(slice.layer); + } + + // data size + archive.SaveValue(dataSize); + SKY_ASSERT(dataSize == static_cast(rawData.storage.size())); + + // save raw + archive.SaveValue(reinterpret_cast(rawData.storage.data()), dataSize); + } + + CounterPtr CreateTextureFromAsset(const ImageAssetPtr &asset) + { + const auto &data = asset->Data(); + const auto &uuid = asset->GetUuid(); + + auto *am = AssetManager::Get(); + auto file = am->OpenFile(uuid); + SKY_ASSERT(file); + + ImageData imageData; + auto *fileStream = new rhi::FileStream(file, data.dataOffset); + + for (const auto &slice : data.slices) { + rhi::ImageUploadRequest request = {}; + request.source = fileStream; + request.offset = slice.offset; + request.size = slice.size; + request.layer = slice.layer; + request.mipLevel = slice.mipLevel; + request.imageExtent.width = std::max(1U, data.width >> slice.mipLevel); + request.imageExtent.height = std::max(1U, data.height >> slice.mipLevel); + request.imageExtent.depth = std::max(1U, data.depth >> slice.mipLevel); + imageData.slices.emplace_back(request); + } + + if (data.type == TextureType::TEXTURE_2D) { + auto *texture2D = new Texture2D(); + texture2D->Init(data.format, data.width, data.height, data.mipLevels); + texture2D->SetUploadStream(std::move(imageData)); + return texture2D; + } + + if (data.type == TextureType::TEXTURE_CUBE) { + auto *textureCube = new TextureCube(); + textureCube->Init(data.format, data.width, data.height, data.mipLevels); + textureCube->SetUploadStream(std::move(imageData)); + return textureCube; + } + return {}; + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/assets/MaterialAsset.cpp b/runtime/render/adaptor/src/assets/MaterialAsset.cpp new file mode 100644 index 00000000..d4584b91 --- /dev/null +++ b/runtime/render/adaptor/src/assets/MaterialAsset.cpp @@ -0,0 +1,355 @@ +// +// Created by Zach Lee on 2023/2/23. +// + +#include +#include +#include +#include + +namespace sky { + void LoadProperties(BinaryInputArchive &archive, MaterialProperties &properties) + { + uint32_t size = 0; + archive.LoadValue(size); + properties.images.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(properties.images[i]); + } + + size = 0; + archive.LoadValue(size); + for (uint32_t i = 0; i < size; ++i) { + std::string key; + archive.LoadValue(key); + MaterialValueType type; + archive.LoadValue(type); + switch (type) { + case MaterialValueType::TEXTURE: { + MaterialTexture tex = {}; + archive.LoadValue(tex.texIndex); + properties.valueMap[key] = tex; + } + break; + case MaterialValueType::VEC2: { + Vector2 vec = {}; + archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector2)); + properties.valueMap[key] = vec; + } + break; + case MaterialValueType::VEC3: { + Vector3 vec = {}; + archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector3)); + properties.valueMap[key] = vec; + } + break; + case MaterialValueType::VEC4: { + Vector4 vec = {}; + archive.LoadValue(reinterpret_cast(&vec), sizeof(Vector4)); + properties.valueMap[key] = vec; + } + break; + case MaterialValueType::FLOAT: { + float val = {}; + archive.LoadValue(val); + properties.valueMap[key] = val; + } + break; + case MaterialValueType::U32: { + uint32_t val = {}; + archive.LoadValue(val); + properties.valueMap[key] = val; + } + break; + case MaterialValueType::I32: { + int32_t val = {}; + archive.LoadValue(val); + properties.valueMap[key] = val; + } + break; + default: + SKY_UNEXPECTED; + } + } + + size = 0; + archive.LoadValue(size); + for (uint32_t i = 0; i < size; ++i) { + std::string key; + archive.LoadValue(key); + MaterialValueType type; + archive.LoadValue(type); + switch (type) { + case MaterialValueType::BOOL: { + bool val = {}; + archive.LoadValue(val); + properties.options[key] = val; + } + break; + case MaterialValueType::U32: { + uint32_t val = {}; + archive.LoadValue(val); + properties.options[key] = val; + } + break; + default: + SKY_UNEXPECTED; + } + } + } + + void SaveProperties(BinaryOutputArchive &archive, const MaterialProperties &properties) { + archive.SaveValue(static_cast(properties.images.size())); + for (const auto &image: properties.images) { + archive.SaveValue(image); + } + + archive.SaveValue(static_cast(properties.valueMap.size())); + for (const auto &[key, value]: properties.valueMap) { + archive.SaveValue(key); + + std::visit(Overloaded{ + [&archive](const MaterialTexture &v) { + archive.SaveValue(MaterialValueType::TEXTURE); + archive.SaveValue(v.texIndex); + }, + [&archive](const Vector2 &v) { + archive.SaveValue(MaterialValueType::VEC2); + archive.SaveValue(reinterpret_cast(&v), sizeof(Vector2)); + }, + [&archive](const Vector3 &v) { + archive.SaveValue(MaterialValueType::VEC3); + archive.SaveValue(reinterpret_cast(&v), sizeof(Vector3)); + }, + [&archive](const Vector4 &v) { + archive.SaveValue(MaterialValueType::VEC4); + archive.SaveValue(reinterpret_cast(&v), sizeof(Vector4)); + }, + [&archive](const float &v) { + archive.SaveValue(MaterialValueType::FLOAT); + archive.SaveValue(v); + }, + [&archive](const uint32_t &v) { + archive.SaveValue(MaterialValueType::U32); + archive.SaveValue(v); + }, + [&archive](const int32_t &v) { + archive.SaveValue(MaterialValueType::I32); + archive.SaveValue(v); + }, + }, value); + } + + archive.SaveValue(static_cast(properties.options.size())); + for (const auto &[key, value]: properties.options) { + archive.SaveValue(key); + + std::visit(Overloaded{ + [&archive](const bool &v) { + archive.SaveValue(MaterialValueType::BOOL); + archive.SaveValue(v); + }, + [&archive](const uint32_t &v) { + archive.SaveValue(MaterialValueType::U32); + archive.SaveValue(v); + } + }, value); + } + } + + void MaterialAssetData::LoadBin(BinaryInputArchive &archive) + { + archive.LoadValue(version); + uint32_t size = 0; + archive.LoadValue(size); + techniques.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(techniques[i]); + } + + LoadProperties(archive, defaultProperties); + } + + void MaterialAssetData::SaveBin(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + archive.SaveValue(static_cast(techniques.size())); + for (const auto &tech :techniques) { + archive.SaveValue(tech); + } + SaveProperties(archive, defaultProperties); + } + + void MaterialInstanceData::LoadBin(BinaryInputArchive &archive) + { + archive.LoadValue(version); + auto *am = AssetManager::Get(); + archive.LoadValue(material); + LoadProperties(archive, properties); + } + + void MaterialInstanceData::SaveBin(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + archive.SaveValue(material); + SaveProperties(archive, properties); + } + + void MaterialInstanceData::LoadJson(JsonInputArchive &archive) + { + archive.Start("material"); + material = Uuid::CreateFromString(archive.LoadString()); + archive.End(); + + properties.LoadJson(archive); + } + + void MaterialInstanceData::SaveJson(JsonOutputArchive &archive) const + { + archive.StartObject(); + + archive.Key("material"); + + auto source = AssetDataBase::Get()->FindAsset(material); + if (source) { + archive.SaveValue(source->path.path.GetStr()); + } else { + archive.SaveValue(""); + } + + properties.SaveJson(archive); + + archive.EndObject(); + } + + void MaterialProperties::LoadJson(JsonInputArchive &archive) + { + archive.Start("properties"); + + // std::variant; + archive.ForEachMember([this, &archive](const std::string &key, const auto &obj) { + if (obj.IsString()) { + auto value = Uuid::CreateFromString(obj.GetString()); + auto iter = std::find(images.begin(), images.end(), value); + if (iter != images.end()) { + valueMap[key] = MaterialTexture{static_cast(std::distance(iter, images.begin()))}; + } else { + valueMap[key] = MaterialTexture{static_cast(images.size())}; + images.emplace_back(value); + } + + } else if (obj.IsFloat()) { + valueMap[key] = obj.GetFloat(); + } else if (obj.IsBool()) { + valueMap[key] = static_cast(obj.GetBool()); + } else if (obj.IsUint()) { + valueMap[key] = static_cast(obj.GetUint()); + } else if (obj.IsArray()) { + auto array = obj.GetArray(); + float *v = nullptr; + if (array.Size() == 2) { + v = std::get(valueMap.emplace(key, Vector2{}).first->second).v; + } else if (array.Size() == 3) { + v = std::get(valueMap.emplace(key, Vector3{}).first->second).v; + } else if (array.Size() == 4) { + v = std::get(valueMap.emplace(key, Vector4{}).first->second).v; + } + for (auto &val : array) { + (*v) = val.GetFloat(); + ++v; + } + } + }); + archive.End(); + + archive.Start("options"); + archive.ForEachMember([this, &archive](const std::string &key, const auto &obj) { + if (obj.IsBool()) { + options[key] = obj.GetBool(); + } else if (obj.IsUint()) { + options[key] = obj.GetUint(); + } + }); + archive.End(); + } + + void MaterialProperties::SaveJson(JsonOutputArchive &archive) const + { + archive.Key("properties"); + archive.StartObject(); + for (const auto &[key, value] : valueMap) { + archive.Key(key.c_str()); + + // std::variant; + std::visit(Overloaded{ + [&archive, this](const MaterialTexture &tex) { + auto asset = AssetDataBase::Get()->FindAsset(images[tex.texIndex]); + if (asset) { + archive.SaveValue(asset->path.path.GetStr()); + } else { + archive.SaveValue(""); + } + }, + [&archive](const auto& arg) { archive.SaveValueObject(arg); } + }, value); + } + archive.EndObject(); + + archive.Key("options"); + archive.StartObject(); + for (const auto &[key, value] : options) { + archive.Key(key.c_str()); + std::visit(Overloaded{ + [&archive](const bool &val) { + archive.SaveValue(val); + }, + [&archive](const uint32_t &val) { + archive.SaveValue(val); + }, + }, value); + } + archive.EndObject(); + } + + CounterPtr CreateMaterialFromAsset(const MaterialAssetPtr &asset) + { + auto &data = asset->Data(); + + auto *am = AssetManager::Get(); + auto *mat = new Material(); + for (const auto &tech : data.techniques) { + auto techAsset = am->LoadAsset(tech); + mat->AddTechnique(GreateGfxTechFromAsset(techAsset)); + } + return mat; + } + + CounterPtr CreateMaterialInstanceFromAsset(const MaterialInstanceAssetPtr &asset) + { + auto &data = asset->Data(); + + auto *am = AssetManager::Get(); + auto matAsset = am->FindAsset(data.material); + auto *mi = new MaterialInstance(); +// mi->SetName(asset->GetName()); + mi->SetMaterial(CreateMaterialFromAsset(matAsset)); + for (const auto &[key, val] : data.properties.options) { + mi->SetOption(key, val); + } + mi->Compile(); + + for (const auto &[key, val] : data.properties.valueMap) { + std::visit(Overloaded{ + [&mi, &data, &am, key_ = key](const MaterialTexture &v) { + auto imageAsset = am->FindAsset(data.properties.images[v.texIndex]); + mi->SetTexture(key_, CreateTextureFromAsset(imageAsset), 0); + }, + [&mi, key_ = key](const auto &v) { + mi->SetValue(key_, reinterpret_cast(&v), sizeof(decltype(v))); + } + }, val); + } + mi->Update(); + return mi; + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/assets/MeshAsset.cpp b/runtime/render/adaptor/src/assets/MeshAsset.cpp new file mode 100644 index 00000000..a4f3527f --- /dev/null +++ b/runtime/render/adaptor/src/assets/MeshAsset.cpp @@ -0,0 +1,147 @@ +// +// Created by Zach Lee on 2023/2/26. +// + +#include +#include +#include +#include + +namespace sky { + void MeshAssetData::Load(BinaryInputArchive &archive) + { + archive.LoadValue(version); + archive.LoadValue(skeleton); + + uint32_t size = 0; + archive.LoadValue(size); + + // subMesh + subMeshes.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(reinterpret_cast(&subMeshes[i]), sizeof(SubMeshAssetData)); + } + + // buffers + archive.LoadValue(size); + buffers.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(buffers[i].type); + archive.LoadValue(buffers[i].offset); + archive.LoadValue(buffers[i].size); + archive.LoadValue(buffers[i].stride); + } + + // vertex streams + archive.LoadValue(size); + attributes.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(attributes[i].sematic); + archive.LoadValue(attributes[i].binding); + archive.LoadValue(attributes[i].offset); + archive.LoadValue(attributes[i].format); + archive.LoadValue(attributes[i].rate); + } + + // data size + archive.LoadValue(indexBuffer); + archive.LoadValue(indexType); + archive.LoadValue(dataSize); + dataOffset = static_cast(archive.GetStream().Tell()); + } + + void MeshAssetData::Save(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + archive.SaveValue(skeleton); + + // subMesh + archive.SaveValue(static_cast(subMeshes.size())); + for (const auto &subMesh : subMeshes) { + archive.SaveValue(reinterpret_cast(&subMesh), sizeof(SubMeshAssetData)); + } + + // primitives + archive.SaveValue(static_cast(buffers.size())); + for (const auto &primitive : buffers) { + archive.SaveValue(primitive.type); + archive.SaveValue(primitive.offset); + archive.SaveValue(primitive.size); + archive.SaveValue(primitive.stride); + } + + // vertex streams + archive.SaveValue(static_cast(attributes.size())); + for (const auto &stream : attributes) { + archive.SaveValue(stream.sematic); + archive.SaveValue(stream.binding); + archive.SaveValue(stream.offset); + archive.SaveValue(stream.format); + archive.SaveValue(stream.rate); + } + + // index + archive.SaveValue(indexBuffer); + archive.SaveValue(indexType); + + // data size + archive.SaveValue(dataSize); + + SKY_ASSERT(dataSize == static_cast(rawData.storage.size())); + + // save raw + archive.SaveValue(reinterpret_cast(rawData.storage.data()), dataSize); + } + + CounterPtr CreateMeshFromAsset(const MeshAssetPtr &asset) + { + const auto &data = asset->Data(); + const auto &uuid = asset->GetUuid(); + + auto *am = AssetManager::Get(); + auto file = am->OpenFile(uuid); + SKY_ASSERT(file); + + auto *mesh = new Mesh(); + for (const auto &sub : data.subMeshes) { + auto matAsset = am->FindAsset(sub.material); + auto mat = CreateMaterialInstanceFromAsset(matAsset); + + mesh->AddSubMesh(SubMesh { + sub.firstVertex, + sub.vertexCount, + sub.firstIndex, + sub.indexCount, + mat, + sub.aabb + }); + } + + mesh->SetVertexAttributes(data.attributes); + mesh->SetIndexType(data.indexType); + + MeshData meshData = {}; + auto *fileStream = new rhi::FileStream(file, data.dataOffset); + + for (const auto &buffer : data.buffers) { + rhi::BufferUploadRequest request = {}; + + request.source = fileStream; + request.offset = buffer.offset; + request.size = buffer.size; + meshData.vertexStreams.emplace_back(request, buffer.stride); + } + + if (data.indexType != rhi::IndexType::NONE) { + SKY_ASSERT(data.indexBuffer < data.buffers.size()); + rhi::BufferUploadRequest &request = meshData.indexStream; + const auto &buffer = data.buffers[data.indexBuffer]; + request.source = fileStream; + request.offset = buffer.offset; + request.size = buffer.size; + } + mesh->SetUploadStream(std::move(meshData)); + return mesh; + } + +} \ No newline at end of file diff --git a/runtime/render/adaptor/src/assets/RenderPrefab.cpp b/runtime/render/adaptor/src/assets/RenderPrefab.cpp new file mode 100644 index 00000000..930a0d46 --- /dev/null +++ b/runtime/render/adaptor/src/assets/RenderPrefab.cpp @@ -0,0 +1,69 @@ +// +// Created by Zach Lee on 2023/2/26. +// + +#include + +namespace sky { + void RenderPrefabAssetData::LoadBin(BinaryInputArchive &archive) + { + uint32_t size = 0; + archive.LoadValue(size); + nodes.resize(size); + for (uint32_t i = 0; i < size; ++i) { + auto &node = nodes[i]; + archive.LoadValue(reinterpret_cast(&node.mesh), sizeof(Uuid)); + archive.LoadValue(node.parentIndex); + archive.LoadValue(reinterpret_cast(&node.localTransform), sizeof(Transform)); + } + } + + void RenderPrefabAssetData::SaveBin(BinaryOutputArchive &archive) const + { + archive.SaveValue(static_cast(nodes.size())); + for (const auto &node : nodes) { + archive.SaveValue(reinterpret_cast(&node.mesh), sizeof(Uuid)); + archive.SaveValue(node.parentIndex); + archive.SaveValue(reinterpret_cast(&node.localTransform), sizeof(Transform)); + } + } + + void RenderPrefabAssetData::LoadJson(JsonInputArchive &archive) + { + + + } + + void RenderPrefabAssetData::SaveJson(JsonOutputArchive &archive) const + { + archive.StartObject(); + + archive.Key("nodes"); + archive.StartArray(); + + for (const auto &node : nodes) { + archive.StartObject(); + + archive.Key("translation"); + archive.SaveValueObject(node.localTransform.translation); + + archive.Key("rotation"); + archive.SaveValueObject(node.localTransform.rotation); + + archive.Key("scale"); + archive.SaveValueObject(node.localTransform.scale); + + archive.Key("mesh"); + archive.SaveValue(node.mesh.ToString()); + + archive.Key("parent"); + archive.SaveValue(node.parentIndex); + + archive.EndObject(); + } + + archive.EndArray(); + + archive.EndObject(); + } +} // namespace sky \ No newline at end of file diff --git a/render/adaptor/src/assets/ShaderAsset.cpp b/runtime/render/adaptor/src/assets/ShaderAsset.cpp similarity index 74% rename from render/adaptor/src/assets/ShaderAsset.cpp rename to runtime/render/adaptor/src/assets/ShaderAsset.cpp index 8758fd76..d0bd95b0 100644 --- a/render/adaptor/src/assets/ShaderAsset.cpp +++ b/runtime/render/adaptor/src/assets/ShaderAsset.cpp @@ -23,8 +23,9 @@ namespace sky { archive.SaveValue(hash); } - std::shared_ptr CreateShader(const ShaderAssetData &data) + CounterPtr CreateShaderFromAsset(const ShaderAssetPtr &asset) { - return std::make_shared(data.name, data.shaderSource, data.hash); + const auto &data = asset->Data(); + return new ShaderCollection(data.name, data.shaderSource, data.hash); } } diff --git a/runtime/render/adaptor/src/assets/SkeletonAsset.cpp b/runtime/render/adaptor/src/assets/SkeletonAsset.cpp new file mode 100644 index 00000000..8228566b --- /dev/null +++ b/runtime/render/adaptor/src/assets/SkeletonAsset.cpp @@ -0,0 +1,89 @@ +// +// Created by blues on 2024/8/10. +// + +#include + +namespace sky { + + uint32_t SkeletonAssetData::AdddBone(const std::string &name, const Matrix4 &matrix) + { + SKY_ASSERT(!nameToIndexMap.contains(name)) + + auto boneIndex = static_cast(nameToIndexMap.size()); + nameToIndexMap.emplace(name, boneIndex); + boneData.emplace_back(name, INVALID_BONE_ID); + inverseBindMatrix.emplace_back(matrix); + refPos.emplace_back(Transform::GetIdentity()); + return boneIndex; + } + + uint32_t SkeletonAssetData::FindBoneByName(const Name &name) const + { + auto iter = nameToIndexMap.find(name); + return iter != nameToIndexMap.end() ? iter->second : INVALID_BONE_ID; + } + + void SkeletonAssetData::Load(BinaryInputArchive &archive) + { + archive.LoadValue(version); + uint32_t count = 0; + + archive.LoadValue(count); + boneData.resize(count); + inverseBindMatrix.resize(count); + refPos.resize(count); + for (uint32_t i = 0; i < count; ++i) { + archive.LoadValue(boneData[i].parentIndex); + + } + + for (uint32_t i = 0; i < count; ++i) { + archive.LoadValue(reinterpret_cast(inverseBindMatrix[i].v), sizeof(Matrix4)); + } + + for (uint32_t i = 0; i < count; ++i) { + archive.LoadValue(reinterpret_cast(refPos[i].translation.v), sizeof(Vector3)); + archive.LoadValue(reinterpret_cast(refPos[i].rotation.v), sizeof(Quaternion)); + archive.LoadValue(reinterpret_cast(refPos[i].scale.v), sizeof(Vector3)); + } + + archive.LoadValue(count); + for (uint32_t i = 0; i < count; ++i) { + std::string name; + archive.LoadValue(name); + uint32_t boneIndex = 0; + archive.LoadValue(boneIndex); + + nameToIndexMap.emplace(name, boneIndex); + } + } + + void SkeletonAssetData::Save(BinaryOutputArchive &archive) const + { + archive.SaveValue(version); + + archive.SaveValue(static_cast(boneData.size())); + for (const auto &bone : boneData) { + archive.SaveValue(bone.parentIndex); + + } + + for (const auto &mtx : inverseBindMatrix) { + archive.SaveValue(reinterpret_cast(mtx.v), sizeof(Matrix4)); + } + + for (const auto &trans : refPos) { + archive.SaveValue(reinterpret_cast(trans.translation.v), sizeof(Vector3)); + archive.SaveValue(reinterpret_cast(trans.rotation.v), sizeof(Quaternion)); + archive.SaveValue(reinterpret_cast(trans.scale.v), sizeof(Vector3)); + } + + archive.SaveValue(static_cast(nameToIndexMap.size())); + for (const auto &[name, index] : nameToIndexMap) { + archive.SaveValue(name); + archive.SaveValue(index); + } + } + +} // namespace sky::adaptor \ No newline at end of file diff --git a/render/adaptor/src/assets/TechniqueAsset.cpp b/runtime/render/adaptor/src/assets/TechniqueAsset.cpp similarity index 62% rename from render/adaptor/src/assets/TechniqueAsset.cpp rename to runtime/render/adaptor/src/assets/TechniqueAsset.cpp index 629d06db..d916768b 100644 --- a/render/adaptor/src/assets/TechniqueAsset.cpp +++ b/runtime/render/adaptor/src/assets/TechniqueAsset.cpp @@ -9,13 +9,14 @@ namespace sky { void TechniqueAssetData::Load(BinaryInputArchive &archive) { - archive.LoadValue(shader.path); + archive.LoadValue(version); + archive.LoadValue(shader.shader.word[0]); + archive.LoadValue(shader.shader.word[1]); archive.LoadValue(shader.objectOrCSMain); archive.LoadValue(shader.vertOrMeshMain); archive.LoadValue(shader.fragmentMain); archive.LoadValue(passTag); - archive.LoadValue(vertexDesc); archive.LoadValue(type); archive.LoadValue(depthStencil.depthWrite); @@ -40,16 +41,31 @@ namespace sky { archive.LoadValue(blend.colorBlendOp); archive.LoadValue(blend.alphaBlendOp); } + + archive.LoadValue(size); + preDefines.resize(size); + for (uint32_t i = 0; i < size; ++i) { + archive.LoadValue(preDefines[i]); + } + + archive.LoadValue(size); + vertexFlags.resize(size); + for (uint32_t i = 0; i < size; ++i) { + auto &flag = vertexFlags[i]; + archive.LoadValue(flag.flag); + archive.LoadValue(flag.macro); + } } void TechniqueAssetData::Save(BinaryOutputArchive &archive) const { - archive.SaveValue(shader.path); + archive.SaveValue(version); + archive.SaveValue(shader.shader.word[0]); + archive.SaveValue(shader.shader.word[1]); archive.SaveValue(shader.objectOrCSMain); archive.SaveValue(shader.vertOrMeshMain); archive.SaveValue(shader.fragmentMain); archive.SaveValue(passTag); - archive.SaveValue(vertexDesc); archive.SaveValue(type); archive.SaveValue(depthStencil.depthWrite); @@ -71,26 +87,44 @@ namespace sky { archive.SaveValue(blend.colorBlendOp); archive.SaveValue(blend.alphaBlendOp); } + + archive.SaveValue(static_cast(preDefines.size())); + for (const auto &def : preDefines) { + archive.SaveValue(def); + } + + archive.SaveValue(static_cast(vertexFlags.size())); + for (const auto &flag : vertexFlags) { + archive.SaveValue(flag.flag); + archive.SaveValue(flag.macro); + } } - std::shared_ptr CreateTechnique(const TechniqueAssetData &data) + CounterPtr CreateTechniqueFromAsset(const TechniqueAssetPtr &asset) { + auto &data = asset->Data(); + if (data.type == TechAssetType::GRAPHIC) { - auto tech = std::make_shared(); + auto *tech = new GraphicsTechnique(); - auto shaderAsset = AssetManager::Get()->LoadAsset(data.shader.path); + auto shaderAsset = AssetManager::Get()->FindAsset(data.shader.shader); if (shaderAsset) { - tech->SetShader(ShaderRef{shaderAsset->CreateInstance(), data.shader.objectOrCSMain, data.shader.vertOrMeshMain, data.shader.fragmentMain}); + auto shader = CreateShaderFromAsset(shaderAsset); + tech->SetShader({shader, data.shader.objectOrCSMain, data.shader.vertOrMeshMain, data.shader.fragmentMain}); } tech->SetDepthStencil(data.depthStencil); tech->SetBlendState(data.blendStates); tech->SetRasterState(data.rasterState); tech->SetRasterTag(data.passTag); - tech->SetVertexLayout(data.vertexDesc); - return tech; } return nullptr; } + + CounterPtr GreateGfxTechFromAsset(const TechniqueAssetPtr &asset) + { + auto tech = CreateTechniqueFromAsset(asset); + return static_cast(tech.Get()); + } } diff --git a/runtime/render/adaptor/src/components/CameraComponent.cpp b/runtime/render/adaptor/src/components/CameraComponent.cpp new file mode 100644 index 00000000..60272f9c --- /dev/null +++ b/runtime/render/adaptor/src/components/CameraComponent.cpp @@ -0,0 +1,121 @@ +// +// Created by Zach Lee on 2021/12/1. +// + +#include +#include +#include +#include +#include + +#include +#include + +namespace sky { + CameraComponent::~CameraComponent() + { + ShutDown(); + } + + void CameraComponent::Reflect(SerializationContext *context) + { + context->Register("ProjectType") + .Enum(ProjectType::PROJECTIVE, "Projective") + .Enum(ProjectType::ORTHOGONAL, "Orthogonal"); + + context->Register("CameraComponent") + .Member<&CameraComponent::near>("near") + .Member<&CameraComponent::far>("far") + .Member<&CameraComponent::fov>("fov"); +// .Member<&CameraComponent::type>("type"); +// .Property(UI_PROP_VISIBLE, false); + } + + void CameraComponent::Perspective(float near_, float far_, float fov_) + { + near = near_; + far = far_; + fov = fov_; + type = ProjectType::PROJECTIVE; + } + + void CameraComponent::Otho(float h) + { + othoH = h; + type = ProjectType::ORTHOGONAL; + } + + void CameraComponent::SetAspect(uint32_t width_, uint32_t height_) + { + width = width_; + height = height_; + aspect = static_cast(width) / static_cast(height); + } + + void CameraComponent::Tick(float time) + { + auto *transform = actor->GetComponent(); + auto world = transform->GetWorldMatrix(); + sceneView->SetMatrix(world); + + if (type == ProjectType::PROJECTIVE) { + sceneView->SetPerspective(near, far, fov / 180.f * 3.14f, aspect); + } else { + const float x = othoH; + const float y = othoH; + sceneView->SetOrthogonal(-x, x, + y, -y, + near, far, 0); + } + } + + const Matrix4 &CameraComponent::GetProject() const + { + return sceneView != nullptr ? sceneView->GetProject() : Matrix4::Identity(); + } + + const Matrix4 &CameraComponent::GetView() const + { + return sceneView != nullptr ? sceneView->GetView() : Matrix4::Identity(); + } + + void CameraComponent::OnAttachToWorld() + { + sceneView = GetRenderSceneFromActor(actor)->CreateSceneView(1); + } + + void CameraComponent::OnDetachFromWorld() + { + ShutDown(); + } + + void CameraComponent::ShutDown() + { + if (sceneView != nullptr) { + GetRenderSceneFromActor(actor)->RemoveSceneView(sceneView); + sceneView = nullptr; + } + } + + void CameraComponent::SaveJson(JsonOutputArchive &ar) const + { + ar.StartObject(); + ar.SaveValueObject(std::string("near"), near); + ar.SaveValueObject(std::string("far"), far); + ar.SaveValueObject(std::string("fov"), fov); + ar.SaveValueObject(std::string("aspect"), aspect); + ar.SaveValueObject(std::string("othoH"), othoH); + ar.SaveValueObject(std::string("type"), type); + ar.EndObject(); + } + + void CameraComponent::LoadJson(JsonInputArchive &ar) + { + ar.LoadKeyValue("near", near); + ar.LoadKeyValue("far", far); + ar.LoadKeyValue("fov", fov); + ar.LoadKeyValue("aspect", aspect); + ar.LoadKeyValue("othoH", othoH); + ar.LoadKeyValue("type", type); + } +} // namespace sky diff --git a/runtime/render/adaptor/src/components/LightComponent.cpp b/runtime/render/adaptor/src/components/LightComponent.cpp new file mode 100644 index 00000000..096089d3 --- /dev/null +++ b/runtime/render/adaptor/src/components/LightComponent.cpp @@ -0,0 +1,60 @@ +// +// Created by Zach Lee on 2023/2/28. +// + +#include +#include +#include +#include +#include +#include + +namespace sky { + + void LightComponent::Reflect(SerializationContext *context) + { + context->Register("LightComponent") + .Member<&LightComponent::lightColor>("lightColor"); + } + + void LightComponent::Tick(float time) + { + if (light == nullptr) { + return; + } + + auto *transform = actor->GetComponent(); + auto world = Cast(transform->GetWorldMatrix()); + auto direct = world * (-VEC3_Z); + light->SetDirection(direct); + light->SetColor(Cast(lightColor)); + } + + void LightComponent::OnAttachToWorld() + { + SKY_ASSERT(light == nullptr); + auto *lf = GetFeatureProcessor(actor); + light = lf->CreateLight(); + } + + void LightComponent::OnDetachFromWorld() + { + SKY_ASSERT(light != nullptr); + auto *lf = GetFeatureProcessor(actor); + lf->RemoveLight(light); + } + + void LightComponent::SaveJson(JsonOutputArchive &ar) const + { + ar.StartObject(); + ar.SaveValueObject(std::string("lightColor"), lightColor); + ar.EndObject(); + } + + void LightComponent::LoadJson(JsonInputArchive &ar) + { + ar.LoadKeyValue("lightColor", lightColor); + } + + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/components/SkeletonMeshComponent.cpp b/runtime/render/adaptor/src/components/SkeletonMeshComponent.cpp new file mode 100644 index 00000000..6f3d978a --- /dev/null +++ b/runtime/render/adaptor/src/components/SkeletonMeshComponent.cpp @@ -0,0 +1,121 @@ +// +// Created by blues on 2024/8/11. +// + +#include +#include + +#include +#include +#include + +#include + +namespace sky { + SkeletonMeshComponent::~SkeletonMeshComponent() + { + ShutDown(); + } + + void SkeletonMeshComponent::Reflect(SerializationContext *context) + { + context->Register("SkeletonMeshComponent") + .Member<&SkeletonMeshComponent::SetMeshUuid, &SkeletonMeshComponent::GetMeshUuid>("mesh") + .Property(static_cast(CommonPropertyKey::ASSET_TYPE), Any(AssetTraits::ASSET_TYPE)); + } + + void SkeletonMeshComponent::Tick(float time) + { + if (dirty.load()) { + BuildRenderer(); + dirty.store(false); + } + + if (renderer != nullptr) { + auto *ts = actor->GetComponent(); + renderer->UpdateTransform(ts->GetWorldMatrix()); + } + } + + void SkeletonMeshComponent::BuildRenderer() + { + if (meshAsset) { + meshInstance = CreateMeshFromAsset(meshAsset); + } else { + meshInstance = nullptr; + } + + auto *mf = GetFeatureProcessor(actor); + + if (!meshInstance) { + if (renderer != nullptr) { + mf->RemoveStaticMesh(renderer); + } + renderer = nullptr; + return; + } + + if (renderer == nullptr) { + renderer = mf->CreateSkeletonMesh(); + } + renderer->SetMesh(meshInstance); + } + + void SkeletonMeshComponent::SaveJson(JsonOutputArchive &ar) const + { + ar.StartObject(); + ar.SaveValueObject(std::string("mesh"), meshAsset ? meshAsset->GetUuid() : Uuid()); + ar.EndObject(); + } + + void SkeletonMeshComponent::LoadJson(JsonInputArchive &ar) + { + Uuid uuid; + ar.LoadKeyValue("mesh", uuid); + SetMeshUuid(uuid); + } + + void SkeletonMeshComponent::OnAttachToWorld() + { + + } + + void SkeletonMeshComponent::OnDetachFromWorld() + { + ShutDown(); + } + + void SkeletonMeshComponent::SetMeshUuid(const Uuid &uuid) + { + const auto ¤t = meshAsset ? meshAsset->GetUuid() : Uuid::GetEmpty(); + if (current == uuid) { + return; + } + + if (uuid) { + binder.Bind(this, uuid); + } else { + binder.Reset(); + } + dirty.store(false); + + meshAsset = uuid ? AssetManager::Get()->LoadAsset(uuid) : MeshAssetPtr {}; + if (meshAsset && meshAsset->IsLoaded() && !dirty.load()) { + OnAssetLoaded(); + } + } + + void SkeletonMeshComponent::ShutDown() + { + if (renderer != nullptr) { + GetFeatureProcessor(actor)->RemoveStaticMesh(renderer); + renderer = nullptr; + } + } + + void SkeletonMeshComponent::OnAssetLoaded() + { + dirty.store(true); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/components/StaticMeshComponent.cpp b/runtime/render/adaptor/src/components/StaticMeshComponent.cpp new file mode 100644 index 00000000..a9c4f834 --- /dev/null +++ b/runtime/render/adaptor/src/components/StaticMeshComponent.cpp @@ -0,0 +1,130 @@ +// +// Created by Zach Lee on 2023/2/28. +// + +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace sky { + + StaticMeshComponent::~StaticMeshComponent() + { + ShutDown(); + } + + void StaticMeshComponent::Reflect(SerializationContext *context) + { + context->Register("StaticMeshComponent") + .Member<&StaticMeshComponent::isStatic>("static") + .Member<&StaticMeshComponent::SetMeshUuid, &StaticMeshComponent::GetMeshUuid>("mesh") + .Property(static_cast(CommonPropertyKey::ASSET_TYPE), Any(AssetTraits::ASSET_TYPE)); + } + + void StaticMeshComponent::SaveJson(JsonOutputArchive &ar) const + { + ar.StartObject(); + ar.SaveValueObject(std::string("static"), isStatic); + ar.SaveValueObject(std::string("castShadow"), castShadow); + ar.SaveValueObject(std::string("receiveShadow"), receiveShadow); + ar.SaveValueObject(std::string("mesh"), meshAsset ? meshAsset->GetUuid() : Uuid()); + ar.EndObject(); + } + + void StaticMeshComponent::LoadJson(JsonInputArchive &ar) + { + ar.LoadKeyValue("static", isStatic); + ar.LoadKeyValue("castShadow", castShadow); + ar.LoadKeyValue("receiveShadow", receiveShadow); + Uuid uuid; + ar.LoadKeyValue("mesh", uuid); + SetMeshUuid(uuid); + } + + void StaticMeshComponent::SetMeshUuid(const Uuid &uuid) + { + const auto ¤t = meshAsset ? meshAsset->GetUuid() : Uuid::GetEmpty(); + if (current == uuid) { + return; + } + + if (uuid) { + binder.Bind(this, uuid); + } else { + binder.Reset(); + } + dirty.store(false); + + meshAsset = uuid ? AssetManager::Get()->LoadAsset(uuid) : MeshAssetPtr {}; + if (meshAsset && meshAsset->IsLoaded() && !dirty.load()) { + OnAssetLoaded(); + } + } + + void StaticMeshComponent::BuildRenderer() + { + if (meshAsset) { + meshInstance = CreateMeshFromAsset(meshAsset); + } else { + meshInstance = nullptr; + } + + auto *mf = GetFeatureProcessor(actor); + + if (!meshInstance) { + if (renderer != nullptr) { + mf->RemoveStaticMesh(renderer); + } + renderer = nullptr; + return; + } + + if (renderer == nullptr) { + renderer = mf->CreateStaticMesh(); + } + renderer->SetMesh(meshInstance); + } + + void StaticMeshComponent::ShutDown() + { + if (renderer != nullptr) { + GetFeatureProcessor(actor)->RemoveStaticMesh(renderer); + renderer = nullptr; + } + } + + void StaticMeshComponent::OnAssetLoaded() + { + dirty.store(true); + } + + void StaticMeshComponent::Tick(float time) + { + if (dirty.load()) { + BuildRenderer(); + dirty.store(false); + } + + if (renderer != nullptr) { + auto *ts = actor->GetComponent(); + renderer->UpdateTransform(ts->GetWorldMatrix()); + } + } + + void StaticMeshComponent::OnAttachToWorld() + { + + } + + void StaticMeshComponent::OnDetachFromWorld() + { + ShutDown(); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/pipeline/DefaultForwardPipeline.cpp b/runtime/render/adaptor/src/pipeline/DefaultForwardPipeline.cpp new file mode 100644 index 00000000..b983d523 --- /dev/null +++ b/runtime/render/adaptor/src/pipeline/DefaultForwardPipeline.cpp @@ -0,0 +1,62 @@ +// +// Created by blues on 2024/9/6. +// + +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + void DefaultForwardPipeline::InitPass() + { + auto postTechAsset = AssetManager::Get()->LoadAssetFromPath("techniques/post_processing.tech"); + postTechAsset->BlockUntilLoaded(); + auto postTech = GreateGfxTechFromAsset(std::static_pointer_cast>(postTechAsset)); + + forward = std::make_unique(rhi::PixelFormat::RGBA16_SFLOAT, depthStencilFormat, rhi::SampleCount::X4); + postProcess = std::make_unique(postTech); + present = std::make_unique(output->GetSwapChain()); + } + + void DefaultForwardPipeline::SetOutput(RenderWindow *wnd) + { + output = wnd; + if (!RHI::Get()->GetDevice()->CheckFormatFeature(depthStencilFormat, rhi::PixelFormatFeatureFlagBit::DEPTH_STENCIL)) { + depthStencilFormat = rhi::PixelFormat::D32_S8; + } + + globalUbo = std::make_shared(); + globalUbo->Init(sizeof(ShaderPassInfo)); + + InitPass(); + } + + void DefaultForwardPipeline::Collect(rdg::RenderGraph &rdg) + { + const auto renderWidth = output->GetWidth(); + const auto renderHeight = output->GetHeight(); + + auto *sceneView = scene->GetSceneViews()[0].get(); + + const char* globalUboName = "globalUBO"; + const char* colorViewName = "SCENE_VIEW"; + + auto &rg = rdg.resourceGraph; + rg.ImportUBO(colorViewName, sceneView->GetUBO()); + rg.ImportUBO(globalUboName, globalUbo); + + forward->Resize(renderWidth, renderHeight); + AddPass(forward.get()); + + postProcess->Resize(renderWidth, renderHeight); + AddPass(postProcess.get()); + + AddPass(present.get()); + } + +} // namespace sky diff --git a/runtime/render/adaptor/src/pipeline/ForwardMSAAPass.cpp b/runtime/render/adaptor/src/pipeline/ForwardMSAAPass.cpp new file mode 100644 index 00000000..37956b3d --- /dev/null +++ b/runtime/render/adaptor/src/pipeline/ForwardMSAAPass.cpp @@ -0,0 +1,97 @@ +// +// Created by blues on 2024/9/3. +// + +#include +#include +#include +#include +#include + +namespace sky { + + ForwardMSAAPass::ForwardMSAAPass(rhi::PixelFormat format, rhi::PixelFormat ds, rhi::SampleCount samples_) + : RasterPass("ForwardMSAA") + , colorFormat(format) + , depthStenFormat(rhi::PixelFormat::D24_S8) + , samples(samples_) + { + rdg::GraphImage image = {}; + image.extent.width = width; + image.extent.height = height; + image.samples = samples; + image.usage = rhi::ImageUsageFlagBit::RENDER_TARGET; + image.format = colorFormat; + + images.emplace_back(FWD_MSAA_CL, image); + + image.samples = rhi::SampleCount::X1; + image.usage = rhi::ImageUsageFlagBit::RENDER_TARGET | rhi::ImageUsageFlagBit::SAMPLED; + images.emplace_back(FWD_CL, image); + + image.samples = samples; + image.usage = rhi::ImageUsageFlagBit::DEPTH_STENCIL; + image.format = depthStenFormat; + images.emplace_back(FWD_MSAA_DS, image); + + colors.emplace_back(Attachment{ + rdg::RasterAttachment{FWD_MSAA_CL.data(), rhi::LoadOp::CLEAR, rhi::StoreOp::DONT_CARE}, + rhi::ClearValue(0.2f, 0.2f, 0.2f, 0.f) + }); + + resolves.emplace_back(Attachment{ + rdg::RasterAttachment{FWD_CL.data(), rhi::LoadOp::DONT_CARE, rhi::StoreOp::STORE}, + rhi::ClearValue(0, 0, 0, 0) + }); + + depthStencil = Attachment{ + rdg::RasterAttachment{FWD_MSAA_DS.data(), rhi::LoadOp::CLEAR, rhi::StoreOp::DONT_CARE}, + rhi::ClearValue(1.f, 0) + }; + +// computeResources.emplace_back(ComputeResource{ +// FWD_CL.data(), +// rdg::ComputeView{"globalUBO", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS} +// }); + + computeResources.emplace_back(ComputeResource{ + "SCENE_VIEW", + rdg::ComputeView{"viewInfo", rdg::ComputeType::CBV, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS} + }); + + rhi::DescriptorSetLayout::Descriptor desc = {}; +// desc.bindings.emplace_back( +// rhi::DescriptorType::UNIFORM_BUFFER, 1, 0, rhi::ShaderStageFlagBit::FS, "passInfo"); + desc.bindings.emplace_back( + rhi::DescriptorType::UNIFORM_BUFFER, 1, 1, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS, "viewInfo"); +// desc.bindings.emplace_back( +// rhi::DescriptorType::SAMPLED_IMAGE, 1, 2, rhi::ShaderStageFlagBit::FS, "ShadowMap"); +// desc.bindings.emplace_back( +// rhi::DescriptorType::SAMPLER, 1, 3, rhi::ShaderStageFlagBit::FS, "ShadowMapSampler"); + + layout = new ResourceGroupLayout(); + layout->SetRHILayout(RHI::Get()->GetDevice()->CreateDescriptorSetLayout(desc)); + layout->AddNameHandler("passInfo", {0, sizeof(ShaderPassInfo)}); + layout->AddNameHandler("viewInfo", {1, sizeof(SceneViewInfo)}); +// layout->AddNameHandler("ShadowMap", {2}); +// layout->AddNameHandler("ShadowMapSampler", {3}); + } + + void ForwardMSAAPass::SetupSubPass(rdg::RasterSubPassBuilder& subPass, RenderScene &scene) + { + auto *sceneView = scene.GetSceneViews()[0].get(); + + subPass.SetViewMask(0); + + subPass.AddQueue("queue1") + .SetRasterID("ForwardColor") + .SetView(sceneView) + .SetLayout(layout); + + subPass.AddQueue("queue2") + .SetRasterID("SkyBox") + .SetView(sceneView) + .SetLayout(layout); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/pipeline/PostProcessingPass.cpp b/runtime/render/adaptor/src/pipeline/PostProcessingPass.cpp new file mode 100644 index 00000000..314c8e78 --- /dev/null +++ b/runtime/render/adaptor/src/pipeline/PostProcessingPass.cpp @@ -0,0 +1,35 @@ +// +// Created by blues on 2024/9/5. +// + +#include +#include +#include + +namespace sky { + + PostProcessingPass::PostProcessingPass(const RDGfxTechPtr &tech) + : FullScreenPass("PostProcessingPass", tech) + { + colors.emplace_back(Attachment{ + rdg::RasterAttachment{SWAP_CHAIN.data(), rhi::LoadOp::DONT_CARE, rhi::StoreOp::STORE}, + rhi::ClearValue(0, 0, 0, 0) + }); + + computeResources.emplace_back(ComputeResource{ + FWD_CL.data(), + rdg::ComputeView{"InColor", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS} + }); + } + + void PostProcessingPass::Setup(rdg::RenderGraph &rdg, RenderScene &scene) + { + FullScreenPass::Setup(rdg, scene); + } + + void PostProcessingPass::SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) + { + builder.AddQueue("queue").SetRasterID("ui"); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/pipeline/PresentPass.cpp b/runtime/render/adaptor/src/pipeline/PresentPass.cpp new file mode 100644 index 00000000..927d809a --- /dev/null +++ b/runtime/render/adaptor/src/pipeline/PresentPass.cpp @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/9/6. +// + +#include +#include +#include + +namespace sky { + + PresentPass::PresentPass(const rhi::SwapChainPtr &swc) // NOLINT + : PassBase("Present") + , swapChain(swc) + { + } + + void PresentPass::Prepare(rdg::RenderGraph &rdg, RenderScene &scene) + { + rdg.resourceGraph.ImportSwapChain(SWAP_CHAIN.data(), swapChain); + } + + void PresentPass::Setup(rdg::RenderGraph &rdg, RenderScene &scene) + { + rdg.AddPresentPass(name.c_str(), SWAP_CHAIN.data()); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/adaptor/src/pipeline/ShadowMapPass.cpp b/runtime/render/adaptor/src/pipeline/ShadowMapPass.cpp new file mode 100644 index 00000000..5f5d7aac --- /dev/null +++ b/runtime/render/adaptor/src/pipeline/ShadowMapPass.cpp @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/9/6. +// + +#include +#include + +namespace sky { + + ShadowMapPass::ShadowMapPass(uint32_t width_, uint32_t height_) + : RasterPass("ShadowMap") + { + width = width_; + height = height_; + + // TODO + Transform trans = {}; + trans.translation = Vector3(21, 28, -7); + trans.rotation.FromEulerYZX(Vector3(-50, 113, 0)); + +// shadowScene = scenes[0]->CreateSceneView(1); +// shadowScene->SetPerspective(1.f, 100.f, 75.f / 180.f * PI, 1.f); +// shadowScene->SetMatrix(trans.ToMatrix()); +// shadowScene->Update(); + + rdg::GraphImage image = {}; + image.extent.width = width; + image.extent.height = height; + image.usage = rhi::ImageUsageFlagBit::SAMPLED | rhi::ImageUsageFlagBit::DEPTH_STENCIL; + image.format = rhi::PixelFormat::D32; + + images.emplace_back(SHADOW_MAP, image); + } + + void ShadowMapPass::SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) + { + } +} // namespace sky \ No newline at end of file diff --git a/render/backend/rhi/CMakeLists.txt b/runtime/render/animation/CMakeLists.txt similarity index 77% rename from render/backend/rhi/CMakeLists.txt rename to runtime/render/animation/CMakeLists.txt index c753ccd7..f3386460 100644 --- a/render/backend/rhi/CMakeLists.txt +++ b/runtime/render/animation/CMakeLists.txt @@ -1,15 +1,14 @@ file(GLOB_RECURSE SRC_FILES src/*) file(GLOB_RECURSE INC_FILES include/*) -sky_add_library(TARGET RHI STATIC +sky_add_library(TARGET Animation STATIC SOURCES ${SRC_FILES} ${INC_FILES} - ${PLATFORM_SRC} PRIVATE_INC src PUBLIC_INC include LINK_LIBS Core - ) +) \ No newline at end of file diff --git a/runtime/render/animation/include/animation/core/Animation.h b/runtime/render/animation/include/animation/core/Animation.h new file mode 100644 index 00000000..85f11c69 --- /dev/null +++ b/runtime/render/animation/include/animation/core/Animation.h @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/8/2. +// + +#pragma once + +#include + +namespace sky { + + class Animation : public RefObject { + public: + Animation() = default; + ~Animation() override = default; + + virtual void Tick(float delta) = 0; + }; + + class SimpleAnimation : public Animation { + public: + SimpleAnimation() = default; + ~SimpleAnimation() override = default; + + protected: + void Tick(float delta) override {} + }; +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/core/AnimationChannel.h b/runtime/render/animation/include/animation/core/AnimationChannel.h new file mode 100644 index 00000000..ad633944 --- /dev/null +++ b/runtime/render/animation/include/animation/core/AnimationChannel.h @@ -0,0 +1,32 @@ +// +// Created by blues on 2024/8/1. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + struct AnimSampleResult : RefObject { + AnimSampleResult() = default; + ~AnimSampleResult() override = default; + }; + using AnimSampleResultPtr = CounterPtr; + + class AnimationChannel : public RefObject { + public: + explicit AnimationChannel(const Name &name_) : name(name_) {} // NOLINT + ~AnimationChannel() override = default; + + virtual void Sample(const SampleParam ¶m, const AnimSampleResultPtr &ptr) = 0; + protected: + Name name; + }; + + using AnimChannelPtr = CounterPtr; + +} // namespace sky diff --git a/runtime/render/animation/include/animation/core/AnimationClip.h b/runtime/render/animation/include/animation/core/AnimationClip.h new file mode 100644 index 00000000..56cc3e1e --- /dev/null +++ b/runtime/render/animation/include/animation/core/AnimationClip.h @@ -0,0 +1,25 @@ +// +// Created by blues on 2024/8/1. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class AnimationClip : public RefObject { + public: + explicit AnimationClip(const Name &name_) : name(name_) {} // NOLINT + ~AnimationClip() override = default; + + void AddChannel(const AnimChannelPtr &channel); + private: + Name name; + std::vector channels; + }; + using AnimClipPtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/core/AnimationInterpolation.h b/runtime/render/animation/include/animation/core/AnimationInterpolation.h new file mode 100644 index 00000000..c9308ad6 --- /dev/null +++ b/runtime/render/animation/include/animation/core/AnimationInterpolation.h @@ -0,0 +1,59 @@ +// +// Created by blues on 2024/8/15. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + /* + * https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.pdf : Appendix C + */ + + template + T AnimInterpolateLinear(const T &vk, const T &vk1, float t) + { + return (1 - t) * vk + t * vk1; + } + + Quaternion AnimSphericalLinear(const Quaternion &vk, const Quaternion &vk1, float t); + + template + T AnimSampleChannel(const AnimChannelData &data, const SampleParam ¶m) + { + SKY_ASSERT(data.time.size() == data.keys.size()); + SKY_ASSERT(!data.time.empty()); + + uint32_t k = 0; + for (k = 0; k < data.time.size(); ++k) { + if (param.timePoint < data.time[k]) { + break; + } + } + + const T vk1 = {}; + const T vk2 = {}; + float t = 0.f; + + switch (param.interpolation) { + case Interpolation::STEP: + return vk1; + break; + case Interpolation::CUBIC_SPLINE: // not supported yet. + case Interpolation::LINEAR: + if constexpr (std::is_same_v) { + return SphericalLinear(vk1, vk2, t); + } else { + return AnimInterpolateLinear(vk1, vk2, t); + } + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/core/AnimationNodeChannel.h b/runtime/render/animation/include/animation/core/AnimationNodeChannel.h new file mode 100644 index 00000000..9a48f30d --- /dev/null +++ b/runtime/render/animation/include/animation/core/AnimationNodeChannel.h @@ -0,0 +1,39 @@ +// +// Created by blues on 2024/8/10. +// + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace sky { + + struct AnimNodeChannelData { + Name name; + AnimChannelData position; + AnimChannelData scale; + AnimChannelData rotation; + }; + + class AnimationNodeChannel : public AnimationChannel { + public: + explicit AnimationNodeChannel(const Name &name) : AnimationChannel(name) {} + explicit AnimationNodeChannel(const AnimNodeChannelData &data_); + + ~AnimationNodeChannel() override = default; + + void Sample(const SampleParam ¶m, const AnimSampleResultPtr &ptr) override; + private: + AnimChannelData position; + AnimChannelData scale; + AnimChannelData rotation; + }; + using AnimNodeChannelPtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/core/AnimationTypes.h b/runtime/render/animation/include/animation/core/AnimationTypes.h new file mode 100644 index 00000000..ddb132e8 --- /dev/null +++ b/runtime/render/animation/include/animation/core/AnimationTypes.h @@ -0,0 +1,27 @@ +// +// Created by blues on 2024/8/1. +// + +#pragma once + +#include + +namespace sky { + + enum class Interpolation { + LINEAR, + STEP, + CUBIC_SPLINE, + }; + + struct SampleParam { + float timePoint = 0.f; + Interpolation interpolation; + }; + + template + struct AnimChannelData { + std::vector time; + std::vector keys; + }; +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/skeleton/Pose.h b/runtime/render/animation/include/animation/skeleton/Pose.h new file mode 100644 index 00000000..515df35d --- /dev/null +++ b/runtime/render/animation/include/animation/skeleton/Pose.h @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/8/10. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class PoseBase : public RefObject { + public: + explicit PoseBase(std::vector transforms) : bones(std::move(transforms)) {} + ~PoseBase() override = default; + + private: + std::vector bones; + }; + using PosePtr = CounterPtr; + +} // namespace sky diff --git a/runtime/render/animation/include/animation/skeleton/PoseSolver.h b/runtime/render/animation/include/animation/skeleton/PoseSolver.h new file mode 100644 index 00000000..206ec4cd --- /dev/null +++ b/runtime/render/animation/include/animation/skeleton/PoseSolver.h @@ -0,0 +1,30 @@ +// +// Created by blues on 2024/8/30. +// + +#pragma once + +#include +#include +#include + +namespace sky { + class BoneSolver { + public: + explicit BoneSolver(const AnimNodeChannelPtr &channel_) : channel(channel_) {} // NOLINT + ~BoneSolver() = default; + + private: + AnimNodeChannelPtr channel; + }; + + class PoseSolver { + public: + explicit PoseSolver(const PosePtr &pose_) : pose(pose_) {} // NOLINT + ~PoseSolver() = default; + + private: + PosePtr pose; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/skeleton/Skeleton.h b/runtime/render/animation/include/animation/skeleton/Skeleton.h new file mode 100644 index 00000000..c9ecee4f --- /dev/null +++ b/runtime/render/animation/include/animation/skeleton/Skeleton.h @@ -0,0 +1,46 @@ +// +// Created by blues on 2024/8/1. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + static const uint32_t INVALID_BONE_ID = ~(0U); + + struct BoneData { + Name name; + uint32_t parentIndex = INVALID_BONE_ID; + }; + + struct SkeletonData { + std::vector boneData; + std::vector inverseBindMatrix; + std::vector refPos; + std::unordered_map nameToIndexMap; + }; + + class Skeleton : public RefObject { + public: + Skeleton() = default; + ~Skeleton() override = default; + + private: + PosePtr refPose; + + std::vector boneData; + std::vector inverseBindMatrix; + std::unordered_map nameToIndexMap; + }; + using SkeletonPtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/include/animation/skeleton/SkeletonAnimation.h b/runtime/render/animation/include/animation/skeleton/SkeletonAnimation.h new file mode 100644 index 00000000..ac491271 --- /dev/null +++ b/runtime/render/animation/include/animation/skeleton/SkeletonAnimation.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/8/30. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class SkeletonAnimation : public Animation { + public: + SkeletonAnimation() = default; + ~SkeletonAnimation() override = default; + + private: + void Tick(float delta) override; + + AnimClipPtr clip; + SkeletonPtr skeleton; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/croe/Animation.cpp b/runtime/render/animation/src/croe/Animation.cpp new file mode 100644 index 00000000..94d9d1fb --- /dev/null +++ b/runtime/render/animation/src/croe/Animation.cpp @@ -0,0 +1,11 @@ +// +// Created by blues on 2024/8/2. +// + +#include + +namespace sky { + + + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/croe/AnimationChannel.cpp b/runtime/render/animation/src/croe/AnimationChannel.cpp new file mode 100644 index 00000000..b5860ecd --- /dev/null +++ b/runtime/render/animation/src/croe/AnimationChannel.cpp @@ -0,0 +1,10 @@ +// +// Created by blues on 2024/8/1. +// + +#include + +namespace sky { + + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/croe/AnimationClip.cpp b/runtime/render/animation/src/croe/AnimationClip.cpp new file mode 100644 index 00000000..5140e607 --- /dev/null +++ b/runtime/render/animation/src/croe/AnimationClip.cpp @@ -0,0 +1,14 @@ +// +// Created by blues on 2024/8/1. +// + +#include + +namespace sky { + + void AnimationClip::AddChannel(const AnimChannelPtr &channel) + { + channels.emplace_back(channel); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/croe/AnimationInterpolation.cpp b/runtime/render/animation/src/croe/AnimationInterpolation.cpp new file mode 100644 index 00000000..bf3ee3bd --- /dev/null +++ b/runtime/render/animation/src/croe/AnimationInterpolation.cpp @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/8/15. +// + +#include + +namespace sky { + + Quaternion AnimSphericalLinear(const Quaternion &vk, const Quaternion &vk1, float t) + { + float d = vk.Dot(vk1); + float sign = FloatSelect(d, 1.f, -1.f); + d *= sign; + + float k1 = 1 - t; + float k2 = sign * t; + + if (d < 0.9999) { + const float a = acos(sign * d); + const float invS = 1.f / sin(a); + k1 = sin(a * (1 - t)) * invS; + k2 = sin(a * t) * invS * sign; + } + + return { + k1 * vk.x + k2 * vk1.x, + k1 * vk.w + k2 * vk1.w, + k1 * vk.z + k2 * vk1.z, + k1 * vk.w + k2 * vk1.w + }; + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/croe/AnimationNodeChannel.cpp b/runtime/render/animation/src/croe/AnimationNodeChannel.cpp new file mode 100644 index 00000000..70c8129a --- /dev/null +++ b/runtime/render/animation/src/croe/AnimationNodeChannel.cpp @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/8/11. +// + +#include + +namespace sky { + + AnimationNodeChannel::AnimationNodeChannel(const AnimNodeChannelData &data) + : AnimationChannel(data.name) + , position(data.position) + , scale(data.scale) + , rotation(data.rotation) + { + } + + void AnimationNodeChannel::Sample(const SampleParam ¶m, const AnimSampleResultPtr &ptr) + { + + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/skeleton/PoseSolver.cpp b/runtime/render/animation/src/skeleton/PoseSolver.cpp new file mode 100644 index 00000000..6a580f78 --- /dev/null +++ b/runtime/render/animation/src/skeleton/PoseSolver.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/8/30. +// + +#include + +namespace sky { + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/animation/src/skeleton/Skeleton.cpp b/runtime/render/animation/src/skeleton/Skeleton.cpp new file mode 100644 index 00000000..7cfbadcd --- /dev/null +++ b/runtime/render/animation/src/skeleton/Skeleton.cpp @@ -0,0 +1,12 @@ +// +// Created by blues on 2024/8/1. +// + +#include +#include + +namespace sky { + + + +} // namespace sky diff --git a/runtime/render/animation/src/skeleton/SkeletonAnimation.cpp b/runtime/render/animation/src/skeleton/SkeletonAnimation.cpp new file mode 100644 index 00000000..abf207f9 --- /dev/null +++ b/runtime/render/animation/src/skeleton/SkeletonAnimation.cpp @@ -0,0 +1,14 @@ +// +// Created by blues on 2024/8/30. +// + +#include + +namespace sky { + + void SkeletonAnimation::Tick(float delta) + { + + } + +} // namespace sky \ No newline at end of file diff --git a/render/backend/CMakeLists.txt b/runtime/render/backend/CMakeLists.txt similarity index 100% rename from render/backend/CMakeLists.txt rename to runtime/render/backend/CMakeLists.txt diff --git a/render/backend/dx12/CMakeLists.txt b/runtime/render/backend/dx12/CMakeLists.txt similarity index 100% rename from render/backend/dx12/CMakeLists.txt rename to runtime/render/backend/dx12/CMakeLists.txt diff --git a/render/backend/dx12/include/dx12/Base.h b/runtime/render/backend/dx12/include/dx12/Base.h similarity index 100% rename from render/backend/dx12/include/dx12/Base.h rename to runtime/render/backend/dx12/include/dx12/Base.h diff --git a/render/backend/dx12/include/dx12/Buffer.h b/runtime/render/backend/dx12/include/dx12/Buffer.h similarity index 100% rename from render/backend/dx12/include/dx12/Buffer.h rename to runtime/render/backend/dx12/include/dx12/Buffer.h diff --git a/render/backend/dx12/include/dx12/CommandBuffer.h b/runtime/render/backend/dx12/include/dx12/CommandBuffer.h similarity index 100% rename from render/backend/dx12/include/dx12/CommandBuffer.h rename to runtime/render/backend/dx12/include/dx12/CommandBuffer.h diff --git a/render/backend/dx12/include/dx12/CommandPool.h b/runtime/render/backend/dx12/include/dx12/CommandPool.h similarity index 100% rename from render/backend/dx12/include/dx12/CommandPool.h rename to runtime/render/backend/dx12/include/dx12/CommandPool.h diff --git a/render/backend/dx12/include/dx12/Conversion.h b/runtime/render/backend/dx12/include/dx12/Conversion.h similarity index 100% rename from render/backend/dx12/include/dx12/Conversion.h rename to runtime/render/backend/dx12/include/dx12/Conversion.h diff --git a/render/backend/dx12/include/dx12/DescriptorSetLayout.h b/runtime/render/backend/dx12/include/dx12/DescriptorSetLayout.h similarity index 100% rename from render/backend/dx12/include/dx12/DescriptorSetLayout.h rename to runtime/render/backend/dx12/include/dx12/DescriptorSetLayout.h diff --git a/render/backend/dx12/include/dx12/DescriptorSetPool.h b/runtime/render/backend/dx12/include/dx12/DescriptorSetPool.h similarity index 100% rename from render/backend/dx12/include/dx12/DescriptorSetPool.h rename to runtime/render/backend/dx12/include/dx12/DescriptorSetPool.h diff --git a/render/backend/dx12/include/dx12/DevObject.h b/runtime/render/backend/dx12/include/dx12/DevObject.h similarity index 100% rename from render/backend/dx12/include/dx12/DevObject.h rename to runtime/render/backend/dx12/include/dx12/DevObject.h diff --git a/render/backend/dx12/include/dx12/Device.h b/runtime/render/backend/dx12/include/dx12/Device.h similarity index 100% rename from render/backend/dx12/include/dx12/Device.h rename to runtime/render/backend/dx12/include/dx12/Device.h diff --git a/render/backend/dx12/include/dx12/GraphicsPipeline.h b/runtime/render/backend/dx12/include/dx12/GraphicsPipeline.h similarity index 100% rename from render/backend/dx12/include/dx12/GraphicsPipeline.h rename to runtime/render/backend/dx12/include/dx12/GraphicsPipeline.h diff --git a/render/backend/dx12/include/dx12/Image.h b/runtime/render/backend/dx12/include/dx12/Image.h similarity index 100% rename from render/backend/dx12/include/dx12/Image.h rename to runtime/render/backend/dx12/include/dx12/Image.h diff --git a/render/backend/dx12/include/dx12/ImageView.h b/runtime/render/backend/dx12/include/dx12/ImageView.h similarity index 100% rename from render/backend/dx12/include/dx12/ImageView.h rename to runtime/render/backend/dx12/include/dx12/ImageView.h diff --git a/render/backend/dx12/include/dx12/Instance.h b/runtime/render/backend/dx12/include/dx12/Instance.h similarity index 100% rename from render/backend/dx12/include/dx12/Instance.h rename to runtime/render/backend/dx12/include/dx12/Instance.h diff --git a/render/backend/dx12/include/dx12/PipelineLayout.h b/runtime/render/backend/dx12/include/dx12/PipelineLayout.h similarity index 100% rename from render/backend/dx12/include/dx12/PipelineLayout.h rename to runtime/render/backend/dx12/include/dx12/PipelineLayout.h diff --git a/render/backend/dx12/include/dx12/PipelineLibrary.h b/runtime/render/backend/dx12/include/dx12/PipelineLibrary.h similarity index 100% rename from render/backend/dx12/include/dx12/PipelineLibrary.h rename to runtime/render/backend/dx12/include/dx12/PipelineLibrary.h diff --git a/render/backend/dx12/include/dx12/Queue.h b/runtime/render/backend/dx12/include/dx12/Queue.h similarity index 100% rename from render/backend/dx12/include/dx12/Queue.h rename to runtime/render/backend/dx12/include/dx12/Queue.h diff --git a/render/backend/dx12/include/dx12/RenderPass.h b/runtime/render/backend/dx12/include/dx12/RenderPass.h similarity index 100% rename from render/backend/dx12/include/dx12/RenderPass.h rename to runtime/render/backend/dx12/include/dx12/RenderPass.h diff --git a/render/backend/dx12/include/dx12/Shader.h b/runtime/render/backend/dx12/include/dx12/Shader.h similarity index 100% rename from render/backend/dx12/include/dx12/Shader.h rename to runtime/render/backend/dx12/include/dx12/Shader.h diff --git a/render/backend/dx12/include/dx12/Swapchain.h b/runtime/render/backend/dx12/include/dx12/Swapchain.h similarity index 100% rename from render/backend/dx12/include/dx12/Swapchain.h rename to runtime/render/backend/dx12/include/dx12/Swapchain.h diff --git a/render/backend/dx12/include/dx12/VertexInput.h b/runtime/render/backend/dx12/include/dx12/VertexInput.h similarity index 100% rename from render/backend/dx12/include/dx12/VertexInput.h rename to runtime/render/backend/dx12/include/dx12/VertexInput.h diff --git a/render/backend/dx12/src/Buffer.cpp b/runtime/render/backend/dx12/src/Buffer.cpp similarity index 100% rename from render/backend/dx12/src/Buffer.cpp rename to runtime/render/backend/dx12/src/Buffer.cpp diff --git a/render/backend/dx12/src/CommandBuffer.cpp b/runtime/render/backend/dx12/src/CommandBuffer.cpp similarity index 100% rename from render/backend/dx12/src/CommandBuffer.cpp rename to runtime/render/backend/dx12/src/CommandBuffer.cpp diff --git a/render/backend/dx12/src/CommandPool.cpp b/runtime/render/backend/dx12/src/CommandPool.cpp similarity index 100% rename from render/backend/dx12/src/CommandPool.cpp rename to runtime/render/backend/dx12/src/CommandPool.cpp diff --git a/render/backend/dx12/src/Conversion.cpp b/runtime/render/backend/dx12/src/Conversion.cpp similarity index 97% rename from render/backend/dx12/src/Conversion.cpp rename to runtime/render/backend/dx12/src/Conversion.cpp index 3a8ef944..10e82e6b 100644 --- a/render/backend/dx12/src/Conversion.cpp +++ b/runtime/render/backend/dx12/src/Conversion.cpp @@ -47,9 +47,10 @@ namespace sky::dx { {rhi::Format::F_RG32, DXGI_FORMAT_R32G32_FLOAT}, {rhi::Format::F_RGB32, DXGI_FORMAT_R32G32B32_FLOAT}, {rhi::Format::F_RGBA32, DXGI_FORMAT_R32G32B32A32_FLOAT}, - {rhi::Format::F_R8, DXGI_FORMAT_R8_UNORM}, - {rhi::Format::F_RG8, DXGI_FORMAT_R8G8_UNORM}, - {rhi::Format::F_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM}, + {rhi::Format::U_R32, DXGI_FORMAT_R32_UINT}, + {rhi::Format::U_RG32, DXGI_FORMAT_R32G32_UINT}, + {rhi::Format::U_RGB32, DXGI_FORMAT_R32G32B32_UINT}, + {rhi::Format::U_RGBA32, DXGI_FORMAT_R32G32B32A32_UINT}, }; D3D12_BLEND BLEND_MAP[] = { diff --git a/render/backend/dx12/src/DescriptorSetLayout.cpp b/runtime/render/backend/dx12/src/DescriptorSetLayout.cpp similarity index 100% rename from render/backend/dx12/src/DescriptorSetLayout.cpp rename to runtime/render/backend/dx12/src/DescriptorSetLayout.cpp diff --git a/render/backend/dx12/src/DescriptorSetPool.cpp b/runtime/render/backend/dx12/src/DescriptorSetPool.cpp similarity index 100% rename from render/backend/dx12/src/DescriptorSetPool.cpp rename to runtime/render/backend/dx12/src/DescriptorSetPool.cpp diff --git a/render/backend/dx12/src/Device.cpp b/runtime/render/backend/dx12/src/Device.cpp similarity index 100% rename from render/backend/dx12/src/Device.cpp rename to runtime/render/backend/dx12/src/Device.cpp diff --git a/render/backend/dx12/src/GraphicsPipeline.cpp b/runtime/render/backend/dx12/src/GraphicsPipeline.cpp similarity index 100% rename from render/backend/dx12/src/GraphicsPipeline.cpp rename to runtime/render/backend/dx12/src/GraphicsPipeline.cpp diff --git a/render/backend/dx12/src/Image.cpp b/runtime/render/backend/dx12/src/Image.cpp similarity index 100% rename from render/backend/dx12/src/Image.cpp rename to runtime/render/backend/dx12/src/Image.cpp diff --git a/render/backend/dx12/src/ImageView.cpp b/runtime/render/backend/dx12/src/ImageView.cpp similarity index 100% rename from render/backend/dx12/src/ImageView.cpp rename to runtime/render/backend/dx12/src/ImageView.cpp diff --git a/render/backend/dx12/src/Instance.cpp b/runtime/render/backend/dx12/src/Instance.cpp similarity index 100% rename from render/backend/dx12/src/Instance.cpp rename to runtime/render/backend/dx12/src/Instance.cpp diff --git a/render/backend/dx12/src/PipelineLayout.cpp b/runtime/render/backend/dx12/src/PipelineLayout.cpp similarity index 100% rename from render/backend/dx12/src/PipelineLayout.cpp rename to runtime/render/backend/dx12/src/PipelineLayout.cpp diff --git a/render/backend/dx12/src/PipelineLibrary.cpp b/runtime/render/backend/dx12/src/PipelineLibrary.cpp similarity index 100% rename from render/backend/dx12/src/PipelineLibrary.cpp rename to runtime/render/backend/dx12/src/PipelineLibrary.cpp diff --git a/render/backend/dx12/src/Queue.cpp b/runtime/render/backend/dx12/src/Queue.cpp similarity index 100% rename from render/backend/dx12/src/Queue.cpp rename to runtime/render/backend/dx12/src/Queue.cpp diff --git a/render/backend/dx12/src/RenderPass.cpp b/runtime/render/backend/dx12/src/RenderPass.cpp similarity index 100% rename from render/backend/dx12/src/RenderPass.cpp rename to runtime/render/backend/dx12/src/RenderPass.cpp diff --git a/render/backend/dx12/src/Shader.cpp b/runtime/render/backend/dx12/src/Shader.cpp similarity index 100% rename from render/backend/dx12/src/Shader.cpp rename to runtime/render/backend/dx12/src/Shader.cpp diff --git a/render/backend/dx12/src/Swapchain.cpp b/runtime/render/backend/dx12/src/Swapchain.cpp similarity index 100% rename from render/backend/dx12/src/Swapchain.cpp rename to runtime/render/backend/dx12/src/Swapchain.cpp diff --git a/render/backend/dx12/src/VertexInput.cpp b/runtime/render/backend/dx12/src/VertexInput.cpp similarity index 100% rename from render/backend/dx12/src/VertexInput.cpp rename to runtime/render/backend/dx12/src/VertexInput.cpp diff --git a/render/backend/gles/CMakeLists.txt b/runtime/render/backend/gles/CMakeLists.txt similarity index 100% rename from render/backend/gles/CMakeLists.txt rename to runtime/render/backend/gles/CMakeLists.txt diff --git a/render/backend/gles/Export.cpp b/runtime/render/backend/gles/Export.cpp similarity index 100% rename from render/backend/gles/Export.cpp rename to runtime/render/backend/gles/Export.cpp diff --git a/render/backend/gles/include/gles/Buffer.h b/runtime/render/backend/gles/include/gles/Buffer.h similarity index 100% rename from render/backend/gles/include/gles/Buffer.h rename to runtime/render/backend/gles/include/gles/Buffer.h diff --git a/render/backend/gles/include/gles/BufferView.h b/runtime/render/backend/gles/include/gles/BufferView.h similarity index 100% rename from render/backend/gles/include/gles/BufferView.h rename to runtime/render/backend/gles/include/gles/BufferView.h diff --git a/render/backend/gles/include/gles/CommandBuffer.h b/runtime/render/backend/gles/include/gles/CommandBuffer.h similarity index 100% rename from render/backend/gles/include/gles/CommandBuffer.h rename to runtime/render/backend/gles/include/gles/CommandBuffer.h diff --git a/render/backend/gles/include/gles/CommandContext.h b/runtime/render/backend/gles/include/gles/CommandContext.h similarity index 100% rename from render/backend/gles/include/gles/CommandContext.h rename to runtime/render/backend/gles/include/gles/CommandContext.h diff --git a/render/backend/gles/include/gles/Conversion.h b/runtime/render/backend/gles/include/gles/Conversion.h similarity index 100% rename from render/backend/gles/include/gles/Conversion.h rename to runtime/render/backend/gles/include/gles/Conversion.h diff --git a/render/backend/gles/include/gles/Core.h b/runtime/render/backend/gles/include/gles/Core.h similarity index 100% rename from render/backend/gles/include/gles/Core.h rename to runtime/render/backend/gles/include/gles/Core.h diff --git a/render/backend/gles/include/gles/DescriptorSet.h b/runtime/render/backend/gles/include/gles/DescriptorSet.h similarity index 100% rename from render/backend/gles/include/gles/DescriptorSet.h rename to runtime/render/backend/gles/include/gles/DescriptorSet.h diff --git a/render/backend/gles/include/gles/DescriptorSetLayout.h b/runtime/render/backend/gles/include/gles/DescriptorSetLayout.h similarity index 100% rename from render/backend/gles/include/gles/DescriptorSetLayout.h rename to runtime/render/backend/gles/include/gles/DescriptorSetLayout.h diff --git a/render/backend/gles/include/gles/DescriptorSetPool.h b/runtime/render/backend/gles/include/gles/DescriptorSetPool.h similarity index 100% rename from render/backend/gles/include/gles/DescriptorSetPool.h rename to runtime/render/backend/gles/include/gles/DescriptorSetPool.h diff --git a/render/backend/gles/include/gles/DevObject.h b/runtime/render/backend/gles/include/gles/DevObject.h similarity index 100% rename from render/backend/gles/include/gles/DevObject.h rename to runtime/render/backend/gles/include/gles/DevObject.h diff --git a/render/backend/gles/include/gles/Device.h b/runtime/render/backend/gles/include/gles/Device.h similarity index 100% rename from render/backend/gles/include/gles/Device.h rename to runtime/render/backend/gles/include/gles/Device.h diff --git a/render/backend/gles/include/gles/Ext.h b/runtime/render/backend/gles/include/gles/Ext.h similarity index 100% rename from render/backend/gles/include/gles/Ext.h rename to runtime/render/backend/gles/include/gles/Ext.h diff --git a/render/backend/gles/include/gles/Fence.h b/runtime/render/backend/gles/include/gles/Fence.h similarity index 100% rename from render/backend/gles/include/gles/Fence.h rename to runtime/render/backend/gles/include/gles/Fence.h diff --git a/render/backend/gles/include/gles/Forward.h b/runtime/render/backend/gles/include/gles/Forward.h similarity index 100% rename from render/backend/gles/include/gles/Forward.h rename to runtime/render/backend/gles/include/gles/Forward.h diff --git a/render/backend/gles/include/gles/FrameBuffer.h b/runtime/render/backend/gles/include/gles/FrameBuffer.h similarity index 100% rename from render/backend/gles/include/gles/FrameBuffer.h rename to runtime/render/backend/gles/include/gles/FrameBuffer.h diff --git a/render/backend/gles/include/gles/FrameBufferBlitHelper.h b/runtime/render/backend/gles/include/gles/FrameBufferBlitHelper.h similarity index 100% rename from render/backend/gles/include/gles/FrameBufferBlitHelper.h rename to runtime/render/backend/gles/include/gles/FrameBufferBlitHelper.h diff --git a/render/backend/gles/include/gles/FrameBufferObject.h b/runtime/render/backend/gles/include/gles/FrameBufferObject.h similarity index 100% rename from render/backend/gles/include/gles/FrameBufferObject.h rename to runtime/render/backend/gles/include/gles/FrameBufferObject.h diff --git a/render/backend/gles/include/gles/GraphicsPipeline.h b/runtime/render/backend/gles/include/gles/GraphicsPipeline.h similarity index 100% rename from render/backend/gles/include/gles/GraphicsPipeline.h rename to runtime/render/backend/gles/include/gles/GraphicsPipeline.h diff --git a/render/backend/gles/include/gles/Image.h b/runtime/render/backend/gles/include/gles/Image.h similarity index 100% rename from render/backend/gles/include/gles/Image.h rename to runtime/render/backend/gles/include/gles/Image.h diff --git a/render/backend/gles/include/gles/ImageView.h b/runtime/render/backend/gles/include/gles/ImageView.h similarity index 100% rename from render/backend/gles/include/gles/ImageView.h rename to runtime/render/backend/gles/include/gles/ImageView.h diff --git a/render/backend/gles/include/gles/Instance.h b/runtime/render/backend/gles/include/gles/Instance.h similarity index 100% rename from render/backend/gles/include/gles/Instance.h rename to runtime/render/backend/gles/include/gles/Instance.h diff --git a/render/backend/gles/include/gles/PipelineLayout.h b/runtime/render/backend/gles/include/gles/PipelineLayout.h similarity index 100% rename from render/backend/gles/include/gles/PipelineLayout.h rename to runtime/render/backend/gles/include/gles/PipelineLayout.h diff --git a/render/backend/gles/include/gles/PipelineStateCache.h b/runtime/render/backend/gles/include/gles/PipelineStateCache.h similarity index 100% rename from render/backend/gles/include/gles/PipelineStateCache.h rename to runtime/render/backend/gles/include/gles/PipelineStateCache.h diff --git a/render/backend/gles/include/gles/QueryPool.h b/runtime/render/backend/gles/include/gles/QueryPool.h similarity index 100% rename from render/backend/gles/include/gles/QueryPool.h rename to runtime/render/backend/gles/include/gles/QueryPool.h diff --git a/render/backend/gles/include/gles/Queue.h b/runtime/render/backend/gles/include/gles/Queue.h similarity index 100% rename from render/backend/gles/include/gles/Queue.h rename to runtime/render/backend/gles/include/gles/Queue.h diff --git a/render/backend/gles/include/gles/RenderPass.h b/runtime/render/backend/gles/include/gles/RenderPass.h similarity index 100% rename from render/backend/gles/include/gles/RenderPass.h rename to runtime/render/backend/gles/include/gles/RenderPass.h diff --git a/render/backend/gles/include/gles/Sampler.h b/runtime/render/backend/gles/include/gles/Sampler.h similarity index 100% rename from render/backend/gles/include/gles/Sampler.h rename to runtime/render/backend/gles/include/gles/Sampler.h diff --git a/render/backend/gles/include/gles/Semaphore.h b/runtime/render/backend/gles/include/gles/Semaphore.h similarity index 100% rename from render/backend/gles/include/gles/Semaphore.h rename to runtime/render/backend/gles/include/gles/Semaphore.h diff --git a/render/backend/gles/include/gles/Shader.h b/runtime/render/backend/gles/include/gles/Shader.h similarity index 100% rename from render/backend/gles/include/gles/Shader.h rename to runtime/render/backend/gles/include/gles/Shader.h diff --git a/render/backend/gles/include/gles/Swapchain.h b/runtime/render/backend/gles/include/gles/Swapchain.h similarity index 100% rename from render/backend/gles/include/gles/Swapchain.h rename to runtime/render/backend/gles/include/gles/Swapchain.h diff --git a/render/backend/gles/include/gles/VertexAssembly.h b/runtime/render/backend/gles/include/gles/VertexAssembly.h similarity index 100% rename from render/backend/gles/include/gles/VertexAssembly.h rename to runtime/render/backend/gles/include/gles/VertexAssembly.h diff --git a/render/backend/gles/include/gles/VertexInput.h b/runtime/render/backend/gles/include/gles/VertexInput.h similarity index 100% rename from render/backend/gles/include/gles/VertexInput.h rename to runtime/render/backend/gles/include/gles/VertexInput.h diff --git a/render/backend/gles/include/gles/egl/Config.h b/runtime/render/backend/gles/include/gles/egl/Config.h similarity index 100% rename from render/backend/gles/include/gles/egl/Config.h rename to runtime/render/backend/gles/include/gles/egl/Config.h diff --git a/render/backend/gles/include/gles/egl/Context.h b/runtime/render/backend/gles/include/gles/egl/Context.h similarity index 100% rename from render/backend/gles/include/gles/egl/Context.h rename to runtime/render/backend/gles/include/gles/egl/Context.h diff --git a/render/backend/gles/include/gles/egl/PBuffer.h b/runtime/render/backend/gles/include/gles/egl/PBuffer.h similarity index 100% rename from render/backend/gles/include/gles/egl/PBuffer.h rename to runtime/render/backend/gles/include/gles/egl/PBuffer.h diff --git a/render/backend/gles/include/gles/egl/Surface.h b/runtime/render/backend/gles/include/gles/egl/Surface.h similarity index 100% rename from render/backend/gles/include/gles/egl/Surface.h rename to runtime/render/backend/gles/include/gles/egl/Surface.h diff --git a/render/backend/gles/include/gles/egl/WindowSurface.h b/runtime/render/backend/gles/include/gles/egl/WindowSurface.h similarity index 100% rename from render/backend/gles/include/gles/egl/WindowSurface.h rename to runtime/render/backend/gles/include/gles/egl/WindowSurface.h diff --git a/render/backend/gles/src/Buffer.cpp b/runtime/render/backend/gles/src/Buffer.cpp similarity index 100% rename from render/backend/gles/src/Buffer.cpp rename to runtime/render/backend/gles/src/Buffer.cpp diff --git a/render/backend/gles/src/BufferView.cpp b/runtime/render/backend/gles/src/BufferView.cpp similarity index 100% rename from render/backend/gles/src/BufferView.cpp rename to runtime/render/backend/gles/src/BufferView.cpp diff --git a/render/backend/gles/src/CommandBuffer.cpp b/runtime/render/backend/gles/src/CommandBuffer.cpp similarity index 100% rename from render/backend/gles/src/CommandBuffer.cpp rename to runtime/render/backend/gles/src/CommandBuffer.cpp diff --git a/render/backend/gles/src/Commands.cpp b/runtime/render/backend/gles/src/Commands.cpp similarity index 100% rename from render/backend/gles/src/Commands.cpp rename to runtime/render/backend/gles/src/Commands.cpp diff --git a/render/backend/gles/src/Conversion.cpp b/runtime/render/backend/gles/src/Conversion.cpp similarity index 100% rename from render/backend/gles/src/Conversion.cpp rename to runtime/render/backend/gles/src/Conversion.cpp diff --git a/render/backend/gles/src/DescriptorSet.cpp b/runtime/render/backend/gles/src/DescriptorSet.cpp similarity index 100% rename from render/backend/gles/src/DescriptorSet.cpp rename to runtime/render/backend/gles/src/DescriptorSet.cpp diff --git a/render/backend/gles/src/DescriptorSetLayout.cpp b/runtime/render/backend/gles/src/DescriptorSetLayout.cpp similarity index 100% rename from render/backend/gles/src/DescriptorSetLayout.cpp rename to runtime/render/backend/gles/src/DescriptorSetLayout.cpp diff --git a/render/backend/gles/src/DescriptorSetPool.cpp b/runtime/render/backend/gles/src/DescriptorSetPool.cpp similarity index 100% rename from render/backend/gles/src/DescriptorSetPool.cpp rename to runtime/render/backend/gles/src/DescriptorSetPool.cpp diff --git a/render/backend/gles/src/Device.cpp b/runtime/render/backend/gles/src/Device.cpp similarity index 100% rename from render/backend/gles/src/Device.cpp rename to runtime/render/backend/gles/src/Device.cpp diff --git a/render/backend/gles/src/Fence.cpp b/runtime/render/backend/gles/src/Fence.cpp similarity index 100% rename from render/backend/gles/src/Fence.cpp rename to runtime/render/backend/gles/src/Fence.cpp diff --git a/render/backend/gles/src/FrameBuffer.cpp b/runtime/render/backend/gles/src/FrameBuffer.cpp similarity index 100% rename from render/backend/gles/src/FrameBuffer.cpp rename to runtime/render/backend/gles/src/FrameBuffer.cpp diff --git a/render/backend/gles/src/FrameBufferBlitHelper.cpp b/runtime/render/backend/gles/src/FrameBufferBlitHelper.cpp similarity index 100% rename from render/backend/gles/src/FrameBufferBlitHelper.cpp rename to runtime/render/backend/gles/src/FrameBufferBlitHelper.cpp diff --git a/render/backend/gles/src/FrameBufferObject.cpp b/runtime/render/backend/gles/src/FrameBufferObject.cpp similarity index 100% rename from render/backend/gles/src/FrameBufferObject.cpp rename to runtime/render/backend/gles/src/FrameBufferObject.cpp diff --git a/render/backend/gles/src/GraphicsPipeline.cpp b/runtime/render/backend/gles/src/GraphicsPipeline.cpp similarity index 100% rename from render/backend/gles/src/GraphicsPipeline.cpp rename to runtime/render/backend/gles/src/GraphicsPipeline.cpp diff --git a/render/backend/gles/src/Image.cpp b/runtime/render/backend/gles/src/Image.cpp similarity index 100% rename from render/backend/gles/src/Image.cpp rename to runtime/render/backend/gles/src/Image.cpp diff --git a/render/backend/gles/src/ImageView.cpp b/runtime/render/backend/gles/src/ImageView.cpp similarity index 100% rename from render/backend/gles/src/ImageView.cpp rename to runtime/render/backend/gles/src/ImageView.cpp diff --git a/render/backend/gles/src/Instance.cpp b/runtime/render/backend/gles/src/Instance.cpp similarity index 100% rename from render/backend/gles/src/Instance.cpp rename to runtime/render/backend/gles/src/Instance.cpp diff --git a/render/backend/gles/src/PipelineLayout.cpp b/runtime/render/backend/gles/src/PipelineLayout.cpp similarity index 100% rename from render/backend/gles/src/PipelineLayout.cpp rename to runtime/render/backend/gles/src/PipelineLayout.cpp diff --git a/render/backend/gles/src/QueryPool.cpp b/runtime/render/backend/gles/src/QueryPool.cpp similarity index 100% rename from render/backend/gles/src/QueryPool.cpp rename to runtime/render/backend/gles/src/QueryPool.cpp diff --git a/render/backend/gles/src/Queue.cpp b/runtime/render/backend/gles/src/Queue.cpp similarity index 100% rename from render/backend/gles/src/Queue.cpp rename to runtime/render/backend/gles/src/Queue.cpp diff --git a/render/backend/gles/src/RenderPass.cpp b/runtime/render/backend/gles/src/RenderPass.cpp similarity index 100% rename from render/backend/gles/src/RenderPass.cpp rename to runtime/render/backend/gles/src/RenderPass.cpp diff --git a/render/backend/gles/src/Sampler.cpp b/runtime/render/backend/gles/src/Sampler.cpp similarity index 100% rename from render/backend/gles/src/Sampler.cpp rename to runtime/render/backend/gles/src/Sampler.cpp diff --git a/render/backend/gles/src/Semaphore.cpp b/runtime/render/backend/gles/src/Semaphore.cpp similarity index 100% rename from render/backend/gles/src/Semaphore.cpp rename to runtime/render/backend/gles/src/Semaphore.cpp diff --git a/render/backend/gles/src/Shader.cpp b/runtime/render/backend/gles/src/Shader.cpp similarity index 100% rename from render/backend/gles/src/Shader.cpp rename to runtime/render/backend/gles/src/Shader.cpp diff --git a/render/backend/gles/src/Swapchain.cpp b/runtime/render/backend/gles/src/Swapchain.cpp similarity index 100% rename from render/backend/gles/src/Swapchain.cpp rename to runtime/render/backend/gles/src/Swapchain.cpp diff --git a/render/backend/gles/src/VertexAssembly.cpp b/runtime/render/backend/gles/src/VertexAssembly.cpp similarity index 100% rename from render/backend/gles/src/VertexAssembly.cpp rename to runtime/render/backend/gles/src/VertexAssembly.cpp diff --git a/render/backend/gles/src/VertexInput.cpp b/runtime/render/backend/gles/src/VertexInput.cpp similarity index 100% rename from render/backend/gles/src/VertexInput.cpp rename to runtime/render/backend/gles/src/VertexInput.cpp diff --git a/render/backend/gles/src/egl/Context.cpp b/runtime/render/backend/gles/src/egl/Context.cpp similarity index 100% rename from render/backend/gles/src/egl/Context.cpp rename to runtime/render/backend/gles/src/egl/Context.cpp diff --git a/render/backend/gles/src/egl/Surface.cpp b/runtime/render/backend/gles/src/egl/Surface.cpp similarity index 100% rename from render/backend/gles/src/egl/Surface.cpp rename to runtime/render/backend/gles/src/egl/Surface.cpp diff --git a/render/backend/gles/src/egl/egl_android.inl b/runtime/render/backend/gles/src/egl/egl_android.inl similarity index 100% rename from render/backend/gles/src/egl/egl_android.inl rename to runtime/render/backend/gles/src/egl/egl_android.inl diff --git a/render/backend/gles/src/egl/egl_win32.inl b/runtime/render/backend/gles/src/egl/egl_win32.inl similarity index 100% rename from render/backend/gles/src/egl/egl_win32.inl rename to runtime/render/backend/gles/src/egl/egl_win32.inl diff --git a/render/backend/metal/CMakeLists.txt b/runtime/render/backend/metal/CMakeLists.txt similarity index 100% rename from render/backend/metal/CMakeLists.txt rename to runtime/render/backend/metal/CMakeLists.txt diff --git a/render/backend/metal/include/mtl/Buffer.h b/runtime/render/backend/metal/include/mtl/Buffer.h similarity index 100% rename from render/backend/metal/include/mtl/Buffer.h rename to runtime/render/backend/metal/include/mtl/Buffer.h diff --git a/render/backend/metal/include/mtl/BufferView.h b/runtime/render/backend/metal/include/mtl/BufferView.h similarity index 100% rename from render/backend/metal/include/mtl/BufferView.h rename to runtime/render/backend/metal/include/mtl/BufferView.h diff --git a/render/backend/metal/include/mtl/CommandBuffer.h b/runtime/render/backend/metal/include/mtl/CommandBuffer.h similarity index 100% rename from render/backend/metal/include/mtl/CommandBuffer.h rename to runtime/render/backend/metal/include/mtl/CommandBuffer.h diff --git a/render/backend/metal/include/mtl/Conversion.h b/runtime/render/backend/metal/include/mtl/Conversion.h similarity index 100% rename from render/backend/metal/include/mtl/Conversion.h rename to runtime/render/backend/metal/include/mtl/Conversion.h diff --git a/render/backend/metal/include/mtl/DescriptorSet.h b/runtime/render/backend/metal/include/mtl/DescriptorSet.h similarity index 100% rename from render/backend/metal/include/mtl/DescriptorSet.h rename to runtime/render/backend/metal/include/mtl/DescriptorSet.h diff --git a/render/backend/metal/include/mtl/DescriptorSetLayout.h b/runtime/render/backend/metal/include/mtl/DescriptorSetLayout.h similarity index 100% rename from render/backend/metal/include/mtl/DescriptorSetLayout.h rename to runtime/render/backend/metal/include/mtl/DescriptorSetLayout.h diff --git a/render/backend/metal/include/mtl/DescriptorSetPool.h b/runtime/render/backend/metal/include/mtl/DescriptorSetPool.h similarity index 100% rename from render/backend/metal/include/mtl/DescriptorSetPool.h rename to runtime/render/backend/metal/include/mtl/DescriptorSetPool.h diff --git a/render/backend/metal/include/mtl/DevObject.h b/runtime/render/backend/metal/include/mtl/DevObject.h similarity index 100% rename from render/backend/metal/include/mtl/DevObject.h rename to runtime/render/backend/metal/include/mtl/DevObject.h diff --git a/render/backend/metal/include/mtl/Device.h b/runtime/render/backend/metal/include/mtl/Device.h similarity index 100% rename from render/backend/metal/include/mtl/Device.h rename to runtime/render/backend/metal/include/mtl/Device.h diff --git a/render/backend/metal/include/mtl/Fence.h b/runtime/render/backend/metal/include/mtl/Fence.h similarity index 100% rename from render/backend/metal/include/mtl/Fence.h rename to runtime/render/backend/metal/include/mtl/Fence.h diff --git a/render/backend/metal/include/mtl/FrameBuffer.h b/runtime/render/backend/metal/include/mtl/FrameBuffer.h similarity index 100% rename from render/backend/metal/include/mtl/FrameBuffer.h rename to runtime/render/backend/metal/include/mtl/FrameBuffer.h diff --git a/render/backend/metal/include/mtl/GraphicsPipeline.h b/runtime/render/backend/metal/include/mtl/GraphicsPipeline.h similarity index 100% rename from render/backend/metal/include/mtl/GraphicsPipeline.h rename to runtime/render/backend/metal/include/mtl/GraphicsPipeline.h diff --git a/render/backend/metal/include/mtl/Image.h b/runtime/render/backend/metal/include/mtl/Image.h similarity index 100% rename from render/backend/metal/include/mtl/Image.h rename to runtime/render/backend/metal/include/mtl/Image.h diff --git a/render/backend/metal/include/mtl/ImageView.h b/runtime/render/backend/metal/include/mtl/ImageView.h similarity index 100% rename from render/backend/metal/include/mtl/ImageView.h rename to runtime/render/backend/metal/include/mtl/ImageView.h diff --git a/render/backend/metal/include/mtl/Instance.h b/runtime/render/backend/metal/include/mtl/Instance.h similarity index 100% rename from render/backend/metal/include/mtl/Instance.h rename to runtime/render/backend/metal/include/mtl/Instance.h diff --git a/render/backend/metal/include/mtl/MetalView.h b/runtime/render/backend/metal/include/mtl/MetalView.h similarity index 100% rename from render/backend/metal/include/mtl/MetalView.h rename to runtime/render/backend/metal/include/mtl/MetalView.h diff --git a/render/backend/metal/include/mtl/PipelineLayout.h b/runtime/render/backend/metal/include/mtl/PipelineLayout.h similarity index 100% rename from render/backend/metal/include/mtl/PipelineLayout.h rename to runtime/render/backend/metal/include/mtl/PipelineLayout.h diff --git a/render/backend/metal/include/mtl/QueryPool.h b/runtime/render/backend/metal/include/mtl/QueryPool.h similarity index 100% rename from render/backend/metal/include/mtl/QueryPool.h rename to runtime/render/backend/metal/include/mtl/QueryPool.h diff --git a/render/backend/metal/include/mtl/Queue.h b/runtime/render/backend/metal/include/mtl/Queue.h similarity index 100% rename from render/backend/metal/include/mtl/Queue.h rename to runtime/render/backend/metal/include/mtl/Queue.h diff --git a/render/backend/metal/include/mtl/RenderPass.h b/runtime/render/backend/metal/include/mtl/RenderPass.h similarity index 100% rename from render/backend/metal/include/mtl/RenderPass.h rename to runtime/render/backend/metal/include/mtl/RenderPass.h diff --git a/render/backend/metal/include/mtl/Sampler.h b/runtime/render/backend/metal/include/mtl/Sampler.h similarity index 100% rename from render/backend/metal/include/mtl/Sampler.h rename to runtime/render/backend/metal/include/mtl/Sampler.h diff --git a/render/backend/metal/include/mtl/Semaphore.h b/runtime/render/backend/metal/include/mtl/Semaphore.h similarity index 100% rename from render/backend/metal/include/mtl/Semaphore.h rename to runtime/render/backend/metal/include/mtl/Semaphore.h diff --git a/render/backend/metal/include/mtl/Shader.h b/runtime/render/backend/metal/include/mtl/Shader.h similarity index 100% rename from render/backend/metal/include/mtl/Shader.h rename to runtime/render/backend/metal/include/mtl/Shader.h diff --git a/render/backend/metal/include/mtl/Swapchain.h b/runtime/render/backend/metal/include/mtl/Swapchain.h similarity index 100% rename from render/backend/metal/include/mtl/Swapchain.h rename to runtime/render/backend/metal/include/mtl/Swapchain.h diff --git a/render/backend/metal/include/mtl/VertexAssembly.h b/runtime/render/backend/metal/include/mtl/VertexAssembly.h similarity index 100% rename from render/backend/metal/include/mtl/VertexAssembly.h rename to runtime/render/backend/metal/include/mtl/VertexAssembly.h diff --git a/render/backend/metal/include/mtl/VertexInput.h b/runtime/render/backend/metal/include/mtl/VertexInput.h similarity index 100% rename from render/backend/metal/include/mtl/VertexInput.h rename to runtime/render/backend/metal/include/mtl/VertexInput.h diff --git a/render/backend/metal/platform/macos/MetalView.mm b/runtime/render/backend/metal/platform/macos/MetalView.mm similarity index 100% rename from render/backend/metal/platform/macos/MetalView.mm rename to runtime/render/backend/metal/platform/macos/MetalView.mm diff --git a/render/backend/metal/src/Buffer.mm b/runtime/render/backend/metal/src/Buffer.mm similarity index 100% rename from render/backend/metal/src/Buffer.mm rename to runtime/render/backend/metal/src/Buffer.mm diff --git a/render/backend/metal/src/BufferView.mm b/runtime/render/backend/metal/src/BufferView.mm similarity index 100% rename from render/backend/metal/src/BufferView.mm rename to runtime/render/backend/metal/src/BufferView.mm diff --git a/render/backend/metal/src/CommandBuffer.mm b/runtime/render/backend/metal/src/CommandBuffer.mm similarity index 100% rename from render/backend/metal/src/CommandBuffer.mm rename to runtime/render/backend/metal/src/CommandBuffer.mm diff --git a/render/backend/metal/src/Conversion.mm b/runtime/render/backend/metal/src/Conversion.mm similarity index 98% rename from render/backend/metal/src/Conversion.mm rename to runtime/render/backend/metal/src/Conversion.mm index bced097e..c1fe0542 100644 --- a/render/backend/metal/src/Conversion.mm +++ b/runtime/render/backend/metal/src/Conversion.mm @@ -11,8 +11,6 @@ std::unordered_map PIXEL_FORMAT_TABLE = { {rhi::PixelFormat::UNDEFINED, MTLPixelFormatInvalid}, - {rhi::PixelFormat::RGB8_UNORM, MTLPixelFormatInvalid}, - {rhi::PixelFormat::RGB8_SRGB, MTLPixelFormatInvalid}, {rhi::PixelFormat::RGBA8_UNORM, MTLPixelFormatRGBA8Unorm}, {rhi::PixelFormat::RGBA8_SRGB, MTLPixelFormatRGBA8Unorm_sRGB}, {rhi::PixelFormat::BGRA8_UNORM, MTLPixelFormatBGRA8Unorm}, @@ -60,7 +58,6 @@ {rhi::Format::F_RGBA32, MTLVertexFormatFloat4}, {rhi::Format::F_R8, MTLVertexFormatChar}, {rhi::Format::F_RG8, MTLVertexFormatChar2}, - {rhi::Format::F_RGB8, MTLVertexFormatChar3}, {rhi::Format::F_RGBA8, MTLVertexFormatChar4}, }; diff --git a/render/backend/metal/src/Device.mm b/runtime/render/backend/metal/src/Device.mm similarity index 100% rename from render/backend/metal/src/Device.mm rename to runtime/render/backend/metal/src/Device.mm diff --git a/render/backend/metal/src/Fence.mm b/runtime/render/backend/metal/src/Fence.mm similarity index 100% rename from render/backend/metal/src/Fence.mm rename to runtime/render/backend/metal/src/Fence.mm diff --git a/render/backend/metal/src/FrameBuffer.mm b/runtime/render/backend/metal/src/FrameBuffer.mm similarity index 100% rename from render/backend/metal/src/FrameBuffer.mm rename to runtime/render/backend/metal/src/FrameBuffer.mm diff --git a/render/backend/metal/src/GraphicsPipeline.mm b/runtime/render/backend/metal/src/GraphicsPipeline.mm similarity index 100% rename from render/backend/metal/src/GraphicsPipeline.mm rename to runtime/render/backend/metal/src/GraphicsPipeline.mm diff --git a/render/backend/metal/src/Image.mm b/runtime/render/backend/metal/src/Image.mm similarity index 100% rename from render/backend/metal/src/Image.mm rename to runtime/render/backend/metal/src/Image.mm diff --git a/render/backend/metal/src/ImageView.mm b/runtime/render/backend/metal/src/ImageView.mm similarity index 100% rename from render/backend/metal/src/ImageView.mm rename to runtime/render/backend/metal/src/ImageView.mm diff --git a/render/backend/metal/src/Instance.mm b/runtime/render/backend/metal/src/Instance.mm similarity index 100% rename from render/backend/metal/src/Instance.mm rename to runtime/render/backend/metal/src/Instance.mm diff --git a/render/backend/metal/src/QueryPool.mm b/runtime/render/backend/metal/src/QueryPool.mm similarity index 100% rename from render/backend/metal/src/QueryPool.mm rename to runtime/render/backend/metal/src/QueryPool.mm diff --git a/render/backend/metal/src/Queue.mm b/runtime/render/backend/metal/src/Queue.mm similarity index 100% rename from render/backend/metal/src/Queue.mm rename to runtime/render/backend/metal/src/Queue.mm diff --git a/render/backend/metal/src/RenderPass.mm b/runtime/render/backend/metal/src/RenderPass.mm similarity index 100% rename from render/backend/metal/src/RenderPass.mm rename to runtime/render/backend/metal/src/RenderPass.mm diff --git a/render/backend/metal/src/Sampler.mm b/runtime/render/backend/metal/src/Sampler.mm similarity index 100% rename from render/backend/metal/src/Sampler.mm rename to runtime/render/backend/metal/src/Sampler.mm diff --git a/render/backend/metal/src/Semaphore.mm b/runtime/render/backend/metal/src/Semaphore.mm similarity index 100% rename from render/backend/metal/src/Semaphore.mm rename to runtime/render/backend/metal/src/Semaphore.mm diff --git a/render/backend/metal/src/Shader.mm b/runtime/render/backend/metal/src/Shader.mm similarity index 100% rename from render/backend/metal/src/Shader.mm rename to runtime/render/backend/metal/src/Shader.mm diff --git a/render/backend/metal/src/Swapchain.mm b/runtime/render/backend/metal/src/Swapchain.mm similarity index 100% rename from render/backend/metal/src/Swapchain.mm rename to runtime/render/backend/metal/src/Swapchain.mm diff --git a/render/backend/metal/src/VertexAssembly.mm b/runtime/render/backend/metal/src/VertexAssembly.mm similarity index 100% rename from render/backend/metal/src/VertexAssembly.mm rename to runtime/render/backend/metal/src/VertexAssembly.mm diff --git a/render/backend/metal/src/VertexInput.mm b/runtime/render/backend/metal/src/VertexInput.mm similarity index 100% rename from render/backend/metal/src/VertexInput.mm rename to runtime/render/backend/metal/src/VertexInput.mm diff --git a/runtime/render/backend/rhi/CMakeLists.txt b/runtime/render/backend/rhi/CMakeLists.txt new file mode 100644 index 00000000..ba444727 --- /dev/null +++ b/runtime/render/backend/rhi/CMakeLists.txt @@ -0,0 +1,24 @@ +file(GLOB_RECURSE SRC_FILES src/*) +file(GLOB_RECURSE INC_FILES include/*) + +if (SKY_BUILD_XR) + set(RHI_EXT_LIB 3rdParty::OpenXR) +endif () + +sky_add_library(TARGET RHI STATIC + SOURCES + ${SRC_FILES} + ${INC_FILES} + ${PLATFORM_SRC} + PRIVATE_INC + src + PUBLIC_INC + include + LINK_LIBS + Core + ${RHI_EXT_LIB} + ) + +if (SKY_BUILD_XR) + target_compile_definitions(RHI PUBLIC -DSKY_ENABLE_XR) +endif () \ No newline at end of file diff --git a/render/backend/rhi/include/rhi/ASTC.h b/runtime/render/backend/rhi/include/rhi/ASTC.h similarity index 100% rename from render/backend/rhi/include/rhi/ASTC.h rename to runtime/render/backend/rhi/include/rhi/ASTC.h diff --git a/render/backend/rhi/include/rhi/Allocator.h b/runtime/render/backend/rhi/include/rhi/Allocator.h similarity index 100% rename from render/backend/rhi/include/rhi/Allocator.h rename to runtime/render/backend/rhi/include/rhi/Allocator.h diff --git a/render/backend/rhi/include/rhi/Buffer.h b/runtime/render/backend/rhi/include/rhi/Buffer.h similarity index 74% rename from render/backend/rhi/include/rhi/Buffer.h rename to runtime/render/backend/rhi/include/rhi/Buffer.h index 21539b84..3dc4760c 100644 --- a/render/backend/rhi/include/rhi/Buffer.h +++ b/runtime/render/backend/rhi/include/rhi/Buffer.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include namespace sky::rhi { @@ -18,9 +17,8 @@ namespace sky::rhi { struct Descriptor { uint64_t size = 0; Flags usage; - MemoryType memory = MemoryType::GPU_ONLY; + MemoryType memory = MemoryType::GPU_ONLY; }; - virtual rhi::BufferViewPtr CreateView(const rhi::BufferViewDesc &desc) = 0; virtual uint8_t *Map() { return nullptr; } virtual void UnMap() {} @@ -30,4 +28,10 @@ namespace sky::rhi { Descriptor bufferDesc; }; using BufferPtr = std::shared_ptr; -} + + struct BufferView { + BufferPtr buffer; + uint64_t offset = 0; + uint64_t range = 0; + }; +} // namespace sky::rhi diff --git a/render/backend/rhi/include/rhi/BufferPool.h b/runtime/render/backend/rhi/include/rhi/BufferPool.h similarity index 100% rename from render/backend/rhi/include/rhi/BufferPool.h rename to runtime/render/backend/rhi/include/rhi/BufferPool.h diff --git a/render/backend/rhi/include/rhi/CommandBuffer.h b/runtime/render/backend/rhi/include/rhi/CommandBuffer.h similarity index 95% rename from render/backend/rhi/include/rhi/CommandBuffer.h rename to runtime/render/backend/rhi/include/rhi/CommandBuffer.h index dfc9c22c..b70d7978 100644 --- a/render/backend/rhi/include/rhi/CommandBuffer.h +++ b/runtime/render/backend/rhi/include/rhi/CommandBuffer.h @@ -39,6 +39,8 @@ namespace sky::rhi { virtual GraphicsEncoder &BeginPass(const PassBeginInfo &beginInfo) = 0; virtual GraphicsEncoder &BindPipeline(const GraphicsPipelinePtr &pso) = 0; virtual GraphicsEncoder &BindAssembly(const VertexAssemblyPtr &assembly) = 0; + virtual GraphicsEncoder &BindVertexBuffers(const std::vector &vbs) = 0; + virtual GraphicsEncoder &BindIndexBuffer(const rhi::BufferView& view, rhi::IndexType type) = 0; virtual GraphicsEncoder &SetViewport(uint32_t count, const Viewport *viewport) = 0; virtual GraphicsEncoder &SetScissor(uint32_t count, const Rect2D *scissor) = 0; virtual GraphicsEncoder &DrawIndexed(const CmdDrawIndexed &indexed) = 0; @@ -78,7 +80,7 @@ namespace sky::rhi { AccessFlags dstFlags; uint32_t srcQueueFamily = (~0U); uint32_t dstQueueFamily = (~0U); - BufferViewPtr view; + BufferView view; }; struct ImageBarrier { diff --git a/render/backend/rhi/include/rhi/Commands.h b/runtime/render/backend/rhi/include/rhi/Commands.h similarity index 100% rename from render/backend/rhi/include/rhi/Commands.h rename to runtime/render/backend/rhi/include/rhi/Commands.h diff --git a/render/backend/rhi/include/rhi/ComputePipeline.h b/runtime/render/backend/rhi/include/rhi/ComputePipeline.h similarity index 100% rename from render/backend/rhi/include/rhi/ComputePipeline.h rename to runtime/render/backend/rhi/include/rhi/ComputePipeline.h diff --git a/render/backend/rhi/include/rhi/Core.h b/runtime/render/backend/rhi/include/rhi/Core.h similarity index 96% rename from render/backend/rhi/include/rhi/Core.h rename to runtime/render/backend/rhi/include/rhi/Core.h index 7e30c219..9324759b 100644 --- a/render/backend/rhi/include/rhi/Core.h +++ b/runtime/render/backend/rhi/include/rhi/Core.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace sky { static constexpr uint32_t INVALID_INDEX = ~(0U); @@ -16,20 +17,12 @@ namespace sky { namespace sky::rhi { -#define ENABLE_FLAG_BIT_OPERATOR(Type) \ - constexpr Flags operator&(Type const& lhs, Type const& rhs) noexcept \ - { \ - return Flags(lhs) & rhs; \ - } \ - constexpr Flags operator|(Type const& lhs, Type const& rhs) noexcept \ - { \ - return Flags(lhs) | rhs; \ - } \ - constexpr Flags operator^(Type const& lhs, Type const& rhs) noexcept \ - { \ - return Flags(lhs) ^ rhs; \ - } - + enum class BaseType : uint32_t { + UNDEFINED = 0, + FLOAT, + INT, + UINT, + }; enum class PixelFormat : uint32_t { UNDEFINED = 0, @@ -84,13 +77,19 @@ namespace sky::rhi { F_RG32 = 2, F_RGB32 = 3, F_RGBA32 = 4, - F_R8 = 5, - F_RG8 = 6, - F_RGBA8 = 8 + F_R8 = 4, + F_RG8 = 5, + F_RGB8 = 6, + F_RGBA8 = 7, + U_R32 = 9, + U_RG32 = 10, + U_RGB32 = 11, + U_RGBA32 = 12, }; enum class IndexType : uint32_t { - U16 = 0, + NONE = 0, + U16, U32, }; @@ -495,21 +494,21 @@ namespace sky::rhi { uint32_t size; }; - struct IStream { - IStream() = default; - virtual ~IStream() = default; - virtual const uint8_t *GetData(uint64_t offset) = 0; + struct IUploadStream : public RefObject { + IUploadStream() = default; + ~IUploadStream() override = default; + virtual const uint8_t *Data(uint64_t offset) = 0; virtual void ReadData(uint64_t offset, uint64_t size, uint8_t *out) = 0; }; struct BufferUploadRequest { - std::shared_ptr source; + CounterPtr source; uint64_t offset = 0; uint64_t size = 0; }; struct ImageUploadRequest { - std::shared_ptr source; + CounterPtr source; uint64_t offset = 0; uint64_t size = 0; uint32_t mipLevel = 0; diff --git a/render/backend/rhi/include/rhi/DDS.h b/runtime/render/backend/rhi/include/rhi/DDS.h similarity index 100% rename from render/backend/rhi/include/rhi/DDS.h rename to runtime/render/backend/rhi/include/rhi/DDS.h diff --git a/render/backend/rhi/include/rhi/Decode.h b/runtime/render/backend/rhi/include/rhi/Decode.h similarity index 100% rename from render/backend/rhi/include/rhi/Decode.h rename to runtime/render/backend/rhi/include/rhi/Decode.h diff --git a/render/backend/rhi/include/rhi/DescriptorSet.h b/runtime/render/backend/rhi/include/rhi/DescriptorSet.h similarity index 92% rename from render/backend/rhi/include/rhi/DescriptorSet.h rename to runtime/render/backend/rhi/include/rhi/DescriptorSet.h index 8f2dcc58..5feff7a7 100644 --- a/render/backend/rhi/include/rhi/DescriptorSet.h +++ b/runtime/render/backend/rhi/include/rhi/DescriptorSet.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include #include @@ -27,7 +26,7 @@ namespace sky::rhi { BindBuffer(binding, buffer, offset, size, 0); } - void BindBuffer(uint32_t binding, const BufferViewPtr &view) + void BindBuffer(uint32_t binding, const BufferView &view) { BindBuffer(binding, view, 0); } @@ -48,7 +47,7 @@ namespace sky::rhi { } virtual void BindBuffer(uint32_t binding, const BufferPtr &buffer, uint64_t offset, uint64_t size, uint32_t index) = 0; - virtual void BindBuffer(uint32_t binding, const BufferViewPtr &view, uint32_t index) = 0; + virtual void BindBuffer(uint32_t binding, const BufferView &view, uint32_t index) = 0; virtual void BindImageView(uint32_t binding, const ImageViewPtr &view, uint32_t index, DescriptorBindFlags flags) = 0; virtual void BindSampler(uint32_t binding, const SamplerPtr &sampler, uint32_t index) = 0; virtual void Update() = 0; diff --git a/render/backend/rhi/include/rhi/DescriptorSetLayout.h b/runtime/render/backend/rhi/include/rhi/DescriptorSetLayout.h similarity index 93% rename from render/backend/rhi/include/rhi/DescriptorSetLayout.h rename to runtime/render/backend/rhi/include/rhi/DescriptorSetLayout.h index bf270af8..e3d77482 100644 --- a/render/backend/rhi/include/rhi/DescriptorSetLayout.h +++ b/runtime/render/backend/rhi/include/rhi/DescriptorSetLayout.h @@ -32,13 +32,11 @@ namespace sky::rhi { uint32_t GetHash() const { return hash; } uint32_t GetDynamicNum() const { return dynamicNum; } uint32_t GetDescriptorNum() const { return descriptorNum; } - uint32_t GetDescriptorCount() const { return descriptorCount; } uint32_t GetDescriptorSetOffsetByBinding(uint32_t binding) const { return bindingIndices.at(binding).first; } uint32_t GetDescriptorSetCountByBinding(uint32_t binding) const { return bindingIndices.at(binding).second; } const std::vector &GetBindings() const { return bindings; } protected: - uint32_t descriptorCount = 0; uint32_t hash = 0; uint32_t dynamicNum = 0; uint32_t descriptorNum = 0; diff --git a/render/backend/rhi/include/rhi/DescriptorSetPool.h b/runtime/render/backend/rhi/include/rhi/DescriptorSetPool.h similarity index 100% rename from render/backend/rhi/include/rhi/DescriptorSetPool.h rename to runtime/render/backend/rhi/include/rhi/DescriptorSetPool.h diff --git a/render/backend/rhi/include/rhi/Device.h b/runtime/render/backend/rhi/include/rhi/Device.h similarity index 93% rename from render/backend/rhi/include/rhi/Device.h rename to runtime/render/backend/rhi/include/rhi/Device.h index 591c0e27..da9c4e1d 100644 --- a/render/backend/rhi/include/rhi/Device.h +++ b/runtime/render/backend/rhi/include/rhi/Device.h @@ -20,6 +20,10 @@ #include #include +#ifdef SKY_ENABLE_XR +#include +#endif + #define CREATE_DEV_OBJ(name) \ std::shared_ptr Create##name(const rhi::name::Descriptor &desc) override \ { \ @@ -59,6 +63,8 @@ namespace sky::rhi { struct Descriptor { DeviceFeature feature; }; + + virtual std::string GetDeviceInfo() const { return ""; } virtual void WaitIdle() const = 0; // device object @@ -78,6 +84,10 @@ namespace sky::rhi { virtual SamplerPtr CreateSampler(const Sampler::Descriptor &desc) = 0; virtual DescriptorSetPoolPtr CreateDescriptorSetPool(const DescriptorSetPool::Descriptor &desc) = 0; virtual QueryPoolPtr CreateQueryPool(const QueryPool::Descriptor &desc) = 0; +#ifdef SKY_ENABLE_XR + virtual XRSwapChainPtr CreateXRSwapChain(const XRSwapChain::Descriptor &desc) { return nullptr; }; +#endif + // query virtual uint32_t CheckPipelineStatisticFlags(const PipelineStatisticFlags &val, PipelineStatisticFlags &res) { return 0; } @@ -101,4 +111,4 @@ namespace sky::rhi { std::array(PixelFormat::MAX)> formatFeatures; }; -} +} // namespace sky::rhi diff --git a/render/backend/rhi/include/rhi/Fence.h b/runtime/render/backend/rhi/include/rhi/Fence.h similarity index 100% rename from render/backend/rhi/include/rhi/Fence.h rename to runtime/render/backend/rhi/include/rhi/Fence.h diff --git a/render/backend/rhi/include/rhi/FrameBuffer.h b/runtime/render/backend/rhi/include/rhi/FrameBuffer.h similarity index 100% rename from render/backend/rhi/include/rhi/FrameBuffer.h rename to runtime/render/backend/rhi/include/rhi/FrameBuffer.h diff --git a/render/backend/rhi/include/rhi/GraphicsPipeline.h b/runtime/render/backend/rhi/include/rhi/GraphicsPipeline.h similarity index 85% rename from render/backend/rhi/include/rhi/GraphicsPipeline.h rename to runtime/render/backend/rhi/include/rhi/GraphicsPipeline.h index 60f59c55..d041906b 100644 --- a/render/backend/rhi/include/rhi/GraphicsPipeline.h +++ b/runtime/render/backend/rhi/include/rhi/GraphicsPipeline.h @@ -26,6 +26,11 @@ namespace sky::rhi { PipelineLayoutPtr pipelineLayout; uint32_t subPassIndex = 0; }; + + uint32_t GetDescriptorMask() const { return descriptorMask; } + + protected: + uint32_t descriptorMask = 0; }; using GraphicsPipelinePtr = std::shared_ptr; } diff --git a/render/backend/rhi/include/rhi/Hash.h b/runtime/render/backend/rhi/include/rhi/Hash.h similarity index 100% rename from render/backend/rhi/include/rhi/Hash.h rename to runtime/render/backend/rhi/include/rhi/Hash.h diff --git a/render/backend/rhi/include/rhi/Image.h b/runtime/render/backend/rhi/include/rhi/Image.h similarity index 100% rename from render/backend/rhi/include/rhi/Image.h rename to runtime/render/backend/rhi/include/rhi/Image.h diff --git a/render/backend/rhi/include/rhi/ImageView.h b/runtime/render/backend/rhi/include/rhi/ImageView.h similarity index 100% rename from render/backend/rhi/include/rhi/ImageView.h rename to runtime/render/backend/rhi/include/rhi/ImageView.h diff --git a/render/backend/rhi/include/rhi/Instance.h b/runtime/render/backend/rhi/include/rhi/Instance.h similarity index 76% rename from render/backend/rhi/include/rhi/Instance.h rename to runtime/render/backend/rhi/include/rhi/Instance.h index b75d7402..5c31d7ee 100644 --- a/render/backend/rhi/include/rhi/Instance.h +++ b/runtime/render/backend/rhi/include/rhi/Instance.h @@ -10,6 +10,10 @@ #include namespace sky::rhi { +#ifdef SKY_ENABLE_XR + class XRInterface; +#endif + enum class API { DEFAULT = 0, VULKAN, @@ -25,6 +29,9 @@ namespace sky::rhi { std::string engineName; bool enableDebugLayer; API api; +#ifdef SKY_ENABLE_XR + XRInterface *xrInterface = nullptr; +#endif }; static Instance *Create(const Descriptor &); @@ -32,9 +39,17 @@ namespace sky::rhi { virtual Device *CreateDevice(const Device::Descriptor &desc) { return nullptr; } virtual bool Init(const Descriptor &) { return false; } + +#ifdef SKY_ENABLE_XR + XRInterface *GetXRInterface() { return xrInterface; } +#endif protected: Instance() = default; virtual ~Instance() = default; + +#ifdef SKY_ENABLE_XR + XRInterface *xrInterface; +#endif }; API GetApiByString(const std::string &str); diff --git a/render/backend/rhi/include/rhi/PipelineLayout.h b/runtime/render/backend/rhi/include/rhi/PipelineLayout.h similarity index 100% rename from render/backend/rhi/include/rhi/PipelineLayout.h rename to runtime/render/backend/rhi/include/rhi/PipelineLayout.h diff --git a/render/backend/rhi/include/rhi/PipelineLibrary.h b/runtime/render/backend/rhi/include/rhi/PipelineLibrary.h similarity index 100% rename from render/backend/rhi/include/rhi/PipelineLibrary.h rename to runtime/render/backend/rhi/include/rhi/PipelineLibrary.h diff --git a/render/backend/rhi/include/rhi/QueryPool.h b/runtime/render/backend/rhi/include/rhi/QueryPool.h similarity index 100% rename from render/backend/rhi/include/rhi/QueryPool.h rename to runtime/render/backend/rhi/include/rhi/QueryPool.h diff --git a/render/backend/rhi/include/rhi/Queue.h b/runtime/render/backend/rhi/include/rhi/Queue.h similarity index 100% rename from render/backend/rhi/include/rhi/Queue.h rename to runtime/render/backend/rhi/include/rhi/Queue.h diff --git a/render/backend/rhi/include/rhi/RenderPass.h b/runtime/render/backend/rhi/include/rhi/RenderPass.h similarity index 97% rename from render/backend/rhi/include/rhi/RenderPass.h rename to runtime/render/backend/rhi/include/rhi/RenderPass.h index 6e086754..d984fba4 100644 --- a/render/backend/rhi/include/rhi/RenderPass.h +++ b/runtime/render/backend/rhi/include/rhi/RenderPass.h @@ -87,6 +87,4 @@ namespace sky::rhi { }; using RenderPassPtr = std::shared_ptr; - - void CalculateRenderPassHash(const RenderPass::Descriptor &desc); }; diff --git a/render/backend/rhi/include/rhi/Sampler.h b/runtime/render/backend/rhi/include/rhi/Sampler.h similarity index 100% rename from render/backend/rhi/include/rhi/Sampler.h rename to runtime/render/backend/rhi/include/rhi/Sampler.h diff --git a/render/backend/rhi/include/rhi/Semaphore.h b/runtime/render/backend/rhi/include/rhi/Semaphore.h similarity index 100% rename from render/backend/rhi/include/rhi/Semaphore.h rename to runtime/render/backend/rhi/include/rhi/Semaphore.h diff --git a/render/backend/rhi/include/rhi/Shader.h b/runtime/render/backend/rhi/include/rhi/Shader.h similarity index 100% rename from render/backend/rhi/include/rhi/Shader.h rename to runtime/render/backend/rhi/include/rhi/Shader.h diff --git a/runtime/render/backend/rhi/include/rhi/Stream.h b/runtime/render/backend/rhi/include/rhi/Stream.h new file mode 100644 index 00000000..3007737c --- /dev/null +++ b/runtime/render/backend/rhi/include/rhi/Stream.h @@ -0,0 +1,50 @@ +// +// Created by Zach Lee on 2023/9/12. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky::rhi { + + class FileStream : public IUploadStream { + public: + FileStream(const FilePtr &f, uint64_t base); + ~FileStream() override = default; + + const uint8_t *Data(uint64_t offset) override; + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + + private: + FilePtr file; + uint64_t baseOffset; + }; + + class RawPtrStream : public IUploadStream { + public: + explicit RawPtrStream(const uint8_t *ptr) : data(ptr) {} + ~RawPtrStream() override = default; + + const uint8_t *Data(uint64_t offset) override; + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + + private: + const uint8_t *data; + }; + + class RawBufferStream : public IUploadStream { + public: + explicit RawBufferStream(std::vector &&ptr) : data(std::move(ptr)) {} + ~RawBufferStream() override = default; + + const uint8_t *Data(uint64_t offset) override; + void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override; + private: + std::vector data; + }; + +} // namespace sky::rhi \ No newline at end of file diff --git a/render/backend/rhi/include/rhi/Swapchain.h b/runtime/render/backend/rhi/include/rhi/Swapchain.h similarity index 58% rename from render/backend/rhi/include/rhi/Swapchain.h rename to runtime/render/backend/rhi/include/rhi/Swapchain.h index 2cc0304f..bb03275a 100644 --- a/render/backend/rhi/include/rhi/Swapchain.h +++ b/runtime/render/backend/rhi/include/rhi/Swapchain.h @@ -8,6 +8,10 @@ #include #include +#ifdef SKY_ENABLE_XR +#include +#endif + namespace sky::rhi { class Queue; @@ -43,4 +47,34 @@ namespace sky::rhi { virtual void Present(Queue &queue, const PresentInfo &info) = 0; }; using SwapChainPtr = std::shared_ptr; -} + +#ifdef SKY_ENABLE_XR + class XRSwapChain { + public: + XRSwapChain() = default; + virtual ~XRSwapChain() = default; + + struct Descriptor { + PixelFormat format; + }; + + virtual PixelFormat GetFormat() const = 0; + virtual const Extent2D &GetExtent() const = 0; + virtual ImagePtr GetImage(uint32_t index) const = 0; + virtual ImageViewPtr GetImageView(uint32_t index) const = 0; + virtual uint32_t GetImageCount() const = 0; + virtual uint32_t GetArrayLayers() const = 0; + virtual uint32_t AcquireNextImage() = 0; + virtual void Present() = 0; + + bool RequestViewData(const XRViewInput &input, std::vector &data) + { + return swapChain->RequestViewData(input, data); + } + + protected: + rhi::IXRSwapChain *swapChain = nullptr; + }; + using XRSwapChainPtr = std::shared_ptr; +#endif +} // namespace sky::rhi diff --git a/runtime/render/backend/rhi/include/rhi/Util.h b/runtime/render/backend/rhi/include/rhi/Util.h new file mode 100644 index 00000000..1330cdcc --- /dev/null +++ b/runtime/render/backend/rhi/include/rhi/Util.h @@ -0,0 +1,13 @@ +// +// Created by blues on 2024/3/7. +// + +#pragma once + +#include + +namespace sky::rhi { + + std::vector ParseExtensionString(char* names); + +} // namespace sky::rhi \ No newline at end of file diff --git a/render/backend/rhi/include/rhi/VertexAssembly.h b/runtime/render/backend/rhi/include/rhi/VertexAssembly.h similarity index 72% rename from render/backend/rhi/include/rhi/VertexAssembly.h rename to runtime/render/backend/rhi/include/rhi/VertexAssembly.h index 7080e05a..a524a0b8 100644 --- a/render/backend/rhi/include/rhi/VertexAssembly.h +++ b/runtime/render/backend/rhi/include/rhi/VertexAssembly.h @@ -4,7 +4,7 @@ #pragma once -#include +#include #include #include #include @@ -17,10 +17,8 @@ namespace sky::rhi { virtual ~VertexAssembly() = default; struct Descriptor { - std::vector vertexBuffers; - BufferViewPtr indexBuffer; + std::vector vertexBuffers; VertexInputPtr vertexInput; - IndexType indexType = IndexType::U16; }; protected: diff --git a/render/backend/rhi/include/rhi/VertexInput.h b/runtime/render/backend/rhi/include/rhi/VertexInput.h similarity index 100% rename from render/backend/rhi/include/rhi/VertexInput.h rename to runtime/render/backend/rhi/include/rhi/VertexInput.h diff --git a/runtime/render/backend/rhi/include/rhi/XRInterface.h b/runtime/render/backend/rhi/include/rhi/XRInterface.h new file mode 100644 index 00000000..0f330d67 --- /dev/null +++ b/runtime/render/backend/rhi/include/rhi/XRInterface.h @@ -0,0 +1,62 @@ +// +// Created by blues on 2024/3/3. +// + +#pragma once + +#include +#include +#include + +#include + +#ifdef SKY_ENABLE_XR +#include + +namespace sky::rhi { + struct XRViewInput { + float vNear; + float vFar; + }; + struct XRViewData { + Matrix4 world; + Matrix4 project; + }; + + class IXRSwapChain { + public: + IXRSwapChain() = default; + virtual ~IXRSwapChain() = default; + + struct Descriptor { + int64_t format; + bool enableMultiView; + }; + + virtual bool RequestViewData(const XRViewInput &input, std::vector &data) = 0; + virtual XrSwapchain GetHandle(uint32_t index) const = 0; + virtual uint32_t GetWidth() const = 0; + virtual uint32_t GetHeight() const = 0; + virtual uint32_t GetArrayLayers() const = 0; + virtual int64_t GetFormat() const = 0; + virtual uint32_t AcquireNextImage() = 0; + virtual void Present() = 0; + }; + + class XRInterface { + public: + XRInterface() = default; + virtual ~XRInterface() = default; + + virtual PFN_xrVoidFunction GetFunction(const std::string_view &func) const { return nullptr; } + + virtual XrInstance GetXrInstanceHandle() const { return XR_NULL_HANDLE; } + virtual XrSystemId GetXrSystemId() const { return XR_NULL_SYSTEM_ID; } + virtual IXRSwapChain* CreateXrSwapChain(const IXRSwapChain::Descriptor &desc) { return XR_NULL_HANDLE; } + virtual void DestroyXrSwapChain(IXRSwapChain *) {} + + virtual void SetSessionGraphicsBinding(const void *data) {} + }; +} // namespace sky::rhi + +#endif \ No newline at end of file diff --git a/render/backend/rhi/src/Allocator.cpp b/runtime/render/backend/rhi/src/Allocator.cpp similarity index 100% rename from render/backend/rhi/src/Allocator.cpp rename to runtime/render/backend/rhi/src/Allocator.cpp diff --git a/render/backend/rhi/src/BufferPool.cpp b/runtime/render/backend/rhi/src/BufferPool.cpp similarity index 100% rename from render/backend/rhi/src/BufferPool.cpp rename to runtime/render/backend/rhi/src/BufferPool.cpp diff --git a/render/backend/rhi/src/Decode.cpp b/runtime/render/backend/rhi/src/Decode.cpp similarity index 98% rename from render/backend/rhi/src/Decode.cpp rename to runtime/render/backend/rhi/src/Decode.cpp index 26ccbb77..af74665c 100644 --- a/render/backend/rhi/src/Decode.cpp +++ b/runtime/render/backend/rhi/src/Decode.cpp @@ -181,7 +181,7 @@ namespace sky::rhi { uint32_t blockSize = iter->second.blockSize; ImageUploadRequest request = {}; - request.source = std::make_shared(input); + request.source = new RawPtrStream(input); request.imageExtent.width = imageDesc.extent.width; request.imageExtent.height = imageDesc.extent.height; @@ -194,7 +194,7 @@ namespace sky::rhi { uint32_t imageHeight = (height + blockHeight - 1) / blockHeight; uint32_t currentSize = rowLength * imageHeight * blockSize; request.imageExtent.depth = 1; - request.source = std::make_shared(input); + request.source = new RawPtrStream(input); request.offset = offset; request.size = currentSize; request.mipLevel = i; diff --git a/render/backend/rhi/src/Instance.cpp b/runtime/render/backend/rhi/src/Instance.cpp similarity index 97% rename from render/backend/rhi/src/Instance.cpp rename to runtime/render/backend/rhi/src/Instance.cpp index 55dc7089..58ced097 100644 --- a/render/backend/rhi/src/Instance.cpp +++ b/runtime/render/backend/rhi/src/Instance.cpp @@ -47,7 +47,7 @@ namespace sky::rhi { if (instanceFunc == nullptr) { return nullptr; } - auto instance = instanceFunc(); + auto *instance = instanceFunc(); if (instance != nullptr && instance->Init(desc)) { return instance; } diff --git a/render/backend/rhi/src/Queue.cpp b/runtime/render/backend/rhi/src/Queue.cpp similarity index 100% rename from render/backend/rhi/src/Queue.cpp rename to runtime/render/backend/rhi/src/Queue.cpp diff --git a/render/backend/rhi/src/RenderPass.cpp b/runtime/render/backend/rhi/src/RenderPass.cpp similarity index 100% rename from render/backend/rhi/src/RenderPass.cpp rename to runtime/render/backend/rhi/src/RenderPass.cpp diff --git a/runtime/render/backend/rhi/src/Stream.cpp b/runtime/render/backend/rhi/src/Stream.cpp new file mode 100644 index 00000000..ccde9ab4 --- /dev/null +++ b/runtime/render/backend/rhi/src/Stream.cpp @@ -0,0 +1,42 @@ +// +// Created by Zach Lee on 2023/9/12. +// + +#include + +namespace sky::rhi { + + FileStream::FileStream(const FilePtr &f, uint64_t base) : file(f), baseOffset(base) // NOLINT + { + } + + const uint8_t *FileStream::Data(uint64_t offset) + { + return nullptr; + } + + void FileStream::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + file->ReadData(baseOffset + offset, size, out); + } + + const uint8_t *RawPtrStream::Data(uint64_t offset) + { + return data + offset; + } + + void RawPtrStream::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + memcpy(out, data + offset, size); + } + + const uint8_t *RawBufferStream::Data(uint64_t offset) + { + return data.data(); + } + + void RawBufferStream::ReadData(uint64_t offset, uint64_t size, uint8_t *out) + { + memcpy(out, data.data() + offset, size); + } +} // namespace sky::rhi \ No newline at end of file diff --git a/runtime/render/backend/rhi/src/Util.cpp b/runtime/render/backend/rhi/src/Util.cpp new file mode 100644 index 00000000..35c852f7 --- /dev/null +++ b/runtime/render/backend/rhi/src/Util.cpp @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/3/7. +// + +#include + +namespace sky::rhi { + + std::vector ParseExtensionString(char* names) + { + std::vector list; + while (names != nullptr && *names != 0) { + list.push_back(names); + while (*(++names) != 0) { + if (*names == ' ') { + *names++ = '\0'; + break; + } + } + } + return list; + } + +} // namespace sky::rhi \ No newline at end of file diff --git a/render/backend/vulkan/CMakeLists.txt b/runtime/render/backend/vulkan/CMakeLists.txt similarity index 91% rename from render/backend/vulkan/CMakeLists.txt rename to runtime/render/backend/vulkan/CMakeLists.txt index 20191f47..1d76913c 100644 --- a/render/backend/vulkan/CMakeLists.txt +++ b/runtime/render/backend/vulkan/CMakeLists.txt @@ -35,6 +35,10 @@ sky_add_library(TARGET VulkanRHI.Static STATIC ${PLATFORM_EXT_LIBS} ) +if (SKY_BUILD_XR) + target_compile_definitions(VulkanRHI.Static PUBLIC -DXR_USE_GRAPHICS_API_VULKAN) +endif () + if(ANDROID) target_compile_definitions(VulkanRHI.Static PUBLIC -DVMA_VULKAN_VERSION=1002000) endif() diff --git a/render/backend/vulkan/Export.cpp b/runtime/render/backend/vulkan/Export.cpp similarity index 100% rename from render/backend/vulkan/Export.cpp rename to runtime/render/backend/vulkan/Export.cpp diff --git a/render/backend/vulkan/include/vulkan/Barrier.h b/runtime/render/backend/vulkan/include/vulkan/Barrier.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Barrier.h rename to runtime/render/backend/vulkan/include/vulkan/Barrier.h diff --git a/render/backend/vulkan/include/vulkan/Basic.h b/runtime/render/backend/vulkan/include/vulkan/Basic.h similarity index 99% rename from render/backend/vulkan/include/vulkan/Basic.h rename to runtime/render/backend/vulkan/include/vulkan/Basic.h index a88edbf2..4963f81e 100644 --- a/render/backend/vulkan/include/vulkan/Basic.h +++ b/runtime/render/backend/vulkan/include/vulkan/Basic.h @@ -37,5 +37,4 @@ namespace sky::vk { return strcmp(prop.extensionName, ext) == 0; }); } - } // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/Buffer.h b/runtime/render/backend/vulkan/include/vulkan/Buffer.h similarity index 58% rename from render/backend/vulkan/include/vulkan/Buffer.h rename to runtime/render/backend/vulkan/include/vulkan/Buffer.h index a05668f2..b7eb1297 100644 --- a/render/backend/vulkan/include/vulkan/Buffer.h +++ b/runtime/render/backend/vulkan/include/vulkan/Buffer.h @@ -11,21 +11,10 @@ namespace sky::vk { class Device; - class Buffer : public rhi::Buffer, public DevObject, public std::enable_shared_from_this { + class Buffer : public rhi::Buffer, public DevObject { public: ~Buffer() override; - struct VkDescriptor { - VkDeviceSize size = 0; - VkBufferUsageFlags usage = 0; - VmaMemoryUsage memory = VMA_MEMORY_USAGE_UNKNOWN; - VkBufferCreateFlags flags = 0; - bool allocateMem = true; - }; - - rhi::BufferViewPtr CreateView(const rhi::BufferViewDesc &desc) override; - - uint64_t GetSize() const; bool IsTransient() const; uint8_t *Map() override; void UnMap() override; @@ -36,19 +25,16 @@ namespace sky::vk { private: friend class Device; - friend class BufferView; explicit Buffer(Device &); bool Init(const Descriptor &); - bool Init(const VkDescriptor &); VkBuffer buffer; VmaAllocation allocation; VkBufferCreateInfo bufferInfo; uint8_t* mappedPtr = nullptr; }; - using BufferPtr = std::shared_ptr; } // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/CacheManager.h b/runtime/render/backend/vulkan/include/vulkan/CacheManager.h similarity index 100% rename from render/backend/vulkan/include/vulkan/CacheManager.h rename to runtime/render/backend/vulkan/include/vulkan/CacheManager.h diff --git a/render/backend/vulkan/include/vulkan/CommandBuffer.h b/runtime/render/backend/vulkan/include/vulkan/CommandBuffer.h similarity index 97% rename from render/backend/vulkan/include/vulkan/CommandBuffer.h rename to runtime/render/backend/vulkan/include/vulkan/CommandBuffer.h index 6ad33160..dfe6d897 100644 --- a/render/backend/vulkan/include/vulkan/CommandBuffer.h +++ b/runtime/render/backend/vulkan/include/vulkan/CommandBuffer.h @@ -70,6 +70,8 @@ namespace sky::vk { rhi::GraphicsEncoder &BeginPass(const rhi::PassBeginInfo &info) override; rhi::GraphicsEncoder &BindPipeline(const rhi::GraphicsPipelinePtr &pso) override; rhi::GraphicsEncoder &BindAssembly(const rhi::VertexAssemblyPtr &assembly) override; + rhi::GraphicsEncoder &BindVertexBuffers(const std::vector &vbs) override; + rhi::GraphicsEncoder &BindIndexBuffer(const rhi::BufferView& view, rhi::IndexType type) override; rhi::GraphicsEncoder &SetViewport(uint32_t count, const rhi::Viewport *viewport) override; rhi::GraphicsEncoder &SetScissor(uint32_t count, const rhi::Rect2D *scissor) override; rhi::GraphicsEncoder &DrawIndexed(const rhi::CmdDrawIndexed &indexed) override; diff --git a/render/backend/vulkan/include/vulkan/CommandPool.h b/runtime/render/backend/vulkan/include/vulkan/CommandPool.h similarity index 100% rename from render/backend/vulkan/include/vulkan/CommandPool.h rename to runtime/render/backend/vulkan/include/vulkan/CommandPool.h diff --git a/render/backend/vulkan/include/vulkan/ComputePipeline.h b/runtime/render/backend/vulkan/include/vulkan/ComputePipeline.h similarity index 100% rename from render/backend/vulkan/include/vulkan/ComputePipeline.h rename to runtime/render/backend/vulkan/include/vulkan/ComputePipeline.h diff --git a/runtime/render/backend/vulkan/include/vulkan/Configs.h b/runtime/render/backend/vulkan/include/vulkan/Configs.h new file mode 100644 index 00000000..177c4c15 --- /dev/null +++ b/runtime/render/backend/vulkan/include/vulkan/Configs.h @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/17. +// + +#pragma once + +#if _DEBUG +#define VMA_STATS_STRING_ENABLED 1 +#endif \ No newline at end of file diff --git a/render/backend/vulkan/include/vulkan/Conversion.h b/runtime/render/backend/vulkan/include/vulkan/Conversion.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Conversion.h rename to runtime/render/backend/vulkan/include/vulkan/Conversion.h diff --git a/render/backend/vulkan/include/vulkan/DescriptorSet.h b/runtime/render/backend/vulkan/include/vulkan/DescriptorSet.h similarity index 91% rename from render/backend/vulkan/include/vulkan/DescriptorSet.h rename to runtime/render/backend/vulkan/include/vulkan/DescriptorSet.h index 677eb0a5..2d46dc09 100644 --- a/render/backend/vulkan/include/vulkan/DescriptorSet.h +++ b/runtime/render/backend/vulkan/include/vulkan/DescriptorSet.h @@ -13,7 +13,6 @@ #include #include #include -#include #include namespace sky::vk { @@ -24,11 +23,12 @@ namespace sky::vk { ~DescriptorSet() override; VkDescriptorSet GetNativeHandle() const; + uint32_t GetDescriptorNum() const { return layout->GetDescriptorNum(); } static std::shared_ptr Allocate(const DescriptorSetPoolPtr &pool, const DescriptorSetLayoutPtr &layout); DescriptorSetLayoutPtr GetLayout() const { return layout; } - void BindBuffer(uint32_t binding, const rhi::BufferViewPtr &view, uint32_t index) override; + void BindBuffer(uint32_t binding, const rhi::BufferView &view, uint32_t index) override; void BindBuffer(uint32_t binding, const rhi::BufferPtr &buffer, uint64_t offset, uint64_t size, uint32_t index) override; void BindImageView(uint32_t binding, const rhi::ImageViewPtr &view, uint32_t index, rhi::DescriptorBindFlags flags) override; void BindSampler(uint32_t binding, const rhi::SamplerPtr &sampler, uint32_t index) override; diff --git a/render/backend/vulkan/include/vulkan/DescriptorSetBinder.h b/runtime/render/backend/vulkan/include/vulkan/DescriptorSetBinder.h similarity index 100% rename from render/backend/vulkan/include/vulkan/DescriptorSetBinder.h rename to runtime/render/backend/vulkan/include/vulkan/DescriptorSetBinder.h diff --git a/render/backend/vulkan/include/vulkan/DescriptorSetLayout.h b/runtime/render/backend/vulkan/include/vulkan/DescriptorSetLayout.h similarity index 100% rename from render/backend/vulkan/include/vulkan/DescriptorSetLayout.h rename to runtime/render/backend/vulkan/include/vulkan/DescriptorSetLayout.h diff --git a/render/backend/vulkan/include/vulkan/DescriptorSetPool.h b/runtime/render/backend/vulkan/include/vulkan/DescriptorSetPool.h similarity index 100% rename from render/backend/vulkan/include/vulkan/DescriptorSetPool.h rename to runtime/render/backend/vulkan/include/vulkan/DescriptorSetPool.h diff --git a/render/backend/vulkan/include/vulkan/DevObject.h b/runtime/render/backend/vulkan/include/vulkan/DevObject.h similarity index 89% rename from render/backend/vulkan/include/vulkan/DevObject.h rename to runtime/render/backend/vulkan/include/vulkan/DevObject.h index 2f2ce1d6..f46e9a10 100644 --- a/render/backend/vulkan/include/vulkan/DevObject.h +++ b/runtime/render/backend/vulkan/include/vulkan/DevObject.h @@ -13,7 +13,7 @@ namespace sky::vk { class DevObject { public: - DevObject(Device &dev) : device(dev) + explicit DevObject(Device &dev) : device(dev) { } virtual ~DevObject() = default; diff --git a/render/backend/vulkan/include/vulkan/Device.h b/runtime/render/backend/vulkan/include/vulkan/Device.h similarity index 95% rename from render/backend/vulkan/include/vulkan/Device.h rename to runtime/render/backend/vulkan/include/vulkan/Device.h index 18e1b8da..1034ada7 100644 --- a/render/backend/vulkan/include/vulkan/Device.h +++ b/runtime/render/backend/vulkan/include/vulkan/Device.h @@ -51,12 +51,15 @@ namespace sky::vk { return res; } + std::string GetDeviceInfo() const override; void WaitIdle() const override; VmaAllocator GetAllocator() const; VkDevice GetNativeHandle() const; VkPhysicalDevice GetGpuHandle() const; - VkInstance GetInstance() const; + VkInstance GetInstanceId() const; + + Instance &GetInstance() const { return instance; } // Queue Queue *GetQueue(VkQueueFlags preferred, VkQueueFlags excluded) const; @@ -97,6 +100,10 @@ namespace sky::vk { CREATE_DEV_OBJ(QueryPool) CREATE_DEV_OBJ_FUNC(Semaphore, Sema) +#ifdef SKY_ENABLE_XR + CREATE_DEV_OBJ(XRSwapChain) +#endif + const SamplerPtr &GetDefaultSampler() const { return defaultSampler; } // Special Device Object @@ -111,7 +118,7 @@ namespace sky::vk { uint32_t CheckPipelineStatisticFlags(const rhi::PipelineStatisticFlags &val, rhi::PipelineStatisticFlags &res) override; private: bool Init(const Descriptor &, bool enableDebug); - + void InitPropAndFeatureChain(); void ValidateFeature(const rhi::DeviceFeature &feature, std::vector &outExtensions); void UpdateDeviceLimits(); void UpdateFormatFeatures(); @@ -167,4 +174,6 @@ namespace sky::vk { CacheManager accessInfos; }; + const std::vector &GetDeviceExtensions(); + } // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/DrawItem.h b/runtime/render/backend/vulkan/include/vulkan/DrawItem.h similarity index 100% rename from render/backend/vulkan/include/vulkan/DrawItem.h rename to runtime/render/backend/vulkan/include/vulkan/DrawItem.h diff --git a/render/backend/vulkan/include/vulkan/Ext.h b/runtime/render/backend/vulkan/include/vulkan/Ext.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Ext.h rename to runtime/render/backend/vulkan/include/vulkan/Ext.h diff --git a/render/backend/vulkan/include/vulkan/Fence.h b/runtime/render/backend/vulkan/include/vulkan/Fence.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Fence.h rename to runtime/render/backend/vulkan/include/vulkan/Fence.h diff --git a/render/backend/vulkan/include/vulkan/FrameBuffer.h b/runtime/render/backend/vulkan/include/vulkan/FrameBuffer.h similarity index 86% rename from render/backend/vulkan/include/vulkan/FrameBuffer.h rename to runtime/render/backend/vulkan/include/vulkan/FrameBuffer.h index 13957ac1..fca14f8e 100644 --- a/render/backend/vulkan/include/vulkan/FrameBuffer.h +++ b/runtime/render/backend/vulkan/include/vulkan/FrameBuffer.h @@ -26,11 +26,8 @@ namespace sky::vk { std::vector views; }; - VkFramebuffer GetNativeHandle() const; - - const VkExtent2D &GetExtent() const; - - uint32_t GetAttachmentCount() const; + VkFramebuffer GetNativeHandle() const { return frameBuffer; } + const VkExtent2D &GetVkExtent() const { return descriptor.extent; } private: friend class Device; diff --git a/render/backend/vulkan/include/vulkan/GraphicsPipeline.h b/runtime/render/backend/vulkan/include/vulkan/GraphicsPipeline.h similarity index 100% rename from render/backend/vulkan/include/vulkan/GraphicsPipeline.h rename to runtime/render/backend/vulkan/include/vulkan/GraphicsPipeline.h diff --git a/render/backend/vulkan/include/vulkan/Image.h b/runtime/render/backend/vulkan/include/vulkan/Image.h similarity index 98% rename from render/backend/vulkan/include/vulkan/Image.h rename to runtime/render/backend/vulkan/include/vulkan/Image.h index a89da67c..b41914af 100644 --- a/render/backend/vulkan/include/vulkan/Image.h +++ b/runtime/render/backend/vulkan/include/vulkan/Image.h @@ -47,6 +47,7 @@ namespace sky::vk { friend class Device; friend class ImageView; friend class SwapChain; + friend class XRSwapChain; rhi::ImageViewPtr CreateView(const rhi::ImageViewDesc &desc) override; explicit Image(Device &); diff --git a/render/backend/vulkan/include/vulkan/ImageView.h b/runtime/render/backend/vulkan/include/vulkan/ImageView.h similarity index 62% rename from render/backend/vulkan/include/vulkan/ImageView.h rename to runtime/render/backend/vulkan/include/vulkan/ImageView.h index 334695ea..040b6482 100644 --- a/render/backend/vulkan/include/vulkan/ImageView.h +++ b/runtime/render/backend/vulkan/include/vulkan/ImageView.h @@ -19,15 +19,6 @@ namespace sky::vk { explicit ImageView(Device &); ~ImageView() override; - struct VkDescriptor { - VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D; - VkFormat format = VK_FORMAT_UNDEFINED; - VkComponentMapping components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY}; - VkImageSubresourceRange subResourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - }; - - static std::shared_ptr CreateImageView(const ImagePtr &image, const ImageView::VkDescriptor &des); std::shared_ptr CreateView(const rhi::ImageViewDesc &desc) const override; rhi::PixelFormat GetFormat() const override; const rhi::Extent3D &GetExtent() const override; @@ -41,7 +32,6 @@ namespace sky::vk { friend class SwapChain; bool Init(const rhi::ImageViewDesc &); - bool Init(const VkDescriptor &); ImagePtr source; VkImageView view; diff --git a/render/backend/vulkan/include/vulkan/Instance.h b/runtime/render/backend/vulkan/include/vulkan/Instance.h similarity index 70% rename from render/backend/vulkan/include/vulkan/Instance.h rename to runtime/render/backend/vulkan/include/vulkan/Instance.h index c7268a97..242fc66d 100644 --- a/render/backend/vulkan/include/vulkan/Instance.h +++ b/runtime/render/backend/vulkan/include/vulkan/Instance.h @@ -10,21 +10,19 @@ #include "vulkan/Ext.h" namespace sky::vk { - class Instance : public rhi::Instance { public: Instance(); - ~Instance(); + ~Instance() override; static Instance *Create(const Descriptor &); static void Destroy(Instance *); - Device *CreateDevice(const Device::Descriptor &); + Device *CreateDevice(const Device::Descriptor &) override; VkInstance GetInstance() const; private: - bool Init(const Descriptor &); - static void PrintSupportedExtensions() ; + bool Init(const Descriptor &) override; VkInstance instance; VkDebugUtilsMessengerEXT debug; @@ -32,4 +30,7 @@ namespace sky::vk { uint32_t minorVersion = 0; }; + const std::vector &GetInstanceExtensions(); + const std::vector &GetValidationLayers(); + } // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/MemoryPool.h b/runtime/render/backend/vulkan/include/vulkan/MemoryPool.h similarity index 100% rename from render/backend/vulkan/include/vulkan/MemoryPool.h rename to runtime/render/backend/vulkan/include/vulkan/MemoryPool.h diff --git a/render/backend/vulkan/include/vulkan/PipelineLayout.h b/runtime/render/backend/vulkan/include/vulkan/PipelineLayout.h similarity index 100% rename from render/backend/vulkan/include/vulkan/PipelineLayout.h rename to runtime/render/backend/vulkan/include/vulkan/PipelineLayout.h diff --git a/render/backend/vulkan/include/vulkan/PipelineLibrary.h b/runtime/render/backend/vulkan/include/vulkan/PipelineLibrary.h similarity index 100% rename from render/backend/vulkan/include/vulkan/PipelineLibrary.h rename to runtime/render/backend/vulkan/include/vulkan/PipelineLibrary.h diff --git a/render/backend/vulkan/include/vulkan/PushConstants.h b/runtime/render/backend/vulkan/include/vulkan/PushConstants.h similarity index 100% rename from render/backend/vulkan/include/vulkan/PushConstants.h rename to runtime/render/backend/vulkan/include/vulkan/PushConstants.h diff --git a/render/backend/vulkan/include/vulkan/QueryPool.h b/runtime/render/backend/vulkan/include/vulkan/QueryPool.h similarity index 100% rename from render/backend/vulkan/include/vulkan/QueryPool.h rename to runtime/render/backend/vulkan/include/vulkan/QueryPool.h diff --git a/render/backend/vulkan/include/vulkan/Queue.h b/runtime/render/backend/vulkan/include/vulkan/Queue.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Queue.h rename to runtime/render/backend/vulkan/include/vulkan/Queue.h diff --git a/render/backend/vulkan/include/vulkan/RenderPass.h b/runtime/render/backend/vulkan/include/vulkan/RenderPass.h similarity index 100% rename from render/backend/vulkan/include/vulkan/RenderPass.h rename to runtime/render/backend/vulkan/include/vulkan/RenderPass.h diff --git a/render/backend/vulkan/include/vulkan/Sampler.h b/runtime/render/backend/vulkan/include/vulkan/Sampler.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Sampler.h rename to runtime/render/backend/vulkan/include/vulkan/Sampler.h diff --git a/render/backend/vulkan/include/vulkan/Semaphore.h b/runtime/render/backend/vulkan/include/vulkan/Semaphore.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Semaphore.h rename to runtime/render/backend/vulkan/include/vulkan/Semaphore.h diff --git a/render/backend/vulkan/include/vulkan/Shader.h b/runtime/render/backend/vulkan/include/vulkan/Shader.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Shader.h rename to runtime/render/backend/vulkan/include/vulkan/Shader.h diff --git a/render/backend/vulkan/include/vulkan/ShaderOption.h b/runtime/render/backend/vulkan/include/vulkan/ShaderOption.h similarity index 100% rename from render/backend/vulkan/include/vulkan/ShaderOption.h rename to runtime/render/backend/vulkan/include/vulkan/ShaderOption.h diff --git a/render/backend/vulkan/include/vulkan/SparseImage.h b/runtime/render/backend/vulkan/include/vulkan/SparseImage.h similarity index 96% rename from render/backend/vulkan/include/vulkan/SparseImage.h rename to runtime/render/backend/vulkan/include/vulkan/SparseImage.h index 14d0593a..13b7b5dc 100644 --- a/render/backend/vulkan/include/vulkan/SparseImage.h +++ b/runtime/render/backend/vulkan/include/vulkan/SparseImage.h @@ -50,7 +50,7 @@ namespace sky::vk { private: friend class Device; - SparseImage(Device &dev) : DevObject(dev) {} + explicit SparseImage(Device &dev) : DevObject(dev) {} bool Init(const VkDescriptor &); void InitMipTail(); diff --git a/render/backend/vulkan/include/vulkan/Swapchain.h b/runtime/render/backend/vulkan/include/vulkan/Swapchain.h similarity index 68% rename from render/backend/vulkan/include/vulkan/Swapchain.h rename to runtime/render/backend/vulkan/include/vulkan/Swapchain.h index 9828bed8..d5d07a8d 100644 --- a/render/backend/vulkan/include/vulkan/Swapchain.h +++ b/runtime/render/backend/vulkan/include/vulkan/Swapchain.h @@ -12,6 +12,11 @@ #include #include +#ifdef SKY_ENABLE_XR +#include +#endif + + namespace sky::vk { class Device; @@ -31,20 +36,11 @@ namespace sky::vk { VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; }; - struct PresentInfo { - std::vector signals; - uint32_t imageIndex = 0; - }; - void Resize(uint32_t width, uint32_t height, void* window) override; // for vulkan - VkSwapchainKHR GetNativeHandle() const; - VkFormat GetVkFormat() const; - const VkExtent2D &GetVkExtent() const; - void Present(const PresentInfo &) const; + VkSwapchainKHR GetNativeHandle() const { return swapChain; }; VkResult AcquireNext(const SemaphorePtr& semaphore, uint32_t &next) const; - ImagePtr GetVkImage(uint32_t image) const; // for rhi uint32_t AcquireNextImage(const rhi::SemaphorePtr &semaphore) override; @@ -63,7 +59,6 @@ namespace sky::vk { explicit SwapChain(Device &); bool Init(const Descriptor &); - bool Init(const VkDescriptor &); bool CreateSurface(); void DestroySurface(); @@ -86,4 +81,31 @@ namespace sky::vk { using SwapChainPtr = std::shared_ptr; +#ifdef SKY_ENABLE_XR + class XRSwapChain : public rhi::XRSwapChain, public DevObject { + public: + explicit XRSwapChain(Device &dev); + ~XRSwapChain() override; + + uint32_t AcquireNextImage() override; + void Present() override; + + uint32_t GetArrayLayers() const override { return arrayLayers; } + uint32_t GetImageCount() const override { return static_cast(images.size()); } + rhi::PixelFormat GetFormat() const override { return format; } + rhi::ImagePtr GetImage(uint32_t index) const override { return images[index]; } + rhi::ImageViewPtr GetImageView(uint32_t index) const override { return imageViews[index]; } + const rhi::Extent2D &GetExtent() const override { return extent; } + private: + friend class Device; + bool Init(const Descriptor &); + + rhi::PixelFormat format; + rhi::Extent2D extent; + uint32_t arrayLayers; + std::vector images; + std::vector imageViews; + }; + using XRSwapChainPtr = std::shared_ptr; +#endif } // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/TransientPool.h b/runtime/render/backend/vulkan/include/vulkan/TransientPool.h similarity index 100% rename from render/backend/vulkan/include/vulkan/TransientPool.h rename to runtime/render/backend/vulkan/include/vulkan/TransientPool.h diff --git a/render/backend/vulkan/include/vulkan/Util.h b/runtime/render/backend/vulkan/include/vulkan/Util.h similarity index 100% rename from render/backend/vulkan/include/vulkan/Util.h rename to runtime/render/backend/vulkan/include/vulkan/Util.h diff --git a/runtime/render/backend/vulkan/include/vulkan/VertexAssembly.h b/runtime/render/backend/vulkan/include/vulkan/VertexAssembly.h new file mode 100644 index 00000000..129c2390 --- /dev/null +++ b/runtime/render/backend/vulkan/include/vulkan/VertexAssembly.h @@ -0,0 +1,37 @@ +// +// Created by Zach Lee on 2022/7/31. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky::vk { + class Device; + + class VertexAssembly : public rhi::VertexAssembly, public DevObject { + public: + explicit VertexAssembly(Device &dev) : DevObject(dev) {} + ~VertexAssembly() override = default; + + void OnBind(VkCommandBuffer) const; + + private: + friend class Device; + bool Init(const Descriptor &desc); + + void SetVertexInput(VertexInputPtr input); + void AddVertexBuffer(const rhi::BufferView &buffer); + + VertexInputPtr vertexInput; + std::vector vertexBuffers; + std::vector vkBuffers; + std::vector offsets; + }; + using VertexAssemblyPtr = std::shared_ptr; + +} // namespace sky::vk diff --git a/render/backend/vulkan/include/vulkan/VertexInput.h b/runtime/render/backend/vulkan/include/vulkan/VertexInput.h similarity index 100% rename from render/backend/vulkan/include/vulkan/VertexInput.h rename to runtime/render/backend/vulkan/include/vulkan/VertexInput.h diff --git a/runtime/render/backend/vulkan/platform/android/PlatformImpl.cpp b/runtime/render/backend/vulkan/platform/android/PlatformImpl.cpp new file mode 100644 index 00000000..e30dc7e8 --- /dev/null +++ b/runtime/render/backend/vulkan/platform/android/PlatformImpl.cpp @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/3/12. +// + +#include + +namespace sky::vk { + + std::vector INSTANCE_EXTENSIONS = { + "VK_KHR_surface", + "VK_KHR_android_surface", + }; + + const std::vector DEVICE_EXTENSIONS = {"VK_KHR_swapchain"}; + std::vector EMPTY; + + const std::vector &GetInstanceExtensions() + { + return INSTANCE_EXTENSIONS; + } + + const std::vector &GetValidationLayers() + { + return EMPTY; + } + + const std::vector &GetDeviceExtensions() + { + return DEVICE_EXTENSIONS; + } +} // namespace sky::vk \ No newline at end of file diff --git a/render/backend/vulkan/platform/android/SwapchainImpl.cpp b/runtime/render/backend/vulkan/platform/android/SwapchainImpl.cpp similarity index 82% rename from render/backend/vulkan/platform/android/SwapchainImpl.cpp rename to runtime/render/backend/vulkan/platform/android/SwapchainImpl.cpp index ecbb2086..3e6eea07 100644 --- a/render/backend/vulkan/platform/android/SwapchainImpl.cpp +++ b/runtime/render/backend/vulkan/platform/android/SwapchainImpl.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -20,7 +21,7 @@ namespace sky::vk { surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; surfaceInfo.window = reinterpret_cast(descriptor.window); - VkResult rst = vkCreateAndroidSurfaceKHR(device.GetInstance(), &surfaceInfo, VKL_ALLOC, &surface); + VkResult rst = vkCreateAndroidSurfaceKHR(device.GetInstance().GetInstance(), &surfaceInfo, VKL_ALLOC, &surface); if (rst != VK_SUCCESS) { LOG_E(TAG, "create win32 surface failed, %d", rst); return false; diff --git a/runtime/render/backend/vulkan/platform/macos/PlatformImpl.cpp b/runtime/render/backend/vulkan/platform/macos/PlatformImpl.cpp new file mode 100644 index 00000000..15d84b97 --- /dev/null +++ b/runtime/render/backend/vulkan/platform/macos/PlatformImpl.cpp @@ -0,0 +1,36 @@ +// +// Created by blues on 2024/3/12. +// + +#include + +namespace sky::vk { + + std::vector INSTANCE_EXTENSIONS = { + "VK_KHR_surface", + "VK_KHR_portability_enumeration", + "VK_MVK_macos_surface", + "VK_EXT_metal_surface", +#if _DEBUG + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, +#endif + }; + const std::vector DEVICE_EXTENSIONS = {"VK_KHR_swapchain", "VK_KHR_portability_subset"}; + const std::vector VALIDATION_LAYERS = {"VK_LAYER_KHRONOS_validation"}; + + const std::vector &GetInstanceExtensions() + { + return INSTANCE_EXTENSIONS; + } + + const std::vector &GetValidationLayers() + { + return VALIDATION_LAYERS; + } + + const std::vector &GetDeviceExtensions() + { + return DEVICE_EXTENSIONS; + } + +} // namespace sky::vk \ No newline at end of file diff --git a/render/backend/vulkan/platform/macos/SwapchainImpl.mm b/runtime/render/backend/vulkan/platform/macos/SwapchainImpl.mm similarity index 88% rename from render/backend/vulkan/platform/macos/SwapchainImpl.mm rename to runtime/render/backend/vulkan/platform/macos/SwapchainImpl.mm index 54495cd8..52346ea8 100644 --- a/render/backend/vulkan/platform/macos/SwapchainImpl.mm +++ b/runtime/render/backend/vulkan/platform/macos/SwapchainImpl.mm @@ -24,7 +24,7 @@ createInfo.pView = view; createInfo.pNext = nullptr; - if (vkCreateMacOSSurfaceMVK(device.GetInstance(), &createInfo, nullptr, &surface) != VK_SUCCESS) { + if (vkCreateMacOSSurfaceMVK(device.GetInstanceId(), &createInfo, nullptr, &surface) != VK_SUCCESS) { return false; } return true; diff --git a/runtime/render/backend/vulkan/platform/windows/PlatformImpl.cpp b/runtime/render/backend/vulkan/platform/windows/PlatformImpl.cpp new file mode 100644 index 00000000..4e536a26 --- /dev/null +++ b/runtime/render/backend/vulkan/platform/windows/PlatformImpl.cpp @@ -0,0 +1,34 @@ +// +// Created by blues on 2024/3/12. +// + +#include + +namespace sky::vk { + + std::vector INSTANCE_EXTENSIONS = { + "VK_KHR_surface", + "VK_KHR_win32_surface", +#if _DEBUG + VK_EXT_DEBUG_UTILS_EXTENSION_NAME, +#endif + }; + const std::vector DEVICE_EXTENSIONS = {"VK_KHR_swapchain"}; + const std::vector VALIDATION_LAYERS = {"VK_LAYER_KHRONOS_validation"}; + + const std::vector &GetInstanceExtensions() + { + return INSTANCE_EXTENSIONS; + } + + const std::vector &GetValidationLayers() + { + return VALIDATION_LAYERS; + } + + const std::vector &GetDeviceExtensions() + { + return DEVICE_EXTENSIONS; + } + +} // namespace sky::vk \ No newline at end of file diff --git a/render/backend/vulkan/platform/windows/SwapchainImpl.cpp b/runtime/render/backend/vulkan/platform/windows/SwapchainImpl.cpp similarity index 92% rename from render/backend/vulkan/platform/windows/SwapchainImpl.cpp rename to runtime/render/backend/vulkan/platform/windows/SwapchainImpl.cpp index 6c0bc9c2..10168f08 100644 --- a/render/backend/vulkan/platform/windows/SwapchainImpl.cpp +++ b/runtime/render/backend/vulkan/platform/windows/SwapchainImpl.cpp @@ -20,7 +20,7 @@ namespace sky::vk { surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; surfaceInfo.hwnd = (HWND)descriptor.window; surfaceInfo.hinstance = GetModuleHandle(0); - VkResult rst = vkCreateWin32SurfaceKHR(device.GetInstance(), &surfaceInfo, VKL_ALLOC, &surface); + VkResult rst = vkCreateWin32SurfaceKHR(device.GetInstanceId(), &surfaceInfo, VKL_ALLOC, &surface); if (rst != VK_SUCCESS) { LOG_E(TAG, "create win32 surface failed, %d", rst); return false; diff --git a/render/backend/vulkan/src/Barrier.cpp b/runtime/render/backend/vulkan/src/Barrier.cpp similarity index 100% rename from render/backend/vulkan/src/Barrier.cpp rename to runtime/render/backend/vulkan/src/Barrier.cpp diff --git a/render/backend/vulkan/src/Buffer.cpp b/runtime/render/backend/vulkan/src/Buffer.cpp similarity index 66% rename from render/backend/vulkan/src/Buffer.cpp rename to runtime/render/backend/vulkan/src/Buffer.cpp index f5c2ed0e..4f07ffff 100644 --- a/render/backend/vulkan/src/Buffer.cpp +++ b/runtime/render/backend/vulkan/src/Buffer.cpp @@ -50,33 +50,6 @@ namespace sky::vk { return true; } - bool Buffer::Init(const VkDescriptor &des) - { - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = des.size; - bufferInfo.usage = des.usage; - - VkResult res; - if (des.allocateMem) { - VmaAllocationCreateInfo allocInfo = {}; - allocInfo.usage = des.memory; - res = vmaCreateBuffer(device.GetAllocator(), &bufferInfo, &allocInfo, &buffer, - &allocation, nullptr); - } else { - res = vkCreateBuffer(device.GetNativeHandle(), &bufferInfo, VKL_ALLOC, &buffer); - } - if (res != VK_SUCCESS) { - LOG_E(TAG, "create buffer failed, %d", res); - return false; - } - return true; - } - - uint64_t Buffer::GetSize() const - { - return bufferInfo.size; - } - VkBuffer Buffer::GetNativeHandle() const { return buffer; @@ -110,14 +83,4 @@ namespace sky::vk { vmaFreeMemory(device.GetAllocator(), allocation); allocation = VK_NULL_HANDLE; } - - rhi::BufferViewPtr Buffer::CreateView(const rhi::BufferViewDesc &desc) - { - BufferViewPtr ret = std::make_shared(device); - ret->source = shared_from_this(); - if (!ret->Init(desc)) { - ret = nullptr; - } - return std::static_pointer_cast(ret); - } } // namespace sky::vk diff --git a/render/backend/vulkan/src/CommandBuffer.cpp b/runtime/render/backend/vulkan/src/CommandBuffer.cpp similarity index 96% rename from render/backend/vulkan/src/CommandBuffer.cpp rename to runtime/render/backend/vulkan/src/CommandBuffer.cpp index a76ec968..3766d4b8 100644 --- a/render/backend/vulkan/src/CommandBuffer.cpp +++ b/runtime/render/backend/vulkan/src/CommandBuffer.cpp @@ -364,7 +364,7 @@ namespace sky::vk { void GraphicsEncoder::BeginPass(const PassBeginInfo &beginInfo) { vkBeginInfo.renderPass = beginInfo.renderPass->GetNativeHandle(); - const auto &extent = beginInfo.frameBuffer->GetExtent(); + const auto &extent = beginInfo.frameBuffer->GetVkExtent(); if (beginInfo.renderArea != nullptr) { vkBeginInfo.renderArea = *beginInfo.renderArea; @@ -507,7 +507,7 @@ namespace sky::vk { } vkBeginInfo.renderPass = pass->GetNativeHandle(); - const auto &extent = fb->GetExtent(); + const auto &extent = fb->GetVkExtent(); vkBeginInfo.framebuffer = fb->GetNativeHandle(); vkBeginInfo.renderArea.offset.x = 0; @@ -550,6 +550,32 @@ namespace sky::vk { return *this; } + rhi::GraphicsEncoder &GraphicsEncoder::BindVertexBuffers(const std::vector &vbs) + { + std::vector vertexBuffers; + std::vector offsets; + + auto vbSize = static_cast(vbs.size()); + vertexBuffers.reserve(vbSize); + offsets.reserve(vbSize); + + for (const auto &vb : vbs) { + auto vBuffer = std::static_pointer_cast(vb.buffer); + vertexBuffers.emplace_back(vBuffer->GetNativeHandle()); + offsets.emplace_back(vb.offset); + } + + vkCmdBindVertexBuffers(cmd, 0, vbSize, vertexBuffers.data(), offsets.data()); + return *this; + } + + rhi::GraphicsEncoder &GraphicsEncoder::BindIndexBuffer(const rhi::BufferView& view, rhi::IndexType type) + { + auto vBuffer = std::static_pointer_cast(view.buffer); + vkCmdBindIndexBuffer(cmd, vBuffer->GetNativeHandle(), view.offset, FromRHI(type)); + return *this; + } + rhi::GraphicsEncoder &GraphicsEncoder::SetViewport(uint32_t count, const rhi::Viewport *viewports) { std::vector vkViewPorts(count); diff --git a/render/backend/vulkan/src/CommandPool.cpp b/runtime/render/backend/vulkan/src/CommandPool.cpp similarity index 100% rename from render/backend/vulkan/src/CommandPool.cpp rename to runtime/render/backend/vulkan/src/CommandPool.cpp diff --git a/render/backend/vulkan/src/ComputePipeline.cpp b/runtime/render/backend/vulkan/src/ComputePipeline.cpp similarity index 100% rename from render/backend/vulkan/src/ComputePipeline.cpp rename to runtime/render/backend/vulkan/src/ComputePipeline.cpp diff --git a/render/backend/vulkan/src/Conversion.cpp b/runtime/render/backend/vulkan/src/Conversion.cpp similarity index 97% rename from render/backend/vulkan/src/Conversion.cpp rename to runtime/render/backend/vulkan/src/Conversion.cpp index 323f2ef7..86a0517c 100644 --- a/render/backend/vulkan/src/Conversion.cpp +++ b/runtime/render/backend/vulkan/src/Conversion.cpp @@ -54,13 +54,18 @@ namespace sky::vk { std::unordered_map FORMAT_TABLE = { {rhi::Format::UNDEFINED, VK_FORMAT_UNDEFINED}, - {rhi::Format::F_R32, VK_FORMAT_R32_SFLOAT}, - {rhi::Format::F_RG32, VK_FORMAT_R32G32_SFLOAT}, - {rhi::Format::F_RGB32, VK_FORMAT_R32G32B32_SFLOAT}, - {rhi::Format::F_RGBA32, VK_FORMAT_R32G32B32A32_SFLOAT}, - {rhi::Format::F_R8, VK_FORMAT_R8_UNORM}, - {rhi::Format::F_RG8, VK_FORMAT_R8G8_UNORM}, - {rhi::Format::F_RGBA8, VK_FORMAT_R8G8B8A8_UNORM}, + {rhi::Format::F_R32, VK_FORMAT_R32_SFLOAT}, + {rhi::Format::F_RG32, VK_FORMAT_R32G32_SFLOAT}, + {rhi::Format::F_RGB32, VK_FORMAT_R32G32B32_SFLOAT}, + {rhi::Format::F_RGBA32, VK_FORMAT_R32G32B32A32_SFLOAT}, + {rhi::Format::F_R8, VK_FORMAT_R8_UNORM}, + {rhi::Format::F_RG8, VK_FORMAT_R8G8_UNORM}, + {rhi::Format::F_RGB8, VK_FORMAT_R8G8B8_UNORM}, + {rhi::Format::F_RGBA8, VK_FORMAT_R8G8B8A8_UNORM}, + {rhi::Format::U_R32, VK_FORMAT_R32_UINT}, + {rhi::Format::U_RG32, VK_FORMAT_R32G32_UINT}, + {rhi::Format::U_RGB32, VK_FORMAT_R32G32B32_UINT}, + {rhi::Format::U_RGBA32, VK_FORMAT_R32G32B32A32_UINT}, }; std::unordered_map SAMPLER_ADDRESS_TABLE = { diff --git a/render/backend/vulkan/src/DescriptorSet.cpp b/runtime/render/backend/vulkan/src/DescriptorSet.cpp similarity index 93% rename from render/backend/vulkan/src/DescriptorSet.cpp rename to runtime/render/backend/vulkan/src/DescriptorSet.cpp index e0104625..8427691f 100644 --- a/render/backend/vulkan/src/DescriptorSet.cpp +++ b/runtime/render/backend/vulkan/src/DescriptorSet.cpp @@ -105,17 +105,16 @@ namespace sky::vk { } } - void DescriptorSet::BindBuffer(uint32_t binding, const rhi::BufferViewPtr &view, uint32_t index) + void DescriptorSet::BindBuffer(uint32_t binding, const rhi::BufferView &view, uint32_t index) { - auto vkBufferView = std::static_pointer_cast(view); + auto vkBuffer = std::static_pointer_cast(view.buffer); auto &writeInfo = writeInfos[layout->GetDescriptorSetOffsetByBinding(binding) + index]; - const auto &viewInfo = vkBufferView->GetViewDesc(); - if (writeInfo.buffer.buffer != vkBufferView->GetBuffer()->GetNativeHandle() || - writeInfo.buffer.offset != viewInfo.offset || - writeInfo.buffer.range != viewInfo.range) { - writeInfo.buffer.buffer = vkBufferView->GetBuffer()->GetNativeHandle(); - writeInfo.buffer.range = viewInfo.range; - writeInfo.buffer.offset = viewInfo.offset; + if (writeInfo.buffer.buffer != vkBuffer->GetNativeHandle() || + writeInfo.buffer.offset != view.offset || + writeInfo.buffer.range != view.range) { + writeInfo.buffer.buffer = vkBuffer->GetNativeHandle(); + writeInfo.buffer.range = view.range; + writeInfo.buffer.offset = view.offset; dirty = true; } } diff --git a/render/backend/vulkan/src/DescriptorSetBinder.cpp b/runtime/render/backend/vulkan/src/DescriptorSetBinder.cpp similarity index 100% rename from render/backend/vulkan/src/DescriptorSetBinder.cpp rename to runtime/render/backend/vulkan/src/DescriptorSetBinder.cpp diff --git a/render/backend/vulkan/src/DescriptorSetLayout.cpp b/runtime/render/backend/vulkan/src/DescriptorSetLayout.cpp similarity index 90% rename from render/backend/vulkan/src/DescriptorSetLayout.cpp rename to runtime/render/backend/vulkan/src/DescriptorSetLayout.cpp index 3b1d0261..a4ae9c97 100644 --- a/render/backend/vulkan/src/DescriptorSetLayout.cpp +++ b/runtime/render/backend/vulkan/src/DescriptorSetLayout.cpp @@ -27,16 +27,18 @@ namespace sky::vk { bool DescriptorSetLayout::Init(const Descriptor &desc) { - descriptorCount = 0; bindings = desc.bindings; + std::sort(bindings.begin(), bindings.end(), [](const SetBinding& v1, const SetBinding& v2) -> bool { + return v1.binding < v2.binding; + }); - std::vector bindings; + std::vector vkBindings; std::vector bindingFlags; std::vector entries; std::list samplers; descriptorNum = 0; - for (const auto &binding : desc.bindings) { + for (const auto &binding : bindings) { HashCombine32(hash, Crc32::Cal(binding.binding)); HashCombine32(hash, Crc32::Cal(binding.count)); HashCombine32(hash, Crc32::Cal(binding.type)); @@ -50,7 +52,7 @@ namespace sky::vk { layoutBinding.descriptorCount = binding.count; layoutBinding.stageFlags = FromRHI(binding.visibility); layoutBinding.pImmutableSamplers = nullptr; - bindings.emplace_back(layoutBinding); + vkBindings.emplace_back(layoutBinding); bindingFlags.emplace_back(FromRHI(binding.flags)); if (IsDynamicDescriptor(layoutBinding.descriptorType)) { dynamicNum += binding.count; @@ -81,8 +83,8 @@ namespace sky::vk { VkDescriptorSetLayoutCreateInfo layoutInfo = {}; layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; layoutInfo.pNext = &setLayoutBindingFlags; - layoutInfo.bindingCount = static_cast(bindings.size()); - layoutInfo.pBindings = bindings.data(); + layoutInfo.bindingCount = static_cast(vkBindings.size()); + layoutInfo.pBindings = vkBindings.data(); layout = device.GetDescriptorSetLayout(hash, &layoutInfo); if (layout == VK_NULL_HANDLE) { return false; diff --git a/render/backend/vulkan/src/DescriptorSetPool.cpp b/runtime/render/backend/vulkan/src/DescriptorSetPool.cpp similarity index 100% rename from render/backend/vulkan/src/DescriptorSetPool.cpp rename to runtime/render/backend/vulkan/src/DescriptorSetPool.cpp diff --git a/render/backend/vulkan/src/Device.cpp b/runtime/render/backend/vulkan/src/Device.cpp similarity index 74% rename from render/backend/vulkan/src/Device.cpp rename to runtime/render/backend/vulkan/src/Device.cpp index b37d7818..3049d7a3 100644 --- a/render/backend/vulkan/src/Device.cpp +++ b/runtime/render/backend/vulkan/src/Device.cpp @@ -3,27 +3,30 @@ // #include -#include #include #include #include #include -#include +#include -static const char *TAG = "Vulkan"; -const std::vector DEVICE_EXTS = {"VK_KHR_swapchain", -#ifdef __APPLE__ - "VK_KHR_portability_subset" +#include + +#ifdef SKY_ENABLE_XR +#include #endif -}; + +#include +#include + +static const char *TAG = "Vulkan"; const std::vector VALIDATION_LAYERS = {"VK_LAYER_KHRONOS_validation"}; namespace sky::vk { int32_t Device::FindProperties( uint32_t memoryTypeBits, VkMemoryPropertyFlags requiredProperties) const { - auto &properties = memoryProperties.memoryProperties; + const auto &properties = memoryProperties.memoryProperties; const uint32_t memoryCount = properties.memoryTypeCount; for (uint32_t i = 0; i < memoryCount; ++i) { const bool isRequiredMemoryType = static_cast(memoryTypeBits & (1 << i)); @@ -52,16 +55,24 @@ namespace sky::vk { } queues.clear(); - if (allocator != VK_NULL_HANDLE) { - vmaDestroyAllocator(allocator); - } - samplers.Shutdown(); setLayouts.Shutdown(); pipelineLayouts.Shutdown(); pipelines.Shutdown(); renderPasses.Shutdown(); +#ifdef _DEBUG + char* str = nullptr; + vmaBuildStatsString(allocator, &str, VK_TRUE); + std::fstream stream("device.txt", std::ios::out | std::ios::binary); + stream.write(str, static_cast(strlen(str) + 1)); + vmaFreeStatsString(allocator, str); +#endif + + if (allocator != VK_NULL_HANDLE) { + vmaDestroyAllocator(allocator); + } + if (device != VK_NULL_HANDLE) { vkDestroyDevice(device, VKL_ALLOC); } @@ -77,53 +88,53 @@ namespace sky::vk { void Device::ValidateFeature(const rhi::DeviceFeature &feature, std::vector &outExtensions) { - enabledPhyFeatures.multiViewport = feature.multiView && phyFeatures.features.multiViewport; + enabledPhyFeatures.multiViewport = static_cast(feature.multiView && (phyFeatures.features.multiViewport != 0u)); enabledPhyFeatures.samplerAnisotropy = phyFeatures.features.samplerAnisotropy; enabledPhyFeatures.pipelineStatisticsQuery = phyFeatures.features.pipelineStatisticsQuery; enabledPhyFeatures.inheritedQueries = phyFeatures.features.inheritedQueries; enabledPhyFeatures.fragmentStoresAndAtomics = phyFeatures.features.fragmentStoresAndAtomics; - enabledPhyFeatures.multiDrawIndirect = feature.multiDrawIndirect && phyFeatures.features.multiDrawIndirect; - enabledPhyFeatures.drawIndirectFirstInstance = feature.firstInstanceIndirect && phyFeatures.features.drawIndirectFirstInstance; + enabledPhyFeatures.multiDrawIndirect = static_cast(feature.multiDrawIndirect && (phyFeatures.features.multiDrawIndirect != 0u)); + enabledPhyFeatures.drawIndirectFirstInstance = static_cast(feature.firstInstanceIndirect && (phyFeatures.features.drawIndirectFirstInstance != 0u)); - enabledFeature.sparseBinding = CheckFeature(feature.sparseBinding, + enabledFeature.sparseBinding = (CheckFeature(feature.sparseBinding, phyFeatures.features.sparseBinding, phyFeatures.features.sparseResidencyBuffer, phyFeatures.features.sparseResidencyImage2D, - phyFeatures.features.shaderResourceResidency); - enabledPhyFeatures.sparseBinding = enabledFeature.sparseBinding; - enabledPhyFeatures.sparseResidencyBuffer = enabledFeature.sparseBinding; - enabledPhyFeatures.sparseResidencyImage2D = enabledFeature.sparseBinding; - enabledPhyFeatures.shaderResourceResidency = enabledFeature.sparseBinding; + phyFeatures.features.shaderResourceResidency) != 0u); + enabledPhyFeatures.sparseBinding = static_cast(enabledFeature.sparseBinding); + enabledPhyFeatures.sparseResidencyBuffer = static_cast(enabledFeature.sparseBinding); + enabledPhyFeatures.sparseResidencyImage2D = static_cast(enabledFeature.sparseBinding); + enabledPhyFeatures.shaderResourceResidency = static_cast(enabledFeature.sparseBinding); - enabledFeature.descriptorIndexing = CheckFeature(feature.descriptorIndexing, + enabledFeature.descriptorIndexing = (CheckFeature(feature.descriptorIndexing, phyIndexingFeatures.runtimeDescriptorArray, phyIndexingFeatures.descriptorBindingVariableDescriptorCount, - phyIndexingFeatures.shaderSampledImageArrayNonUniformIndexing) && CheckExtension(supportedExtensions, "VK_EXT_descriptor_indexing"); + phyIndexingFeatures.shaderSampledImageArrayNonUniformIndexing) != 0u) && CheckExtension(supportedExtensions, "VK_EXT_descriptor_indexing"); enabledPhyIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES; - enabledPhyIndexingFeatures.runtimeDescriptorArray = enabledFeature.descriptorIndexing; - enabledPhyIndexingFeatures.descriptorBindingVariableDescriptorCount = enabledFeature.descriptorIndexing; - enabledPhyIndexingFeatures.shaderSampledImageArrayNonUniformIndexing = enabledFeature.descriptorIndexing; + enabledPhyIndexingFeatures.runtimeDescriptorArray = static_cast(enabledFeature.descriptorIndexing); + enabledPhyIndexingFeatures.descriptorBindingVariableDescriptorCount = static_cast(enabledFeature.descriptorIndexing); + enabledPhyIndexingFeatures.shaderSampledImageArrayNonUniformIndexing = static_cast(enabledFeature.descriptorIndexing); if (enabledFeature.descriptorIndexing) { outExtensions.emplace_back("VK_EXT_descriptor_indexing"); } - enabledFeature.variableRateShading = CheckFeature(feature.variableRateShading, + enabledFeature.variableRateShading = (CheckFeature(feature.variableRateShading, shadingRateFeatures.attachmentFragmentShadingRate, shadingRateFeatures.pipelineFragmentShadingRate, - shadingRateFeatures.primitiveFragmentShadingRate) && CheckExtension(supportedExtensions, "VK_KHR_fragment_shading_rate"); + shadingRateFeatures.primitiveFragmentShadingRate) != 0u) && CheckExtension(supportedExtensions, "VK_KHR_fragment_shading_rate"); enabledShadingRateFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR; - enabledShadingRateFeatures.attachmentFragmentShadingRate = enabledFeature.variableRateShading; - enabledShadingRateFeatures.pipelineFragmentShadingRate = enabledFeature.variableRateShading; - enabledShadingRateFeatures.primitiveFragmentShadingRate = enabledFeature.variableRateShading; + enabledShadingRateFeatures.attachmentFragmentShadingRate = static_cast(enabledFeature.variableRateShading); + enabledShadingRateFeatures.pipelineFragmentShadingRate = static_cast(enabledFeature.variableRateShading); + enabledShadingRateFeatures.primitiveFragmentShadingRate = static_cast(enabledFeature.variableRateShading); enabledPhyIndexingFeatures.pNext = &enabledShadingRateFeatures; if (enabledFeature.variableRateShading) { outExtensions.emplace_back("VK_KHR_fragment_shading_rate"); } - enabledFeature.multiView = CheckFeature(feature.multiView, - mvrFeature.multiview) && CheckExtension(supportedExtensions, "VK_KHR_multiview"); + enabledFeature.multiView = (CheckFeature(feature.multiView, + mvrFeature.multiview) != 0u) && CheckExtension(supportedExtensions, "VK_KHR_multiview"); enabledMvrFeature.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES; - enabledMvrFeature.multiview = enabledFeature.multiView; + enabledMvrFeature.multiview = static_cast(enabledFeature.multiView); enabledShadingRateFeatures.pNext = &enabledMvrFeature; if (enabledFeature.multiView) { outExtensions.emplace_back("VK_KHR_multiview"); @@ -156,20 +167,8 @@ namespace sky::vk { constants.flipY = true; } - bool Device::Init(const Descriptor &des, bool enableDebug) + void Device::InitPropAndFeatureChain() { - auto *vkInstance = instance.GetInstance(); - - uint32_t count = 0; - // Pick Physical Device - vkEnumeratePhysicalDevices(vkInstance, &count, nullptr); - if (count == 0) { - return false; - } - - std::vector phyDevices(count); - vkEnumeratePhysicalDevices(vkInstance, &count, phyDevices.data()); - phyFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; phyFeatures.pNext = &phyIndexingFeatures; @@ -187,18 +186,66 @@ namespace sky::vk { shadingRateProps.pNext = &dsResolveProps; dsResolveProps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR; + } + + bool Device::Init(const Descriptor &des, bool enableDebug) + { + VkInstance vkInstance = instance.GetInstance(); + + InitPropAndFeatureChain(); + std::vector extensions = GetDeviceExtensions(); +#ifdef SKY_ENABLE_XR + auto *xrInterface = instance.GetXRInterface(); + std::vector extensionNames; + if (xrInterface != nullptr) { + auto *xrInstance = xrInterface->GetXrInstanceHandle(); + auto xrSystemId = xrInterface->GetXrSystemId(); + + XrGraphicsRequirementsVulkanKHR requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR}; + auto gfxReqFunc = reinterpret_cast(xrInterface->GetFunction("xrGetVulkanGraphicsRequirementsKHR")); + gfxReqFunc(xrInstance, xrSystemId, &requirements); + + auto devExtFunc = reinterpret_cast(xrInterface->GetFunction("xrGetVulkanDeviceExtensionsKHR")); + uint32_t extensionNamesSize = 0; + devExtFunc(xrInstance, xrSystemId, 0, &extensionNamesSize, nullptr); + extensionNames.resize(extensionNamesSize); + devExtFunc(xrInstance, xrSystemId, extensionNamesSize, &extensionNamesSize, extensionNames.data()); + + std::vector xrExtensions = rhi::ParseExtensionString(extensionNames.data()); + for (auto &ext : xrExtensions) { + extensions.emplace_back(ext); + } + + auto func = reinterpret_cast(xrInterface->GetFunction("xrGetVulkanGraphicsDeviceKHR")); + func(xrInstance, xrSystemId, vkInstance, &phyDev); - uint32_t i = 0; - for (; i < count; ++i) { - auto *pDev = phyDevices[i]; - vkGetPhysicalDeviceFeatures2(pDev, &phyFeatures); - vkGetPhysicalDeviceProperties2(pDev, &phyProps); + vkGetPhysicalDeviceFeatures2(phyDev, &phyFeatures); + vkGetPhysicalDeviceProperties2(phyDev, &phyProps); + } +#endif - if (phyProps.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - break; + uint32_t count = 0; + if (phyDev == VK_NULL_HANDLE) { + // Pick Physical Device + vkEnumeratePhysicalDevices(vkInstance, &count, nullptr); + if (count == 0) { + return false; } + + std::vector phyDevices(count); + vkEnumeratePhysicalDevices(vkInstance, &count, phyDevices.data()); + uint32_t i = 0; + for (; i < count; ++i) { + auto *pDev = phyDevices[i]; + vkGetPhysicalDeviceFeatures2(pDev, &phyFeatures); + vkGetPhysicalDeviceProperties2(pDev, &phyProps); + + if (phyProps.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { + break; + } + } + phyDev = phyDevices[i >= count ? 0 : i]; } - phyDev = phyDevices[i >= count ? 0 : i]; vkEnumerateDeviceExtensionProperties(phyDev, nullptr, &count, nullptr); supportedExtensions.resize(count); @@ -224,14 +271,13 @@ namespace sky::vk { std::vector queueCreateInfos; VkDeviceQueueCreateInfo queueInfo = {}; queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - for (i = 0; i < count; ++i) { + for (uint32_t i = 0; i < count; ++i) { queueInfo.queueFamilyIndex = i; queueInfo.queueCount = 1; queueInfo.pQueuePriorities = &queuePriority; queueCreateInfos.emplace_back(queueInfo); LOG_I(TAG, "queue family index %u, count %u, flags %u", i, queueFamilies[i].queueCount, queueFamilies[i].queueFlags); } - std::vector extensions = DEVICE_EXTS; ValidateFeature(des.feature, extensions); UpdateDeviceLimits(); UpdateFormatFeatures(); @@ -273,7 +319,7 @@ namespace sky::vk { } queues.resize(count); - for (i = 0; i < count; ++i) { + for (uint32_t i = 0; i < count; ++i) { VkQueue queue = VK_NULL_HANDLE; vkGetDeviceQueue(device, i, 0, &queue); queues[i] = std::unique_ptr(new Queue(*this, queue, i)); @@ -292,6 +338,19 @@ namespace sky::vk { // update barrier map ValidateAccessInfoMapByExtension(supportedExtensions); +#ifdef SKY_ENABLE_XR + if (xrInterface != nullptr) { + XrGraphicsBindingVulkanKHR binding{XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR}; + binding.instance = vkInstance; + binding.physicalDevice = phyDev; + binding.device = device; + binding.queueFamilyIndex = graphicsQueue->GetQueueFamilyIndex(); + binding.queueIndex = 0; + + xrInterface->SetSessionGraphicsBinding(&binding); + } +#endif + SetupDefaultResources(); LoadDevice(device); // PrintSupportedExtensions(); @@ -313,21 +372,20 @@ namespace sky::vk { return phyDev; } - VkInstance Device::GetInstance() const + VkInstance Device::GetInstanceId() const { return instance.GetInstance(); } Queue *Device::GetQueue(VkQueueFlags preferred, VkQueueFlags excluded) const { - Queue *res = nullptr; for (uint32_t i = 0; i < queueFamilies.size(); ++i) { const auto& flag = queueFamilies[i].queueFlags; if (((flag & preferred) == preferred) && ((flag & excluded) == 0)) { - res = queues[i].get(); + return queues[i].get(); } } - return res; + return nullptr; } Queue *Device::GetGraphicsQueue() const @@ -437,6 +495,16 @@ namespace sky::vk { vkDeviceWaitIdle(device); } + std::string Device::GetDeviceInfo() const + { + VkPhysicalDeviceProperties2 prop = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2}; + vkGetPhysicalDeviceProperties2(phyDev, &prop); + + std::string ret; + ret += prop.properties.deviceName; + return ret; + } + bool Device::FillMemoryRequirements(VkMemoryRequirements2 &requirements, const VkMemoryDedicatedRequirements &dedicated, VkMemoryPropertyFlags flags, MemoryRequirement &out) const { int32_t index = FindProperties(requirements.memoryRequirements.memoryTypeBits, flags); @@ -488,7 +556,7 @@ namespace sky::vk { void Device::PrintSupportedExtensions() const { - for (auto &ext : supportedExtensions) { + for (const auto &ext : supportedExtensions) { LOG_I(TAG, "supported device extensions name %s, version %u", ext.extensionName, ext.specVersion); } } @@ -513,7 +581,7 @@ namespace sky::vk { uint32_t count = 0; res = rhi::PipelineStatisticFlags {0}; - for (auto &support : supportedFlags) { + for (const auto &support : supportedFlags) { if (val & support) { res |= support; ++count; @@ -524,8 +592,12 @@ namespace sky::vk { rhi::Queue *Device::GetQueue(rhi::QueueType type) const { - if (type == rhi::QueueType::COMPUTE) return computeQueue; - if (type == rhi::QueueType::TRANSFER) return transferQueue; + if (type == rhi::QueueType::COMPUTE) { + return computeQueue; + } + if (type == rhi::QueueType::TRANSFER) { + return transferQueue; + } return graphicsQueue; } diff --git a/render/backend/vulkan/src/Ext.cpp b/runtime/render/backend/vulkan/src/Ext.cpp similarity index 100% rename from render/backend/vulkan/src/Ext.cpp rename to runtime/render/backend/vulkan/src/Ext.cpp diff --git a/render/backend/vulkan/src/Fence.cpp b/runtime/render/backend/vulkan/src/Fence.cpp similarity index 100% rename from render/backend/vulkan/src/Fence.cpp rename to runtime/render/backend/vulkan/src/Fence.cpp diff --git a/render/backend/vulkan/src/FrameBuffer.cpp b/runtime/render/backend/vulkan/src/FrameBuffer.cpp similarity index 88% rename from render/backend/vulkan/src/FrameBuffer.cpp rename to runtime/render/backend/vulkan/src/FrameBuffer.cpp index 3c9a5d58..883d09b7 100644 --- a/render/backend/vulkan/src/FrameBuffer.cpp +++ b/runtime/render/backend/vulkan/src/FrameBuffer.cpp @@ -70,19 +70,4 @@ namespace sky::vk { descriptor = des; return true; } - - VkFramebuffer FrameBuffer::GetNativeHandle() const - { - return frameBuffer; - } - - const VkExtent2D &FrameBuffer::GetExtent() const - { - return descriptor.extent; - } - - uint32_t FrameBuffer::GetAttachmentCount() const - { - return static_cast(descriptor.views.size()); - } } // namespace sky::vk diff --git a/render/backend/vulkan/src/GraphicsPipeline.cpp b/runtime/render/backend/vulkan/src/GraphicsPipeline.cpp similarity index 97% rename from render/backend/vulkan/src/GraphicsPipeline.cpp rename to runtime/render/backend/vulkan/src/GraphicsPipeline.cpp index f2058835..9f0e4f44 100644 --- a/render/backend/vulkan/src/GraphicsPipeline.cpp +++ b/runtime/render/backend/vulkan/src/GraphicsPipeline.cpp @@ -144,6 +144,13 @@ namespace sky::vk { pipelineLayout = std::static_pointer_cast(des.pipelineLayout); renderPass = std::static_pointer_cast(des.renderPass); + auto num = pipelineLayout->GetSetNumber(); + for (uint32_t i = 0; i < num; ++i) { + if (pipelineLayout->GetLayout(i)->GetDescriptorNum() != 0) { + descriptorMask |= 1 << (i); + } + } + pipelineInfo.layout = pipelineLayout->GetNativeHandle(); pipelineInfo.renderPass = renderPass->GetNativeHandle(); pipelineInfo.subpass = des.subPassIndex; diff --git a/render/backend/vulkan/src/Image.cpp b/runtime/render/backend/vulkan/src/Image.cpp similarity index 100% rename from render/backend/vulkan/src/Image.cpp rename to runtime/render/backend/vulkan/src/Image.cpp diff --git a/render/backend/vulkan/src/ImageView.cpp b/runtime/render/backend/vulkan/src/ImageView.cpp similarity index 66% rename from render/backend/vulkan/src/ImageView.cpp rename to runtime/render/backend/vulkan/src/ImageView.cpp index 76a0b16a..a0b4a1df 100644 --- a/render/backend/vulkan/src/ImageView.cpp +++ b/runtime/render/backend/vulkan/src/ImageView.cpp @@ -23,22 +23,6 @@ namespace sky::vk { } } - bool ImageView::Init(const VkDescriptor &des) - { - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = source->GetNativeHandle(); - viewInfo.viewType = des.viewType; - viewInfo.format = des.format; - viewInfo.components = des.components; - viewInfo.subresourceRange = des.subResourceRange; - VkResult rst = vkCreateImageView(device.GetNativeHandle(), &viewInfo, VKL_ALLOC, &view); - if (rst != VK_SUCCESS) { - LOG_E(TAG, "create image view failed, -%d", rst); - return false; - } - return true; - } - bool ImageView::Init(const rhi::ImageViewDesc &desc) { viewDesc = desc; @@ -71,19 +55,6 @@ namespace sky::vk { return source->CreateView(desc); } - std::shared_ptr ImageView::CreateImageView(const ImagePtr &image, const ImageView::VkDescriptor &des) - { - ImageViewPtr ret; - if (image) { - ret = std::make_shared(image->device); - ret->source = image; - if (!ret->Init(des)) { - ret = nullptr; - } - } - return ret; - } - rhi::PixelFormat ImageView::GetFormat() const { return source->GetDescriptor().format; diff --git a/render/backend/vulkan/src/Instance.cpp b/runtime/render/backend/vulkan/src/Instance.cpp similarity index 79% rename from render/backend/vulkan/src/Instance.cpp rename to runtime/render/backend/vulkan/src/Instance.cpp index 3599a4b8..385a1f4e 100644 --- a/render/backend/vulkan/src/Instance.cpp +++ b/runtime/render/backend/vulkan/src/Instance.cpp @@ -2,10 +2,17 @@ // Created by Zach Lee on 2021/11/7. // -#include "vulkan/Instance.h" -#include +#include #include -#include "core/logger/Logger.h" +#include + +#include + +#ifdef SKY_ENABLE_XR +#include +#endif + +#include static const char *TAG = "Vulkan"; @@ -45,31 +52,6 @@ namespace sky::vk { return VK_FALSE; } - const std::vector extensions = { - "VK_KHR_surface", - "VK_KHR_get_physical_device_properties2", - -#if !__ANDROID__ && _DEBUG - VK_EXT_DEBUG_UTILS_EXTENSION_NAME, -#endif - -#if _WIN32 - "VK_KHR_win32_surface", -#elif __ANDROID__ - "VK_KHR_android_surface", -#elif __APPLE__ - "VK_KHR_portability_enumeration", - "VK_MVK_macos_surface", - "VK_EXT_metal_surface", -#endif - }; - -#if !defined(__ANDROID__) - const std::vector validationLayers = {"VK_LAYER_KHRONOS_validation"}; -#else - const std::vector validationLayers; -#endif - Instance *Instance::Create(const Descriptor &des) { auto *instance = new Instance(); @@ -114,6 +96,35 @@ namespace sky::vk { bool Instance::Init(const Descriptor &des) { + uint32_t count; + vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); + std::vector supported(count); + vkEnumerateInstanceExtensionProperties(nullptr, &count, supported.data()); + + auto extensions = GetInstanceExtensions(); + +#ifdef SKY_ENABLE_XR + xrInterface = des.xrInterface; + std::vector extensionNames; + if (xrInterface != nullptr) { + PFN_xrGetVulkanInstanceExtensionsKHR func = reinterpret_cast(xrInterface->GetFunction("xrGetVulkanInstanceExtensionsKHR")); + uint32_t extensionNamesSize = 0; + func(xrInterface->GetXrInstanceHandle(), xrInterface->GetXrSystemId(), 0, &extensionNamesSize, nullptr); + extensionNames.resize(extensionNamesSize); + func(xrInterface->GetXrInstanceHandle(), xrInterface->GetXrSystemId(), extensionNamesSize, &extensionNamesSize, extensionNames.data()); + + std::vector xrExtensions = rhi::ParseExtensionString(extensionNames.data()); + for (auto &ext : xrExtensions) { + auto iter = std::find_if(supported.begin(), supported.end(), [ext](const auto &prop) { + return strcmp(ext, prop.extensionName) == 0; + }); + if (iter != supported.end()) { + extensions.emplace_back(ext); + } + } + } +#endif + uint32_t version = 0; vkEnumerateInstanceVersion(&version); majorVersion = SKY_VK_API_VERSION_MAJOR(version); @@ -140,8 +151,9 @@ namespace sky::vk { VkDebugUtilsMessengerCreateInfoEXT debugInfo = {}; if (des.enableDebugLayer) { - instInfo.enabledLayerCount = static_cast(validationLayers.size()); - instInfo.ppEnabledLayerNames = validationLayers.data(); + const auto &layers = GetValidationLayers(); + instInfo.enabledLayerCount = static_cast(layers.size()); + instInfo.ppEnabledLayerNames = layers.data(); debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; debugInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; @@ -162,7 +174,6 @@ namespace sky::vk { } LoadInstance(instance, minorVersion); - PrintSupportedExtensions(); return true; } @@ -170,16 +181,4 @@ namespace sky::vk { { return instance; } - - void Instance::PrintSupportedExtensions() - { - uint32_t count; - vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); - std::vector supported(count); - vkEnumerateInstanceExtensionProperties(nullptr, &count, supported.data()); - for (auto &ext : supported) { - LOG_I(TAG, "supported extensions name %s, version %u", ext.extensionName, ext.specVersion); - } - } - } // namespace sky::vk diff --git a/render/backend/vulkan/src/MemoryPool.cpp b/runtime/render/backend/vulkan/src/MemoryPool.cpp similarity index 100% rename from render/backend/vulkan/src/MemoryPool.cpp rename to runtime/render/backend/vulkan/src/MemoryPool.cpp diff --git a/render/backend/vulkan/src/PipelineLayout.cpp b/runtime/render/backend/vulkan/src/PipelineLayout.cpp similarity index 100% rename from render/backend/vulkan/src/PipelineLayout.cpp rename to runtime/render/backend/vulkan/src/PipelineLayout.cpp diff --git a/render/backend/vulkan/src/PipelineLibrary.cpp b/runtime/render/backend/vulkan/src/PipelineLibrary.cpp similarity index 94% rename from render/backend/vulkan/src/PipelineLibrary.cpp rename to runtime/render/backend/vulkan/src/PipelineLibrary.cpp index 499c8228..7b997834 100644 --- a/render/backend/vulkan/src/PipelineLibrary.cpp +++ b/runtime/render/backend/vulkan/src/PipelineLibrary.cpp @@ -26,7 +26,7 @@ namespace sky::vk { cacheInfo.pInitialData = desc.data; auto res = vkCreatePipelineCache(device.GetNativeHandle(), &cacheInfo, VKL_ALLOC, &cache); if (res != VK_SUCCESS) { - LOG_E(TAG, "create buffer failed, %d", res); + LOG_E(TAG, "create pipeline cache failed, %d", res); return false; } diff --git a/render/backend/vulkan/src/PushConstants.cpp b/runtime/render/backend/vulkan/src/PushConstants.cpp similarity index 100% rename from render/backend/vulkan/src/PushConstants.cpp rename to runtime/render/backend/vulkan/src/PushConstants.cpp diff --git a/render/backend/vulkan/src/QueryPool.cpp b/runtime/render/backend/vulkan/src/QueryPool.cpp similarity index 97% rename from render/backend/vulkan/src/QueryPool.cpp rename to runtime/render/backend/vulkan/src/QueryPool.cpp index 5d0fc457..11002770 100644 --- a/render/backend/vulkan/src/QueryPool.cpp +++ b/runtime/render/backend/vulkan/src/QueryPool.cpp @@ -74,7 +74,8 @@ namespace sky::vk { void QueryPool::Reset(uint32_t first, uint32_t count) const { - vkResetQueryPool(device.GetNativeHandle(), pool, first, count); + // TODO: Android SDK 29 +// vkResetQueryPool(device.GetNativeHandle(), pool, first, count); } void QueryPool::ConvertPipelineStatisticData(const rhi::BufferPtr &buffer, uint32_t offset, uint32_t size, diff --git a/render/backend/vulkan/src/Queue.cpp b/runtime/render/backend/vulkan/src/Queue.cpp similarity index 99% rename from render/backend/vulkan/src/Queue.cpp rename to runtime/render/backend/vulkan/src/Queue.cpp index 2a840226..542e0184 100644 --- a/render/backend/vulkan/src/Queue.cpp +++ b/runtime/render/backend/vulkan/src/Queue.cpp @@ -197,7 +197,7 @@ namespace sky::vk { copy.srcOffset = view.offset; copy.dstOffset = dstOffset; - request.source->ReadData(dstOffset, copy.size, view.ptr); + request.source->ReadData(request.offset + dstOffset, copy.size, view.ptr); inflightCommands[currentFrameId]->Copy(std::static_pointer_cast(stagingBuffer->GetBuffer()), vkBuffer, copy); dstOffset += BUFFER_PER_FRAME_SIZE; diff --git a/render/backend/vulkan/src/RenderPass.cpp b/runtime/render/backend/vulkan/src/RenderPass.cpp similarity index 100% rename from render/backend/vulkan/src/RenderPass.cpp rename to runtime/render/backend/vulkan/src/RenderPass.cpp diff --git a/render/backend/vulkan/src/Sampler.cpp b/runtime/render/backend/vulkan/src/Sampler.cpp similarity index 100% rename from render/backend/vulkan/src/Sampler.cpp rename to runtime/render/backend/vulkan/src/Sampler.cpp diff --git a/render/backend/vulkan/src/Semaphore.cpp b/runtime/render/backend/vulkan/src/Semaphore.cpp similarity index 100% rename from render/backend/vulkan/src/Semaphore.cpp rename to runtime/render/backend/vulkan/src/Semaphore.cpp diff --git a/render/backend/vulkan/src/Shader.cpp b/runtime/render/backend/vulkan/src/Shader.cpp similarity index 100% rename from render/backend/vulkan/src/Shader.cpp rename to runtime/render/backend/vulkan/src/Shader.cpp diff --git a/render/backend/vulkan/src/ShaderOption.cpp b/runtime/render/backend/vulkan/src/ShaderOption.cpp similarity index 100% rename from render/backend/vulkan/src/ShaderOption.cpp rename to runtime/render/backend/vulkan/src/ShaderOption.cpp diff --git a/render/backend/vulkan/src/SparseImage.cpp b/runtime/render/backend/vulkan/src/SparseImage.cpp similarity index 93% rename from render/backend/vulkan/src/SparseImage.cpp rename to runtime/render/backend/vulkan/src/SparseImage.cpp index ae4ae98c..dba4b269 100644 --- a/render/backend/vulkan/src/SparseImage.cpp +++ b/runtime/render/backend/vulkan/src/SparseImage.cpp @@ -10,7 +10,7 @@ namespace sky::vk { static bool Check1D(uint32_t length, int32_t offset, uint32_t total, uint32_t granularity) { - return length % granularity == 0 ? true : (length + offset) == total; + return length % granularity == 0 || (length + offset) == total; } static bool CheckPage(const VkExtent3D &extent, const SparseImage::VkPageInfo &pageExtent, const VkExtent3D &imageGranularity) @@ -25,7 +25,7 @@ namespace sky::vk { image = nullptr; view = nullptr; - auto allocator = device.GetAllocator(); + auto *allocator = device.GetAllocator(); for (auto &page : pageMemory) { vmaFreeMemoryPages(allocator, 1, &page.allocation); } @@ -58,7 +58,7 @@ namespace sky::vk { imageDesc.allocateMem = false; image = device.CreateDeviceObject(imageDesc); - auto &imageInfo = image->GetImageInfo(); + const auto &imageInfo = image->GetImageInfo(); vkGetImageMemoryRequirements(device.GetNativeHandle(), image->GetNativeHandle(), &memReq); @@ -73,11 +73,12 @@ namespace sky::vk { InitMipTail(); } - ImageView::VkDescriptor viewDesc = {}; - viewDesc.format = imageInfo.format; - viewDesc.viewType = desc.viewType; - viewDesc.subResourceRange = {sparseMemReq.formatProperties.aspectMask, 0, imageInfo.mipLevels, 0, imageInfo.arrayLayers}; - view = ImageView::CreateImageView(image, viewDesc); + // TODO +// ImageView::VkDescriptor viewDesc = {}; +// viewDesc.format = imageInfo.format; +// viewDesc.viewType = desc.viewType; +// viewDesc.subResourceRange = {sparseMemReq.formatProperties.aspectMask, 0, imageInfo.mipLevels, 0, imageInfo.arrayLayers}; +// view = ImageView::CreateImageView(image, viewDesc); VmaPoolCreateInfo poolInfo = {}; poolInfo.memoryTypeIndex = device.FindProperties(memReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); @@ -88,7 +89,7 @@ namespace sky::vk { void SparseImage::InitMipTail() { - auto allocator = device.GetAllocator(); + auto *allocator = device.GetAllocator(); auto allocateFn = [this, allocator](VkDeviceSize offset) { VmaAllocationCreateInfo allocationCreateInfo = {}; allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; @@ -147,7 +148,7 @@ namespace sky::vk { page.level = info.level; page.layer = info.layer; - auto allocator = device.GetAllocator(); + auto *allocator = device.GetAllocator(); VmaAllocationCreateInfo allocationCreateInfo = {}; allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; allocationCreateInfo.pool = pool; diff --git a/render/backend/vulkan/src/Swapchain.cpp b/runtime/render/backend/vulkan/src/Swapchain.cpp similarity index 64% rename from render/backend/vulkan/src/Swapchain.cpp rename to runtime/render/backend/vulkan/src/Swapchain.cpp index a3add8f3..58726671 100644 --- a/render/backend/vulkan/src/Swapchain.cpp +++ b/runtime/render/backend/vulkan/src/Swapchain.cpp @@ -2,13 +2,19 @@ // Created by Zach Lee on 2021/11/7. // -#include "vulkan/Swapchain.h" -#include "core/logger/Logger.h" -#include "vulkan/Basic.h" -#include "vulkan/Device.h" -#include "vulkan/ImageView.h" -#include "vulkan/Semaphore.h" -#include "vulkan/Conversion.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SKY_ENABLE_XR +#include +#endif + static const char *TAG = "Vulkan"; namespace sky::vk { @@ -44,54 +50,14 @@ namespace sky::vk { return true; } - bool SwapChain::Init(const VkDescriptor &des) - { - descriptor = des; - if (!CreateSurface()) { - return false; - } - - if (!CreateSwapChain()) { - return false; - } - return true; - } - - VkSwapchainKHR SwapChain::GetNativeHandle() const - { - return swapChain; - } - void SwapChain::DestroySurface() { if (surface != VK_NULL_HANDLE) { - vkDestroySurfaceKHR(device.GetInstance(), surface, VKL_ALLOC); + vkDestroySurfaceKHR(device.GetInstanceId(), surface, VKL_ALLOC); surface = VK_NULL_HANDLE; } } - VkFormat SwapChain::GetVkFormat() const - { - return format.format; - } - - const VkExtent2D &SwapChain::GetVkExtent() const - { - return extent; - } - - void SwapChain::Present(const PresentInfo &info) const - { - std::vector semaphores; - for (const auto &sem : info.signals) { - semaphores.emplace_back(sem->GetNativeHandle()); - } - - VkPresentInfoKHR presentInfo = { - VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, nullptr, (uint32_t)semaphores.size(), semaphores.data(), 1, &swapChain, &info.imageIndex}; - vkQueuePresentKHR(queue->GetNativeHandle(), &presentInfo); - } - bool SwapChain::CreateSwapChain() { std::pair preferred[] = { @@ -116,7 +82,7 @@ namespace sky::vk { std::vector formats; std::vector presentModes; - VkResult rst = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &capabilities); + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &capabilities); uint32_t num = 0; vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &num, nullptr); @@ -179,7 +145,7 @@ namespace sky::vk { swcInfo.preTransform = descriptor.preTransform; swcInfo.compositeAlpha = descriptor.compositeAlpha; - rst = vkCreateSwapchainKHR(device.GetNativeHandle(), &swcInfo, VKL_ALLOC, &swapChain); + auto rst = vkCreateSwapchainKHR(device.GetNativeHandle(), &swcInfo, VKL_ALLOC, &swapChain); if (rst != VK_SUCCESS) { LOG_E(TAG, "create swapChain failed-%d", rst); return false; @@ -227,11 +193,6 @@ namespace sky::vk { CreateSwapChain(); } - ImagePtr SwapChain::GetVkImage(uint32_t image) const - { - return images[image]; - } - uint32_t SwapChain::GetImageCount() const { return imageCount; @@ -253,18 +214,97 @@ namespace sky::vk { uint32_t SwapChain::AcquireNextImage(const rhi::SemaphorePtr &semaphore) { uint32_t next = 0; - AcquireNext(std::static_pointer_cast(semaphore), next); + auto result = AcquireNext(std::static_pointer_cast(semaphore), next); + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + printf("acquire failed %d", result); + } return next; } - void SwapChain::Present(rhi::Queue &queue, const rhi::PresentInfo &info) + void SwapChain::Present(rhi::Queue &presentQueue, const rhi::PresentInfo &info) + { + std::vector semaphores; + for (const auto &sem : info.semaphores) { + semaphores.emplace_back(std::static_pointer_cast(sem)->GetNativeHandle()); + } + + VkPresentInfoKHR presentInfo = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR}; + presentInfo.waitSemaphoreCount = static_cast(semaphores.size()); + presentInfo.pWaitSemaphores = semaphores.data(); + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapChain; + presentInfo.pImageIndices = &info.imageIndex; + vkQueuePresentKHR(static_cast(presentQueue).GetNativeHandle(), &presentInfo); + } + +#ifdef SKY_ENABLE_XR + XRSwapChain::XRSwapChain(Device &dev) : DevObject(dev) + { + } + + XRSwapChain::~XRSwapChain() + { + auto *xrInterface = device.GetInstance().GetXRInterface(); + xrInterface->DestroyXrSwapChain(swapChain); + } + + uint32_t XRSwapChain::AcquireNextImage() { - PresentInfo presentInfo = {}; - presentInfo.imageIndex = info.imageIndex; - for (const auto &sema : info.semaphores) { - presentInfo.signals.emplace_back(std::static_pointer_cast(sema)); + return swapChain->AcquireNextImage(); + } + + void XRSwapChain::Present() + { + swapChain->Present(); + } + + bool XRSwapChain::Init(const Descriptor &desc) + { + auto *xrInterface = device.GetInstance().GetXRInterface(); + swapChain = xrInterface->CreateXrSwapChain({static_cast(FromRHI(desc.format))}); + XrSwapchain xrSwapChain = swapChain->GetHandle(0); + format = desc.format; + + auto fn = reinterpret_cast(xrInterface->GetFunction("xrEnumerateSwapchainImages")); + uint32_t imageCount = 0; + fn(xrSwapChain, 0, &imageCount, nullptr); + std::vector xrImages(imageCount); + std::vector headers(imageCount); + for (uint32_t i = 0; i < imageCount; ++i) { + xrImages[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; + headers[i] = reinterpret_cast(&xrImages[i]); + } + fn(xrSwapChain, imageCount, &imageCount, headers[0]); + + extent = {swapChain->GetWidth(), swapChain->GetHeight()}; + arrayLayers = swapChain->GetArrayLayers(); + + VkImageCreateInfo imageInfo = {}; + imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + imageInfo.imageType = VK_IMAGE_TYPE_2D; + imageInfo.extent = VkExtent3D{swapChain->GetWidth(), swapChain->GetHeight(), 1}; + imageInfo.mipLevels = 1; + imageInfo.arrayLayers = arrayLayers; + imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + imageInfo.format = static_cast(swapChain->GetFormat()); + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + rhi::ImageViewDesc viewInfo = {}; + viewInfo.subRange.layers = arrayLayers; + viewInfo.viewType = rhi::ImageViewType::VIEW_2D_ARRAY; + + images.resize(imageCount); + imageViews.resize(imageCount); + for (uint32_t i = 0; i < imageCount; ++i) { + images[i] = std::shared_ptr(new Image(device, xrImages[i].image)); + images[i]->imageInfo = imageInfo; + imageViews[i] = images[i]->CreateView(viewInfo); } - Present(presentInfo); + + return swapChain != nullptr; } +#endif } // namespace sky::vk diff --git a/render/backend/vulkan/src/TransientPool.cpp b/runtime/render/backend/vulkan/src/TransientPool.cpp similarity index 100% rename from render/backend/vulkan/src/TransientPool.cpp rename to runtime/render/backend/vulkan/src/TransientPool.cpp diff --git a/render/backend/vulkan/src/Util.cpp b/runtime/render/backend/vulkan/src/Util.cpp similarity index 100% rename from render/backend/vulkan/src/Util.cpp rename to runtime/render/backend/vulkan/src/Util.cpp diff --git a/render/backend/vulkan/src/VMAImpl.cpp b/runtime/render/backend/vulkan/src/VMAImpl.cpp similarity index 73% rename from render/backend/vulkan/src/VMAImpl.cpp rename to runtime/render/backend/vulkan/src/VMAImpl.cpp index 077352c2..40ce3a9b 100644 --- a/render/backend/vulkan/src/VMAImpl.cpp +++ b/runtime/render/backend/vulkan/src/VMAImpl.cpp @@ -2,7 +2,7 @@ // Created by Zach Lee on 2022/10/12. // +#include #define VMA_IMPLEMENTATION -#define VMA_STATS_STRING_ENABLED 0 #include \ No newline at end of file diff --git a/runtime/render/backend/vulkan/src/VertexAssembly.cpp b/runtime/render/backend/vulkan/src/VertexAssembly.cpp new file mode 100644 index 00000000..da6d147e --- /dev/null +++ b/runtime/render/backend/vulkan/src/VertexAssembly.cpp @@ -0,0 +1,40 @@ +// +// Created by Zach Lee on 2022/7/31. +// + +#include +#include + +#include + +namespace sky::vk { + + void VertexAssembly::SetVertexInput(VertexInputPtr input) + { + vertexInput = std::move(input); + } + + void VertexAssembly::AddVertexBuffer(const rhi::BufferView &buffer) + { + vertexBuffers.emplace_back(buffer); + vkBuffers.emplace_back(std::static_pointer_cast(buffer.buffer)->GetNativeHandle()); + offsets.emplace_back(buffer.offset); + } + + void VertexAssembly::OnBind(VkCommandBuffer cmd) const + { + if (!vkBuffers.empty()) { + vkCmdBindVertexBuffers(cmd, 0, static_cast(vkBuffers.size()), vkBuffers.data(), offsets.data()); + } + } + + bool VertexAssembly::Init(const Descriptor &desc) + { + SetVertexInput(std::static_pointer_cast(desc.vertexInput)); + for (const auto &vb : desc.vertexBuffers) { + AddVertexBuffer(vb); + } + return true; + } + +} // namespace sky::vk diff --git a/render/backend/vulkan/src/VertexInput.cpp b/runtime/render/backend/vulkan/src/VertexInput.cpp similarity index 92% rename from render/backend/vulkan/src/VertexInput.cpp rename to runtime/render/backend/vulkan/src/VertexInput.cpp index 0c3bdf28..b7645115 100644 --- a/render/backend/vulkan/src/VertexInput.cpp +++ b/runtime/render/backend/vulkan/src/VertexInput.cpp @@ -31,8 +31,8 @@ namespace sky::vk { vInputInfo.vertexBindingDescriptionCount = static_cast(bindings.size()); vInputInfo.pVertexBindingDescriptions = bindings.data(); hash = 0; - HashCombine32(hash, Crc32::Cal((uint8_t *)attributes.data(), static_cast(attributes.size()))); - HashCombine32(hash, Crc32::Cal((uint8_t *)bindings.data(), static_cast(bindings.size()))); + HashCombine32(hash, Crc32::Cal((uint8_t *)attributes.data(), static_cast(attributes.size() * sizeof(VkVertexInputAttributeDescription)))); + HashCombine32(hash, Crc32::Cal((uint8_t *)bindings.data(), static_cast(bindings.size() * sizeof(VkVertexInputBindingDescription)))); } VertexInput::Builder &VertexInput::Builder::Begin() diff --git a/render/builder/CMakeLists.txt b/runtime/render/builder/CMakeLists.txt similarity index 93% rename from render/builder/CMakeLists.txt rename to runtime/render/builder/CMakeLists.txt index 08af4331..ce562bb5 100644 --- a/render/builder/CMakeLists.txt +++ b/runtime/render/builder/CMakeLists.txt @@ -10,4 +10,4 @@ sky_add_library(TARGET RenderBuilder SHARED LINK_LIBS RenderBuilder.Static ) -sky_add_dependency(TARGET RenderBuilder DEPENDENCIES Launcher Editor AssetBrowser) +sky_add_dependency(TARGET RenderBuilder DEPENDENCIES Launcher Editor AssetBuilder) diff --git a/runtime/render/builder/module/BuilderModule.cpp b/runtime/render/builder/module/BuilderModule.cpp new file mode 100644 index 00000000..42f7544c --- /dev/null +++ b/runtime/render/builder/module/BuilderModule.cpp @@ -0,0 +1,84 @@ +// +// Created by Zach Lee on 2023/2/20. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace sky::builder { + + class BuilderModule : public IModule { + public: + BuilderModule() = default; + ~BuilderModule() override = default; + + bool Init(const StartArguments &args) override; + void Tick(float delta) override {} + void ProcessPreloadAssets(); + + private: + NativeFileSystemPtr engineFs; + NativeFileSystemPtr workSpaceFs; + }; + + bool BuilderModule::Init(const StartArguments &args) + { + auto *am = AssetBuilderManager::Get(); + am->RegisterBuilder(new ShaderBuilder()); + am->RegisterBuilder(new TechniqueBuilder()); + am->RegisterBuilder(new MaterialBuilder()); + am->RegisterBuilder(new ImageBuilder()); + am->RegisterBuilder(new PrefabBuilder()); + am->RegisterBuilder(new MeshBuilder()); + am->RegisterBuilder(new AnimationBuilder()); + am->RegisterBuilder(new SkeletonBuilder()); + + // init shader compiler + engineFs = AssetBuilderManager::Get()->GetEngineFs(); + workSpaceFs = AssetBuilderManager::Get()->GetWorkSpaceFs(); + + auto *compiler = ShaderCompiler::Get(); + compiler->AddSearchPath(engineFs->GetPath()); + compiler->AddSearchPath(workSpaceFs->GetPath()); + + ProcessPreloadAssets(); + return true; + } + + void BuilderModule::ProcessPreloadAssets() + { + auto file = workSpaceFs->OpenFile("configs/render_preload_assets.json"); + if (!file) { + return; + } + + auto archive = file->ReadAsArchive(); + JsonInputArchive json(*archive); + + uint32_t count = json.StartArray("assets"); + + for (uint32_t i = 0; i < count; ++i) { + AssetSourcePath path = {}; + path.path = json.LoadString(); + path.bundle = SourceAssetBundle::ENGINE; + + auto source = AssetDataBase::Get()->RegisterAsset(path); + SKY_ASSERT(source); + json.NextArrayElement(); + } + + json.End(); + } +} +REGISTER_MODULE(sky::builder::BuilderModule) diff --git a/render/builder/render/CMakeLists.txt b/runtime/render/builder/render/CMakeLists.txt similarity index 91% rename from render/builder/render/CMakeLists.txt rename to runtime/render/builder/render/CMakeLists.txt index fc24dbdc..8c1f2093 100644 --- a/render/builder/render/CMakeLists.txt +++ b/runtime/render/builder/render/CMakeLists.txt @@ -12,11 +12,12 @@ sky_add_library(TARGET RenderBuilder.Static STATIC LINK_LIBS Framework ShaderCompiler.Static - SkyRenderAdaptor + RenderAdaptor 3rdParty::stb 3rdParty::assimp 3rdParty::ispc_texcomp 3rdParty::meshoptimizer + 3rdParty::pmp ) sky_add_dependency(TARGET RenderBuilder DEPENDENCIES AssetTool Editor) diff --git a/runtime/render/builder/render/include/builder/render/AnimationBuilder.h b/runtime/render/builder/render/include/builder/render/AnimationBuilder.h new file mode 100644 index 00000000..4e8fbbe3 --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/AnimationBuilder.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/8/5. +// + +#pragma once + +#include +#include + +namespace sky::builder { + + class AnimationBuilder : public AssetBuilder { + public: + AnimationBuilder() = default; + ~AnimationBuilder() override = default; + + private: + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + + const std::vector &GetExtensions() const override { return extensions; } + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } + + std::vector extensions = {".anim"}; + }; + +} // namespace sky::builder \ No newline at end of file diff --git a/runtime/render/builder/render/include/builder/render/ImageBuilder.h b/runtime/render/builder/render/include/builder/render/ImageBuilder.h new file mode 100644 index 00000000..67b75531 --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/ImageBuilder.h @@ -0,0 +1,50 @@ +// +// Created by Zach Lee on 2023/2/26. +// + +#pragma once + +#include + +#include + +#include + +#include +#include + +namespace sky::builder { + + struct ImageBuildConfig { + PlatformType platform = PlatformType::Default; + bool compress = true; + bool generateMip = true; + uint32_t maxWidth = 0xFFFFFFFF; + uint32_t maxHeight = 0xFFFFFFFF; + rhi::PixelFormat alphaFormat = rhi::PixelFormat::BC7_UNORM_BLOCK; + rhi::PixelFormat opaqueFormat = rhi::PixelFormat::BC7_UNORM_BLOCK; + rhi::PixelFormat hdrFormat = rhi::PixelFormat::BC6H_SFLOAT_BLOCK; + }; + + class ImageBuilder : public AssetBuilder { + public: + ImageBuilder(); + ~ImageBuilder() override = default; + + void UseCompress(bool en) { compress = en; } + private: + void RequestDDS(const AssetBuildRequest &request, AssetBuildResult &result); + void RequestSTB(const AssetBuildRequest &request, AssetBuildResult &result); + + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + void LoadConfig(const FileSystemPtr &cfg) override; + + const std::vector &GetExtensions() const override { return extensions; } + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } + + std::vector extensions = {".jpg", ".dds", ".ktx", ".png"}; + std::unordered_map configs; + + bool compress = true; + }; +} diff --git a/render/builder/render/include/builder/render/ImageCompressor.h b/runtime/render/builder/render/include/builder/render/ImageCompressor.h similarity index 100% rename from render/builder/render/include/builder/render/ImageCompressor.h rename to runtime/render/builder/render/include/builder/render/ImageCompressor.h diff --git a/runtime/render/builder/render/include/builder/render/MaterialBuilder.h b/runtime/render/builder/render/include/builder/render/MaterialBuilder.h new file mode 100644 index 00000000..edd534a8 --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/MaterialBuilder.h @@ -0,0 +1,37 @@ +// +// Created by Zach Lee on 2023/2/23. +// + +#pragma once + +#include +#include +#include + +namespace sky::builder { + + class MaterialBuilder : public AssetBuilder { + public: + MaterialBuilder() = default; + ~MaterialBuilder() override = default; + + private: + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + + const std::vector &GetExtensions() const override + { + return extensions; + } + + std::string_view QueryType(const std::string &ext) const override + { + return ext == ".mat" ? AssetTraits::ASSET_TYPE : AssetTraits::ASSET_TYPE; + } + + static void BuildMaterial(const AssetBuildRequest &request, AssetBuildResult &result); + static void BuildMaterialInstance(const AssetBuildRequest &request, AssetBuildResult &result); + + std::vector extensions = {".mat", ".mati"}; + }; + +} diff --git a/runtime/render/builder/render/include/builder/render/MeshBuilder.h b/runtime/render/builder/render/include/builder/render/MeshBuilder.h new file mode 100644 index 00000000..7826fd8f --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/MeshBuilder.h @@ -0,0 +1,32 @@ +// +// Created by blues on 2024/7/14. +// + +#pragma once + +#include +#include + +namespace sky::builder { + class MeshBuilder : public AssetBuilder { + public: + MeshBuilder() = default; + ~MeshBuilder() override = default; + + private: + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + + const std::vector &GetExtensions() const override + { + return extensions; + } + + std::string_view QueryType(const std::string &ext) const override + { + return AssetTraits::ASSET_TYPE; + } + + std::vector extensions = {".mesh"}; + }; + +} // namespace sky::builder diff --git a/render/builder/render/include/builder/render/PrefabBuilder.h b/runtime/render/builder/render/include/builder/render/PrefabBuilder.h similarity index 56% rename from render/builder/render/include/builder/render/PrefabBuilder.h rename to runtime/render/builder/render/include/builder/render/PrefabBuilder.h index c7c3c4ce..4aae2838 100644 --- a/render/builder/render/include/builder/render/PrefabBuilder.h +++ b/runtime/render/builder/render/include/builder/render/PrefabBuilder.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include namespace sky::builder { @@ -14,14 +15,14 @@ namespace sky::builder { PrefabBuilder() = default; ~PrefabBuilder() override = default; - static constexpr std::string_view KEY = "GFX_PREFAB"; + void Import(const AssetImportRequest &request) const override; - void Request(const BuildRequest &build, BuildResult &result) override; + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; const std::vector &GetExtensions() const override { return extensions; } - + std::string_view QueryType(const std::string &ext) const override { return ext == ".prefab" ? AssetTraits::ASSET_TYPE : ""; } private: - std::vector extensions = {".gltf", ".glb", ".fbx"}; + std::vector extensions = {".gltf", ".glb", ".fbx", ".prefab"}; }; } // namespace sky::builder diff --git a/render/builder/render/include/builder/render/ShaderBuilder.h b/runtime/render/builder/render/include/builder/render/ShaderBuilder.h similarity index 58% rename from render/builder/render/include/builder/render/ShaderBuilder.h rename to runtime/render/builder/render/include/builder/render/ShaderBuilder.h index b56971fc..fbcceaab 100644 --- a/render/builder/render/include/builder/render/ShaderBuilder.h +++ b/runtime/render/builder/render/include/builder/render/ShaderBuilder.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include namespace sky::builder { @@ -14,11 +15,10 @@ namespace sky::builder { ShaderBuilder() = default; ~ShaderBuilder() override = default; - static constexpr std::string_view KEY = "GFX_SHADER"; - - void Request(const BuildRequest &build, BuildResult &result) override; - void LoadConfig(const std::string &path) override; + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + void LoadConfig(const FileSystemPtr &cfg) override; const std::vector &GetExtensions() const override { return extensions; } + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } private: std::vector extensions = {".hlsl"}; }; diff --git a/runtime/render/builder/render/include/builder/render/SkeletonBuilder.h b/runtime/render/builder/render/include/builder/render/SkeletonBuilder.h new file mode 100644 index 00000000..c065d572 --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/SkeletonBuilder.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/8/10. +// + +#pragma once + +#include +#include + +namespace sky::builder { + + class SkeletonBuilder : public AssetBuilder { + public: + SkeletonBuilder() = default; + ~SkeletonBuilder() override = default; + + private: + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; + + const std::vector &GetExtensions() const override { return extensions; } + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } + + std::vector extensions = {".skeleton"}; + }; + +} // namespace sky::builder \ No newline at end of file diff --git a/render/builder/render/include/builder/render/TechniqueBuilder.h b/runtime/render/builder/render/include/builder/render/TechniqueBuilder.h similarity index 64% rename from render/builder/render/include/builder/render/TechniqueBuilder.h rename to runtime/render/builder/render/include/builder/render/TechniqueBuilder.h index defcbb8d..7da90229 100644 --- a/render/builder/render/include/builder/render/TechniqueBuilder.h +++ b/runtime/render/builder/render/include/builder/render/TechniqueBuilder.h @@ -6,6 +6,7 @@ #include #include +#include namespace sky::builder { @@ -14,12 +15,11 @@ namespace sky::builder { TechniqueBuilder() = default; ~TechniqueBuilder() override = default; - static constexpr std::string_view KEY = "GFX_TECH"; - - void Request(const BuildRequest &build, BuildResult &result) override; + private: + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override; const std::vector &GetExtensions() const override { return extensions; } + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } - private: std::vector extensions = {".tech"}; }; diff --git a/runtime/render/builder/render/include/builder/render/mesh/PolygonProcess.h b/runtime/render/builder/render/include/builder/render/mesh/PolygonProcess.h new file mode 100644 index 00000000..d12eff49 --- /dev/null +++ b/runtime/render/builder/render/include/builder/render/mesh/PolygonProcess.h @@ -0,0 +1,11 @@ +// +// Created by blues on 2024/9/24. +// + +#pragma once + + + +namespace sky::builder { + +} // namespace sky::builder \ No newline at end of file diff --git a/runtime/render/builder/render/src/AnimationBuilder.cpp b/runtime/render/builder/render/src/AnimationBuilder.cpp new file mode 100644 index 00000000..f036815a --- /dev/null +++ b/runtime/render/builder/render/src/AnimationBuilder.cpp @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/8/5. +// + +#include + +namespace sky::builder { + + void AnimationBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + auto asset = AssetManager::Get()->FindOrCreateAsset(request.assetInfo->uuid); + auto archive = request.file->ReadAsArchive(); + BinaryInputArchive bin(*archive); + + auto &data = asset->Data(); + data.Load(bin); + + asset->ResetDependencies(); + AssetManager::Get()->SaveAsset(asset, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } + +} // namespace sky::builder \ No newline at end of file diff --git a/runtime/render/builder/render/src/ImageBuilder.cpp b/runtime/render/builder/render/src/ImageBuilder.cpp new file mode 100644 index 00000000..7397b254 --- /dev/null +++ b/runtime/render/builder/render/src/ImageBuilder.cpp @@ -0,0 +1,144 @@ +// +// Created by Zach Lee on 2023/2/26. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include + +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include + +namespace sky::builder { + + Uuid CreateBufferID(const Uuid &imageId) + { + uint32_t seed = 0; + HashCombine32(seed, imageId.u32[0]); + HashCombine32(seed, imageId.u32[1]); + HashCombine32(seed, imageId.u32[2]); + HashCombine32(seed, imageId.u32[3]); + return Uuid::CreateWithSeed(seed); + } + + ImageBuilder::ImageBuilder() + { + InitializeCompressor(); + } + + void ImageBuilder::RequestDDS(const AssetBuildRequest &request, AssetBuildResult &result) + { + std::vector data; + request.file->ReadBin(data); + + rhi::Image::Descriptor imageDesc = {}; + uint32_t offset = rhi::ProcessDDSHeader(data.data(), data.size(), imageDesc); + + auto asset = AssetManager::Get()->FindOrCreateAsset(request.assetInfo->uuid); + auto &imageData = asset->Data(); + + imageData.format = imageDesc.format; + imageData.width = imageDesc.extent.width; + imageData.height = imageDesc.extent.height; + imageData.depth = imageDesc.extent.depth; + imageData.arrayLayers = imageDesc.arrayLayers; + imageData.mipLevels = imageDesc.mipLevels; + imageData.type = imageData.arrayLayers == 6 ? TextureType::TEXTURE_CUBE : TextureType::TEXTURE_2D; + +// auto buffer = AssetManager::Get()->FindOrCreateAsset(imageData.bufferID); +// auto &bufferData = buffer->Data(); +// bufferData.rawData.resize(imageData.dataSize); +// memcpy(bufferData.rawData.data(), data.data() + offset, imageData.dataSize); + + result.retCode = AssetBuildRetCode::SUCCESS; + } + + void ImageBuilder::RequestSTB(const AssetBuildRequest &request, AssetBuildResult &result) + { + int x; + int y; + int n; + int request_comp = 4; + + std::vector rawData; + request.file->ReadBin(rawData); + + unsigned char *data = nullptr; + data = stbi_load_from_memory(static_cast(rawData.data()), static_cast(rawData.size()), &x, &y, &n, request_comp); + if (data == nullptr) { + return; + } + auto *am = AssetManager::Get(); + + auto asset = am->FindOrCreateAsset(request.assetInfo->uuid); + auto &imageData = asset->Data(); + imageData.width = static_cast(x); + imageData.height = static_cast(y); + imageData.type = TextureType::TEXTURE_2D; + imageData.dataSize = 0; + imageData.slices.clear(); + + if (compress) { + CompressOption option = {}; + option.quality = Quality::SLOW; + option.targetFormat = rhi::PixelFormat::BC7_UNORM_BLOCK; + option.hasAlpha = true; + imageData.format = option.targetFormat; + + std::vector compressedData; + + BufferImageInfo info = {}; + info.width = imageData.width; + info.height = imageData.height; + info.stride = imageData.width * 4; + + CompressImage(data, info, compressedData, option); + + ImageSliceHeader slice = {}; + slice.offset = 0; + slice.size = static_cast(compressedData.size()); + + imageData.dataSize += slice.size; + imageData.slices.emplace_back(slice); + + imageData.rawData.storage.resize(imageData.dataSize); + memcpy(imageData.rawData.storage.data(), compressedData.data(), imageData.dataSize); + } else { + imageData.format = rhi::PixelFormat::RGBA8_UNORM; + + ImageSliceHeader slice = {}; + slice.offset = 0; + slice.size = imageData.width * imageData.height * 4;; + + imageData.dataSize += slice.size; + imageData.slices.emplace_back(slice); + + imageData.rawData.storage.resize(imageData.dataSize); + memcpy(imageData.rawData.storage.data(), reinterpret_cast(data), imageData.dataSize); + } + + AssetManager::Get()->SaveAsset(asset, request.target); + stbi_image_free(data); + } + + void ImageBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + if (request.assetInfo->ext == ".dds") { + RequestDDS(request, result); + } else { + RequestSTB(request, result); + } + } + + void ImageBuilder::LoadConfig(const FileSystemPtr &cfg) + { + } +} diff --git a/render/builder/render/src/ImageCompressor.cpp b/runtime/render/builder/render/src/ImageCompressor.cpp similarity index 99% rename from render/builder/render/src/ImageCompressor.cpp rename to runtime/render/builder/render/src/ImageCompressor.cpp index c9ca6938..dc61a19c 100644 --- a/render/builder/render/src/ImageCompressor.cpp +++ b/runtime/render/builder/render/src/ImageCompressor.cpp @@ -146,7 +146,7 @@ namespace sky::builder { void CompressImage(uint8_t *ptr, const BufferImageInfo ©, std::vector &out, const CompressOption &options) { - rgba_surface input = {}; + rgba_surface input = {};\ input.ptr = ptr + copy.offset; input.width = static_cast(copy.width); input.height = static_cast(copy.height); diff --git a/runtime/render/builder/render/src/MaterialBuilder.cpp b/runtime/render/builder/render/src/MaterialBuilder.cpp new file mode 100644 index 00000000..9a4c168d --- /dev/null +++ b/runtime/render/builder/render/src/MaterialBuilder.cpp @@ -0,0 +1,168 @@ +// +// Created by Zach Lee on 2023/2/23. +// + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +static const char* TAG = "MaterialBuilder"; + +namespace sky::builder { + + void ProcessProperties(rapidjson::Document &document, MaterialProperties &properties, const AssetBuildRequest &request) + { + if (!document.HasMember("properties")) { + return; + } + + auto &proValues = document["properties"]; + if (proValues.IsObject()) { + for (auto iter = proValues.MemberBegin(); iter != proValues.MemberEnd(); ++iter) { + auto &obj = iter->value; + + if (obj.IsString()) { + const auto *imagePath = obj.GetString(); + auto texId = AssetDataBase::Get()->RegisterAsset(imagePath); + properties.valueMap[iter->name.GetString()] = MaterialTexture{static_cast(properties.images.size())}; + properties.images.emplace_back(texId->uuid); + + request.assetInfo->dependencies.emplace_back(texId->uuid); + } else if (obj.IsFloat()) { + properties.valueMap[iter->name.GetString()] = obj.GetFloat(); + } else if (obj.IsBool()) { + properties.valueMap[iter->name.GetString()] = static_cast(obj.GetBool()); + } else if (obj.IsArray()) { + auto array = obj.GetArray(); + float *v = nullptr; + if (array.Size() == 2) { + v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector2{}).first->second).v; + } else if (array.Size() == 3) { + v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector3{}).first->second).v; + } else if (array.Size() == 4) { + v = std::get(properties.valueMap.emplace(iter->name.GetString(), Vector4{}).first->second).v; + } + for (auto &val : array) { + (*v) = val.GetFloat(); + ++v; + } + } + } + } + + if (document.HasMember("options")) { + auto &optionValue = document["options"]; + if (optionValue.IsObject()) { + for (auto iter = optionValue.MemberBegin(); iter != optionValue.MemberEnd(); ++iter) { + auto &obj = iter->value; + + if (obj.IsUint()) { + properties.options[iter->name.GetString()] = obj.GetUint(); + } else if (obj.IsBool()) { + properties.options[iter->name.GetString()] = obj.GetBool(); + } + } + } + } + } + + void MaterialBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + if (request.assetInfo->ext == ".mat") { + BuildMaterial(request, result); + } else if (request.assetInfo->ext == ".mati") { + BuildMaterialInstance(request, result); + } + } + + void MaterialBuilder::BuildMaterialInstance(const AssetBuildRequest &request, AssetBuildResult &result) + { + std::string json; + request.file->ReadString(json); + + rapidjson::Document document; + document.Parse(json.c_str()); + + if (!document.HasMember("material")) { + return; + } + auto *am = AssetManager::Get(); + auto asset = am->FindOrCreateAsset(request.assetInfo->uuid); + auto &assetData = asset->Data(); + + const auto *materialPath = document["material"].GetString(); + auto mat = AssetDataBase::Get()->RegisterAsset(materialPath); + if (!mat) { + result.retCode = AssetBuildRetCode::FAILED; + return; + } + + assetData.material = mat->uuid; + asset->AddDependencies(mat->uuid); + + ProcessProperties(document, assetData.properties, request); + for (auto &image : assetData.properties.images) { + AssetBuilderManager::Get()->BuildRequest(image, request.target); + asset->AddDependencies(image); + } + + AssetManager::Get()->SaveAsset(asset, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } + + void MaterialBuilder::BuildMaterial(const AssetBuildRequest &request, AssetBuildResult &result) + { + std::string json; + request.file->ReadString(json); + + rapidjson::Document document; + document.Parse(json.c_str()); + + if (!document.HasMember("techniques")) { + return; + } + + auto *am = AssetManager::Get(); + auto asset = am->FindOrCreateAsset(request.assetInfo->uuid); + auto &assetData = asset->Data(); + + auto &val = document["techniques"]; + if (val.IsArray()) { + auto techArray = val.GetArray(); + for (auto &tech : techArray) { + if (tech.IsString()) { + const auto *techPath = tech.GetString(); + auto techId = AssetDataBase::Get()->RegisterAsset(techPath); + if (!techId) { + LOG_W(TAG, "Material %s import technique failed %s", request.assetInfo->uuid.ToString().c_str(), techPath); + continue; + } + asset->AddDependencies(techId->uuid); + + AssetBuilderManager::Get()->BuildRequest(techId->uuid, request.target); + request.assetInfo->dependencies.emplace_back(techId->uuid); + assetData.techniques.emplace_back(techId->uuid); + } + } + } + + ProcessProperties(document, assetData.defaultProperties, request); + for (auto &image : assetData.defaultProperties.images) { + AssetBuilderManager::Get()->BuildRequest(image, request.target); + asset->AddDependencies(image); + } + + AssetManager::Get()->SaveAsset(asset, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } +} diff --git a/runtime/render/builder/render/src/MeshBuilder.cpp b/runtime/render/builder/render/src/MeshBuilder.cpp new file mode 100644 index 00000000..06a4ab47 --- /dev/null +++ b/runtime/render/builder/render/src/MeshBuilder.cpp @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/7/14. +// + +#include +#include +#include + +namespace sky::builder { + + void MeshBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + auto asset = AssetManager::Get()->FindOrCreateAsset(request.assetInfo->uuid); + + auto archive = request.file->ReadAsArchive(); + BinaryInputArchive bin(*archive); + + auto &data = asset->Data(); + data.Load(bin); + + asset->ResetDependencies(); + for (auto &sub : asset->Data().subMeshes) { + AssetBuilderManager::Get()->BuildRequest(sub.material, request.target); + asset->AddDependencies(sub.material); + } + + if (data.skeleton) { + asset->AddDependencies(data.skeleton); + } + + data.rawData.storage.resize(data.dataSize); + bin.LoadValue(reinterpret_cast(data.rawData.storage.data()), data.dataSize); + + AssetManager::Get()->SaveAsset(asset, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } + +} // namespace sky::builder \ No newline at end of file diff --git a/runtime/render/builder/render/src/PrefabBuilder.cpp b/runtime/render/builder/render/src/PrefabBuilder.cpp new file mode 100644 index 00000000..73c988df --- /dev/null +++ b/runtime/render/builder/render/src/PrefabBuilder.cpp @@ -0,0 +1,700 @@ +// +// Created by Zach Lee on 2023/2/20. +// +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +//#include + +#include +#include + +static const char* TAG = "PrefabBuilder"; + +namespace sky::builder { + +#define OFFSET_OF(s, m) static_cast(offsetof(s, m)) + + enum class MeshAttributeType : uint32_t { + POSITION = 0, + UV, + NORMAL, + TANGENT, + COLOR, + NUM, + }; + + struct StandardVertexData { + Vector4 uv; + Vector4 normal; + Vector4 tangent; + Vector4 color; + }; + + struct MeshBuildContext { + std::vector position; + std::vector ext; + std::vector bone; + std::vector indices; + }; + + struct PrefabBuildContext { + std::string name; + AssetSourcePath path; + std::unordered_map textures; + std::vector meshes; + std::vector materials; + + SkeletonAssetData skeleton; + AssetSourcePtr skeletonSource; + std::vector nodes; + }; + + static inline Vector4 FromAssimp(const aiColor4D &color) + { + return {color.r, color.g, color.b, color.a}; + } + + static inline Matrix4 FromAssimp(const aiMatrix4x4& trans) + { + Matrix4 res; + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + res[i][j] = trans[j][i]; + } + } + return res; + } + + static inline Vector3 FromAssimp(const aiVector3D &vec) + { + return {vec.x, vec.y, vec.z}; + } + + static inline Quaternion FromAssimp(const aiQuaternion &vec) + { + return {vec.w, vec.x, vec.y, vec.z}; + } + + static std::string GetIndexedName(const std::string &prefix, const std::string_view &type, const std::string_view &ext, size_t index) + { + std::stringstream ss; + ss << prefix << "_" << type << "_" << index << "." << ext; + return ss.str(); + } + + static void SaveEmbeddedTexture(const aiTexture* tex, const AssetSourcePath &sourcePath) + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + file->WriteAsArchive()->SaveRaw(reinterpret_cast(tex->pcData), tex->mWidth); + } + + static Uuid ProcessTexture(const aiScene *scene, const aiString& str, PrefabBuildContext &context, const AssetImportRequest &request) + { + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + + auto texPath = request.filePath.Parent() / FilePath(str.C_Str()); + if (texPath.Exist()) { + sourcePath.path = context.path.path / FilePath(str.C_Str()); + AssetDataBase::Get()->GetWorkSpaceFs()->Copy(texPath, sourcePath.path); + } else { + auto [tex, index] = scene->GetEmbeddedTextureAndIndex(str.C_Str()); + if (tex == nullptr) { + return {}; + } + sourcePath.path = context.path.path / FilePath(GetIndexedName(context.name, "texture", tex->achFormatHint, index)); + SaveEmbeddedTexture(tex, sourcePath); + } + auto res = context.textures.emplace(sourcePath, AssetDataBase::Get()->RegisterAsset(sourcePath)); + return res.first->second->uuid; + } + + static void ProcessPbrBRDF(const aiScene *scene, aiMaterial *material, PrefabBuildContext &context, const AssetImportRequest &request) + { + std::string matName = material->GetName().length == 0 ? + GetIndexedName(context.name, "material", "mati", context.materials.size()) : + std::string(material->GetName().C_Str()) + ".mati"; + + MaterialInstanceData data = {}; + data.material = AssetDataBase::Get()->RegisterAsset("materials/standard_pbr.mat")->uuid; + + aiString str; + bool useAOMap = false; + bool useEmissiveMap = false; + bool useBaseColorMap = false; + bool useNormalMap = false; + bool useMetallicRoughnessMap = false; + bool useMask = false; + Vector4 baseColor = Vector4(1.f, 1.f, 1.f, 1.f); + float metallic = 1.f; + float roughness = 1.f; + Uuid normalMap; + Uuid emissiveMap; + Uuid aoMap; + Uuid baseColorMap; + Uuid metallicRoughnessMap; + + aiString aiAlphaMode; + if (material->Get(AI_MATKEY_GLTF_ALPHAMODE, aiAlphaMode) == 0) { + std::string mode = aiAlphaMode.data; + if (mode == "MASK") { + useMask = true; + } + } + + float alphaCutoff = 0.5f; + material->Get(AI_MATKEY_GLTF_ALPHACUTOFF, alphaCutoff); + + if (material->Get(AI_MATKEY_TEXTURE_NORMALS(0), str) == 0) { + // normalMap + normalMap = ProcessTexture(scene, str, context, request); + useNormalMap = static_cast(normalMap); + } + + if (material->Get(AI_MATKEY_TEXTURE_EMISSIVE(0), str) == 0) { + // emissiveMap + emissiveMap = ProcessTexture(scene, str, context, request); + useEmissiveMap = static_cast(emissiveMap); + } + + if (material->Get(AI_MATKEY_TEXTURE_LIGHTMAP(0), str) == 0) { + // aoMap; + aoMap = ProcessTexture(scene, str, context, request); + useAOMap = static_cast(aoMap); + } + + aiColor4D color = {}; + aiGetMaterialColor(material, AI_MATKEY_BASE_COLOR, &color); + if (color.IsBlack()) { + aiGetMaterialColor(material, AI_MATKEY_COLOR_DIFFUSE, &color); + } + baseColor = FromAssimp(color); + + aiGetMaterialFloat(material, AI_MATKEY_METALLIC_FACTOR, &metallic); + aiGetMaterialFloat(material, AI_MATKEY_ROUGHNESS_FACTOR, &roughness); + + if (material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &str) == 0) { + // baseColorMap + baseColorMap = ProcessTexture(scene, str, context, request); + useBaseColorMap = static_cast(baseColorMap); + } + + if (material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &str) == 0) { + // metallicRoughnessMap + metallicRoughnessMap = ProcessTexture(scene, str, context, request); + useMetallicRoughnessMap = static_cast(metallicRoughnessMap); + } + + data.properties.options.emplace("ENABLE_AO_MAP", useAOMap); + if (useAOMap) { + data.properties.valueMap.emplace("AoMap", + MaterialTexture{static_cast(data.properties.images.size())}); + data.properties.images.emplace_back(aoMap); + } + + data.properties.options.emplace("ENABLE_EMISSIVE_MAP", useEmissiveMap); + if (useEmissiveMap) { + data.properties.valueMap.emplace("EmissiveMap", + MaterialTexture{static_cast(data.properties.images.size())}); + data.properties.images.emplace_back(emissiveMap); + } + +// data.properties.valueMap.emplace("useBaseColorMap", static_cast(useBaseColorMap)); + if (useBaseColorMap) { + data.properties.valueMap.emplace("AlbedoMap", + MaterialTexture{static_cast(data.properties.images.size())}); + data.properties.images.emplace_back(baseColorMap); + } + + data.properties.options.emplace("useMetallicRoughnessMap", useMetallicRoughnessMap); + if (useMetallicRoughnessMap) { + data.properties.valueMap.emplace("MetallicRoughnessMap", + MaterialTexture{static_cast(data.properties.images.size())}); + data.properties.images.emplace_back(metallicRoughnessMap); + } + +// data.properties.valueMap.emplace("useNormalMap", static_cast(useNormalMap)); + if (useNormalMap) { + data.properties.valueMap.emplace("NormalMap", + MaterialTexture{static_cast(data.properties.images.size())}); + data.properties.images.emplace_back(normalMap); + } + + data.properties.options.emplace("ENABLE_ALPHA_MASK", useMask); + + data.properties.valueMap.emplace("Albedo", baseColor); + data.properties.valueMap.emplace("Metallic", metallic); + data.properties.valueMap.emplace("Roughness", roughness); + data.properties.valueMap.emplace("AlphaCutoff", alphaCutoff); + + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + sourcePath.path = context.path.path / FilePath(matName); + + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + auto archive = file->WriteAsArchive(); + JsonOutputArchive bin(*archive); + data.SaveJson(bin); + } + + auto source = AssetDataBase::Get()->RegisterAsset(sourcePath); + context.materials.emplace_back(source); + } + + static void ProcessMaterials(const aiScene *scene, PrefabBuildContext &context, const AssetImportRequest &request) + { + uint32_t matSize = scene->mNumMaterials; + for (uint32_t i = 0; i < matSize; ++i) { + aiMaterial* material = scene->mMaterials[i]; + aiShadingMode shadingModel = aiShadingMode_Flat; + material->Get(AI_MATKEY_SHADING_MODEL, shadingModel); + + ProcessPbrBRDF(scene, material, context, request); +// if (shadingModel == aiShadingMode_PBR_BRDF) { +// } else { +// } + } + } + + static void ProcessSkeletonBone(aiMesh *mesh, const aiScene *scene, SkeletonAssetData &skeleton) + { + for (uint32_t i = 0; i < mesh->mNumBones; ++i) { + auto &aBone = mesh->mBones[i]; + std::string boneName = aBone->mName.C_Str(); + + uint32_t boneIndex = 0; + if (auto iter = skeleton.nameToIndexMap.find(boneName); iter != skeleton.nameToIndexMap.end()) { + boneIndex = iter->second; + } else { + boneIndex = skeleton.AdddBone(boneName, FromAssimp(aBone->mOffsetMatrix)); + } + } + } + + static void ProcessSkinData(aiMesh* mesh, PrefabBuildContext& prefabContext, MeshBuildContext &context) + { + auto baseVertex = static_cast(context.bone.size()); + context.bone.resize(baseVertex + mesh->mNumVertices); + + for (uint32_t i = 0; i < mesh->mNumBones; ++i) { + auto *bone = mesh->mBones[i]; + + for (uint32_t j = 0; j < bone->mNumWeights; ++j) { + uint32_t vertexId = baseVertex + bone->mWeights[j].mVertexId; + auto &vBone = context.bone[vertexId]; + + auto boneId = prefabContext.skeleton.FindBoneByName(bone->mName.C_Str()); + SKY_ASSERT(boneId < prefabContext.skeleton.nameToIndexMap.size()); + + for (uint32_t k = 0; k < MAX_BONE_PER_VERTEX; ++k) { + if (bone->mWeights[j].mWeight == 0.0f) { + vBone.boneId[k] = boneId; + vBone.weight[k] = bone->mWeights[j].mWeight; + return; + } + } + } + } + } + + static void ProcessSkeletonHierarchy(const aiScene *scene, const aiNode* node, uint32_t parentIndex, SkeletonAssetData &skeleton) // NOLINT + { + uint32_t boneIndex = skeleton.FindBoneByName(node->mName.C_Str()); + + if (boneIndex != INVALID_BONE_ID) { + skeleton.boneData[boneIndex].parentIndex = parentIndex; + + aiVector3t scaling = {}; + aiQuaterniont rotation = {}; + aiVector3t position = {}; + node->mTransformation.Decompose(scaling, rotation, position); + skeleton.refPos[boneIndex].translation = FromAssimp(position); + skeleton.refPos[boneIndex].rotation = FromAssimp(rotation); + skeleton.refPos[boneIndex].scale = FromAssimp(scaling); + parentIndex = boneIndex; + } + + for (uint32_t i = 0 ; i < node->mNumChildren ; i++) { + ProcessSkeletonHierarchy(scene, node->mChildren[i], parentIndex, skeleton); + } + } + + static void ProcessSubMesh(aiMesh *mesh, const aiScene *scene, PrefabBuildContext& prefabContext, MeshAssetData &meshData, MeshBuildContext &context) + { + SubMeshAssetData subMesh = {}; + subMesh.firstVertex = static_cast(context.position.size()); + subMesh.vertexCount = mesh->mNumVertices; + subMesh.firstIndex = static_cast(context.indices.size()); + subMesh.indexCount = mesh->mNumFaces * 3; + subMesh.material = prefabContext.materials[mesh->mMaterialIndex]->uuid; + + context.position.resize(context.position.size() + subMesh.vertexCount); + context.ext.resize(context.ext.size() + subMesh.vertexCount); + + subMesh.aabb.min = {mesh->mAABB.mMin.x, mesh->mAABB.mMin.y, mesh->mAABB.mMin.z}; + subMesh.aabb.max = {mesh->mAABB.mMax.x, mesh->mAABB.mMax.y, mesh->mAABB.mMax.z}; + + Vector4 *position = &context.position[subMesh.firstVertex]; + StandardVertexData *vtx = &context.ext[subMesh.firstVertex]; + + for (unsigned int i = 0; i < mesh->mNumVertices; i++) { + auto &p = mesh->mVertices[i]; + auto &n = mesh->mNormals[i]; + auto &t = mesh->mTangents[i]; + auto &b = mesh->mBitangents[i]; + + position[i].x = p.x; + position[i].y = p.y; + position[i].z = p.z; + position[i].w = 1.f; + subMesh.aabb.min = Min(subMesh.aabb.min, Vector3(p.x, p.y, p.z)); + subMesh.aabb.max = Max(subMesh.aabb.max, Vector3(p.x, p.y, p.z)); + + vtx[i].normal.x = n.x; + vtx[i].normal.y = n.y; + vtx[i].normal.z = n.z; + vtx[i].normal.w = 1.f; + + vtx[i].tangent.x = t.x; + vtx[i].tangent.y = t.y; + vtx[i].tangent.z = t.z; + vtx[i].tangent.w = 1.f; + + if (mesh->HasVertexColors(0)) { + auto &c = mesh->mColors[0][i]; + vtx[i].color.x = c.r; + vtx[i].color.y = c.g; + vtx[i].color.z = c.b; + vtx[i].color.w = c.a; + } else { + vtx[i].color.x = 1.f; + vtx[i].color.y = 1.f; + vtx[i].color.z = 1.f; + vtx[i].color.w = 1.f; + } + + vtx[i].uv = VEC4_ZERO; + if (mesh->HasTextureCoords(0)) { + auto &u = mesh->mTextureCoords[0][i]; + vtx[i].uv.x = u.x; + vtx[i].uv.y = u.y; + } + if (mesh->HasTextureCoords(1)) { + auto &u = mesh->mTextureCoords[1][i]; + vtx[i].uv.z = u.x; + vtx[i].uv.w = u.y; + } + } + + context.indices.resize(context.indices.size() + subMesh.indexCount); + + uint32_t *indices = &context.indices[subMesh.firstIndex]; + for(unsigned int i = 0; i < mesh->mNumFaces; i++) + { + const aiFace &face = mesh->mFaces[i]; + indices[3 * i + 0] = face.mIndices[0]; + indices[3 * i + 1] = face.mIndices[1]; + indices[3 * i + 2] = face.mIndices[2]; + } + meshData.subMeshes.emplace_back(subMesh); + } + + static Uuid ProcessMesh(const aiScene *scene, const aiNode *node, PrefabBuildContext& context, const AssetImportRequest &request) + { + std::string meshName = node->mName.length == 0 ? + GetIndexedName(context.name, "mesh", "mesh", context.meshes.size()) : + std::string(node->mName.C_Str()) + ".mesh"; + + MeshAssetData meshData; + + uint32_t meshNum = node->mNumMeshes; + MeshBuildContext meshContext; + + bool hasSkin = true; + + for (uint32_t i = 0; i < meshNum; ++i) { + aiMesh *aMesh = scene->mMeshes[node->mMeshes[i]]; + ProcessSubMesh(aMesh, scene, context, meshData, meshContext); + + hasSkin &= aMesh->HasBones(); + } + + for (uint32_t i = 0; hasSkin && i < meshNum; ++i) { + aiMesh *aMesh = scene->mMeshes[node->mMeshes[i]]; + ProcessSkinData(aMesh, context, meshContext); + meshData.skeleton = context.skeletonSource->uuid; + } + + size_t vtxCount = meshContext.position.size(); + size_t idxCount = meshContext.indices.size(); + + auto posSize = static_cast(vtxCount * sizeof(Vector4)); + SKY_ASSERT(vtxCount == meshContext.ext.size()); + auto stdSize = static_cast(vtxCount * sizeof(StandardVertexData)); + SKY_ASSERT(meshContext.bone.empty() || vtxCount == meshContext.bone.size()); + auto skinSize = meshContext.bone.empty() ? 0 : static_cast(vtxCount * sizeof(VertexBoneData)); + + meshData.buffers = { + MeshBufferView{0, posSize, sizeof(Vector4)}, + MeshBufferView{posSize, stdSize, sizeof(StandardVertexData)}, + }; + + meshData.attributes = { + VertexAttribute{VertexSemanticFlagBit::POSITION, 0, 0, rhi::Format::F_RGBA32}, + VertexAttribute{VertexSemanticFlagBit::UV, 1, OFFSET_OF(StandardVertexData, uv), rhi::Format::F_RGBA32}, + VertexAttribute{VertexSemanticFlagBit::NORMAL, 1, OFFSET_OF(StandardVertexData, normal), rhi::Format::F_RGBA32}, + VertexAttribute{VertexSemanticFlagBit::TANGENT, 1, OFFSET_OF(StandardVertexData, tangent), rhi::Format::F_RGBA32}, + VertexAttribute{VertexSemanticFlagBit::COLOR, 1, OFFSET_OF(StandardVertexData, color), rhi::Format::F_RGBA32}, + }; + + if (skinSize != 0) { + meshData.buffers.emplace_back(MeshBufferView{posSize + stdSize, skinSize, static_cast(sizeof(VertexBoneData))}); + + meshData.attributes.emplace_back(VertexAttribute{VertexSemanticFlagBit::JOINT, 2, OFFSET_OF(VertexBoneData, boneId), rhi::Format::U_RGBA32}); + meshData.attributes.emplace_back(VertexAttribute{VertexSemanticFlagBit::WEIGHT, 2, OFFSET_OF(VertexBoneData, weight), rhi::Format::F_RGBA32}); + } + uint32_t idxOffset = posSize + stdSize + skinSize; + auto idxSize = static_cast(meshContext.indices.size() * sizeof(uint32_t)); + meshData.indexBuffer = static_cast(meshData.buffers.size()); + meshData.indexType = rhi::IndexType::U32; + + meshData.buffers.emplace_back(MeshBufferView{idxOffset, idxSize, static_cast(sizeof(uint32_t))}); + + meshData.dataSize = idxOffset + idxSize; + meshData.rawData.storage.resize(meshData.dataSize); + + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + sourcePath.path = context.path.path / FilePath(meshName); + + memcpy(meshData.rawData.storage.data(), reinterpret_cast(meshContext.position.data()), posSize); + memcpy(meshData.rawData.storage.data() + posSize, reinterpret_cast(meshContext.ext.data()), stdSize); + if (skinSize != 0) { + memcpy(meshData.rawData.storage.data() + posSize + stdSize, reinterpret_cast(meshContext.bone.data()), skinSize); + } + memcpy(meshData.rawData.storage.data() + idxOffset, reinterpret_cast(meshContext.indices.data()), idxSize); + + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + auto archive = file->WriteAsArchive(); + BinaryOutputArchive bin(*archive); + meshData.Save(bin); + } + + auto source = AssetDataBase::Get()->RegisterAsset(sourcePath); + context.meshes.emplace_back(source); + return source->uuid; + } + + static void ProcessNode(aiNode *node, const aiScene *scene, uint32_t parent, PrefabBuildContext& context, const AssetImportRequest &request) // NOLINT + { + auto index = static_cast(context.nodes.size()); + context.nodes.emplace_back(); + auto& current = context.nodes.back(); + current.parentIndex = parent; + current.name = node->mName.C_Str(); + + aiVector3D translation; + aiQuaternion rotation; + aiVector3D scale; + node->mTransformation.Decompose(scale, rotation, translation); + current.localTransform.translation = FromAssimp(translation); + current.localTransform.scale = FromAssimp(scale); + current.localTransform.rotation = FromAssimp(rotation); + + if (node->mNumMeshes != 0) { + current.mesh = ProcessMesh(scene, node, context, request); + } + + for(unsigned int i = 0; i < node->mNumChildren; i++) { + ProcessNode(node->mChildren[i], scene, index, context, request); + } + } + + static void ProcessNodeChannel(const aiScene* scene, aiNodeAnim *anim, AnimNodeChannelData& channel) + { + channel.name = anim->mNodeName.C_Str(); + + channel.position.time.resize(anim->mNumPositionKeys); + channel.position.keys.resize(anim->mNumPositionKeys); + for (uint32_t i = 0; i < anim->mNumPositionKeys; ++i) { + const auto &src = anim->mPositionKeys[i]; + auto &dstTime = channel.position.time[i]; + auto &dstPos = channel.position.keys[i]; + dstTime = static_cast(src.mTime); + dstPos.x = src.mValue.x; + dstPos.y = src.mValue.y; + dstPos.z = src.mValue.z; + } + + channel.scale.time.resize(anim->mNumScalingKeys); + channel.scale.keys.resize(anim->mNumScalingKeys); + for (uint32_t i = 0; i < anim->mNumScalingKeys; ++i) { + const auto &src = anim->mScalingKeys[i]; + auto &dstTime = channel.scale.time[i]; + auto &dstScale = channel.scale.keys[i]; + dstTime = static_cast(src.mTime); + dstScale.x = src.mValue.x; + dstScale.y = src.mValue.y; + dstScale.z = src.mValue.z; + } + + channel.rotation.time.resize(anim->mNumRotationKeys); + channel.rotation.keys.resize(anim->mNumRotationKeys); + for (uint32_t i = 0; i < anim->mNumRotationKeys; ++i) { + const auto &src = anim->mRotationKeys[i]; + auto &dstTime = channel.rotation.time[i]; + auto &dstRot = channel.rotation.keys[i]; + dstTime = static_cast(src.mTime); + dstRot.x = src.mValue.x; + dstRot.y = src.mValue.y; + dstRot.z = src.mValue.z; + dstRot.w = src.mValue.w; + } + } + + static void ProcessMeshChannel(const aiScene* scene, aiMeshAnim *anim, PrefabBuildContext& context) + { + // not implement yet + } + + static void ProcessMorphMeshChannel(const aiScene* scene, aiMeshMorphAnim *anim, PrefabBuildContext& context) + { + // not implement yet + } + + static void ProcessSkeleton(const aiScene* scene, PrefabBuildContext& context) + { + for (uint32_t i = 0; i < scene->mNumMeshes; ++i) { + ProcessSkeletonBone(scene->mMeshes[i], scene, context.skeleton); + } + + ProcessSkeletonHierarchy(scene, scene->mRootNode, INVALID_BONE_ID, context.skeleton); + if (!context.skeleton.nameToIndexMap.empty()) { + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + sourcePath.path = context.path.path / FilePath(context.name + ".skeleton"); + + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + auto archive = file->WriteAsArchive(); + BinaryOutputArchive bin(*archive); + context.skeleton.Save(bin); + } + + context.skeletonSource = AssetDataBase::Get()->RegisterAsset(sourcePath); + } + } + + static void ProcessAnimation(const aiScene* scene, PrefabBuildContext& context) + { + for (uint32_t i = 0; i < scene->mNumAnimations; ++i) { + auto &anim = scene->mAnimations[i]; + + AnimationAssetData data; + data.version = 1; + data.name = anim->mName.C_Str(); + data.nodeChannels.resize(anim->mNumChannels); + // node animation + for (uint32_t j = 0; j < anim->mNumChannels; ++j) {; + ProcessNodeChannel(scene, anim->mChannels[j], data.nodeChannels[j]); + } + + // mesh animation + for (uint32_t j = 0; j < anim->mNumMeshChannels; ++j) { + ProcessMeshChannel(scene, anim->mMeshChannels[j], context); + } + + // morph animation + for (uint32_t j = 0; j < anim->mNumMorphMeshChannels; ++j) { + ProcessMorphMeshChannel(scene, anim->mMorphMeshChannels[j], context); + } + + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + sourcePath.path = context.path.path / FilePath(data.name + ".anim"); + + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + auto archive = file->WriteAsArchive(); + BinaryOutputArchive bin(*archive); + data.Save(bin); + } + + AssetDataBase::Get()->RegisterAsset(sourcePath); + } + } + + void PrefabBuilder::Import(const AssetImportRequest &request) const + { + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(request.filePath.GetStr(), + aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace | aiProcess_PopulateArmatureData); + if(scene == nullptr) { + return; + } + + PrefabBuildContext context; + if ((scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) != 0u) { + ProcessAnimation(scene, context); + return; + } + + auto prefabName = request.filePath.FileName(); + context.path.bundle = SourceAssetBundle::WORKSPACE; + context.path.path = FilePath("Prefabs") / prefabName; + context.name = request.filePath.FileNameWithoutExt(); + + AssetDataBase::Get()->GetWorkSpaceFs()->CreateSubSystem(context.path.path.GetStr(), true); + ProcessMaterials(scene, context, request); + + ProcessSkeleton(scene, context); + ProcessAnimation(scene, context); + + if (scene->mRootNode != nullptr) { + ProcessNode(scene->mRootNode, scene, -1, context, request); + } + + RenderPrefabAssetData data; + data.nodes.swap(context.nodes); + + AssetSourcePath sourcePath = {}; + sourcePath.bundle = SourceAssetBundle::WORKSPACE; + sourcePath.path = context.path.path / FilePath(context.name + ".prefab"); + + { + auto file = AssetDataBase::Get()->CreateOrOpenFile(sourcePath); + auto archive = file->WriteAsArchive(); + JsonOutputArchive bin(*archive); + data.SaveJson(bin); + } + + AssetDataBase::Get()->RegisterAsset(sourcePath); + } + + void PrefabBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + } + +} // namespace sky::builder diff --git a/runtime/render/builder/render/src/ShaderBuilder.cpp b/runtime/render/builder/render/src/ShaderBuilder.cpp new file mode 100644 index 00000000..8ecda907 --- /dev/null +++ b/runtime/render/builder/render/src/ShaderBuilder.cpp @@ -0,0 +1,30 @@ +// +// Created by Zach Lee on 2023/2/23. +// + +#include + +#include +#include + +#include +#include + +namespace sky::builder { + + void ShaderBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + auto shader = AssetManager::Get()->FindOrCreateAsset(request.assetInfo->uuid); + shader->Data().name = request.assetInfo->name; + shader->Data().shaderSource = ShaderCompiler::Get()->LoadShader(request.assetInfo->path.path.GetStr()); + shader->Data().hash = Crc32::Cal(shader->Data().shaderSource); + + AssetManager::Get()->SaveAsset(shader, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } + + void ShaderBuilder::LoadConfig(const FileSystemPtr &cfg) + { + + } +} diff --git a/runtime/render/builder/render/src/SkeletonBuilder.cpp b/runtime/render/builder/render/src/SkeletonBuilder.cpp new file mode 100644 index 00000000..f21249d2 --- /dev/null +++ b/runtime/render/builder/render/src/SkeletonBuilder.cpp @@ -0,0 +1,23 @@ +// +// Created by blues on 2024/8/10. +// + +#include + +namespace sky::builder { + + void SkeletonBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) + { + auto asset = AssetManager::Get()->FindOrCreateAsset(request.assetInfo->uuid); + auto archive = request.file->ReadAsArchive(); + BinaryInputArchive bin(*archive); + + auto &data = asset->Data(); + data.Load(bin); + + asset->ResetDependencies(); + AssetManager::Get()->SaveAsset(asset, request.target); + result.retCode = AssetBuildRetCode::SUCCESS; + } + +} // namespace sky::builder \ No newline at end of file diff --git a/render/builder/render/src/TechniqueBuilder.cpp b/runtime/render/builder/render/src/TechniqueBuilder.cpp similarity index 78% rename from render/builder/render/src/TechniqueBuilder.cpp rename to runtime/render/builder/render/src/TechniqueBuilder.cpp index 09c7c54d..ddb67e36 100644 --- a/render/builder/render/src/TechniqueBuilder.cpp +++ b/runtime/render/builder/render/src/TechniqueBuilder.cpp @@ -9,12 +9,12 @@ #include #include +#include -#include namespace sky::builder { - std::unordered_map BLEND_FACTOR_MAP = { + std::unordered_map BLEND_FACTOR_MAP = { {"ZERO", rhi::BlendFactor::ZERO }, {"ONE", rhi::BlendFactor::ONE }, {"SRC_COLOR", rhi::BlendFactor::SRC_COLOR }, @@ -36,34 +36,37 @@ namespace sky::builder { {"ONE_MINUS_SRC1_ALPHA", rhi::BlendFactor::ONE_MINUS_SRC1_ALPHA }, }; - static void ProcessShader(rapidjson::Document &document, ShaderRefData &shader, TechAssetType type) + std::unordered_map VTX_FLAG_MAP = { + {"SKIN", RenderVertexFlagBit::SKIN}, + {"INSTANCE", RenderVertexFlagBit::INSTANCE}, + }; + + static void ProcessShader(rapidjson::Document &document, ShaderRefData &shaderRef, TechAssetType type) { auto &val = document["shader"]; if (type == TechAssetType::MESH) { if (val.HasMember("object")) { - shader.objectOrCSMain = val["object"].GetString(); + shaderRef.objectOrCSMain = val["object"].GetString(); } if (val.HasMember("mesh")) { - shader.vertOrMeshMain = val["mesh"].GetString(); + shaderRef.vertOrMeshMain = val["mesh"].GetString(); } } else { if (val.HasMember("vertex")) { - shader.vertOrMeshMain = val["vertex"].GetString(); + shaderRef.vertOrMeshMain = val["vertex"].GetString(); } } - if (val.HasMember("mesh")) { - shader.vertOrMeshMain = val["mesh"].GetString(); - } - if (val.HasMember("fragment")) { - shader.fragmentMain = val["fragment"].GetString(); + shaderRef.fragmentMain = val["fragment"].GetString(); } if (val.HasMember("path")) { - shader.path = val["path"].GetString(); + const auto *path = val["path"].GetString(); + auto src = AssetDataBase::Get()->RegisterAsset(path); + shaderRef.shader = src->uuid; } } @@ -75,10 +78,27 @@ namespace sky::builder { } } - static void GetVertexDescInfo(rapidjson::Document &document, TechniqueAssetData &data) + static void GetVariants(rapidjson::Document &document, TechniqueAssetData &data) { - if (document.HasMember("vertex")) { - data.vertexDesc = document["vertex"].GetString(); + if (document.HasMember("pre_defines")) { + auto array = document["pre_defines"].GetArray(); + for (auto &def : array) { + data.preDefines.emplace_back(def.GetString()); + } + } + + if (document.HasMember("vertex_options")) { + auto object = document["vertex_options"].GetObject(); + for (auto iter = object.MemberBegin(); iter != object.MemberEnd(); ++iter) { + const auto &member = *iter; + auto flag = VTX_FLAG_MAP.find(member.name.GetString()); + if (flag != VTX_FLAG_MAP.end()) { + data.vertexFlags.emplace_back(TechniqueVertexFlags { + flag->second, + member.value.GetString() + }); + } + } } } @@ -173,26 +193,20 @@ namespace sky::builder { } } - static void ProcessGraphics(rapidjson::Document &document, TechniqueAssetData &data, const BuildRequest &request) + static void ProcessGraphics(rapidjson::Document &document, TechniqueAssetData &data, const AssetBuildRequest &request) { ProcessShader(document, data.shader, data.type); ProcessDepthStencil(document, data.depthStencil); ProcessBlendStates(document, data.blendStates); ProcessRasterStates(document, data.rasterState); GetPassInfo(document, data); - GetVertexDescInfo(document, data); - - AssetManager::Get()->ImportAndBuildAsset(data.shader.path); + GetVariants(document, data); } - void TechniqueBuilder::Request(const BuildRequest &request, BuildResult &result) + void TechniqueBuilder::Request(const AssetBuildRequest &request, AssetBuildResult &result) { - if (!request.buildKey.empty() && request.buildKey != std::string(KEY)) { - return; - } - std::string json; - ReadString(request.fullPath, json); + request.file->ReadString(json); rapidjson::Document document; document.Parse(json.c_str()); @@ -202,15 +216,16 @@ namespace sky::builder { } auto *am = AssetManager::Get(); - std::filesystem::path fullPath(request.fullPath); std::string type = document["type"].GetString(); if (type == "graphics") { - auto asset = am->CreateAsset(request.uuid); + auto asset = am->FindOrCreateAsset(request.assetInfo->uuid); TechniqueAssetData &assetData = asset->Data(); ProcessGraphics(document, assetData, request); - result.products.emplace_back(BuildProduct{"GFX_TECH", asset}); + + asset->AddDependencies(assetData.shader.shader); + AssetManager::Get()->SaveAsset(asset, request.target); } - result.success = true; + result.retCode = AssetBuildRetCode::SUCCESS; } } diff --git a/runtime/render/builder/render/src/mesh/PolygonProcess.cpp b/runtime/render/builder/render/src/mesh/PolygonProcess.cpp new file mode 100644 index 00000000..f467e154 --- /dev/null +++ b/runtime/render/builder/render/src/mesh/PolygonProcess.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/24. +// + +#include + +namespace sky::builder { + +} // namespace sky::builder \ No newline at end of file diff --git a/render/core/CMakeLists.txt b/runtime/render/core/CMakeLists.txt similarity index 85% rename from render/core/CMakeLists.txt rename to runtime/render/core/CMakeLists.txt index 7006c4fb..3e93afaa 100644 --- a/render/core/CMakeLists.txt +++ b/runtime/render/core/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE SRC_FILES src/*) file(GLOB_RECURSE INC_FILES include/*) -sky_add_library(TARGET SkyRenderCore STATIC +sky_add_library(TARGET RenderCore STATIC SOURCES ${SRC_FILES} ${INC_FILES} diff --git a/render/core/include/render/FeatureProcessor.h b/runtime/render/core/include/render/FeatureProcessor.h similarity index 92% rename from render/core/include/render/FeatureProcessor.h rename to runtime/render/core/include/render/FeatureProcessor.h index 4e68b0b0..7a6102f9 100644 --- a/render/core/include/render/FeatureProcessor.h +++ b/runtime/render/core/include/render/FeatureProcessor.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include namespace sky { namespace rdg { @@ -52,7 +52,7 @@ namespace sky { IFeatureProcessor *BuildFeatureProcessor(RenderScene *scene) override { auto *feature = new T(scene); - IFeatureProcessorBuilder::SetFeatureID(feature, TypeInfo::Hash()); + IFeatureProcessorBuilder::SetFeatureID(feature, RuntimeTypeId()); return feature; } }; diff --git a/render/core/include/render/RHI.h b/runtime/render/core/include/render/RHI.h similarity index 68% rename from render/core/include/render/RHI.h rename to runtime/render/core/include/render/RHI.h index d8b071fd..e68d29bb 100644 --- a/render/core/include/render/RHI.h +++ b/runtime/render/core/include/render/RHI.h @@ -16,16 +16,23 @@ namespace sky { RHI() = default; ~RHI() override; - void InitInstance(const rhi::Instance::Descriptor &desc); +#ifdef SKY_ENABLE_XR + void SetXRInterface(rhi::XRInterface *interface) { xrInterface = interface; } +#endif + + void InitInstance(rhi::Instance::Descriptor desc); void InitDevice(const rhi::Device::Descriptor &desc); + std::string GetBackendName() const; rhi::API GetBackend() const { return api; } rhi::Device *GetDevice() const { return device.get(); } private: rhi::Instance *instance = nullptr; rhi::API api = rhi::API::DEFAULT; - +#ifdef SKY_ENABLE_XR + rhi::XRInterface *xrInterface = nullptr; +#endif std::unique_ptr device; }; } // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/RenderBase.h b/runtime/render/core/include/render/RenderBase.h new file mode 100644 index 00000000..ea51af10 --- /dev/null +++ b/runtime/render/core/include/render/RenderBase.h @@ -0,0 +1,47 @@ +// +// Created by blues on 2024/9/13. +// + +#pragma once + +#include +#include + +namespace sky { + + // constants + static constexpr uint32_t MAX_VERTEX_BUFFER_BINDINGS = 64; + + // enums + enum class VertexSemanticFlagBit : uint64_t { + NONE = 0x00, + POSITION = 0x01, + UV = 0x02, + NORMAL = 0x04, + TANGENT = 0x08, + COLOR = 0x10, + JOINT = 0x20, + WEIGHT = 0x40, + INST0 = 0x80, + INST1 = 0x100, + INST2 = 0x200, + INST3 = 0x400, + + HAS_SKIN = JOINT | WEIGHT, + }; + using VertexSemanticFlags = Flags; + ENABLE_FLAG_BIT_OPERATOR(VertexSemanticFlagBit) + + enum class RenderVertexFlagBit : uint32_t { + NONE = 0x00, + SKIN = 0x01, + INSTANCE = 0x02, + }; + using RenderVertexFlags = Flags; + ENABLE_FLAG_BIT_OPERATOR(RenderVertexFlagBit) + + using RenderPipelineFlags = ArrayBit; + +#define OFFSET_OF(s, m) static_cast(offsetof(s, m)) + +} // namespace sky \ No newline at end of file diff --git a/render/core/include/render/RenderBuiltinLayout.h b/runtime/render/core/include/render/RenderBuiltinLayout.h similarity index 66% rename from render/core/include/render/RenderBuiltinLayout.h rename to runtime/render/core/include/render/RenderBuiltinLayout.h index 90fbba6c..95108102 100644 --- a/render/core/include/render/RenderBuiltinLayout.h +++ b/runtime/render/core/include/render/RenderBuiltinLayout.h @@ -7,13 +7,11 @@ #include namespace sky { - struct SceneViewInfo { - Matrix4 worldMatrix; - Matrix4 viewMatrix; - Matrix4 projectMatrix; - Matrix4 viewProjectMatrix; - Matrix4 inverseViewProject; + Matrix4 world; + Matrix4 view; + Matrix4 project; + Matrix4 viewProject; }; struct InstanceLocal { @@ -22,6 +20,7 @@ namespace sky { }; struct ShaderPassInfo { + Matrix4 lightMatrix; Vector4 viewport; }; diff --git a/render/core/include/render/RenderDefaultResource.h b/runtime/render/core/include/render/RenderDefaultResource.h similarity index 92% rename from render/core/include/render/RenderDefaultResource.h rename to runtime/render/core/include/render/RenderDefaultResource.h index 17efb02b..2526f60f 100644 --- a/render/core/include/render/RenderDefaultResource.h +++ b/runtime/render/core/include/render/RenderDefaultResource.h @@ -14,6 +14,7 @@ namespace sky { void Init(); void Reset(); + rhi::VertexInputPtr emptyVI; rhi::DescriptorSetPoolPtr defaultPool; RDResourceLayoutPtr emptyDesLayout; RDResourceGroupPtr emptySet; diff --git a/render/core/include/render/RenderDrawArgs.h b/runtime/render/core/include/render/RenderDrawArgs.h similarity index 100% rename from render/core/include/render/RenderDrawArgs.h rename to runtime/render/core/include/render/RenderDrawArgs.h diff --git a/runtime/render/core/include/render/RenderGeometry.h b/runtime/render/core/include/render/RenderGeometry.h new file mode 100644 index 00000000..82f65005 --- /dev/null +++ b/runtime/render/core/include/render/RenderGeometry.h @@ -0,0 +1,46 @@ +// +// Created by blues on 2024/9/14. +// + +#pragma once + +#include +#include +#include +#include +#include + +namespace sky { + + struct VertexAttribute { + VertexSemanticFlags sematic = {}; + uint32_t binding = 0; // buffer index + uint32_t offset = 0; + rhi::Format format = rhi::Format::F_RGBA32; + rhi::VertexInputRate rate = rhi::VertexInputRate::PER_VERTEX; + }; + + struct RenderGeometry : public RefObject { + void AddVertexAttribute(const VertexAttribute &attribute); + void FillVertexBuffer(std::vector &vbs); + rhi::VertexAssemblyPtr Request(const RDProgramPtr& program, rhi::VertexInputPtr &vtxDesc); + rhi::VertexInputPtr Request(const RDProgramPtr& program); + void Reset(); + void Upload(); + bool IsReady() const; + + // streams + std::vector vertexBuffers; + std::vector vertexAttributes; + IndexBuffer indexBuffer; + bool dynamicVB = false; + + // flags for all attributes + VertexSemanticFlags attributeSemantics; + + uint32_t version = 0; + bool uploaded = false; + }; + using RenderGeometryPtr = CounterPtr; + +} // namespace sky diff --git a/render/core/include/render/RenderNameHandle.h b/runtime/render/core/include/render/RenderNameHandle.h similarity index 100% rename from render/core/include/render/RenderNameHandle.h rename to runtime/render/core/include/render/RenderNameHandle.h diff --git a/runtime/render/core/include/render/RenderPassPipeline.h b/runtime/render/core/include/render/RenderPassPipeline.h new file mode 100644 index 00000000..10bf2478 --- /dev/null +++ b/runtime/render/core/include/render/RenderPassPipeline.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class RenderPassPipeline : public RenderPipeline { + public: + RenderPassPipeline() = default; + ~RenderPassPipeline() override = default; + + void AddScenePass(RenderScenePipeline *ppl); + private: + bool OnSetup(rdg::RenderGraph &rdg, const std::vector &scenes) override; + + std::vector> scenePipelines; + }; + +} // namespace sky diff --git a/render/core/include/render/RenderPipeline.h b/runtime/render/core/include/render/RenderPipeline.h similarity index 71% rename from render/core/include/render/RenderPipeline.h rename to runtime/render/core/include/render/RenderPipeline.h index 635b4276..5a69efcc 100644 --- a/render/core/include/render/RenderPipeline.h +++ b/runtime/render/core/include/render/RenderPipeline.h @@ -5,8 +5,10 @@ #pragma once #include +#include namespace sky { + class RenderScene; namespace rdg { struct RenderGraph; } @@ -16,9 +18,10 @@ namespace sky { RenderPipeline(); virtual ~RenderPipeline(); - virtual void OnSetup(rdg::RenderGraph &rdg) = 0; - void FrameSync(); + virtual bool OnSetup(rdg::RenderGraph &rdg, const std::vector &scenes) = 0; + void Compile(rdg::RenderGraph &rdg); + void Collect(rdg::RenderGraph &rdg, const std::vector &scenes); void Execute(rdg::RenderGraph &rdg); rdg::RenderGraphContext *Context() const { return rdgContext.get(); } diff --git a/runtime/render/core/include/render/RenderPrimitive.h b/runtime/render/core/include/render/RenderPrimitive.h new file mode 100644 index 00000000..d48c3bd9 --- /dev/null +++ b/runtime/render/core/include/render/RenderPrimitive.h @@ -0,0 +1,64 @@ +// +// Created by Zach Lee on 2023/8/19. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + struct TechniqueInstance { + RDGfxTechPtr technique; + RDMaterialInstancePtr material; + ShaderOptionPtr shaderOption; + + // cache values + RDProgramPtr program; + rhi::VertexInputPtr vertexDesc; + rhi::VertexAssemblyPtr vao; + rhi::GraphicsPipelinePtr pso; + + uint32_t vaoVersion = 0; + uint32_t variantHash = 0; + uint32_t renderPassHash = 0; + }; + + struct RenderPrimitive { + explicit RenderPrimitive(PmrResource *res = nullptr) : args(res != nullptr ? res : &defaultRes) {} + // dynamic status + PmrUnSyncPoolRes defaultRes; + uint32_t sortKey = 0; + + bool isReady = false; + + AABB localBound {Vector3(std::numeric_limits::min()), Vector3(std::numeric_limits::max())}; + AABB worldBound {Vector3(std::numeric_limits::min()), Vector3(std::numeric_limits::max())}; + + // geometry + RenderVertexFlags vertexFlags; + RenderGeometryPtr geometry; + PmrVector args; + rhi::BufferPtr indirectBuffer; + + // shader resources + RDResourceGroupPtr batchSet; + RDResourceGroupPtr instanceSet; + + // cache object + std::vector techniques; + }; + + struct RenderDrawItem { + RenderPrimitive *primitive = nullptr; + uint32_t techIndex = 0; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/RenderResource.h b/runtime/render/core/include/render/RenderResource.h new file mode 100644 index 00000000..47a8d57f --- /dev/null +++ b/runtime/render/core/include/render/RenderResource.h @@ -0,0 +1,58 @@ +// +// Created by blues on 2024/7/24. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + + class RenderResource : public RefObject { + public: + RenderResource() = default; + explicit RenderResource(const std::string &name_) : name(name_) {} // NOLINT + ~RenderResource() override = default; + + void SetName(const std::string &name_) { name = name_; } + const std::string &GetName() const { return name; } + protected: + std::string name; + }; + + class IStreamableResource : public RenderResource { + public: + IStreamableResource() = default; + explicit IStreamableResource(const std::string &name_) : RenderResource(name_) {} + ~IStreamableResource() override = default; + + uint64_t Upload(rhi::Queue *queue) + { + uploadQueue = queue; + return UploadImpl(); + } + + void Wait() const + { + if (uploadQueue != nullptr) { + uploadQueue->Wait(uploadHandle); + } + } + + bool IsReady() const + { + return uploadQueue != nullptr && uploadQueue->HasComplete(uploadHandle); + } + + protected: + virtual uint64_t UploadImpl() = 0; + + rhi::Queue* uploadQueue = nullptr; + rhi::TransferTaskHandle uploadHandle = 0; + }; + using RDStreamableResourcePtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/render/core/include/render/RenderResourceGC.h b/runtime/render/core/include/render/RenderResourceGC.h similarity index 100% rename from render/core/include/render/RenderResourceGC.h rename to runtime/render/core/include/render/RenderResourceGC.h diff --git a/render/core/include/render/RenderScene.h b/runtime/render/core/include/render/RenderScene.h similarity index 84% rename from render/core/include/render/RenderScene.h rename to runtime/render/core/include/render/RenderScene.h index 90407ba1..f3c03098 100644 --- a/render/core/include/render/RenderScene.h +++ b/runtime/render/core/include/render/RenderScene.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace sky { @@ -17,9 +18,7 @@ namespace sky { public: void PreTick(float time); void PostTick(float time); - void Render(); - - void SetPipeline(RenderPipeline *pipeline); + void Render(rdg::RenderGraph& rdg); SceneView * CreateSceneView(uint32_t viewCount); void RemoveSceneView(SceneView *view); @@ -32,10 +31,12 @@ namespace sky { void AddFeature(IFeatureProcessor *feature); + const RenderPipelineFlags &GetRenderPipelineFlags() const { return renderFlags; } + template T *GetFeature() const { - auto iter = features.find(TypeInfo::Hash()); + auto iter = features.find(RuntimeTypeId()); if (iter != features.end()) { return static_cast(iter->second.get()); } @@ -54,7 +55,7 @@ namespace sky { PmrVector> sceneViews; PmrVector primitives; - std::unique_ptr pipeline; + RenderPipelineFlags renderFlags; }; } // namespace sky diff --git a/runtime/render/core/include/render/RenderScenePipeline.h b/runtime/render/core/include/render/RenderScenePipeline.h new file mode 100644 index 00000000..20d9c5bd --- /dev/null +++ b/runtime/render/core/include/render/RenderScenePipeline.h @@ -0,0 +1,34 @@ +// +// Created by blues on 2024/9/5. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class RenderScene; + namespace rdg { + struct RenderGraph; + } // namespace rdg + + class RenderScenePipeline { + public: + explicit RenderScenePipeline(RenderScene *scn) : scene(scn) {} + virtual ~RenderScenePipeline() = default; + + void AddPass(PassBase *pass); + + void Setup(rdg::RenderGraph &rdg); + + protected: + virtual void Collect(rdg::RenderGraph &rdg) {} + + RenderScene *scene = nullptr; + std::vector passes; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/RenderSemantics.h b/runtime/render/core/include/render/RenderSemantics.h new file mode 100644 index 00000000..c442057a --- /dev/null +++ b/runtime/render/core/include/render/RenderSemantics.h @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/9/14. +// + +#pragma once + +#include +#include + +namespace sky { + + class RenderSemantics : public Singleton { + public: + RenderSemantics(); + ~RenderSemantics() = default; + + void RegisterVertexSemantic(const std::string &name, VertexSemanticFlagBit flag); + VertexSemanticFlagBit QuerySemanticByName(const std::string &name) const; + + private: + std::unordered_map vtxNameMap; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/RenderStreamManager.h b/runtime/render/core/include/render/RenderStreamManager.h new file mode 100644 index 00000000..4889dbb8 --- /dev/null +++ b/runtime/render/core/include/render/RenderStreamManager.h @@ -0,0 +1,31 @@ +// +// Created by blues on 2024/9/16. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class RenderStreamManager { + public: + RenderStreamManager() = default; + ~RenderStreamManager() = default; + + void SetUploadQueue(rhi::Queue *queue); + void UploadTexture(const RDTexturePtr &texture); + void UploadBuffer(const RDBufferPtr &buffer); + void Tick(); + + private: + std::list uploadQueue; + + rhi::Queue* transferQueue = nullptr; + + uint32_t limitPerFrame = 256 * 1024 * 1024; + }; + +} // namespace sky diff --git a/render/core/include/render/RenderWindow.h b/runtime/render/core/include/render/RenderWindow.h similarity index 61% rename from render/core/include/render/RenderWindow.h rename to runtime/render/core/include/render/RenderWindow.h index fc3e6d13..0d33bec5 100644 --- a/render/core/include/render/RenderWindow.h +++ b/runtime/render/core/include/render/RenderWindow.h @@ -10,12 +10,19 @@ namespace sky { class RenderWindow { public: bool Init(void *hWnd, uint32_t width, uint32_t height, bool vSync); +#ifdef SKY_ENABLE_XR + bool InitByXR(const rhi::XRSwapChainPtr &xr); +#endif + void Resize(uint32_t width, uint32_t height); uint32_t GetWidth() const; uint32_t GetHeight() const; - rhi::PixelFormat GetOutputFormat() const; - const rhi::SwapChainPtr &GetSwaChain() const { return swapChain; } + const rhi::SwapChainPtr &GetSwapChain() const { return swapChain; } + +#ifdef SKY_ENABLE_XR + const rhi::XRSwapChainPtr &GetXRSwaChain() const { return xrSwapChain; } +#endif private: friend class Renderer; @@ -24,6 +31,10 @@ namespace sky { rhi::SwapChainPtr swapChain; void *winHandle = nullptr; + +#ifdef SKY_ENABLE_XR + rhi::XRSwapChainPtr xrSwapChain; +#endif }; } // namespace sky \ No newline at end of file diff --git a/render/core/include/render/Renderer.h b/runtime/render/core/include/render/Renderer.h similarity index 82% rename from render/core/include/render/Renderer.h rename to runtime/render/core/include/render/Renderer.h index cf6707b7..ea498812 100644 --- a/render/core/include/render/Renderer.h +++ b/runtime/render/core/include/render/Renderer.h @@ -12,13 +12,14 @@ #include #include +#include #include #include #include #include - -#include +#include +#include namespace sky { @@ -30,26 +31,32 @@ namespace sky { void Init(); void Tick(float time); + void StopRender(); + RenderScene *CreateScene(); void RemoveScene(RenderScene *scene); RenderWindow *CreateRenderWindow(void *hWnd, uint32_t width, uint32_t height, bool vSync); +#ifdef SKY_ENABLE_XR + RenderWindow *CreateRenderWindowByXR(); +#endif + void DestroyRenderWindow(RenderWindow *); uint32_t GetInflightFrameCount() const { return inflightFrameCount; } - RenderResourceGC *GetResourceGC() const { return delayReleaseCollections[frameIndex].get(); } + RenderResourceGC *GetResourceGC() const; + RenderStreamManager *GetStreamingManager() const { return streamManager.get(); } const RenderDefaultResource &GetDefaultRHIResource() const { return defaultRHIResource; } - void SetVertexDescLibrary(VertexDescLibrary *lib) { vertexLibrary.reset(lib); } - VertexDescLibrary *GetVertexDescLibrary() const { return vertexLibrary.get(); } - void SetCacheFolder(const std::string &path) { cacheFolder = path; } const std::string &GetCacheFolder() const { return cacheFolder; } void SetShaderCompiler(ShaderCompileFunc func) { shaderCompiler = func; } ShaderCompileFunc GetShaderCompiler() const { return shaderCompiler; } + void SetPipeline(RenderPipeline *pipeline); + template void RegisterRenderFeature() { @@ -80,10 +87,10 @@ namespace sky { PmrVector> delayReleaseCollections; PmrVector> features; - std::unique_ptr vertexLibrary; + std::unique_ptr streamManager; + std::unique_ptr pipeline; ShaderCompileFunc shaderCompiler = nullptr; - std::string cacheFolder; }; } // namespace sky diff --git a/render/core/include/render/SceneView.h b/runtime/render/core/include/render/SceneView.h similarity index 68% rename from render/core/include/render/SceneView.h rename to runtime/render/core/include/render/SceneView.h index b9a52fee..7c8977ab 100644 --- a/render/core/include/render/SceneView.h +++ b/runtime/render/core/include/render/SceneView.h @@ -22,9 +22,15 @@ namespace sky { ~SceneView() = default; void SetMatrix(const Matrix4 &mat, uint32_t index = 0); - void SetProjective(float near, float far, float fov, float aspect, uint32_t index = 0); + void SetPerspective(float near, float far, float fov, float aspect, uint32_t index = 0); + void SetOrthogonal(float l, float r, float t, float b, float near, float far, uint32_t index = 0); + void SetFlipY(bool flip) { flipY = flip; } void Update(); + const Matrix4 &GetProject() const { return projects0[0]; } + const Matrix4 &GetView() const { return viewInfo[0].view; } + const Matrix4 &GetViewProject() const { return viewInfo[0].viewProject; } + bool FrustumCulling(const AABB &aabb) const; uint32_t GetViewID() const { return viewID; } @@ -41,9 +47,11 @@ namespace sky { uint32_t viewCount; uint32_t viewMask; + PmrVector projects0; PmrVector viewInfo; PmrVector frustums; bool dirty; + bool flipY = true; RDUniformBufferPtr viewUbo; }; diff --git a/runtime/render/core/include/render/debug/DebugRenderer.h b/runtime/render/core/include/render/debug/DebugRenderer.h new file mode 100644 index 00000000..98fcd99d --- /dev/null +++ b/runtime/render/core/include/render/debug/DebugRenderer.h @@ -0,0 +1,47 @@ +// +// Created by blues on 2024/9/1. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + struct DebugVertex { + Vector4 pos; + Color col; + }; + + class DebugRenderer { + public: + DebugRenderer(); + ~DebugRenderer() = default; + + void Reset(); + void SetColor(const Color &color); + + void DrawLine(const Line &line); + void DrawLine(const Vector3 &from, const Vector3 &to); + + void DrawSphere(const Sphere &sphere); + void DrawAABB(const AABB &aabb); + + void Render(); + private: + Color currentColor = {1.f, 1.f, 1.f, 1.f}; + + rhi::CmdDrawLinear linear; + RDBufferPtr vertexBuffer; + RenderGeometryPtr geometry; + std::vector batchVertices; + + uint32_t capacity = 0; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/debug/Gizmo.h b/runtime/render/core/include/render/debug/Gizmo.h new file mode 100644 index 00000000..1db7ba0f --- /dev/null +++ b/runtime/render/core/include/render/debug/Gizmo.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/21. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class Gizmo : public RefObject { + public: + Gizmo(); + ~Gizmo() override = default; + + void DrawGrid(); + void SetTechnique(const RDGfxTechPtr &tech); + + private: + std::unique_ptr renderer; + std::unique_ptr primitive; + }; + using GizmoPtr = CounterPtr; +} // namespace sky diff --git a/render/core/include/render/env/SkyBoxRenderer.h b/runtime/render/core/include/render/env/SkyBoxRenderer.h similarity index 100% rename from render/core/include/render/env/SkyBoxRenderer.h rename to runtime/render/core/include/render/env/SkyBoxRenderer.h diff --git a/render/core/include/render/geometry/GeometryFeature.h b/runtime/render/core/include/render/geometry/GeometryFeature.h similarity index 100% rename from render/core/include/render/geometry/GeometryFeature.h rename to runtime/render/core/include/render/geometry/GeometryFeature.h diff --git a/render/core/include/render/geometry/GeometryRenderer.h b/runtime/render/core/include/render/geometry/GeometryRenderer.h similarity index 100% rename from render/core/include/render/geometry/GeometryRenderer.h rename to runtime/render/core/include/render/geometry/GeometryRenderer.h diff --git a/runtime/render/core/include/render/light/LightBase.h b/runtime/render/core/include/render/light/LightBase.h new file mode 100644 index 00000000..439d90b5 --- /dev/null +++ b/runtime/render/core/include/render/light/LightBase.h @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/6/10. +// + +#pragma once + +#include + +namespace sky { + + enum class LightType : uint32_t { + DIRECT, + POINT, + SPOT + }; + + struct LightInfo { + Vector4 position; + Vector4 direction; + Vector4 color; + Vector4 rsv; + }; + + class Light { + public: + Light() = default; + virtual ~Light() = default; + + virtual void Collect(LightInfo &info) = 0; + + void SetColor(const Vector4 &clr) { color = clr; } + + protected: + Vector4 color; + }; + + class DirectLight : public Light { + public: + DirectLight() = default; + ~DirectLight() override = default; + + void SetDirection(const Vector3 &dir) { direction = Cast(dir); } + + void Collect(LightInfo &info) override; + private: + Vector4 direction; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/light/LightFeatureProcessor.h b/runtime/render/core/include/render/light/LightFeatureProcessor.h new file mode 100644 index 00000000..bd68cabc --- /dev/null +++ b/runtime/render/core/include/render/light/LightFeatureProcessor.h @@ -0,0 +1,37 @@ +// +// Created by blues on 2024/6/10. +// + +#pragma once + +#include +#include +#include + +namespace sky { + + class LightFeatureProcessor : public IFeatureProcessor { + public: + explicit LightFeatureProcessor(RenderScene *scn) : IFeatureProcessor(scn) {} + ~LightFeatureProcessor() override = default; + + void Render(rdg::RenderGraph &rdg) override; + + template + T* CreateLight() + { + static_assert(std::is_base_of_v); + auto light = new T(); + AddLight(light); + return light; + } + + void AddLight(Light *light); + void RemoveLight(Light *light); + private: + using LightPtr = std::unique_ptr; + + std::vector lights; + }; + +} // namespace sky diff --git a/render/core/include/render/mesh/GridRenderer.h b/runtime/render/core/include/render/mesh/GridRenderer.h similarity index 96% rename from render/core/include/render/mesh/GridRenderer.h rename to runtime/render/core/include/render/mesh/GridRenderer.h index ef251613..1179043c 100644 --- a/render/core/include/render/mesh/GridRenderer.h +++ b/runtime/render/core/include/render/mesh/GridRenderer.h @@ -28,4 +28,4 @@ namespace sky { RDBufferPtr indexBuffer; }; -} // namepace sky \ No newline at end of file +} // namespace sky \ No newline at end of file diff --git a/render/core/include/render/mesh/MeshFeature.h b/runtime/render/core/include/render/mesh/MeshFeature.h similarity index 83% rename from render/core/include/render/mesh/MeshFeature.h rename to runtime/render/core/include/render/mesh/MeshFeature.h index 4bd6be2d..d0e6cb8a 100644 --- a/render/core/include/render/mesh/MeshFeature.h +++ b/runtime/render/core/include/render/mesh/MeshFeature.h @@ -17,9 +17,11 @@ namespace sky { void Init(); RDResourceGroupPtr RequestResourceGroup(); + RDResourceGroupPtr RequestSkinnedResourceGroup(); private: RDResourceLayoutPtr localLayout; + RDResourceLayoutPtr skinnedLayout; rhi::DescriptorSetPoolPtr pool; }; diff --git a/render/core/include/render/mesh/MeshFeatureProcessor.h b/runtime/render/core/include/render/mesh/MeshFeatureProcessor.h similarity index 51% rename from render/core/include/render/mesh/MeshFeatureProcessor.h rename to runtime/render/core/include/render/mesh/MeshFeatureProcessor.h index 81b07959..4d913ab7 100644 --- a/render/core/include/render/mesh/MeshFeatureProcessor.h +++ b/runtime/render/core/include/render/mesh/MeshFeatureProcessor.h @@ -5,8 +5,8 @@ #pragma once #include -#include -#include +#include +#include namespace sky { @@ -18,11 +18,16 @@ namespace sky { void Tick(float time) override; void Render(rdg::RenderGraph &rdg) override; - StaticMeshRenderer *CreateStaticMesh(); - void RemoveStaticMesh(StaticMeshRenderer *mesh); + MeshRenderer *CreateStaticMesh(); + void RemoveStaticMesh(MeshRenderer *mesh); + + SkeletonMeshRenderer *CreateSkeletonMesh(); + void RemoveSkeletonMesh(SkeletonMeshRenderer *mesh); private: - std::list> staticMeshes; + std::list> staticMeshes; + + std::list> skeletonMeshes; }; } // namespace sky diff --git a/render/core/include/render/mesh/StaticMeshRenderer.h b/runtime/render/core/include/render/mesh/MeshRenderer.h similarity index 72% rename from render/core/include/render/mesh/StaticMeshRenderer.h rename to runtime/render/core/include/render/mesh/MeshRenderer.h index 16ee4b9f..a19c23e3 100644 --- a/render/core/include/render/mesh/StaticMeshRenderer.h +++ b/runtime/render/core/include/render/mesh/MeshRenderer.h @@ -10,24 +10,27 @@ namespace sky { class RenderScene; + class MeshFeature; - class StaticMeshRenderer { + class MeshRenderer { public: - StaticMeshRenderer() = default; - virtual ~StaticMeshRenderer(); + MeshRenderer() = default; + virtual ~MeshRenderer(); + void Tick(); void AttachScene(RenderScene *scn); void SetMesh(const RDMeshPtr &mesh); void UpdateTransform(const Matrix4 &matrix); void SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh); - protected: + virtual void PrepareUBO(); + virtual RDResourceGroupPtr RequestResourceGroup(MeshFeature *feature); + RenderScene *scene = nullptr; RDMeshPtr mesh; std::vector> primitives; - rhi::VertexAssemblyPtr va; RDDynamicUniformBufferPtr ubo; }; diff --git a/render/core/include/render/mesh/StandardMeshDefines.h b/runtime/render/core/include/render/mesh/StandardMeshDefines.h similarity index 100% rename from render/core/include/render/mesh/StandardMeshDefines.h rename to runtime/render/core/include/render/mesh/StandardMeshDefines.h diff --git a/render/core/include/render/particle/ParticleEmitter.h b/runtime/render/core/include/render/particle/ParticleEmitter.h similarity index 98% rename from render/core/include/render/particle/ParticleEmitter.h rename to runtime/render/core/include/render/particle/ParticleEmitter.h index bb79439c..eef2c6db 100644 --- a/render/core/include/render/particle/ParticleEmitter.h +++ b/runtime/render/core/include/render/particle/ParticleEmitter.h @@ -36,7 +36,7 @@ namespace sky { template void RegisterPerParticleComponent() { - auto id = TypeInfo::Hash(); + auto id = RuntimeTypeId(); auto iter = particleStorage.perParticleIndexMap.find(id); if (iter != particleStorage.perParticleIndexMap.end()) { particleStorage.perParticleIndexMap.emplace(id, std::pair{static_cast(particleStorage.storages.size()), static_cast(sizeof(T))}); diff --git a/render/core/include/render/particle/ParticleFeature.h b/runtime/render/core/include/render/particle/ParticleFeature.h similarity index 100% rename from render/core/include/render/particle/ParticleFeature.h rename to runtime/render/core/include/render/particle/ParticleFeature.h diff --git a/render/core/include/render/particle/ParticleFeatureProcessor.h b/runtime/render/core/include/render/particle/ParticleFeatureProcessor.h similarity index 100% rename from render/core/include/render/particle/ParticleFeatureProcessor.h rename to runtime/render/core/include/render/particle/ParticleFeatureProcessor.h diff --git a/render/core/include/render/particle/ParticleModules.h b/runtime/render/core/include/render/particle/ParticleModules.h similarity index 99% rename from render/core/include/render/particle/ParticleModules.h rename to runtime/render/core/include/render/particle/ParticleModules.h index 0dbdb575..986ecd83 100644 --- a/render/core/include/render/particle/ParticleModules.h +++ b/runtime/render/core/include/render/particle/ParticleModules.h @@ -41,7 +41,7 @@ namespace sky { template inline T &Component(uint32_t index) { - const auto &[offset, stride] = perParticleIndexMap.at(TypeInfo::Hash()); + const auto &[offset, stride] = perParticleIndexMap.at(RuntimeTypeId()); T *val = reinterpret_cast(storages[offset].data()); return val[entities[index]]; } diff --git a/render/core/include/render/particle/ParticleSpriteRenderer.h b/runtime/render/core/include/render/particle/ParticleSpriteRenderer.h similarity index 100% rename from render/core/include/render/particle/ParticleSpriteRenderer.h rename to runtime/render/core/include/render/particle/ParticleSpriteRenderer.h diff --git a/render/core/include/render/particle/ParticleSystem.h b/runtime/render/core/include/render/particle/ParticleSystem.h similarity index 96% rename from render/core/include/render/particle/ParticleSystem.h rename to runtime/render/core/include/render/particle/ParticleSystem.h index 210894ef..836c0026 100644 --- a/render/core/include/render/particle/ParticleSystem.h +++ b/runtime/render/core/include/render/particle/ParticleSystem.h @@ -5,6 +5,7 @@ #pragma once #include +#include namespace sky { class ParticleSystem { diff --git a/render/core/include/render/rdg/AccessGraphCompiler.h b/runtime/render/core/include/render/rdg/AccessGraphCompiler.h similarity index 100% rename from render/core/include/render/rdg/AccessGraphCompiler.h rename to runtime/render/core/include/render/rdg/AccessGraphCompiler.h diff --git a/render/core/include/render/rdg/AccessUtils.h b/runtime/render/core/include/render/rdg/AccessUtils.h similarity index 100% rename from render/core/include/render/rdg/AccessUtils.h rename to runtime/render/core/include/render/rdg/AccessUtils.h diff --git a/render/core/include/render/rdg/RenderGraph.h b/runtime/render/core/include/render/rdg/RenderGraph.h similarity index 95% rename from render/core/include/render/rdg/RenderGraph.h rename to runtime/render/core/include/render/rdg/RenderGraph.h index 25e6f66a..9368926a 100644 --- a/render/core/include/render/rdg/RenderGraph.h +++ b/runtime/render/core/include/render/rdg/RenderGraph.h @@ -45,6 +45,7 @@ namespace sky::rdg { RasterSubPassBuilder &AddColorInOut(const std::string &name); RasterSubPassBuilder &AddDepthStencil(const std::string &name, const ResourceAccess& access); RasterSubPassBuilder &AddComputeView(const std::string &name, const ComputeView &view); + RasterSubPassBuilder &SetViewMask(uint32_t mask); RasterQueueBuilder AddQueue(const std::string &name); FullScreenBuilder AddFullScreen(const std::string &name); uint32_t GetAttachmentIndex(const std::string &name); @@ -60,6 +61,7 @@ namespace sky::rdg { struct RasterPassBuilder { RasterPassBuilder &AddAttachment(const RasterAttachment &attachment, const rhi::ClearValue &clear = rhi::ClearValue(0, 0, 0, 0)); + RasterPassBuilder &AddCoRelationMasks(uint32_t mask); RasterSubPassBuilder AddRasterSubPass(const std::string &name); RenderGraph &rdg; @@ -123,6 +125,9 @@ namespace sky::rdg { void ImportImage(const char *name, const rhi::ImagePtr &image, rhi::ImageViewType viewType, const rhi::AccessFlags &flags); void ImportSwapChain(const char *name, const rhi::SwapChainPtr &swapchain); +#ifdef SKY_ENABLE_XR + void ImportXRSwapChain(const char *name, const rhi::XRSwapChainPtr &swapchain); +#endif void AddImageView(const char *name, const char *source, const GraphImageView &view); void AddBuffer(const char *name, const GraphBuffer &attachment); @@ -151,6 +156,7 @@ namespace sky::rdg { PmrVector> importImages; PmrVector> imageViews; PmrVector> swapChains; + PmrVector> xrSwapChains; PmrVector> buffers; PmrVector> importBuffers; PmrVector> bufferViews; @@ -160,7 +166,7 @@ namespace sky::rdg { }; struct RenderGraph { - explicit RenderGraph(RenderGraphContext *ctx, RenderScene *scene); + explicit RenderGraph(RenderGraphContext *ctx); ~RenderGraph() = default; using vertex_descriptor = VertexType; @@ -186,7 +192,7 @@ namespace sky::rdg { // memory RenderGraphContext *context; - RenderScene *scene; +// RenderScene *scene; // vertex VertexList vertices; @@ -257,6 +263,9 @@ namespace sky::rdg { } else if constexpr (std::is_same_v) { graph.polymorphicDatas.emplace_back(graph.swapChains.size()); graph.swapChains.emplace_back(std::forward(val)); + } else if constexpr (std::is_same_v) { + graph.polymorphicDatas.emplace_back(graph.xrSwapChains.size()); + graph.xrSwapChains.emplace_back(std::forward(val)); } else if constexpr (std::is_same_v) { graph.polymorphicDatas.emplace_back(graph.buffers.size()); graph.buffers.emplace_back(std::forward(val)); diff --git a/render/core/include/render/rdg/RenderGraphContext.h b/runtime/render/core/include/render/rdg/RenderGraphContext.h similarity index 100% rename from render/core/include/render/rdg/RenderGraphContext.h rename to runtime/render/core/include/render/rdg/RenderGraphContext.h diff --git a/render/core/include/render/rdg/RenderGraphExecutor.h b/runtime/render/core/include/render/rdg/RenderGraphExecutor.h similarity index 100% rename from render/core/include/render/rdg/RenderGraphExecutor.h rename to runtime/render/core/include/render/rdg/RenderGraphExecutor.h diff --git a/render/core/include/render/rdg/RenderGraphProfiler.h b/runtime/render/core/include/render/rdg/RenderGraphProfiler.h similarity index 100% rename from render/core/include/render/rdg/RenderGraphProfiler.h rename to runtime/render/core/include/render/rdg/RenderGraphProfiler.h diff --git a/render/core/include/render/rdg/RenderGraphTypes.h b/runtime/render/core/include/render/rdg/RenderGraphTypes.h similarity index 93% rename from render/core/include/render/rdg/RenderGraphTypes.h rename to runtime/render/core/include/render/rdg/RenderGraphTypes.h index 16923ce9..16e9bf0c 100644 --- a/render/core/include/render/rdg/RenderGraphTypes.h +++ b/runtime/render/core/include/render/rdg/RenderGraphTypes.h @@ -74,11 +74,12 @@ namespace sky::rdg { struct ImportImageTag {}; struct ImageViewTag {}; struct ImportSwapChainTag {}; + struct ImportXRSwapChainTag {}; struct BufferTag {}; struct ImportBufferTag {}; struct ConstantBufferTag {}; struct BufferViewTag {}; - using ResourceGraphTags = std::variant; + using ResourceGraphTags = std::variant; struct AccessPassTag {}; struct AccessResTag {}; @@ -183,6 +184,7 @@ namespace sky::rdg { using Tag = RasterSubPassTag; uint32_t subPassID = 0; + uint32_t viewMask = 0; VertexType parent = INVALID_VERTEX; PmrVector colors; PmrVector resolves; @@ -197,8 +199,8 @@ namespace sky::rdg { using Tag = FullScreenBlitTag; RDGfxTechPtr technique; + RDProgramPtr program; uint32_t passID; - RDResourceLayoutPtr layout; ResourceGroup *resourceGroup = nullptr; rhi::GraphicsPipelinePtr pso; }; @@ -233,6 +235,7 @@ namespace sky::rdg { , attachments(res) , attachmentVertex(res) , subPasses(res) + , correlationMasks{res} , clearValues(res) , dependencies(res) , frontBarriers(res) @@ -246,11 +249,11 @@ namespace sky::rdg { PmrVector attachments; PmrVector attachmentVertex; PmrVector subPasses; + PmrVector correlationMasks; PmrVector clearValues; PmrVector dependencies; PmrHashMap> frontBarriers; // key resID PmrHashMap> rearBarriers; // key resID - RDGfxTechPtr technique; rhi::RenderPassPtr renderPass; rhi::FrameBufferPtr frameBuffer; @@ -298,11 +301,21 @@ namespace sky::rdg { , frontBarriers(res) , rearBarriers(res) {} - +#ifdef SKY_ENABLE_XR + explicit PresentPass(VertexType resID, const rhi::XRSwapChainPtr &swc, PmrResource *res) + : imageID(resID) + , xrSwapChain(swc) + , frontBarriers(res) + , rearBarriers(res) + {} +#endif using Tag = PresentTag; VertexType imageID = INVALID_VERTEX; rhi::SwapChainPtr swapChain; +#ifdef SKY_ENABLE_XR + rhi::XRSwapChainPtr xrSwapChain; +#endif PmrHashMap> frontBarriers; // key resID PmrHashMap> rearBarriers; // key resID }; @@ -347,6 +360,16 @@ namespace sky::rdg { uint32_t imageIndex = 0; }; + + struct GraphXRSwapChain { + using Tag = ImportXRSwapChainTag; + +#ifdef SKY_ENABLE_XR + rhi::XRSwapChainPtr swapchain; + uint32_t imageIndex = 0; +#endif + }; + struct GraphImageView { using Tag = ImageViewTag; diff --git a/render/core/include/render/rdg/RenderGraphUploader.h b/runtime/render/core/include/render/rdg/RenderGraphUploader.h similarity index 100% rename from render/core/include/render/rdg/RenderGraphUploader.h rename to runtime/render/core/include/render/rdg/RenderGraphUploader.h diff --git a/render/core/include/render/rdg/RenderGraphVisitors.h b/runtime/render/core/include/render/rdg/RenderGraphVisitors.h similarity index 100% rename from render/core/include/render/rdg/RenderGraphVisitors.h rename to runtime/render/core/include/render/rdg/RenderGraphVisitors.h diff --git a/render/core/include/render/rdg/RenderLayoutGraph.h b/runtime/render/core/include/render/rdg/RenderLayoutGraph.h similarity index 100% rename from render/core/include/render/rdg/RenderLayoutGraph.h rename to runtime/render/core/include/render/rdg/RenderLayoutGraph.h diff --git a/render/core/include/render/rdg/RenderResourceCompiler.h b/runtime/render/core/include/render/rdg/RenderResourceCompiler.h similarity index 100% rename from render/core/include/render/rdg/RenderResourceCompiler.h rename to runtime/render/core/include/render/rdg/RenderResourceCompiler.h diff --git a/render/core/include/render/rdg/RenderSceneVisitor.h b/runtime/render/core/include/render/rdg/RenderSceneVisitor.h similarity index 64% rename from render/core/include/render/rdg/RenderSceneVisitor.h rename to runtime/render/core/include/render/rdg/RenderSceneVisitor.h index f1a09d9a..e040528f 100644 --- a/render/core/include/render/rdg/RenderSceneVisitor.h +++ b/runtime/render/core/include/render/rdg/RenderSceneVisitor.h @@ -6,15 +6,19 @@ #include #include +namespace sky { + class RenderScene; +} // namespace sky + namespace sky::rdg { struct RenderGraph; struct RenderSceneVisitor{ - explicit RenderSceneVisitor(RenderGraph &g) : graph(g) {} + explicit RenderSceneVisitor(RenderGraph &g, RenderScene *scn) : graph(g), scene(scn) {} [[maybe_unused]] void BuildRenderQueue(); - RenderGraph &graph; + RenderScene *scene; }; } // namespace sky::rdg diff --git a/render/core/include/render/rdg/TransientMemoryPool.h b/runtime/render/core/include/render/rdg/TransientMemoryPool.h similarity index 100% rename from render/core/include/render/rdg/TransientMemoryPool.h rename to runtime/render/core/include/render/rdg/TransientMemoryPool.h diff --git a/render/core/include/render/rdg/TransientObjectPool.h b/runtime/render/core/include/render/rdg/TransientObjectPool.h similarity index 100% rename from render/core/include/render/rdg/TransientObjectPool.h rename to runtime/render/core/include/render/rdg/TransientObjectPool.h diff --git a/render/core/include/render/rdg/TransientPool.h b/runtime/render/core/include/render/rdg/TransientPool.h similarity index 99% rename from render/core/include/render/rdg/TransientPool.h rename to runtime/render/core/include/render/rdg/TransientPool.h index d41b19e3..60694f34 100644 --- a/render/core/include/render/rdg/TransientPool.h +++ b/runtime/render/core/include/render/rdg/TransientPool.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include #include #include diff --git a/runtime/render/core/include/render/renderpass/ComputePass.h b/runtime/render/core/include/render/renderpass/ComputePass.h new file mode 100644 index 00000000..a1313854 --- /dev/null +++ b/runtime/render/core/include/render/renderpass/ComputePass.h @@ -0,0 +1,20 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include + +namespace sky { + + class ComputePass : public PassBase { + public: + explicit ComputePass(const Name &name_) : PassBase(name_) {} + ~ComputePass() override = default; + + private: + RDGfxTechPtr technique; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/renderpass/PassBase.h b/runtime/render/core/include/render/renderpass/PassBase.h new file mode 100644 index 00000000..1147a0fb --- /dev/null +++ b/runtime/render/core/include/render/renderpass/PassBase.h @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include +#include +#include + +namespace sky { + class RenderScene; + namespace rdg { + struct RenderGraph; + } + + class PassBase { + public: + explicit PassBase(const Name &name_) : name(name_) {} // NOLINT + virtual ~PassBase() = default; + + virtual void Prepare(rdg::RenderGraph &rdg, RenderScene &scene); + virtual void Setup(rdg::RenderGraph &rdg, RenderScene &scene) {} + protected: + + Name name; + RDResourceLayoutPtr layout; + + std::vector> images; + std::vector> buffers; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/renderpass/RasterPass.h b/runtime/render/core/include/render/renderpass/RasterPass.h new file mode 100644 index 00000000..41b59949 --- /dev/null +++ b/runtime/render/core/include/render/renderpass/RasterPass.h @@ -0,0 +1,63 @@ +// +// Created by blues on 2024/9/3. +// + +#pragma once + +#include +#include + +namespace sky { + + namespace rdg { + struct RasterSubPassBuilder; + } // namespace rdg + + class RasterPass : public PassBase { + public: + explicit RasterPass(const Name &name_) + : PassBase(name_) + {} + ~RasterPass() override = default; + + void Setup(rdg::RenderGraph &rdg, RenderScene &scene) override; + void Resize(uint32_t w, uint32_t h); + + protected: + virtual void SetupSubPass(rdg::RasterSubPassBuilder& builder, RenderScene &scene) {} + + struct Attachment { + rdg::RasterAttachment attachment; + rhi::ClearValue clearValue; + }; + + struct ComputeResource { + Name name; + rdg::ComputeView computeView; + }; + + uint32_t width; + uint32_t height; + + std::vector computeResources; + + std::vector colors; + std::vector resolves; + Attachment depthStencil; + Attachment depthResolve; + }; + + class FullScreenPass : public RasterPass { + public: + explicit FullScreenPass(const Name &name_, const RDGfxTechPtr &tech) // NOLINT + : RasterPass(name_) + , technique(tech) + {} + ~FullScreenPass() override = default; + + void Setup(rdg::RenderGraph &rdg, RenderScene &scene) override; + private: + RDGfxTechPtr technique; + }; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/resource/Buffer.h b/runtime/render/core/include/render/resource/Buffer.h new file mode 100644 index 00000000..5e67e461 --- /dev/null +++ b/runtime/render/core/include/render/resource/Buffer.h @@ -0,0 +1,122 @@ +// +// Created by Zach Lee on 2023/9/1. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + class Buffer : public IStreamableResource { + public: + Buffer(); + ~Buffer() override; + + void Init(uint64_t size, const rhi::BufferUsageFlags& usage, rhi::MemoryType memoryType); + void SetSourceData(const rhi::BufferUploadRequest &data); + + virtual uint64_t GetSize() const { return bufferDesc.size; } + + const rhi::BufferPtr &GetRHIBuffer() const { return buffer; } + virtual rhi::BufferView MakeView() const; + + protected: + uint64_t UploadImpl() override; + + rhi::Device *device = nullptr; + rhi::Buffer::Descriptor bufferDesc = {}; + rhi::BufferPtr buffer; + + rhi::BufferUploadRequest sourceData; + }; + using RDBufferPtr = CounterPtr; + + struct VertexBuffer { + RDBufferPtr buffer; + uint64_t offset = 0; + uint64_t range = 0; + uint32_t stride = 0; + + rhi::BufferView MakeView() const; + }; + + struct IndexBuffer { + RDBufferPtr buffer; + uint64_t offset = 0; + uint64_t range = 0; + rhi::IndexType indexType = rhi::IndexType::U32; + + rhi::BufferView MakeView() const; + }; + + class UniformBuffer : public Buffer { + public: + UniformBuffer() = default; + ~UniformBuffer() override = default; + + virtual bool Init(uint32_t size); + virtual void Write(uint32_t offset, const uint8_t *ptr, uint32_t size); + template + void WriteT(uint32_t offset, const T& val) + { + SKY_ASSERT(offset + sizeof(T) <= bufferDesc.size); + Write(offset, reinterpret_cast(&val), static_cast(sizeof(T))); + dirty = true; + } + + virtual void Upload(rhi::BlitEncoder &encoder); + + protected: + bool dirty = true; + uint8_t *ptr = nullptr; + std::vector data; + rhi::BufferPtr stagingBuffer; + }; + using RDUniformBufferPtr = std::shared_ptr; + + class DynamicUniformBuffer : public UniformBuffer { + public: + DynamicUniformBuffer() = default; + ~DynamicUniformBuffer() override = default; + + bool Init(uint32_t size) override; + void Upload(); + void Upload(rhi::BlitEncoder &encoder) override; + + uint64_t GetOffset() const { return frameIndex * alignedFrameSize; } + uint64_t GetSize() const override { return frameSize; } + private: + uint32_t frameSize = 0; + uint32_t alignedFrameSize; + uint32_t frameIndex = 0; + }; + using RDDynamicUniformBufferPtr = CounterPtr; + + class DynamicBuffer : public Buffer { + public: + DynamicBuffer() = default; + ~DynamicBuffer() override = default; + + bool Init(uint32_t size, const rhi::BufferUsageFlags& usage); + void Update(uint8_t *ptr, uint32_t offset, uint32_t size); + + void SwapBuffer(); + uint8_t *GetMapped() const; + uint64_t GetOffset() const { return frameIndex * alignedFrameSize; } + uint64_t GetSize() const override { return frameSize; } + + rhi::BufferView MakeView() const override; + private: + uint8_t *mapped = nullptr; + uint32_t frameSize = 0; + uint32_t alignedFrameSize; + uint32_t frameIndex = 0; + }; + using RDDynamicBuffer = CounterPtr; +} // namespace sky diff --git a/render/core/include/render/resource/Material.h b/runtime/render/core/include/render/resource/Material.h similarity index 70% rename from render/core/include/render/resource/Material.h rename to runtime/render/core/include/render/resource/Material.h index dcdb7ed1..981303b5 100644 --- a/render/core/include/render/resource/Material.h +++ b/runtime/render/core/include/render/resource/Material.h @@ -5,7 +5,7 @@ #pragma once #include -#include +#include #include #include #include @@ -26,35 +26,34 @@ namespace sky { VEC4, FLOAT, U32, - I32 + I32, + BOOL }; using MaterialValue = std::variant; - class Material { + class Material : public RenderResource { public: Material() = default; - ~Material() = default; + ~Material() override = default; void AddTechnique(const RDGfxTechPtr &technique); - const RDResourceLayoutPtr &GetLayout() const { return layout; } const std::vector &GetGfxTechniques() const { return gfxTechniques; } - RDResourceGroupPtr RequestResourceGroup(); + RDResourceGroupPtr RequestResourceGroup(const RDResourceLayoutPtr &layout); private: - RDResourceLayoutPtr layout; rhi::DescriptorSetPoolPtr pool; std::vector gfxTechniques; }; - using RDMaterialPtr = std::shared_ptr; + using RDMaterialPtr = CounterPtr; - class MaterialInstance { + class MaterialInstance : public RenderResource { public: - MaterialInstance() = default; - ~MaterialInstance() = default; + MaterialInstance(); + ~MaterialInstance() override = default; void SetMaterial(const RDMaterialPtr &mat); @@ -65,20 +64,29 @@ namespace sky { } void SetValue(const std::string &key, const uint8_t *t, uint32_t size); void SetTexture(const std::string &key, const RDTexturePtr &tex, uint32_t index = 0); + void SetOption(const std::string &key, const MacroValue &val); + + void Compile(); + void Update(); void Upload(); + bool IsReady() const; const RDResourceGroupPtr &GetResourceGroup() const { return resourceGroup; } const RDMaterialPtr &GetMaterial() const { return material; } + void ProcessShaderOption(const ShaderOptionPtr &option) const; + private: + ShaderOptionPtr options; RDMaterialPtr material; RDResourceGroupPtr resourceGroup; bool resDirty = true; + bool uploaded = false; std::unordered_map textures; std::unordered_map uniformBuffers; }; - using RDMaterialInstancePtr = std::shared_ptr; + using RDMaterialInstancePtr = CounterPtr; } // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/resource/Mesh.h b/runtime/render/core/include/render/resource/Mesh.h new file mode 100644 index 00000000..677151ae --- /dev/null +++ b/runtime/render/core/include/render/resource/Mesh.h @@ -0,0 +1,62 @@ +// +// Created by Zach Lee on 2023/8/31. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + + struct SubMesh { + uint32_t firstVertex = 0; + uint32_t vertexCount = 0; + uint32_t firstIndex = 0; + uint32_t indexCount = 0; + RDMaterialInstancePtr material; + AABB aabb; + }; + + struct VertexBufferSource { + rhi::BufferUploadRequest source; + uint32_t stride; + }; + + struct MeshData { + std::vector vertexStreams; + rhi::BufferUploadRequest indexStream; + }; + + class Mesh : public RenderResource { + public: + Mesh(); + ~Mesh() override = default; + + // builder + void AddSubMesh(const SubMesh &sub); + void SetVertexAttributes(const std::vector &attributes); + void SetUploadStream(MeshData&& stream); + void SetIndexType(rhi::IndexType type); + void SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh); + + // geometry + const std::vector &GetSubMeshes() const { return subMeshes; } + const RenderGeometryPtr& GetGeometry() const { return geometry; } + + void Upload(); + bool IsReady() const; + private: + // desc + std::vector subMeshes; + RenderGeometryPtr geometry; + }; + + using RDMeshPtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/render/core/include/render/resource/ResourceGroup.h b/runtime/render/core/include/render/resource/ResourceGroup.h similarity index 88% rename from render/core/include/render/resource/ResourceGroup.h rename to runtime/render/core/include/render/resource/ResourceGroup.h index 9952da45..aadbda86 100644 --- a/render/core/include/render/resource/ResourceGroup.h +++ b/runtime/render/core/include/render/resource/ResourceGroup.h @@ -9,16 +9,17 @@ #include #include #include +#include namespace sky { static constexpr uint32_t PASS_SET = 0; static constexpr uint32_t BATCH_SET = 1; static constexpr uint32_t INSTANCE_SET = 2; - class ResourceGroupLayout { + class ResourceGroupLayout : public RenderResource { public: ResourceGroupLayout() = default; - ~ResourceGroupLayout() = default; + ~ResourceGroupLayout() override = default; struct BufferNameHandler { uint32_t binding; @@ -45,12 +46,12 @@ namespace sky { std::unordered_map bufferHandlers; // name -> buffer name handler rhi::DescriptorSetLayoutPtr layout; }; - using RDResourceLayoutPtr = std::shared_ptr; + using RDResourceLayoutPtr = CounterPtr; - class ResourceGroup { + class ResourceGroup : public RenderResource { public: ResourceGroup() = default; - ~ResourceGroup(); + ~ResourceGroup() override; void Init(const RDResourceLayoutPtr &layout, rhi::DescriptorSetPool &pool); void Update(); @@ -73,6 +74,6 @@ namespace sky { std::unordered_map dynamicUBOS; std::vector slotHash; }; - using RDResourceGroupPtr = std::shared_ptr; + using RDResourceGroupPtr = CounterPtr; } // namespace sky diff --git a/render/core/include/render/resource/Shader.h b/runtime/render/core/include/render/resource/Shader.h similarity index 68% rename from render/core/include/render/resource/Shader.h rename to runtime/render/core/include/render/resource/Shader.h index 345685f5..0be1e691 100644 --- a/render/core/include/render/resource/Shader.h +++ b/runtime/render/core/include/render/resource/Shader.h @@ -12,51 +12,48 @@ #include #include +#include +#include #include #include namespace sky { - class ShaderCollection; - using ShaderCollectionPtr = std::shared_ptr; - - class Program { + class Program : public RenderResource { public: Program() = default; - ~Program() = default; + ~Program() override = default; RDResourceLayoutPtr RequestLayout(uint32_t index) const; const rhi::PipelineLayoutPtr &GetPipelineLayout() const { return pipelineLayout; } const std::vector &GetShaders() const { return shaders; } + const std::vector &GetVertexAttributes() const { return reflection->attributes; } - void SetName(const std::string &name_) { name = name_; } void AddShader(const rhi::ShaderPtr &shader) { shaders.emplace_back(shader); } void MergeReflection(ShaderReflection &&refl); - void BuildPipelineLayout(); + void Build(); private: - std::string name; rhi::PipelineLayoutPtr pipelineLayout; std::vector shaders; std::unique_ptr reflection; }; - using RDProgramPtr = std::shared_ptr; + using RDProgramPtr = CounterPtr; - class ShaderCollection { + class ShaderCollection : public RenderResource { public: - explicit ShaderCollection(std::string name_, std::string source_, uint32_t hash_) - : name(std::move(name_)) + explicit ShaderCollection(const std::string &name_, std::string source_, uint32_t hash_) + : RenderResource(name_) , source(std::move(source_)) , hash(hash_) {} - ~ShaderCollection() = default; + ~ShaderCollection() override = default; void BuildAndCacheShader(const std::string &entry, rhi::ShaderStageFlagBit stage, const ShaderCompileOption &option, ShaderBuildResult &result); const std::string &RequestSource() const { return source; } - const std::string &GetName() const { return name; } uint32_t GetHash() const { return hash; } private: - std::string name; std::string source; uint32_t hash; }; + using ShaderCollectionPtr = CounterPtr; } // namespace sky diff --git a/render/core/include/render/resource/Technique.h b/runtime/render/core/include/render/resource/Technique.h similarity index 68% rename from render/core/include/render/resource/Technique.h rename to runtime/render/core/include/render/resource/Technique.h index f36c840f..50dffdd2 100644 --- a/render/core/include/render/resource/Technique.h +++ b/runtime/render/core/include/render/resource/Technique.h @@ -6,6 +6,8 @@ #include #include +#include +#include namespace sky { @@ -16,19 +18,21 @@ namespace sky { std::string fragmentMain; }; - class Technique { + class Technique : public RenderResource { public: Technique() = default; - virtual ~Technique() = default; + ~Technique() override = default; void SetShader(const ShaderRef &shader); - RDProgramPtr RequestProgram(const ShaderPreprocessorPtr &preprocessor = nullptr); + RDProgramPtr RequestProgram(const ShaderOptionPtr &option = nullptr); protected: virtual void FillProgramInternal(Program &program, const ShaderCompileOption &option) {} ShaderRef shaderData; + + std::unordered_map programCache; }; class GraphicsTechnique : public Technique { @@ -40,26 +44,29 @@ namespace sky { void SetRasterState(const rhi::RasterState &rs); void SetBlendState(const std::vector &blends); void SetRasterTag(const std::string &tag); - void SetVertexLayout(const std::string &key); + + void Process(RenderVertexFlags flags, const ShaderOptionPtr &option); uint32_t GetRasterID() const { return rasterID; } uint32_t GetViewMask() const { return viewMask; } - const std::string &GetVertexDescKey() const { return vertexDescKey; } const rhi::PipelineState &GetPipelineState() const { return state; } - static rhi::GraphicsPipelinePtr BuildPso(GraphicsTechnique &tech, + static rhi::GraphicsPipelinePtr BuildPso(const RDProgramPtr &program, + const rhi::PipelineState &state, + const rhi::VertexInputPtr &vertexDesc, const rhi::RenderPassPtr &pass, uint32_t subPassID); private: void FillProgramInternal(Program &program, const ShaderCompileOption &option) override; rhi::PipelineState state; - std::string vertexDescKey; - rhi::VertexInputPtr vertexDesc; uint32_t rasterID = 0; uint32_t viewMask = 0xFFFFFFFF; + + std::vector preCompiledFlags; + std::unordered_map vertexFlags; }; - using RDGfxTechPtr = std::shared_ptr; + using RDGfxTechPtr = CounterPtr; class ComputeTechnique : public Technique { public: @@ -71,5 +78,5 @@ namespace sky { rhi::PipelineState state; }; - using RDCompTechPtr = std::shared_ptr; + using RDCompTechPtr = CounterPtr; } // namespace sky diff --git a/render/core/include/render/resource/Texture.h b/runtime/render/core/include/render/resource/Texture.h similarity index 65% rename from render/core/include/render/resource/Texture.h rename to runtime/render/core/include/render/resource/Texture.h index e4c6616e..821c1c68 100644 --- a/render/core/include/render/resource/Texture.h +++ b/runtime/render/core/include/render/resource/Texture.h @@ -6,6 +6,8 @@ #include #include +#include +#include #include namespace sky { @@ -16,27 +18,35 @@ namespace sky { TEXTURE_CUBE }; - class Texture { + struct ImageData { + std::vector slices; + }; + + class Texture : public IStreamableResource { public: Texture(); - virtual ~Texture(); + ~Texture() override; - rhi::TransferTaskHandle Upload(const std::string &path, rhi::Queue &queue, uint32_t offset); - rhi::TransferTaskHandle Upload(const uint8_t *ptr, uint64_t size, rhi::Queue &queue); + // upload + void SetUploadStream(ImageData&& stream); + void Upload(std::vector &&rawData, rhi::Queue *queue); bool CheckExtent(uint32_t width, uint32_t height, uint32_t depth = 1) const; - const rhi::ImageViewPtr &GetImageView() const { return imageView; } const rhi::ImagePtr &GetImage() const { return image; } protected: + uint64_t UploadImpl() override; + rhi::Device *device = nullptr; rhi::Image::Descriptor imageDesc = {}; - rhi::ImagePtr image; - rhi::SamplerPtr sampler; + rhi::ImagePtr image; + rhi::SamplerPtr sampler; rhi::ImageViewPtr imageView; + + ImageData data; }; - using RDTexturePtr = std::shared_ptr; + using RDTexturePtr = CounterPtr; class TextureCube : public Texture { public: @@ -45,7 +55,7 @@ namespace sky { bool Init(rhi::PixelFormat format, uint32_t width, uint32_t height, uint32_t mipLevel); }; - using RDTextureCubePtr = std::shared_ptr; + using RDTextureCubePtr = CounterPtr; class Texture2D : public Texture { public: @@ -54,7 +64,7 @@ namespace sky { bool Init(rhi::PixelFormat format, uint32_t width, uint32_t height, uint32_t mipLevel); }; - using RDTexture2DPtr = std::shared_ptr; + using RDTexture2DPtr = CounterPtr; class Texture3D : public Texture { public: @@ -63,5 +73,5 @@ namespace sky { bool Init(rhi::PixelFormat format, uint32_t width, uint32_t height, uint32_t depth); }; - using RDTexture3DPtr = std::shared_ptr; + using RDTexture3DPtr = CounterPtr; } // namespace sky diff --git a/runtime/render/core/include/render/resource/TextureAtlas.h b/runtime/render/core/include/render/resource/TextureAtlas.h new file mode 100644 index 00000000..366754bd --- /dev/null +++ b/runtime/render/core/include/render/resource/TextureAtlas.h @@ -0,0 +1,64 @@ +// +// Created by blues on 2024/9/12. +// + +#pragma once + +#include +#include + +namespace sky { + + class TextureAtlasAllocator { + public: + TextureAtlasAllocator(uint32_t w, uint32_t h) : width(w), height(h) {} + virtual ~TextureAtlasAllocator() = default; + + struct Page { + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; + }; + + virtual Result Allocate(uint32_t w, uint32_t h) = 0; + + protected: + uint32_t width; + uint32_t height; + }; + + // allocate for left -> right, top -> bottom, never free. + class TextureLinearAllocator : public TextureAtlasAllocator { + public: + TextureLinearAllocator(uint32_t w, uint32_t h) : TextureAtlasAllocator(w, h) {} + ~TextureLinearAllocator() override = default; + + Result Allocate(uint32_t w, uint32_t h) override; + + private: + uint32_t currentX = 0; + uint32_t currentY = 0; + + uint32_t rowHeight = 0; + }; + + class Texture2DAtlas : public Texture2D { + public: + Texture2DAtlas() = default; + ~Texture2DAtlas() override = default; + + using Page = TextureAtlasAllocator::Page; + + bool Init(rhi::PixelFormat format, uint32_t width, uint32_t height); + + Result Allocate(uint32_t w, uint32_t h); + + void Upload(const Page &page, rhi::Queue &queue, std::vector &&data); + + private: + std::unique_ptr allocator; + }; + using RDTexture2DAtlasPtr = CounterPtr; + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/include/render/skeleton/SkeletonMeshRenderer.h b/runtime/render/core/include/render/skeleton/SkeletonMeshRenderer.h new file mode 100644 index 00000000..7ad819bf --- /dev/null +++ b/runtime/render/core/include/render/skeleton/SkeletonMeshRenderer.h @@ -0,0 +1,43 @@ +// +// Created by Zach Lee on 2023/9/9. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class RenderScene; + + static constexpr uint32_t MAX_BONE_PER_VERTEX = 4; + static constexpr uint32_t MAX_BONE_NUM = 80; + + struct Skin : RefObject { + std::array boneMatrices; + }; + using SkinPtr = CounterPtr; + + struct VertexBoneData { + uint32_t boneId[MAX_BONE_PER_VERTEX]; + float weight[MAX_BONE_PER_VERTEX]; + }; + + class SkeletonMeshRenderer : public MeshRenderer { + public: + SkeletonMeshRenderer(); + ~SkeletonMeshRenderer() override = default; + + const SkinPtr &GetSkin() const { return skin; } + void SetSkin(const SkinPtr &skin_) { skin = skin_; } + protected: + void PrepareUBO() override; + RDResourceGroupPtr RequestResourceGroup(MeshFeature *feature) override; + + SkinPtr skin; + RDDynamicUniformBufferPtr boneData; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/text/Font.h b/runtime/render/core/include/render/text/Font.h new file mode 100644 index 00000000..6a0b045f --- /dev/null +++ b/runtime/render/core/include/render/text/Font.h @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/11. +// + +#pragma once + +#include +#include + +namespace sky { + + class Font : public RefObject { + public: + explicit Font(const std::string &name) : fontName(name) {} // NOLINT + ~Font() override = default; + + virtual void Load(const FilePtr &file) = 0; + virtual bool IsReady() const = 0; + + protected: + std::string fontName; + }; + + using FontPtr = CounterPtr; + +} // namespace sky diff --git a/runtime/render/core/include/render/text/Text.h b/runtime/render/core/include/render/text/Text.h new file mode 100644 index 00000000..b28a5706 --- /dev/null +++ b/runtime/render/core/include/render/text/Text.h @@ -0,0 +1,89 @@ +// +// Created by blues on 2024/9/11. +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sky { + class RenderScene; + + struct TextDesc { + uint32_t fontSize = 10; + uint32_t texWidth = 512; + uint32_t texHeight = 512; + }; + + enum class TextFlagBit : uint32_t { + NONE = 0x00, + BOLD = 0x01, + ITALIC = 0x02, + SHADOW = 0x03, + }; + using TextFlags = Flags; + ENABLE_FLAG_BIT_OPERATOR(TextFlagBit) + + struct BatchKey { + TextFlags flags; + uint32_t texIndex; + }; + + struct TextInfo { + Color color; + Color shadowColor; + TextFlags flags; + uint32_t shadowThickness = 1; + float scale = 1.f; + }; + + class Text : public RefObject { + public: + explicit Text(const FontPtr &font_) // NOLINT + : font(font_) + { + } + ~Text() override = default; + + virtual bool Init(const TextDesc &desc) = 0; + + virtual void AddText(const std::string &text, const Vector2& pos, const TextInfo &info) = 0; + + virtual void Reset(RenderScene& scene) {} + virtual void Finalize(RenderScene& scene) {} + + virtual void SetDisplaySize(float w, float h) {} + protected: + FontPtr font; + }; +} // namespace sky + +namespace std { + + template <> + struct hash { + size_t operator()(const sky::BatchKey &flags) const noexcept + { + uint32_t hash = flags.flags.value; + sky::HashCombine32(hash, flags.texIndex); + return hash; + } + }; + + template <> + struct equal_to { + bool operator()(const sky::BatchKey &x, const sky::BatchKey &y) const noexcept + { + return x.texIndex == y.texIndex && x.flags == y.flags; + } + }; + +} // namespace std \ No newline at end of file diff --git a/runtime/render/core/include/render/text/TextFeature.h b/runtime/render/core/include/render/text/TextFeature.h new file mode 100644 index 00000000..0c5558ba --- /dev/null +++ b/runtime/render/core/include/render/text/TextFeature.h @@ -0,0 +1,49 @@ +// +// Created by blues on 2024/9/13. +// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace sky { + + class TextFeature : public Singleton { + public: + TextFeature() = default; + ~TextFeature() override = default; + + void Init(); + void SetTechnique(const RDGfxTechPtr &tech); + + RDResourceGroupPtr RequestResourceGroup(); + const RDGfxTechPtr &GetTechnique() const { return technique; } + private: + RDGfxTechPtr technique; + RDResourceLayoutPtr batchLayout; + rhi::DescriptorSetPoolPtr pool; + + std::unordered_map fonts; + }; + + class TextFeatureProcessor : public IFeatureProcessor { + public: + explicit TextFeatureProcessor(RenderScene *scn) : IFeatureProcessor(scn) {} + ~TextFeatureProcessor() override = default; + + Text* CreateText(const FontPtr &font); + void RemoveText(Text *text); + + private: + void Tick(float time) override {} + void Render(rdg::RenderGraph &rdg) override {} + + std::list> texts; + }; + +} // namespace sky diff --git a/runtime/render/core/include/render/text/TextRegistry.h b/runtime/render/core/include/render/text/TextRegistry.h new file mode 100644 index 00000000..999d486a --- /dev/null +++ b/runtime/render/core/include/render/text/TextRegistry.h @@ -0,0 +1,37 @@ +// +// Created by blues on 2024/9/13. +// + +#pragma once + +#include +#include +#include +#include + +namespace sky { + class TextRegistry : public Singleton { + public: + TextRegistry() = default; + ~TextRegistry() override = default; + + class Impl { + public: + Impl() = default; + virtual ~Impl() = default; + + virtual FontPtr LoadFont(const FileSystemPtr &fs, const std::string &name) = 0; + virtual Text* CreateText(const FontPtr &font) = 0; + }; + + FontPtr LoadFont(const FileSystemPtr &fs, const std::string &name); + Text* CreateText(const FontPtr &font); + + void Register(Impl* factory); + void UnRegister(); + + private: + std::unique_ptr factory; + }; + +} // namespace sky diff --git a/runtime/render/core/src/Debug/DebugRenderer.cpp b/runtime/render/core/src/Debug/DebugRenderer.cpp new file mode 100644 index 00000000..ed3a340d --- /dev/null +++ b/runtime/render/core/src/Debug/DebugRenderer.cpp @@ -0,0 +1,134 @@ +// +// Created by blues on 2024/9/1. +// + +#include + +namespace sky { + + static std::vector DEBUG_ATTRIBUTES = { + VertexAttribute{VertexSemanticFlagBit::POSITION, 0, OFFSET_OF(DebugVertex, pos), rhi::Format::F_RGBA32}, + VertexAttribute{VertexSemanticFlagBit::COLOR, 0, OFFSET_OF(DebugVertex, col), rhi::Format::F_RGBA32}, + }; + + static VertexSemanticFlags DEBUG_VTX_SEMANTICS = VertexSemanticFlagBit::POSITION | VertexSemanticFlagBit::COLOR; + + DebugRenderer::DebugRenderer() + : geometry(new RenderGeometry()) + { + geometry->vertexAttributes = DEBUG_ATTRIBUTES; + geometry->attributeSemantics = DEBUG_VTX_SEMANTICS; + } + + void DebugRenderer::Reset() + { + currentColor = {1.f, 1.f, 1.f, 1.f}; + batchVertices.clear(); + } + + void DebugRenderer::SetColor(const Color &color) + { + currentColor = color; + } + + void DebugRenderer::DrawLine(const Line &line) + { + DrawLine(line.begin, line.end); + } + + void DebugRenderer::DrawLine(const Vector3 &from, const Vector3 &to) + { + DebugVertex begin = { + Vector4{from.x, from.y, from.z, 1.f}, + currentColor + }; + + DebugVertex end = { + Vector4{to.x, to.y, to.z, 1.f}, + currentColor + }; + + batchVertices.emplace_back(begin); + batchVertices.emplace_back(end); + } + + void DebugRenderer::DrawSphere(const Sphere &sphere) + { + static const uint32_t STACK_COUNT = 16; + static const uint32_t SECTOR_COUNT = 32; + + float sectorStep = 2 * PI / SECTOR_COUNT; + float stackStep = PI / STACK_COUNT; + + + for(int i = 0; i < STACK_COUNT; ++i) // starting from pi/2 to -pi/2 + { + float stackAngle1 = PI / 2 - static_cast(i) * stackStep; + float stackAngle2 = PI / 2 - static_cast(i + 1) * stackStep; + + float xz1 = sphere.radius * cosf(stackAngle1); + float y1 = sphere.radius * sinf(stackAngle1); + + float xz2 = sphere.radius * cosf(stackAngle2); + float y2 = sphere.radius * sinf(stackAngle2); + + for(int j = 0; j < SECTOR_COUNT; ++j) // starting from 0 to 2pi + { + float sectorAngle1 = static_cast(j) * sectorStep; + float sectorAngle2 = static_cast(j + 1) * sectorStep; + + // vertex position (x, y, z) + float x1 = xz1 * cosf(sectorAngle1); + float z1 = xz1 * sinf(sectorAngle1); + + float x2 = xz2 * cosf(sectorAngle1); + float z2 = xz2 * sinf(sectorAngle1); + + DrawLine(Vector3{x1, y1, z1}, Vector3{x2, y2, z2}); + + if (i != 0) { + float x3 = xz1 * cosf(sectorAngle2); + float z3 = xz1 * sinf(sectorAngle2); + DrawLine(Vector3{x1, y1, z1}, Vector3{x3, y1, z3}); + } + } + } + } + + void DebugRenderer::DrawAABB(const AABB &aabb) + { + DrawLine(Vector3(aabb.min[0], aabb.min[1], aabb.min[2]), Vector3(aabb.max[0], aabb.min[1], aabb.min[2])); + DrawLine(Vector3(aabb.max[0], aabb.min[1], aabb.min[2]), Vector3(aabb.max[0], aabb.max[1], aabb.min[2])); + DrawLine(Vector3(aabb.max[0], aabb.max[1], aabb.min[2]), Vector3(aabb.min[0], aabb.max[1], aabb.min[2])); + DrawLine(Vector3(aabb.min[0], aabb.max[1], aabb.min[2]), Vector3(aabb.min[0], aabb.min[1], aabb.min[2])); + DrawLine(Vector3(aabb.min[0], aabb.min[1], aabb.min[2]), Vector3(aabb.min[0], aabb.min[1], aabb.max[2])); + DrawLine(Vector3(aabb.max[0], aabb.min[1], aabb.min[2]), Vector3(aabb.max[0], aabb.min[1], aabb.max[2])); + DrawLine(Vector3(aabb.max[0], aabb.max[1], aabb.min[2]), Vector3(aabb.max[0], aabb.max[1], aabb.max[2])); + DrawLine(Vector3(aabb.min[0], aabb.max[1], aabb.min[2]), Vector3(aabb.min[0], aabb.max[1], aabb.max[2])); + DrawLine(Vector3(aabb.min[0], aabb.min[1], aabb.max[2]), Vector3(aabb.max[0], aabb.min[1], aabb.max[2])); + DrawLine(Vector3(aabb.max[0], aabb.min[1], aabb.max[2]), Vector3(aabb.max[0], aabb.max[1], aabb.max[2])); + DrawLine(Vector3(aabb.max[0], aabb.max[1], aabb.max[2]), Vector3(aabb.min[0], aabb.max[1], aabb.max[2])); + DrawLine(Vector3(aabb.min[0], aabb.max[1], aabb.max[2]), Vector3(aabb.min[0], aabb.min[1], aabb.max[2])); + } + + void DebugRenderer::Render() + { + auto vtxSize = static_cast(batchVertices.size() * sizeof(DebugVertex)); + + if (!vertexBuffer || vtxSize > capacity) { + capacity = std::max(capacity * 2, vtxSize); + + vertexBuffer = new Buffer(); + vertexBuffer->Init(capacity, rhi::BufferUsageFlagBit::VERTEX, rhi::MemoryType::CPU_TO_GPU); + + geometry->vertexBuffers.clear(); + geometry->vertexBuffers.emplace_back(VertexBuffer { + vertexBuffer, 0, capacity, static_cast(sizeof(DebugVertex)) + }); + geometry->version++; + } + + linear.vertexCount = static_cast(batchVertices.size()); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/Debug/Gizmo.cpp b/runtime/render/core/src/Debug/Gizmo.cpp new file mode 100644 index 00000000..15c8162f --- /dev/null +++ b/runtime/render/core/src/Debug/Gizmo.cpp @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/9/21. +// + +#include + +namespace sky { + + Gizmo::Gizmo() + : renderer(new DebugRenderer()) + , primitive(new RenderPrimitive()) + { + } + + void Gizmo::DrawGrid() + { + + } + + void Gizmo::SetTechnique(const RDGfxTechPtr &tech) + { + TechniqueInstance techInst = {tech}; + primitive->techniques.clear(); + primitive->techniques.emplace_back(techInst); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/RHI.cpp b/runtime/render/core/src/RHI.cpp new file mode 100644 index 00000000..edb6dad7 --- /dev/null +++ b/runtime/render/core/src/RHI.cpp @@ -0,0 +1,46 @@ +// +// Created by Zach Lee on 2023/4/16. +// + +#include + +namespace sky { + + RHI::~RHI() + { + device = nullptr; + rhi::Instance::Destroy(instance); + instance = nullptr; + } + + std::string RHI::GetBackendName() const + { + switch (api) { + case rhi::API::VULKAN: + return "vulkan"; + case rhi::API::METAL: + return "metal"; + case rhi::API::DX12: + return "d3d12"; + case rhi::API::GLES: + return "gles"; + default: + break; + } + return "Unknown"; + } + + void RHI::InitInstance(rhi::Instance::Descriptor desc) + { +#ifdef SKY_ENABLE_XR + desc.xrInterface = xrInterface; +#endif + instance = rhi::Instance::Create(desc); + api = desc.api; + } + + void RHI::InitDevice(const rhi::Device::Descriptor &desc) + { + device.reset(instance->CreateDevice(desc)); + } +} diff --git a/render/core/src/RenderDefaultResource.cpp b/runtime/render/core/src/RenderDefaultResource.cpp similarity index 75% rename from render/core/src/RenderDefaultResource.cpp rename to runtime/render/core/src/RenderDefaultResource.cpp index 546df1e5..c8b45b1e 100644 --- a/render/core/src/RenderDefaultResource.cpp +++ b/runtime/render/core/src/RenderDefaultResource.cpp @@ -9,20 +9,22 @@ namespace sky { - const uint8_t DEFAULT_TEX_DATA[] = { - 255, 255, 255, 255, 127, 127, 127, 255, - 127, 127, 127, 255, 255, 255, 255, 255 + std::vector DEFAULT_TEX_DATA = { + 0, 0, 0, 1, 0, 0, 0, 1, + 0, 0, 0, 1, 0, 0, 0, 1 }; void RenderDefaultResource::Init() { auto *device = RHI::Get()->GetDevice(); defaultPool = device->CreateDescriptorSetPool({1}); + emptyVI = device->CreateVertexInput({}); + auto emptyRHIDesLayout = device->CreateDescriptorSetLayout({}); - emptyDesLayout = std::make_shared(); + emptyDesLayout = new ResourceGroupLayout(); emptyDesLayout->SetRHILayout(emptyRHIDesLayout); - emptySet = std::make_shared(); + emptySet = new ResourceGroup(); emptySet->Init(emptyDesLayout, *defaultPool); rhi::Sampler::Descriptor samplerDesc = {}; @@ -42,18 +44,12 @@ namespace sky { imageDesc.usage = rhi::ImageUsageFlagBit::SAMPLED | rhi::ImageUsageFlagBit::TRANSFER_DST; auto *queue = device->GetQueue(rhi::QueueType::TRANSFER); - rhi::TransferTaskHandle taskHandle = 0; - - rhi::ImageUploadRequest request = {}; - request.source = std::make_shared(DEFAULT_TEX_DATA); - request.size = sizeof(DEFAULT_TEX_DATA); - request.imageOffset = {0, 0, 0}; - request.imageExtent = imageDesc.extent; { - texture2D = std::make_shared(); + texture2D = new Texture2D(); texture2D->Init(rhi::PixelFormat::RGBA8_UNORM, 2, 2, 1); - taskHandle = texture2D->Upload(DEFAULT_TEX_DATA, sizeof(DEFAULT_TEX_DATA), *queue); + texture2D->Upload(std::move(DEFAULT_TEX_DATA), queue); + texture2D->Wait(); } // { @@ -71,8 +67,6 @@ namespace sky { // } // taskHandle = queue->UploadImage(image, requests); // } - - queue->Wait(taskHandle); } void RenderDefaultResource::Reset() diff --git a/render/core/src/RenderDrawArgs.cpp b/runtime/render/core/src/RenderDrawArgs.cpp similarity index 100% rename from render/core/src/RenderDrawArgs.cpp rename to runtime/render/core/src/RenderDrawArgs.cpp diff --git a/runtime/render/core/src/RenderGeometry.cpp b/runtime/render/core/src/RenderGeometry.cpp new file mode 100644 index 00000000..a9e83230 --- /dev/null +++ b/runtime/render/core/src/RenderGeometry.cpp @@ -0,0 +1,167 @@ +// +// Created by blues on 2024/9/14. +// + +#include +#include +#include +#include +#include + +static const char* TAG = "RenderGeometry"; + +namespace sky { + + void RenderGeometry::AddVertexAttribute(const VertexAttribute &attribute) + { + vertexAttributes.emplace_back(attribute); + attributeSemantics |= attribute.sematic; + } + + void RenderGeometry::FillVertexBuffer(std::vector &vbs) + { + vbs.reserve(vertexBuffers.size()); + for (auto &vb : vertexBuffers) { + vbs.emplace_back(vb.MakeView()); + } + } + + rhi::VertexInputPtr RenderGeometry::Request(const RDProgramPtr& program) + { + auto *semantics = RenderSemantics::Get(); + rhi::VertexInput::Descriptor vtxDesc = {}; + + std::array bindingHash; + bindingHash.fill(0xFF); + + for (const auto &attr : program->GetVertexAttributes()) { + auto semantic = semantics->QuerySemanticByName(attr.semantic); + if (semantic == VertexSemanticFlagBit::NONE) { + LOG_E(TAG, "Vertex Semantic not Registered %s", attr.semantic.c_str()); + return {}; + } + + auto iter = std::find_if(vertexAttributes.begin(), vertexAttributes.end(), [semantic](const VertexAttribute &stream) -> bool { + return stream.sematic & semantic; + }); + + if (iter == vertexAttributes.end()) { + // geometry not compatible with shader + return {}; + } + + const auto &stream = *iter; + SKY_ASSERT(stream.binding < MAX_VERTEX_BUFFER_BINDINGS) + + auto &binding = bindingHash[stream.binding]; + if (binding == 0xFF) { + rhi::VertexBindingDesc vbDesc = {}; + vbDesc.binding = static_cast(vtxDesc.bindings.size()); + vbDesc.stride = vertexBuffers[stream.binding].stride; + vbDesc.inputRate = stream.rate; + + binding = vbDesc.binding; + vtxDesc.bindings.emplace_back(vbDesc); + } + + rhi::VertexAttributeDesc attrDesc = {}; + attrDesc.sematic = attr.semantic; + attrDesc.location = attr.location; + attrDesc.binding = binding; + attrDesc.offset = stream.offset; + attrDesc.format = stream.format; + + vtxDesc.attributes.emplace_back(attrDesc); + } + auto *device = RHI::Get()->GetDevice(); + return device->CreateVertexInput(vtxDesc); + } + + rhi::VertexAssemblyPtr RenderGeometry::Request(const RDProgramPtr& program, rhi::VertexInputPtr &vtxInput) + { + auto *semantics = RenderSemantics::Get(); + rhi::VertexAssembly::Descriptor assemDesc = {}; + rhi::VertexInput::Descriptor vtxDesc = {}; + + std::array bindingHash; + bindingHash.fill(0xFF); + + for (const auto &attr : program->GetVertexAttributes()) { + auto semantic = semantics->QuerySemanticByName(attr.semantic); + if (semantic == VertexSemanticFlagBit::NONE) { + LOG_E(TAG, "Vertex Semantic not Registered %s", attr.semantic.c_str()); + return {}; + } + + auto iter = std::find_if(vertexAttributes.begin(), vertexAttributes.end(), [semantic](const VertexAttribute &stream) -> bool { + return stream.sematic & semantic; + }); + + if (iter == vertexAttributes.end()) { + // geometry not compatible with shader + return {}; + } + + const auto &stream = *iter; + SKY_ASSERT(stream.binding < MAX_VERTEX_BUFFER_BINDINGS) + + auto &binding = bindingHash[stream.binding]; + if (binding == 0xFF) { + rhi::VertexBindingDesc vbDesc = {}; + vbDesc.binding = static_cast(vtxDesc.bindings.size()); + vbDesc.stride = vertexBuffers[stream.binding].stride; + vbDesc.inputRate = stream.rate; + + binding = vbDesc.binding; + vtxDesc.bindings.emplace_back(vbDesc); + assemDesc.vertexBuffers.emplace_back(vertexBuffers[stream.binding].MakeView()); + } + + rhi::VertexAttributeDesc attrDesc = {}; + attrDesc.sematic = attr.semantic; + attrDesc.location = attr.location; + attrDesc.binding = binding; + attrDesc.offset = stream.offset; + attrDesc.format = stream.format; + + vtxDesc.attributes.emplace_back(attrDesc); + } + auto *device = RHI::Get()->GetDevice(); + vtxInput = device->CreateVertexInput(vtxDesc); + assemDesc.vertexInput = vtxInput; + return device->CreateVertexAssembly(assemDesc); + } + + void RenderGeometry::Reset() + { + vertexBuffers.clear(); + indexBuffer = IndexBuffer{}; + } + + void RenderGeometry::Upload() + { + if (uploaded) { + return; + } + + auto *sm = Renderer::Get()->GetStreamingManager(); + for (auto &vb : vertexBuffers) { + sm->UploadBuffer(vb.buffer); + } + if (indexBuffer.buffer) { + sm->UploadBuffer(indexBuffer.buffer); + } + uploaded = true; + } + + bool RenderGeometry::IsReady() const + { + for (const auto &vb : vertexBuffers) { + if (!vb.buffer->IsReady()) { + return false; + } + } + return !indexBuffer.buffer || indexBuffer.buffer->IsReady(); + } + +} // namespace sky \ No newline at end of file diff --git a/render/core/src/RenderNameHandle.cpp b/runtime/render/core/src/RenderNameHandle.cpp similarity index 100% rename from render/core/src/RenderNameHandle.cpp rename to runtime/render/core/src/RenderNameHandle.cpp diff --git a/runtime/render/core/src/RenderPassPipeline.cpp b/runtime/render/core/src/RenderPassPipeline.cpp new file mode 100644 index 00000000..96f982b0 --- /dev/null +++ b/runtime/render/core/src/RenderPassPipeline.cpp @@ -0,0 +1,22 @@ +// +// Created by blues on 2024/9/3. +// + +#include + +namespace sky { + + void RenderPassPipeline::AddScenePass(RenderScenePipeline *ppl) + { + scenePipelines.emplace_back(ppl); + } + + bool RenderPassPipeline::OnSetup(rdg::RenderGraph &rdg, const std::vector &scenes) + { + for (auto &ppl : scenePipelines) { + ppl->Setup(rdg); + } + return true; + } + +} // namespace \ No newline at end of file diff --git a/render/core/src/RenderPipeline.cpp b/runtime/render/core/src/RenderPipeline.cpp similarity index 83% rename from render/core/src/RenderPipeline.cpp rename to runtime/render/core/src/RenderPipeline.cpp index 7a720156..293fede3 100644 --- a/render/core/src/RenderPipeline.cpp +++ b/runtime/render/core/src/RenderPipeline.cpp @@ -18,12 +18,11 @@ #include #include +#include + namespace sky { - RenderPipeline::~RenderPipeline() - { - rdgContext->device->WaitIdle(); - } + RenderPipeline::~RenderPipeline() = default; RenderPipeline::RenderPipeline() { @@ -53,41 +52,56 @@ namespace sky { void RenderPipeline::FrameSync() { + SKY_PROFILE_NAME("FrameSync"); rdgContext->frameIndex = frameIndex; rdgContext->Fence()->WaitAndReset(); rdgContext->ImageAvailableSemaPool().Reset(); rdgContext->pool->ResetPool(); } - void RenderPipeline::Execute(rdg::RenderGraph &rdg) + void RenderPipeline::Compile(rdg::RenderGraph &rdg) { using namespace rdg; { + SKY_PROFILE_NAME("AccessCompiler"); AccessCompiler compiler(rdg); PmrVector colors(rdg.accessGraph.vertices.size(), &rdg.context->resources); boost::depth_first_search(rdg.accessGraph.graph, compiler, ColorMap(colors)); } { + SKY_PROFILE_NAME("RenderResourceCompiler"); RenderResourceCompiler compiler(rdg); PmrVector colors(rdg.vertices.size(), &rdg.context->resources); boost::depth_first_search(rdg.graph, compiler, ColorMap(colors)); } { + SKY_PROFILE_NAME("RenderGraphPassCompiler"); RenderGraphPassCompiler compiler(rdg); PmrVector colors(rdg.vertices.size(), &rdg.context->resources); boost::depth_first_search(rdg.graph, compiler, ColorMap(colors)); } + } - { - RenderSceneVisitor sceneVisitor(rdg); + void RenderPipeline::Collect(rdg::RenderGraph &rdg, const std::vector &scenes) + { + using namespace rdg; + SKY_PROFILE_NAME("RenderSceneVisitor"); + for (auto *scene : scenes) { + RenderSceneVisitor sceneVisitor(rdg, scene); sceneVisitor.BuildRenderQueue(); } + } + void RenderPipeline::Execute(rdg::RenderGraph &rdg) + { + using namespace rdg; const auto &commandBuffer = rdgContext->MainCommandBuffer(); auto *queue = rdgContext->device->GetQueue(rhi::QueueType::GRAPHICS); { + SKY_PROFILE_NAME("Encode"); + commandBuffer->Begin(); RenderGraphUploader uploader(rdg); @@ -113,6 +127,11 @@ namespace sky { rhi::PresentInfo presentInfo = {}; presentInfo.semaphores.emplace_back(rdgContext->RenderFinishSemaphore()); for (auto &swc : rdg.presentPasses) { +#ifdef SKY_ENABLE_XR + if (swc.xrSwapChain) { + continue; + } +#endif auto &res = rdg.resourceGraph.swapChains[Index(swc.imageID, rdg.resourceGraph)]; presentInfo.imageIndex = res.desc.imageIndex; swc.swapChain->Present(*queue, presentInfo); @@ -131,9 +150,10 @@ namespace sky { std::string GetDefaultSceneViewUBOName(const SceneView &view) { - std::stringstream ss; - ss << "DEFAULT_VIEW_UBO_" << view.GetViewID(); - return ss.str(); +// std::stringstream ss; +// ss << "DEFAULT_VIEW_UBO_" << view.GetViewID(); +// return ss.str(); + return "DEFAULT_VIEW_UBO_0"; } } // namespace sky diff --git a/render/core/src/RenderPrimitive.cpp b/runtime/render/core/src/RenderPrimitive.cpp similarity index 100% rename from render/core/src/RenderPrimitive.cpp rename to runtime/render/core/src/RenderPrimitive.cpp diff --git a/render/core/src/RenderResourceGC.cpp b/runtime/render/core/src/RenderResourceGC.cpp similarity index 100% rename from render/core/src/RenderResourceGC.cpp rename to runtime/render/core/src/RenderResourceGC.cpp diff --git a/render/core/src/RenderScene.cpp b/runtime/render/core/src/RenderScene.cpp similarity index 75% rename from render/core/src/RenderScene.cpp rename to runtime/render/core/src/RenderScene.cpp index 45c66e4e..113e361b 100644 --- a/render/core/src/RenderScene.cpp +++ b/runtime/render/core/src/RenderScene.cpp @@ -16,7 +16,6 @@ namespace sky { RenderScene::~RenderScene() { - pipeline = nullptr; features.clear(); } @@ -29,10 +28,6 @@ namespace sky { for (auto &view : sceneViews) { view->Update(); } - - if (pipeline != nullptr) { - pipeline->FrameSync(); - } } void RenderScene::PostTick(float time) @@ -40,24 +35,13 @@ namespace sky { } - void RenderScene::Render() + void RenderScene::Render(rdg::RenderGraph& rdg) { - if (pipeline != nullptr) { - rdg::RenderGraph rdg(pipeline->Context(), this); - for (auto &feature : features) { - feature.second->Render(rdg); - } - - pipeline->OnSetup(rdg); - pipeline->Execute(rdg); + for (auto &feature : features) { + feature.second->Render(rdg); } } - void RenderScene::SetPipeline(RenderPipeline *ppl) - { - pipeline.reset(ppl); - } - SceneView *RenderScene::CreateSceneView(uint32_t viewCount) { sceneViews.emplace_back(new SceneView(viewCounter++, viewCount, &resources)); diff --git a/runtime/render/core/src/RenderScenePipeline.cpp b/runtime/render/core/src/RenderScenePipeline.cpp new file mode 100644 index 00000000..c43a95f6 --- /dev/null +++ b/runtime/render/core/src/RenderScenePipeline.cpp @@ -0,0 +1,32 @@ +// +// Created by blues on 2024/9/5. +// + +#include + +namespace sky { + + void RenderScenePipeline::AddPass(PassBase *pass) + { + passes.emplace_back(pass); + } + + void RenderScenePipeline::Setup(rdg::RenderGraph &rdg) + { + if (scene == nullptr) { + return; + } + + passes.clear(); + Collect(rdg); + + for (auto &pass : passes) { + pass->Prepare(rdg, *scene); + } + + for (auto &pass : passes) { + pass->Setup(rdg, *scene); + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/RenderSemantics.cpp b/runtime/render/core/src/RenderSemantics.cpp new file mode 100644 index 00000000..fc71ca94 --- /dev/null +++ b/runtime/render/core/src/RenderSemantics.cpp @@ -0,0 +1,36 @@ +// +// Created by blues on 2024/9/14. +// + +#include + +namespace sky { + + RenderSemantics::RenderSemantics() + { + // built in + RegisterVertexSemantic("POSITION", VertexSemanticFlagBit::POSITION); + RegisterVertexSemantic("UV", VertexSemanticFlagBit::UV); + RegisterVertexSemantic("NORMAL", VertexSemanticFlagBit::NORMAL); + RegisterVertexSemantic("TANGENT", VertexSemanticFlagBit::TANGENT); + RegisterVertexSemantic("COLOR", VertexSemanticFlagBit::COLOR); + RegisterVertexSemantic("JOINT", VertexSemanticFlagBit::JOINT); + RegisterVertexSemantic("WEIGHT", VertexSemanticFlagBit::WEIGHT); + RegisterVertexSemantic("INST0", VertexSemanticFlagBit::INST0); + RegisterVertexSemantic("INST1", VertexSemanticFlagBit::INST1); + RegisterVertexSemantic("INST2", VertexSemanticFlagBit::INST2); + RegisterVertexSemantic("INST3", VertexSemanticFlagBit::INST3); + } + + void RenderSemantics::RegisterVertexSemantic(const std::string &name, VertexSemanticFlagBit flag) + { + vtxNameMap[name] = flag; + } + + VertexSemanticFlagBit RenderSemantics::QuerySemanticByName(const std::string &name) const + { + auto iter = vtxNameMap.find(name); + return iter != vtxNameMap.end() ? iter->second : VertexSemanticFlagBit::NONE; + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/RenderStreamManager.cpp b/runtime/render/core/src/RenderStreamManager.cpp new file mode 100644 index 00000000..c1705d72 --- /dev/null +++ b/runtime/render/core/src/RenderStreamManager.cpp @@ -0,0 +1,38 @@ +// +// Created by blues on 2024/9/16. +// + +#include + +namespace sky { + + void RenderStreamManager::SetUploadQueue(rhi::Queue *queue) + { + transferQueue = queue; + } + + void RenderStreamManager::UploadTexture(const RDTexturePtr &texture) + { + uploadQueue.emplace_back(texture.Get()); + } + + void RenderStreamManager::UploadBuffer(const RDBufferPtr &buffer) + { + uploadQueue.emplace_back(buffer.Get()); + } + + void RenderStreamManager::Tick() + { + uint64_t current = 0; + while (!uploadQueue.empty()) { + auto &res = uploadQueue.front(); + current += res->Upload(transferQueue); + uploadQueue.pop_front(); + + if (current >= limitPerFrame) { + break; + } + } + } + +} // namespace sky \ No newline at end of file diff --git a/render/core/src/RenderWindow.cpp b/runtime/render/core/src/RenderWindow.cpp similarity index 62% rename from render/core/src/RenderWindow.cpp rename to runtime/render/core/src/RenderWindow.cpp index 866ef244..4e513fea 100644 --- a/render/core/src/RenderWindow.cpp +++ b/runtime/render/core/src/RenderWindow.cpp @@ -21,24 +21,36 @@ namespace sky { return static_cast(swapChain); } +#ifdef SKY_ENABLE_XR + bool RenderWindow::InitByXR(const rhi::XRSwapChainPtr &xr) + { + xrSwapChain = xr; + return static_cast(xrSwapChain); + } +#endif + void RenderWindow::Resize(uint32_t width, uint32_t height) { - RHI::Get()->GetDevice()->WaitIdle(); - swapChain->Resize(width, height, winHandle); + if (swapChain) { + swapChain->Resize(width, height, winHandle); + } } uint32_t RenderWindow::GetWidth() const { +#ifdef SKY_ENABLE_XR + return swapChain ? swapChain->GetExtent().width : xrSwapChain->GetExtent().width; +#else return swapChain->GetExtent().width; +#endif } uint32_t RenderWindow::GetHeight() const { +#ifdef SKY_ENABLE_XR + return swapChain ? swapChain->GetExtent().height : xrSwapChain->GetExtent().height; +#else return swapChain->GetExtent().height; +#endif } - - rhi::PixelFormat RenderWindow::GetOutputFormat() const - { - return swapChain->GetFormat(); - } -} // namespace sky \ No newline at end of file +} // namespace sky diff --git a/render/core/src/Renderer.cpp b/runtime/render/core/src/Renderer.cpp similarity index 63% rename from render/core/src/Renderer.cpp rename to runtime/render/core/src/Renderer.cpp index 8cfdfcc5..53a4de7e 100644 --- a/render/core/src/Renderer.cpp +++ b/runtime/render/core/src/Renderer.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace sky { @@ -17,7 +18,8 @@ namespace sky { Renderer::~Renderer() { - device->WaitIdle(); + pipeline = nullptr; + streamManager = nullptr; defaultRHIResource.Reset(); features.clear(); scenes.clear(); @@ -33,7 +35,9 @@ namespace sky { for (uint32_t i = 0; i < inflightFrameCount; ++i) { delayReleaseCollections[i] = std::make_unique(); } - vertexLibrary = std::make_unique(); + + streamManager = std::make_unique(); + streamManager->SetUploadQueue(device->GetQueue(rhi::QueueType::TRANSFER)); } void Renderer::Tick(float time) @@ -50,11 +54,32 @@ namespace sky { } } + void Renderer::SetPipeline(RenderPipeline *ppl) + { + device->WaitIdle(); + pipeline.reset(ppl); + } + void Renderer::Render() { + if (pipeline == nullptr || scenes.empty()) { + return; + } + pipeline->FrameSync(); + + rdg::RenderGraph rdg(pipeline->Context()); + + std::vector renderScenes; for (auto &scn : scenes) { - scn->Render(); + scn->Render(rdg); + + renderScenes.emplace_back(scn.get()); } + + pipeline->OnSetup(rdg, renderScenes); + pipeline->Compile(rdg); + pipeline->Collect(rdg, renderScenes); + pipeline->Execute(rdg); } void Renderer::AfterRender(float time) @@ -62,6 +87,7 @@ namespace sky { for (auto &scn : scenes) { scn->PostTick(time); } + streamManager->Tick(); delayReleaseCollections[(frameIndex + inflightFrameCount - 1) % inflightFrameCount]->Clear(); @@ -69,6 +95,16 @@ namespace sky { frameIndex = totalFrame % inflightFrameCount; } + void Renderer::StopRender() + { + device->WaitIdle(); + } + + RenderResourceGC *Renderer::GetResourceGC() const + { + return delayReleaseCollections[frameIndex].get(); + } + RenderScene *Renderer::CreateScene() { scenes.emplace_back(new RenderScene(), &Renderer::DestroyObj); @@ -85,7 +121,17 @@ namespace sky { rw->Init(hWnd, width, height, vSync); return rw; } - +#ifdef SKY_ENABLE_XR + RenderWindow *Renderer::CreateRenderWindowByXR() + { + auto *renderWindow = new RenderWindow(); + if (!renderWindow->InitByXR(RHI::Get()->GetDevice()->CreateXRSwapChain({rhi::PixelFormat::BGRA8_UNORM}))) { + return nullptr; + } + windows.emplace_back(renderWindow, &Renderer::DestroyObj); + return renderWindow; + } +#endif void Renderer::RemoveScene(sky::RenderScene *scene) { scenes.remove_if([scene](const auto &scn) { diff --git a/render/core/src/SceneView.cpp b/runtime/render/core/src/SceneView.cpp similarity index 61% rename from render/core/src/SceneView.cpp rename to runtime/render/core/src/SceneView.cpp index f28aa344..9c898e4a 100644 --- a/render/core/src/SceneView.cpp +++ b/runtime/render/core/src/SceneView.cpp @@ -18,6 +18,7 @@ namespace sky { , frustums(resource) , dirty(true) { + projects0.resize(viewCount); viewInfo.resize(viewCount); frustums.resize(viewCount); @@ -27,20 +28,20 @@ namespace sky { void SceneView::SetMatrix(const Matrix4 &mat, uint32_t index) { - viewInfo[index].worldMatrix = mat; - viewInfo[index].viewMatrix = mat.Inverse(); -// viewInfo[index].worldPos = Vector4(mat[3][0], mat[3][1], mat[3][2], 1.0); + viewInfo[index].world = mat; + viewInfo[index].view = mat.Inverse(); dirty = true; } - void SceneView::SetProjective(float near, float far, float fov, float aspect, uint32_t index) + void SceneView::SetPerspective(float near, float far, float fov, float aspect, uint32_t index) { Matrix4 p = Matrix4::Identity(); - p[1][1] = RHI::Get()->GetDevice()->GetConstants().flipY ? -1.f : 1.f; - p[2][2] = 0.5f; - p[3][2] = 0.5f; + p[1][1] = RHI::Get()->GetDevice()->GetConstants().flipY && flipY ? -1.f : 1.f; +// p[2][2] = 0.5f; +// p[3][2] = 0.5f; - viewInfo[index].projectMatrix = p * MakePerspective(fov, aspect, near, far); + projects0[index] = MakePerspective(fov, aspect, near, far); + viewInfo[index].project = p * projects0[index]; // viewInfo[index].zParam.x = 1 - far / near; // viewInfo[index].zParam.y = far / near; // viewInfo[index].zParam.z = viewInfo[index].zParam.x / far; @@ -48,6 +49,16 @@ namespace sky { dirty = true; } + void SceneView::SetOrthogonal(float l, float r, float t, float b, float near, float far, uint32_t index) + { + Matrix4 p = Matrix4::Identity(); + p[1][1] = RHI::Get()->GetDevice()->GetConstants().flipY && flipY ? -1.f : 1.f; + + projects0[index] = MakeOrthogonal(l, r, t, b, near, far); + viewInfo[index].project = p * projects0[index]; + dirty = true; + } + void SceneView::Update() { if (!dirty) { @@ -55,11 +66,10 @@ namespace sky { } for (uint32_t i = 0; i < viewCount; ++i) { - viewInfo[i].viewProjectMatrix = viewInfo[i].projectMatrix * viewInfo[i].viewMatrix; - viewInfo[i].inverseViewProject = viewInfo[i].viewProjectMatrix.Inverse(); - frustums[i] = CreateFrustumByViewProjectMatrix(viewInfo[i].viewProjectMatrix); + viewInfo[i].viewProject = viewInfo[i].project * viewInfo[i].view; + frustums[i] = CreateFrustumByViewProjectMatrix(viewInfo[i].viewProject); - viewUbo->Write(i * sizeof(SceneViewInfo), viewInfo[i]); + viewUbo->WriteT(i * sizeof(SceneViewInfo), viewInfo[i]); } dirty = false; } diff --git a/render/core/src/env/SkyBoxRenderer.cpp b/runtime/render/core/src/env/SkyBoxRenderer.cpp similarity index 100% rename from render/core/src/env/SkyBoxRenderer.cpp rename to runtime/render/core/src/env/SkyBoxRenderer.cpp diff --git a/render/core/src/geometry/GeometryFeature.cpp b/runtime/render/core/src/geometry/GeometryFeature.cpp similarity index 95% rename from render/core/src/geometry/GeometryFeature.cpp rename to runtime/render/core/src/geometry/GeometryFeature.cpp index 0e9d1a46..5ab4b6ed 100644 --- a/render/core/src/geometry/GeometryFeature.cpp +++ b/runtime/render/core/src/geometry/GeometryFeature.cpp @@ -31,7 +31,7 @@ namespace sky { RDResourceGroupPtr GeometryFeature::RequestResourceGroup() { - auto rsg = std::make_shared(); + auto rsg = new ResourceGroup(); rsg->Init(localLayout, *pool); return rsg; } diff --git a/render/core/src/geometry/GeometryRenderer.cpp b/runtime/render/core/src/geometry/GeometryRenderer.cpp similarity index 90% rename from render/core/src/geometry/GeometryRenderer.cpp rename to runtime/render/core/src/geometry/GeometryRenderer.cpp index b28a332f..8e46799b 100644 --- a/render/core/src/geometry/GeometryRenderer.cpp +++ b/runtime/render/core/src/geometry/GeometryRenderer.cpp @@ -17,10 +17,9 @@ namespace sky { void GeometryRenderer::Init() { - ubo = std::make_shared(); - ubo->Init(sizeof(InstanceLocal), Renderer::Get()->GetInflightFrameCount()); - ubo->Write(0, InstanceLocal{Matrix4::Identity(), Matrix4::Identity()}); - ubo->Upload(); + ubo = new DynamicUniformBuffer(); + ubo->Init(sizeof(InstanceLocal)); + ubo->WriteT(0, InstanceLocal{Matrix4::Identity(), Matrix4::Identity()}); auto *geomFeature = GeometryFeature::Get(); primitive = std::make_unique(); @@ -45,9 +44,8 @@ namespace sky { void GeometryRenderer::UpdateTransform(const Matrix4 &matrix) { - ubo->Write(0, matrix); - ubo->Write(sizeof(Matrix4), matrix.InverseTranspose()); - ubo->Upload(); + ubo->WriteT(0, matrix); + ubo->WriteT(sizeof(Matrix4), matrix.InverseTranspose()); } void GeometryRenderer::ResetPrimitive(const RDGfxTechPtr &tech) @@ -59,7 +57,7 @@ namespace sky { { batchVertices.resize(size); vertexCapacity = size; - vertexBuffer = std::make_shared(); + vertexBuffer = new Buffer(); vertexBuffer->Init(batchVertices.size() * sizeof(GeometryBatchVertex), rhi::BufferUsageFlagBit::VERTEX | rhi::BufferUsageFlagBit::TRANSFER_DST, rhi::MemoryType::CPU_TO_GPU); @@ -177,12 +175,12 @@ namespace sky { void GeometryRenderer::BuildVertexAssembly() { - if (needRebuildVA) { - rhi::VertexAssembly::Descriptor desc = {}; - desc.vertexBuffers.emplace_back(vertexBuffer->GetRHIBuffer()->CreateView(rhi::BufferViewDesc{0, batchVertices.size() * sizeof(GeometryBatchVertex)})); - primitive->va = RHI::Get()->GetDevice()->CreateVertexAssembly(desc); - needRebuildVA = false; - } +// if (needRebuildVA) { +// rhi::VertexAssembly::Descriptor desc = {}; +// desc.vertexBuffers.emplace_back(rhi::BufferView{vertexBuffer->GetRHIBuffer(), 0, static_cast(batchVertices.size() * sizeof(GeometryBatchVertex))}); +// primitive->va = RHI::Get()->GetDevice()->CreateVertexAssembly(desc); +// needRebuildVA = false; +// } } } // namespace sky diff --git a/runtime/render/core/src/light/LightBase.cpp b/runtime/render/core/src/light/LightBase.cpp new file mode 100644 index 00000000..097503f3 --- /dev/null +++ b/runtime/render/core/src/light/LightBase.cpp @@ -0,0 +1,15 @@ +// +// Created by blues on 2024/6/10. +// + +#include + +namespace sky { + + void DirectLight::Collect(LightInfo &info) + { + info.direction = direction; + info.color = color; + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/light/LightFeatureProcessor.cpp b/runtime/render/core/src/light/LightFeatureProcessor.cpp new file mode 100644 index 00000000..044f0674 --- /dev/null +++ b/runtime/render/core/src/light/LightFeatureProcessor.cpp @@ -0,0 +1,26 @@ +// +// Created by blues on 2024/6/10. +// + +#include + +namespace sky { + + void LightFeatureProcessor::Render(rdg::RenderGraph &rdg) + { + + } + + void LightFeatureProcessor::AddLight(Light *light) + { + lights.emplace_back(light); + } + + void LightFeatureProcessor::RemoveLight(Light *light) + { + lights.erase(std::remove_if(lights.begin(), lights.end(), [light](const LightPtr &v) { + return light == v.get(); + }), lights.end()); + } + +} // namespace sky \ No newline at end of file diff --git a/render/core/src/mesh/GridRenderer.cpp b/runtime/render/core/src/mesh/GridRenderer.cpp similarity index 82% rename from render/core/src/mesh/GridRenderer.cpp rename to runtime/render/core/src/mesh/GridRenderer.cpp index 612dbb5a..e794d832 100644 --- a/render/core/src/mesh/GridRenderer.cpp +++ b/runtime/render/core/src/mesh/GridRenderer.cpp @@ -65,16 +65,16 @@ namespace sky { vertexBuffers.resize(UCast(VertexSemantic::MAX)); for (uint32_t i = 0; i < UCast(VertexSemantic::MAX); ++i) { - vertexBuffers[i] = std::make_shared(); + vertexBuffers[i] = new Buffer(); vertexBuffers[i]->Init(vertexSize, rhi::BufferUsageFlagBit::TRANSFER_DST | rhi::BufferUsageFlagBit::VERTEX, rhi::MemoryType::GPU_ONLY); - request.source = std::make_shared(reinterpret_cast(&pos[i * 4])); + request.source = new rhi::RawPtrStream(reinterpret_cast(&pos[i * 4])); queue->UploadBuffer(vertexBuffers[i]->GetRHIBuffer(), request); } - indexBuffer = std::make_shared(); + indexBuffer = new Buffer(); indexBuffer->Init(indexSize, rhi::BufferUsageFlagBit::TRANSFER_DST | rhi::BufferUsageFlagBit::INDEX, rhi::MemoryType::GPU_ONLY); request.size = indexSize; - request.source = std::make_shared(reinterpret_cast(iPtr)); + request.source = new rhi::RawPtrStream(reinterpret_cast(iPtr)); queue->UploadBuffer(indexBuffer->GetRHIBuffer(), request); auto handle = queue->CreateTask([ptr, iPtr]() { free(ptr); @@ -86,15 +86,15 @@ namespace sky { RDMeshPtr GridRenderer::BuildMesh(const RDMaterialInstancePtr &mat) { - auto mesh = std::make_shared(); - mesh->AddSubMesh({0, 4, 0, 6, mat, AABB{}}); - for (auto &vb : vertexBuffers) { - mesh->AddVertexBuffer(vb); - } - mesh->SetIndexBuffer(indexBuffer); - mesh->SetIndexType(rhi::IndexType::U32); - - return mesh; +// CounterPtr mesh = new Mesh(); +// mesh->AddSubMesh({0, 4, 0, 6, mat, AABB{}}); +// for (auto &vb : vertexBuffers) { +// mesh->AddVertexBuffer(vb); +// } +// mesh->SetIndexBuffer(indexBuffer); +// mesh->SetIndexType(rhi::IndexType::U32); + + return {}; } } // namespace sky \ No newline at end of file diff --git a/render/core/src/mesh/MeshFeature.cpp b/runtime/render/core/src/mesh/MeshFeature.cpp similarity index 62% rename from render/core/src/mesh/MeshFeature.cpp rename to runtime/render/core/src/mesh/MeshFeature.cpp index 27f102cd..71e3be67 100644 --- a/render/core/src/mesh/MeshFeature.cpp +++ b/runtime/render/core/src/mesh/MeshFeature.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include @@ -18,15 +19,24 @@ namespace sky { {rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC, 1, 0, rhi::ShaderStageFlagBit::VS, "localData"}, }; + static const std::vector SKINNED_BINDINGS = { + {rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC, 1, 0, rhi::ShaderStageFlagBit::VS, "localData"}, + {rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC, 1, 1, rhi::ShaderStageFlagBit::VS, "skinData"}, + }; + void MeshFeature::Init() { Renderer::Get()->RegisterRenderFeature(); auto *device = RHI::Get()->GetDevice(); - localLayout = std::make_shared(); + localLayout = new ResourceGroupLayout(); localLayout->SetRHILayout(device->CreateDescriptorSetLayout({BINDINGS})); localLayout->AddNameHandler("localData", {0, sizeof(InstanceLocal)}); + skinnedLayout = new ResourceGroupLayout(); + skinnedLayout->SetRHILayout(device->CreateDescriptorSetLayout({SKINNED_BINDINGS})); + skinnedLayout->AddNameHandler("skinData", {0, sizeof(Skin)}); + { rhi::DescriptorSetPool::Descriptor poolDesc = {}; @@ -39,9 +49,16 @@ namespace sky { RDResourceGroupPtr MeshFeature::RequestResourceGroup() { - auto rsg = std::make_shared(); + auto *rsg = new ResourceGroup(); rsg->Init(localLayout, *pool); return rsg; } + RDResourceGroupPtr MeshFeature::RequestSkinnedResourceGroup() + { + auto *rsg = new ResourceGroup(); + rsg->Init(skinnedLayout, *pool); + return rsg; + } + } // namespace sky diff --git a/runtime/render/core/src/mesh/MeshFeatureProcessor.cpp b/runtime/render/core/src/mesh/MeshFeatureProcessor.cpp new file mode 100644 index 00000000..e1137a80 --- /dev/null +++ b/runtime/render/core/src/mesh/MeshFeatureProcessor.cpp @@ -0,0 +1,48 @@ +// +// Created by Zach Lee on 2023/9/9. +// + +#include + +namespace sky { + + void MeshFeatureProcessor::Tick(float time) + { + for (auto &mesh : staticMeshes) { + mesh->Tick(); + } + } + + void MeshFeatureProcessor::Render(rdg::RenderGraph &rdg) + { + } + + MeshRenderer *MeshFeatureProcessor::CreateStaticMesh() + { + auto *renderer = new MeshRenderer(); + renderer->AttachScene(scene); + return staticMeshes.emplace_back(renderer).get(); + } + + void MeshFeatureProcessor::RemoveStaticMesh(MeshRenderer *mesh) + { + staticMeshes.remove_if([mesh](const auto &val) { + return mesh == val.get(); + }); + } + + SkeletonMeshRenderer *MeshFeatureProcessor::CreateSkeletonMesh() + { + auto *renderer = new SkeletonMeshRenderer(); + renderer->AttachScene(scene); + return skeletonMeshes.emplace_back(renderer).get(); + } + + void MeshFeatureProcessor::RemoveSkeletonMesh(SkeletonMeshRenderer *mesh) + { + skeletonMeshes.remove_if([mesh](const auto &val) { + return mesh == val.get(); + }); + } + +} // namespace sky diff --git a/runtime/render/core/src/mesh/MeshRenderer.cpp b/runtime/render/core/src/mesh/MeshRenderer.cpp new file mode 100644 index 00000000..b7e0814c --- /dev/null +++ b/runtime/render/core/src/mesh/MeshRenderer.cpp @@ -0,0 +1,110 @@ +// +// Created by Zach Lee on 2023/9/9. +// + +#include +#include +#include +#include +#include + +namespace sky { + + MeshRenderer::~MeshRenderer() + { + for (auto &prim : primitives) { + scene->RemovePrimitive(prim.get()); + } + } + + void MeshRenderer::Tick() + { + for (auto &prim : primitives) { + prim->isReady = mesh->IsReady(); + } + } + + void MeshRenderer::AttachScene(RenderScene *scn) + { + scene = scn; + } + + void MeshRenderer::SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh) + { + auto &primitive = primitives[subMesh]; + primitive->techniques.clear(); + + const auto &techniques = mat->GetMaterial()->GetGfxTechniques(); + primitive->techniques.reserve(techniques.size()); + for (const auto &tech : techniques) { + TechniqueInstance inst = {tech, mat}; + inst.shaderOption = new ShaderOption(); + tech->Process(primitive->vertexFlags, inst.shaderOption); + primitive->techniques.emplace_back(inst); + } + + primitive->batchSet = mat->GetResourceGroup(); + } + + void MeshRenderer::SetMesh(const RDMeshPtr &mesh_) + { + mesh = mesh_; + mesh->Upload(); + + if (!ubo) { + PrepareUBO(); + } + + uint32_t index = 0; + auto *meshFeature = MeshFeature::Get(); + for (const auto &sub : mesh->GetSubMeshes()) { + auto &primitive = primitives.emplace_back(std::make_unique()); + primitive->instanceSet = RequestResourceGroup(meshFeature); + primitive->instanceSet->BindDynamicUBO("localData", ubo, 0); + primitive->instanceSet->Update(); + + primitive->localBound = sub.aabb; + primitive->geometry = mesh->GetGeometry(); + + if (primitive->geometry->attributeSemantics.TestBit(VertexSemanticFlagBit::HAS_SKIN)) { + primitive->vertexFlags |= RenderVertexFlagBit::SKIN; + } + + primitive->args.emplace_back(rhi::CmdDrawIndexed { + sub.indexCount, + 1, + sub.firstIndex, + static_cast(sub.firstVertex), + 0 + }); + + SetMaterial(sub.material, index++); + scene->AddPrimitive(primitive.get()); + } + } + + void MeshRenderer::UpdateTransform(const Matrix4 &matrix) + { + ubo->WriteT(0, matrix); + ubo->WriteT(sizeof(Matrix4), matrix.InverseTranspose()); + ubo->Upload(); + + for (auto &prim : primitives) { + prim->worldBound = AABB::Transform(prim->localBound, matrix); + } + } + + void MeshRenderer::PrepareUBO() + { + ubo = new DynamicUniformBuffer(); + ubo->Init(sizeof(InstanceLocal)); + ubo->WriteT(0, InstanceLocal{Matrix4::Identity(), Matrix4::Identity()}); + ubo->Upload(); + } + + RDResourceGroupPtr MeshRenderer::RequestResourceGroup(MeshFeature *feature) + { + return feature->RequestResourceGroup(); + } + +} // namespace sky diff --git a/render/core/src/particle/ParticleEmitter.cpp b/runtime/render/core/src/particle/ParticleEmitter.cpp similarity index 100% rename from render/core/src/particle/ParticleEmitter.cpp rename to runtime/render/core/src/particle/ParticleEmitter.cpp diff --git a/render/core/src/particle/ParticleFeature.cpp b/runtime/render/core/src/particle/ParticleFeature.cpp similarity index 100% rename from render/core/src/particle/ParticleFeature.cpp rename to runtime/render/core/src/particle/ParticleFeature.cpp diff --git a/render/core/src/particle/ParticleFeatureProcessor.cpp b/runtime/render/core/src/particle/ParticleFeatureProcessor.cpp similarity index 100% rename from render/core/src/particle/ParticleFeatureProcessor.cpp rename to runtime/render/core/src/particle/ParticleFeatureProcessor.cpp diff --git a/render/core/src/particle/ParticleSpriteRenderer.cpp b/runtime/render/core/src/particle/ParticleSpriteRenderer.cpp similarity index 100% rename from render/core/src/particle/ParticleSpriteRenderer.cpp rename to runtime/render/core/src/particle/ParticleSpriteRenderer.cpp diff --git a/render/core/src/particle/ParticleSystem.cpp b/runtime/render/core/src/particle/ParticleSystem.cpp similarity index 100% rename from render/core/src/particle/ParticleSystem.cpp rename to runtime/render/core/src/particle/ParticleSystem.cpp diff --git a/render/core/src/rdg/AccessGraphCompiler.cpp b/runtime/render/core/src/rdg/AccessGraphCompiler.cpp similarity index 100% rename from render/core/src/rdg/AccessGraphCompiler.cpp rename to runtime/render/core/src/rdg/AccessGraphCompiler.cpp diff --git a/render/core/src/rdg/AccessUtils.cpp b/runtime/render/core/src/rdg/AccessUtils.cpp similarity index 97% rename from render/core/src/rdg/AccessUtils.cpp rename to runtime/render/core/src/rdg/AccessUtils.cpp index 7171988e..90860500 100644 --- a/render/core/src/rdg/AccessUtils.cpp +++ b/runtime/render/core/src/rdg/AccessUtils.cpp @@ -131,6 +131,13 @@ namespace sky::rdg { range.range = 1; range.layers = 1; }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &tag) { + const auto &res = resourceGraph.xrSwapChains[Index(resID, resourceGraph)]; + range.range = 1; + range.layers = res.desc.swapchain->GetArrayLayers(); + }, +#endif [&](const BufferTag &tag) { const auto &buffer = resourceGraph.buffers[Index(resID, resourceGraph)]; range.range = buffer.desc.size; diff --git a/render/core/src/rdg/RenderGraph.cpp b/runtime/render/core/src/rdg/RenderGraph.cpp similarity index 89% rename from render/core/src/rdg/RenderGraph.cpp rename to runtime/render/core/src/rdg/RenderGraph.cpp index c47497f6..fa337e9e 100644 --- a/render/core/src/rdg/RenderGraph.cpp +++ b/runtime/render/core/src/rdg/RenderGraph.cpp @@ -53,7 +53,12 @@ namespace sky::rdg { { add_edge(0, AddVertex(name, GraphSwapChain{swapchain}, *this), graph); } - +#ifdef SKY_ENABLE_XR + void ResourceGraph::ImportXRSwapChain(const char *name, const rhi::XRSwapChainPtr &swapchain) + { + add_edge(0, AddVertex(name, GraphXRSwapChain{swapchain}, *this), graph); + } +#endif void ResourceGraph::AddImageView(const char *name, const char *source, const GraphImageView &view) { auto src = FindVertex(source, *this); @@ -94,9 +99,8 @@ namespace sky::rdg { add_edge(src, dst, graph); } - RenderGraph::RenderGraph(RenderGraphContext *ctx, RenderScene *scn) + RenderGraph::RenderGraph(RenderGraphContext *ctx) : context(ctx) - , scene(scn) , vertices(&ctx->resources) , names(&ctx->resources) , accessNodes(&ctx->resources) @@ -142,13 +146,26 @@ namespace sky::rdg { void RenderGraph::AddPresentPass(const char *name, const char *resName) { - auto res = FindVertex(resName, resourceGraph); - SKY_ASSERT(res != INVALID_VERTEX); - const auto &swc = resourceGraph.swapChains[Index(res, resourceGraph)]; - auto vtx = AddVertex(name, PresentPass(res, swc.desc.swapchain, &context->resources), *this); - add_edge(0, vtx, graph); - - AddDependency(res, vtx, DependencyInfo{PresentType::PRESENT, ResourceAccessBit::READ, {}}); + auto resID = FindVertex(resName, resourceGraph); + SKY_ASSERT(resID != INVALID_VERTEX); + + std::visit(Overloaded{ + [&](const ImportSwapChainTag &tag) { + const auto &res = resourceGraph.swapChains[Index(resID, resourceGraph)]; + auto vtx = AddVertex(name, PresentPass(resID, res.desc.swapchain, &context->resources), *this); + add_edge(0, vtx, graph); + AddDependency(resID, vtx, DependencyInfo{PresentType::PRESENT, ResourceAccessBit::READ, {}}); + }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &tag) { + const auto &res = resourceGraph.xrSwapChains[Index(resID, resourceGraph)]; + auto vtx = AddVertex(name, PresentPass(resID, res.desc.swapchain, &context->resources), *this); + add_edge(0, vtx, graph); + AddDependency(resID, vtx, DependencyInfo{PresentType::PRESENT, ResourceAccessBit::READ, {}}); + }, +#endif + [&](const auto &) {} + }, rdg::Tag(resID, resourceGraph)); } AccessGraph::AccessGraph(RenderGraphContext *ctx) @@ -249,6 +266,12 @@ namespace sky::rdg { return *this; } + RasterPassBuilder &RasterPassBuilder::AddCoRelationMasks(uint32_t mask) + { + pass.correlationMasks.emplace_back(mask); + return *this; + } + RasterSubPassBuilder RasterPassBuilder::AddRasterSubPass(const std::string &name) { auto dst = AddVertex(name.c_str(), RasterSubPass{&rdg.context->resources}, rdg); @@ -324,6 +347,12 @@ namespace sky::rdg { return *this; } + RasterSubPassBuilder &RasterSubPassBuilder::SetViewMask(uint32_t mask) + { + subPass.viewMask = mask; + return *this; + } + RasterQueueBuilder RasterSubPassBuilder::AddQueue(const std::string &name) { auto res = AddVertex(name.c_str(), RasterQueue(&rdg.context->resources, vertex), rdg); @@ -379,7 +408,7 @@ namespace sky::rdg { FullScreenBuilder &FullScreenBuilder::SetTechnique(const RDGfxTechPtr &tech) { fullscreen.technique = tech; - fullscreen.layout = tech->RequestProgram()->RequestLayout(PASS_SET); + fullscreen.program = tech->RequestProgram(); return *this; } } // namespace sky::rdg diff --git a/render/core/src/rdg/RenderGraphContext.cpp b/runtime/render/core/src/rdg/RenderGraphContext.cpp similarity index 100% rename from render/core/src/rdg/RenderGraphContext.cpp rename to runtime/render/core/src/rdg/RenderGraphContext.cpp diff --git a/render/core/src/rdg/RenderGraphExecutor.cpp b/runtime/render/core/src/rdg/RenderGraphExecutor.cpp similarity index 81% rename from render/core/src/rdg/RenderGraphExecutor.cpp rename to runtime/render/core/src/rdg/RenderGraphExecutor.cpp index 534e6d40..5ef69176 100644 --- a/render/core/src/rdg/RenderGraphExecutor.cpp +++ b/runtime/render/core/src/rdg/RenderGraphExecutor.cpp @@ -21,6 +21,12 @@ namespace sky::rdg { const auto &image = resourceGraph.swapChains[Index(resID, resourceGraph)]; res = image.desc.swapchain->GetImage(image.desc.imageIndex); }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &) { + const auto &image = resourceGraph.xrSwapChains[Index(resID, resourceGraph)]; + res = image.desc.swapchain->GetImage(image.desc.imageIndex); + }, +#endif [&](const auto &) { } }, Tag(resID, resourceGraph)); @@ -65,6 +71,18 @@ namespace sky::rdg { rhi::BarrierInfo{ barrier.srcFlags, barrier.dstFlags}); } }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &) { + auto &image = graph.resourceGraph.xrSwapChains[Index(resID, graph.resourceGraph)]; + for (const auto &barrier : barriers) { + mainCommandBuffer->QueueBarrier(image.desc.swapchain->GetImage(image.desc.imageIndex), + rhi::ImageSubRange{static_cast(barrier.range.base), static_cast(barrier.range.range), + barrier.range.layer, barrier.range.layers, + rhi::AspectFlagBit::COLOR_BIT}, + rhi::BarrierInfo{ barrier.srcFlags, barrier.dstFlags}); + } + }, +#endif [&](const BufferTag &) { auto &buffer = graph.resourceGraph.buffers[Index(resID, graph.resourceGraph)]; for (const auto &barrier : barriers) { @@ -87,7 +105,7 @@ namespace sky::rdg { mainCommandBuffer->FlushBarriers(); } - [[maybe_unused]] void RenderGraphExecutor::discover_vertex(Vertex u, const Graph& g) + [[maybe_unused]] void RenderGraphExecutor::discover_vertex(Vertex u, const Graph& g) // NOLINT { const auto &mainCommandBuffer = graph.context->MainCommandBuffer(); std::visit(Overloaded{ @@ -145,6 +163,12 @@ namespace sky::rdg { [&](const PresentTag &) { auto &present = graph.presentPasses[Index(u, graph)]; Barriers(present.frontBarriers); + +#ifdef SKY_ENABLE_XR + if (present.xrSwapChain) { + present.xrSwapChain->Present(); + } +#endif callStack.emplace_back(graph.names[u]); }, [&](const RasterQueueTag &) { @@ -153,24 +177,33 @@ namespace sky::rdg { auto &tech = item.primitive->techniques[item.techIndex]; currentEncoder->BindPipeline(tech.pso); - if (queue.resourceGroup != nullptr) { + if (queue.resourceGroup != nullptr && ((tech.pso->GetDescriptorMask() & (1 << 0)) != 0u)) { queue.resourceGroup->OnBind(*currentEncoder, 0); } else { graph.context->emptySet->OnBind(*currentEncoder, 0); } - if (item.primitive->batchSet) { + if (item.primitive->batchSet && ((tech.pso->GetDescriptorMask() & (1 << 1)) != 0u)) { item.primitive->batchSet->OnBind(*currentEncoder, 1); } else { graph.context->emptySet->OnBind(*currentEncoder, 1); } - if (item.primitive->instanceSet) { + if (item.primitive->instanceSet && ((tech.pso->GetDescriptorMask() & (1 << 2)) != 0u)) { item.primitive->instanceSet->OnBind(*currentEncoder, 2); } - if (item.primitive->va) { - currentEncoder->BindAssembly(item.primitive->va); + if (tech.vao) { + currentEncoder->BindAssembly(tech.vao); + } else { + std::vector vertexBuffers; + item.primitive->geometry->FillVertexBuffer(vertexBuffers); + currentEncoder->BindVertexBuffers(vertexBuffers); + } + + const auto &ib = item.primitive->geometry->indexBuffer; + if (ib.buffer) { + currentEncoder->BindIndexBuffer(ib.MakeView(), ib.indexType); } for (const auto &arg : item.primitive->args) { @@ -186,7 +219,7 @@ namespace sky::rdg { [&](const FullScreenBlitTag &) { auto &fullScreen = graph.fullScreens[Index(u, graph)]; currentEncoder->BindPipeline(fullScreen.pso); - if (fullScreen.resourceGroup) { + if (fullScreen.resourceGroup != nullptr) { fullScreen.resourceGroup->OnBind(*currentEncoder, 0); } currentEncoder->DrawLinear({3, 1, 0, 0}); diff --git a/render/core/src/rdg/RenderGraphProfiler.cpp b/runtime/render/core/src/rdg/RenderGraphProfiler.cpp similarity index 100% rename from render/core/src/rdg/RenderGraphProfiler.cpp rename to runtime/render/core/src/rdg/RenderGraphProfiler.cpp diff --git a/render/core/src/rdg/RenderGraphUploader.cpp b/runtime/render/core/src/rdg/RenderGraphUploader.cpp similarity index 100% rename from render/core/src/rdg/RenderGraphUploader.cpp rename to runtime/render/core/src/rdg/RenderGraphUploader.cpp diff --git a/render/core/src/rdg/RenderGraphVisitors.cpp b/runtime/render/core/src/rdg/RenderGraphVisitors.cpp similarity index 100% rename from render/core/src/rdg/RenderGraphVisitors.cpp rename to runtime/render/core/src/rdg/RenderGraphVisitors.cpp diff --git a/render/core/src/rdg/RenderLayoutGraph.cpp b/runtime/render/core/src/rdg/RenderLayoutGraph.cpp similarity index 100% rename from render/core/src/rdg/RenderLayoutGraph.cpp rename to runtime/render/core/src/rdg/RenderLayoutGraph.cpp diff --git a/render/core/src/rdg/RenderResourceCompiler.cpp b/runtime/render/core/src/rdg/RenderResourceCompiler.cpp similarity index 88% rename from render/core/src/rdg/RenderResourceCompiler.cpp rename to runtime/render/core/src/rdg/RenderResourceCompiler.cpp index fccfba07..a3aa6ae6 100644 --- a/render/core/src/rdg/RenderResourceCompiler.cpp +++ b/runtime/render/core/src/rdg/RenderResourceCompiler.cpp @@ -4,13 +4,13 @@ #include #include +#include #include #include static const char *TAG = "RDG"; namespace sky::rdg { - void RenderResourceCompiler::discover_vertex(Vertex u, const Graph& g) { std::visit(Overloaded{ @@ -72,6 +72,10 @@ namespace sky::rdg { const auto &swc = rdg.resourceGraph.swapChains[Index(res, rdg.resourceGraph)]; rsg.BindTexture(view.name, swc.res, 0); }, + [&](const ImportXRSwapChainTag &) { + const auto &swc = rdg.resourceGraph.xrSwapChains[Index(res, rdg.resourceGraph)]; + rsg.BindTexture(view.name, swc.res, 0); + }, [&](const ConstantBufferTag &) { const auto &cb = rdg.resourceGraph.constantBuffers[Index(res, rdg.resourceGraph)]; rsg.BindBuffer(view.name, cb.ubo->GetRHIBuffer(), 0); @@ -129,11 +133,13 @@ namespace sky::rdg { { const auto &subPass = rdg.subPasses[Index(fullscreen.passID, rdg)]; const auto &pass = rdg.rasterPasses[Index(subPass.parent, rdg)]; - if (fullscreen.layout) { - fullscreen.resourceGroup = rdg.context->pool->RequestResourceGroup(u, fullscreen.layout); - BindResourceGroup(rdg, subPass.computeViews, *fullscreen.resourceGroup); - } - fullscreen.pso = GraphicsTechnique::BuildPso(*fullscreen.technique, pass.renderPass, subPass.subPassID); + fullscreen.resourceGroup = rdg.context->pool->RequestResourceGroup(u, fullscreen.program->RequestLayout(PASS_SET)); + BindResourceGroup(rdg, subPass.computeViews, *fullscreen.resourceGroup); + fullscreen.pso = GraphicsTechnique::BuildPso(fullscreen.program, + fullscreen.technique->GetPipelineState(), + Renderer::Get()->GetDefaultRHIResource().emptyVI, + pass.renderPass, + subPass.subPassID); } void RenderResourceCompiler::MountResource(Vertex u, ResourceGraph::vertex_descriptor res) @@ -187,6 +193,15 @@ namespace sky::rdg { swc.res = swc.desc.swapchain->GetImageView(swc.desc.imageIndex); } }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &) { + auto &swc = rdg.resourceGraph.xrSwapChains[Index(res, rdg.resourceGraph)]; + if (!swc.res) { + swc.desc.imageIndex = swc.desc.swapchain->AcquireNextImage(); + swc.res = swc.desc.swapchain->GetImageView(swc.desc.imageIndex); + } + }, +#endif [&](const auto &) {} }, Tag(res, rdg.resourceGraph)); } @@ -229,9 +244,15 @@ namespace sky::rdg { [&](const ImportSwapChainTag &) { auto &swc = rdg.resourceGraph.swapChains[Index(attachment, rdg.resourceGraph)]; att.format = swc.desc.swapchain->GetFormat(); - fbDesc.views[i] = swc.res; }, +#ifdef SKY_ENABLE_XR + [&](const ImportXRSwapChainTag &) { + auto &swc = rdg.resourceGraph.xrSwapChains[Index(attachment, rdg.resourceGraph)]; + att.format = swc.desc.swapchain->GetFormat(); + fbDesc.views[i] = swc.res; + }, +#endif [&](const ImageViewTag &) { auto &source = rdg.resourceGraph.images[Index(Source(attachment, rdg.resourceGraph), rdg.resourceGraph)]; att.format = source.desc.format; @@ -284,9 +305,12 @@ namespace sky::rdg { sub.depthStencil.access = subVtx.rasterViews.at(attachmentDesc.name).type == (RasterTypeBit::INPUT | RasterTypeBit::DEPTH_STENCIL) ? rhi::AccessFlagBit::DEPTH_STENCIL_INOUT_WRITE : rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; } + + sub.viewMask = subVtx.viewMask; } passDesc.dependencies.resize(dependencySize); + passDesc.correlatedViewMasks.assign(rasterPass.correlationMasks.begin(), rasterPass.correlationMasks.end()); for (uint32_t i = 0; i < dependencySize; ++i) { auto &dep = passDesc.dependencies[i]; auto &depVtx = rasterPass.dependencies[i]; diff --git a/runtime/render/core/src/rdg/RenderSceneVisitor.cpp b/runtime/render/core/src/rdg/RenderSceneVisitor.cpp new file mode 100644 index 00000000..8310c633 --- /dev/null +++ b/runtime/render/core/src/rdg/RenderSceneVisitor.cpp @@ -0,0 +1,94 @@ +// +// Created by Zach Lee on 2023/8/27. +// + +#include +#include +#include +#include + +namespace sky::rdg { + void RenderSceneVisitor::BuildRenderQueue() + { + const auto &primitives = scene->GetPrimitives(); + for (auto &queue : graph.rasterQueues) { + const auto &subPass = graph.subPasses[Index(queue.passID, graph)]; + const auto &rasterPass = graph.rasterPasses[Index(subPass.parent, graph)]; + const auto &renderPass = rasterPass.renderPass; + + auto passHash = renderPass->GetCompatibleHash(); + + for (const auto &prim : primitives) { + if (!prim->isReady) { + continue; + } + + if (queue.culling && queue.sceneView != nullptr && !queue.sceneView->FrustumCulling(prim->worldBound)) { + continue; + } + + uint32_t techIndex = 0; + for (auto &tech : prim->techniques) { + uint32_t viewMask = tech.technique->GetViewMask(); + uint32_t rasterID = tech.technique->GetRasterID(); + + uint32_t sceneMask = queue.sceneView != nullptr ? queue.sceneView->GetViewMask() : 0xFFFFFFFF; + if ((sceneMask & viewMask) != sceneMask || rasterID != queue.rasterID) { + techIndex++; + continue; + } + + bool needRebuildPso = false; + + uint32_t optionHash = 0; + if (tech.shaderOption) { + if (tech.material) { + tech.material->ProcessShaderOption(tech.shaderOption); + } + optionHash = tech.shaderOption->GetHash(); + } + if (!tech.program || tech.variantHash != optionHash) { + tech.variantHash = optionHash; + tech.program = tech.technique->RequestProgram(tech.shaderOption); + needRebuildPso = true; + } + + if (prim->geometry && prim->geometry->version > tech.vaoVersion) { + if (prim->geometry->dynamicVB) { + tech.vaoVersion = 0; + tech.vao = nullptr; + tech.vertexDesc = prim->geometry->Request(tech.program); + } else { + tech.vaoVersion = prim->geometry->version; + tech.vao = prim->geometry->Request(tech.program, tech.vertexDesc); + } + } + + if (tech.renderPassHash != passHash) { + tech.renderPassHash = passHash; + + needRebuildPso = true; + } + + needRebuildPso &= static_cast(tech.program); + needRebuildPso &= static_cast(tech.vertexDesc); + needRebuildPso &= static_cast(renderPass); + + if (needRebuildPso) { + tech.pso = GraphicsTechnique::BuildPso(tech.program, + tech.technique->GetPipelineState(), + tech.vertexDesc, + renderPass, + subPass.subPassID); + } + + if (tech.pso) { + queue.drawItems.emplace_back(RenderDrawItem{prim, techIndex++}); + } + } + } + } + } + + +} // namespace sky::rdg diff --git a/render/core/src/rdg/TransientMemoryPool.cpp b/runtime/render/core/src/rdg/TransientMemoryPool.cpp similarity index 100% rename from render/core/src/rdg/TransientMemoryPool.cpp rename to runtime/render/core/src/rdg/TransientMemoryPool.cpp diff --git a/render/core/src/rdg/TransientObjectPool.cpp b/runtime/render/core/src/rdg/TransientObjectPool.cpp similarity index 100% rename from render/core/src/rdg/TransientObjectPool.cpp rename to runtime/render/core/src/rdg/TransientObjectPool.cpp diff --git a/render/core/src/rdg/TransientPool.cpp b/runtime/render/core/src/rdg/TransientPool.cpp similarity index 100% rename from render/core/src/rdg/TransientPool.cpp rename to runtime/render/core/src/rdg/TransientPool.cpp diff --git a/runtime/render/core/src/renderpass/ComputePass.cpp b/runtime/render/core/src/renderpass/ComputePass.cpp new file mode 100644 index 00000000..eb41cc40 --- /dev/null +++ b/runtime/render/core/src/renderpass/ComputePass.cpp @@ -0,0 +1,10 @@ +// +// Created by blues on 2024/9/3. +// + +#include + +namespace sky { + + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/renderpass/PassBase.cpp b/runtime/render/core/src/renderpass/PassBase.cpp new file mode 100644 index 00000000..01112c58 --- /dev/null +++ b/runtime/render/core/src/renderpass/PassBase.cpp @@ -0,0 +1,24 @@ +// +// Created by blues on 2024/9/3. +// + +#include +#include +#include + +namespace sky { + + void PassBase::Prepare(rdg::RenderGraph &rdg, RenderScene &scene) + { + auto &rg = rdg.resourceGraph; + + for (auto &[key, image] : images) { + rg.AddImage(key.c_str(), image); + } + + for (auto &[key, buffer] : buffers) { + rg.AddBuffer(key.c_str(), buffer); + } + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/renderpass/RasterPass.cpp b/runtime/render/core/src/renderpass/RasterPass.cpp new file mode 100644 index 00000000..1650f137 --- /dev/null +++ b/runtime/render/core/src/renderpass/RasterPass.cpp @@ -0,0 +1,84 @@ +// +// Created by blues on 2024/9/3. +// + +#include +#include + +namespace sky { + + void RasterPass::Resize(uint32_t w, uint32_t h) + { + width = w; + height = h; + + for (auto &image : images) { + image.second.extent.width = width; + image.second.extent.height = height; + } + } + + void RasterPass::Setup(rdg::RenderGraph &rdg, RenderScene &scene) + { + auto passBuilder = rdg.AddRasterPass(name.data(), width, height); + + auto colorCount = static_cast(colors.size()); + auto resolveCount = static_cast(resolves.size()); + + if (resolveCount != 0) { + SKY_ASSERT(colorCount == resolveCount); + } + + for (auto &color : colors) { + passBuilder.AddAttachment(color.attachment, color.clearValue); + } + + for (auto &resolve : resolves) { + passBuilder.AddAttachment(resolve.attachment, resolve.clearValue); + } + + if (!depthStencil.attachment.name.empty()) { + passBuilder.AddAttachment(depthStencil.attachment, depthStencil.clearValue); + } + + auto subPassBuilder = passBuilder.AddRasterSubPass(name + "@0"); + for (uint32_t i = 0; i < colorCount; ++i) { + subPassBuilder.AddColor(colors[i].attachment.name, rdg::ResourceAccessBit::WRITE); + + if (resolveCount != 0) { + subPassBuilder.AddResolve(resolves[i].attachment.name, rdg::ResourceAccessBit::WRITE); + } + } + + if (!depthStencil.attachment.name.empty()) { + subPassBuilder.AddDepthStencil(depthStencil.attachment.name, rdg::ResourceAccessBit::WRITE); + } + + for (auto &res : computeResources) { + subPassBuilder.AddComputeView(res.name, res.computeView); + } + + SetupSubPass(subPassBuilder, scene); + } + + void FullScreenPass::Setup(rdg::RenderGraph &rdg, RenderScene &scene) + { + auto passBuilder = rdg.AddRasterPass(name.c_str(), width, height); + + SKY_ASSERT(colors.size() == 1); + passBuilder.AddAttachment(colors[0].attachment, colors[0].clearValue); + + auto subPassBuilder = passBuilder.AddRasterSubPass(name + "@0"); + subPassBuilder.AddColor(colors[0].attachment.name, rdg::ResourceAccessBit::WRITE); + + for (auto &res : computeResources) { + subPassBuilder.AddComputeView(res.name, res.computeView); + } + + subPassBuilder.AddFullScreen(name + "_queue") + .SetTechnique(technique); + + SetupSubPass(subPassBuilder, scene); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/resource/Buffer.cpp b/runtime/render/core/src/resource/Buffer.cpp new file mode 100644 index 00000000..9a929f1d --- /dev/null +++ b/runtime/render/core/src/resource/Buffer.cpp @@ -0,0 +1,165 @@ +// +// Created by Zach Lee on 2023/9/1. +// + +#include +#include +#include +#include +#include + +namespace sky { + + Buffer::~Buffer() + { + Renderer::Get()->GetResourceGC()->CollectBuffer(buffer); + } + + Buffer::Buffer() + { + device = RHI::Get()->GetDevice(); + } + + void Buffer::Init(uint64_t size, const rhi::BufferUsageFlags& usage, rhi::MemoryType memoryType) + { + bufferDesc.size = size; + bufferDesc.usage = usage; + bufferDesc.memory = memoryType; + + buffer = device->CreateBuffer(bufferDesc); + } + + void Buffer::SetSourceData(const rhi::BufferUploadRequest &data) + { + sourceData = data; + } + + uint64_t Buffer::UploadImpl() + { + uploadHandle = uploadQueue->UploadBuffer(buffer, sourceData); + sourceData.source = nullptr; + return sourceData.size; + } + + rhi::BufferView Buffer::MakeView() const + { + return rhi::BufferView{buffer, 0, bufferDesc.size}; + } + + rhi::BufferView VertexBuffer::MakeView() const + { + auto res = buffer->MakeView(); + res.offset += offset; + res.range = range; + return res; + } + + rhi::BufferView IndexBuffer::MakeView() const + { + auto res = buffer->MakeView(); + res.offset += offset; + res.range = range; + return res; + } + + bool UniformBuffer::Init(uint32_t size) + { + Buffer::Init(size, rhi::BufferUsageFlagBit::UNIFORM | rhi::BufferUsageFlagBit::TRANSFER_DST, rhi::MemoryType::GPU_ONLY); + + rhi::Buffer::Descriptor desc = {}; + desc.size = size; + desc.memory = rhi::MemoryType::CPU_TO_GPU; + desc.usage = rhi::BufferUsageFlagBit::UNIFORM | rhi::BufferUsageFlagBit::TRANSFER_SRC; + stagingBuffer = RHI::Get()->GetDevice()->CreateBuffer(desc); + + data.resize(size); + ptr = data.data(); + return static_cast(buffer); + } + + void UniformBuffer::Write(uint32_t offset, const uint8_t *src, uint32_t size) + { + SKY_ASSERT(offset + size <= bufferDesc.size); + memcpy(ptr + offset, src, size); + dirty = true; + } + + void UniformBuffer::Upload(rhi::BlitEncoder &encoder) + { + uint8_t *tmp = stagingBuffer->Map(); + memcpy(tmp, data.data(), data.size()); + stagingBuffer->UnMap(); + + encoder.CopyBuffer(stagingBuffer, buffer, data.size(), 0, 0); + } + + void DynamicUniformBuffer::Upload() + { + if (!dirty) { + return; + } + + frameIndex = (frameIndex + 1) % Renderer::Get()->GetInflightFrameCount(); + + auto *mapPtr = buffer->Map() + frameIndex * alignedFrameSize; + memcpy(mapPtr, ptr, alignedFrameSize); + buffer->UnMap(); + + dirty = false; + } + + void DynamicUniformBuffer::Upload(rhi::BlitEncoder &/*encoder*/) + { + Upload(); + } + + bool DynamicUniformBuffer::Init(uint32_t size) + { + frameSize = size; + alignedFrameSize = Align(size, device->GetLimitations().minUniformBufferOffsetAlignment); + + Buffer::Init(alignedFrameSize * Renderer::Get()->GetInflightFrameCount(), rhi::BufferUsageFlagBit::UNIFORM, rhi::MemoryType::CPU_TO_GPU); + + data.resize(frameSize, 0); + ptr = data.data(); + return static_cast(buffer); + } + + bool DynamicBuffer::Init(uint32_t size, const rhi::BufferUsageFlags& usage) + { + frameSize = size; + alignedFrameSize = Align(size, 64U); + + Buffer::Init(alignedFrameSize * Renderer::Get()->GetInflightFrameCount(), usage, rhi::MemoryType::CPU_TO_GPU); + + mapped = buffer->Map(); + return static_cast(buffer); + } + + void DynamicBuffer::Update(uint8_t *ptr, uint32_t offset, uint32_t size) + { + SKY_ASSERT(offset + size <= frameSize); + SKY_ASSERT(mapped != nullptr); + memcpy(mapped + GetOffset() + offset, ptr, size); + } + + void DynamicBuffer::SwapBuffer() + { + frameIndex = (frameIndex + 1) % Renderer::Get()->GetInflightFrameCount(); + } + + uint8_t *DynamicBuffer::GetMapped() const + { + return mapped + GetOffset(); + } + + rhi::BufferView DynamicBuffer::MakeView() const + { + rhi::BufferView res = {}; + res.buffer = buffer; + res.offset = GetOffset(); + res.range = GetSize(); + + return res; + } +} // namespace sky diff --git a/render/core/src/resource/Material.cpp b/runtime/render/core/src/resource/Material.cpp similarity index 56% rename from render/core/src/resource/Material.cpp rename to runtime/render/core/src/resource/Material.cpp index c0797efe..cde98803 100644 --- a/render/core/src/resource/Material.cpp +++ b/runtime/render/core/src/resource/Material.cpp @@ -17,35 +17,79 @@ namespace sky { void Material::AddTechnique(const RDGfxTechPtr &technique) { gfxTechniques.emplace_back(technique); + if (!pool) { + rhi::DescriptorSetPool::Descriptor poolDesc = {}; - if (!layout) { - layout = gfxTechniques.back()->RequestProgram()->RequestLayout(BATCH_SET); - - if (!pool) { - rhi::DescriptorSetPool::Descriptor poolDesc = {}; - - poolDesc.maxSets = MAX_SET_PER_POOL; - poolDesc.sizeCount = static_cast(SIZES.size()); - poolDesc.sizeData = SIZES.data(); - pool = RHI::Get()->GetDevice()->CreateDescriptorSetPool(poolDesc); - } - + poolDesc.maxSets = MAX_SET_PER_POOL; + poolDesc.sizeCount = static_cast(SIZES.size()); + poolDesc.sizeData = SIZES.data(); + pool = RHI::Get()->GetDevice()->CreateDescriptorSetPool(poolDesc); } } - RDResourceGroupPtr Material::RequestResourceGroup() + RDResourceGroupPtr Material::RequestResourceGroup(const RDResourceLayoutPtr &layout) { - auto rsg = std::make_shared(); + if (!layout) { + return {}; + } + + auto *rsg = new ResourceGroup(); rsg->Init(layout, *pool); return rsg; } + MaterialInstance::MaterialInstance() + : options(new ShaderOption()) + { + } + void MaterialInstance::SetMaterial(const RDMaterialPtr &mat) { material = mat; - resourceGroup = material->RequestResourceGroup(); + } + + void MaterialInstance::SetValue(const std::string &key, const uint8_t *t, uint32_t size) + { + if (!resourceGroup) { + return; + } - const auto &defaultRes = Renderer::Get()->GetDefaultRHIResource(); + const auto *handler = resourceGroup->GetLayout()->GetBufferMemberByName(key); + if (handler != nullptr) { + uint32_t index = resourceGroup->GetLayout()->GetRHILayout()->GetDescriptorSetOffsetByBinding(handler->binding); + auto &ubo = uniformBuffers.at(index); + ubo->Write(handler->offset, t, size); + } + } + + void MaterialInstance::SetOption(const std::string &key, const MacroValue &val) + { + options->SetValue(key, val); + } + + void MaterialInstance::SetTexture(const std::string &key, const RDTexturePtr &tex, uint32_t index) + { + if (!resourceGroup) { + return; + } + + const auto *handler = resourceGroup->GetLayout()->GetBindingByeName(key); + if (handler != nullptr) { + uint32_t offset = resourceGroup->GetLayout()->GetRHILayout()->GetDescriptorSetOffsetByBinding(handler->binding); + resourceGroup->BindTexture(key, tex->GetImageView(), index); + textures[offset + index] = tex; + resDirty = true; + } + } + + void MaterialInstance::Compile() + { + const auto &tech = material->GetGfxTechniques()[0]; + auto program = tech->RequestProgram(options); + resourceGroup = material->RequestResourceGroup(program->RequestLayout(BATCH_SET)); + if (!resourceGroup) { + return; + } const auto &bindingHandlers = resourceGroup->GetLayout()->GetBindingHandlers(); const auto &rhiLayout = resourceGroup->GetLayout()->GetRHILayout(); @@ -59,50 +103,51 @@ namespace sky { SKY_ASSERT(iter != bindings.end()); for (uint32_t i = 0; i < count; ++i) { if (iter->type == rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC || iter->type == rhi::DescriptorType::UNIFORM_BUFFER) { - auto ubo = std::make_shared(); - ubo->Init(pair.second.size, Renderer::Get()->GetInflightFrameCount()); + auto *ubo = new DynamicUniformBuffer(); + ubo->Init(pair.second.size); uniformBuffers.emplace(index + i, ubo); resourceGroup->BindDynamicUBO(pair.first, ubo, i); - } else if (iter->type == rhi::DescriptorType::SAMPLED_IMAGE) { - textures.emplace(index + i, defaultRes.texture2D); - resourceGroup->BindTexture(pair.first, defaultRes.texture2D->GetImageView(), i); - } else if (iter->type == rhi::DescriptorType::SAMPLER) { - resourceGroup->BindSampler(pair.first, defaultRes.defaultSampler, i); } } } } - void MaterialInstance::SetValue(const std::string &key, const uint8_t *t, uint32_t size) + void MaterialInstance::Upload() { - const auto *handler = resourceGroup->GetLayout()->GetBufferMemberByName(key); - if (handler != nullptr) { - uint32_t index = resourceGroup->GetLayout()->GetRHILayout()->GetDescriptorSetOffsetByBinding(handler->binding); - auto &ubo = uniformBuffers.at(index); - ubo->Write(handler->offset, t, size); + if (uploaded) { + return; } - } - - void MaterialInstance::SetTexture(const std::string &key, const RDTexturePtr &tex, uint32_t index) - { - const auto *handler = resourceGroup->GetLayout()->GetBindingByeName(key); - if (handler != nullptr) { - resourceGroup->BindTexture(key, tex->GetImageView(), index); - textures[handler->binding + index] = tex; - resDirty = true; + auto *sm = Renderer::Get()->GetStreamingManager(); + for (auto &[idx, tex] : textures) { + sm->UploadTexture(tex); } + uploaded = true; } - void MaterialInstance::Upload() + void MaterialInstance::Update() { for (auto &ubo : uniformBuffers) { ubo.second->Upload(); } - if (resDirty) { + if (resDirty && resourceGroup) { resourceGroup->Update(); resDirty = false; } } -} // namespace sky \ No newline at end of file + bool MaterialInstance::IsReady() const + { + return !std::any_of(textures.begin(), textures.end(), [](const auto &tex) { + return !tex.second->IsReady(); + }); + } + + void MaterialInstance::ProcessShaderOption(const ShaderOptionPtr &outOptions) const + { + for (const auto &[key, val] : options->values) { + outOptions->SetValue(key, val); + } + } + +} // namespace sky diff --git a/runtime/render/core/src/resource/Mesh.cpp b/runtime/render/core/src/resource/Mesh.cpp new file mode 100644 index 00000000..8b122780 --- /dev/null +++ b/runtime/render/core/src/resource/Mesh.cpp @@ -0,0 +1,85 @@ +// +// Created by Zach Lee on 2023/8/31. +// + +#include +#include +#include + +namespace sky { + + Mesh::Mesh() + : geometry(new RenderGeometry()) + { + } + + void Mesh::AddSubMesh(const SubMesh &sub) + { + subMeshes.emplace_back(sub); + } + + void Mesh::SetVertexAttributes(const std::vector &attributes) + { + geometry->vertexAttributes = attributes; + for (auto &attr : attributes) { + geometry->attributeSemantics |= attr.sematic; + } + } + + void Mesh::SetIndexType(rhi::IndexType type) + { + geometry->indexBuffer.indexType = type; + } + + void Mesh::SetMaterial(const RDMaterialInstancePtr &mat, uint32_t subMesh) + { + subMeshes[subMesh].material = mat; + } + + void Mesh::Upload() + { + for (auto &sub : subMeshes) { + sub.material->Upload(); + } + geometry->Upload(); + geometry->version++; + } + + bool Mesh::IsReady() const + { + for (auto &sub : subMeshes) { + if (!sub.material->IsReady()) { + return false; + } + } + return geometry->IsReady(); + } + + void Mesh::SetUploadStream(MeshData&& stream_) + { + geometry->vertexBuffers.reserve(stream_.vertexStreams.size()); + for (auto &stream : stream_.vertexStreams) { + VertexBuffer vb = {}; + vb.buffer = new Buffer(); + vb.buffer->Init(stream.source.size, rhi::BufferUsageFlagBit::VERTEX | rhi::BufferUsageFlagBit::TRANSFER_DST, + rhi::MemoryType::GPU_ONLY); + vb.buffer->SetSourceData(stream.source); + + vb.offset = 0; + vb.range = stream.source.size; + vb.stride = stream.stride; + geometry->vertexBuffers.emplace_back(vb); + } + + if (stream_.indexStream.source) { + geometry->indexBuffer.buffer = new Buffer(); + geometry->indexBuffer.buffer->Init(stream_.indexStream.size, rhi::BufferUsageFlagBit::INDEX | rhi::BufferUsageFlagBit::TRANSFER_DST, + rhi::MemoryType::GPU_ONLY); + geometry->indexBuffer.buffer->SetSourceData(stream_.indexStream); + + geometry->indexBuffer.offset = 0; + geometry->indexBuffer.range = stream_.indexStream.size; + } + } + +} // namespace sky \ No newline at end of file diff --git a/render/core/src/resource/ResourceGroup.cpp b/runtime/render/core/src/resource/ResourceGroup.cpp similarity index 91% rename from render/core/src/resource/ResourceGroup.cpp rename to runtime/render/core/src/resource/ResourceGroup.cpp index 99bfda21..cba1fbc2 100644 --- a/render/core/src/resource/ResourceGroup.cpp +++ b/runtime/render/core/src/resource/ResourceGroup.cpp @@ -63,7 +63,7 @@ namespace sky { } } - slotHash.resize(layout->GetRHILayout()->GetDescriptorCount()); + slotHash.resize(layout->GetRHILayout()->GetDescriptorNum()); } void ResourceGroup::Update() @@ -83,14 +83,17 @@ namespace sky { { const auto *res = layout->GetBindingByeName(key); if (res != nullptr) { - set->BindBuffer(res->binding, buffer->GetRHIBuffer(), 0, buffer->GetRange(), index); + set->BindBuffer(res->binding, buffer->GetRHIBuffer(), 0, buffer->GetSize(), index); dynamicUBOS.emplace(layout->GetRHILayout()->GetDescriptorSetOffsetByBinding(res->binding) + index, buffer); } } void ResourceGroup::BindTexture(const std::string &key, const rhi::ImageViewPtr &view, uint32_t index) { - BindTexture(key, view, Renderer::Get()->GetDefaultRHIResource().defaultSampler, index); + const auto *res = layout->GetBindingByeName(key); + if (res != nullptr) { + set->BindImageView(res->binding, view, index); + } } void ResourceGroup::BindTexture(const std::string &key, const rhi::ImageViewPtr &view, const rhi::SamplerPtr &sampler, uint32_t index) @@ -114,7 +117,7 @@ namespace sky { { encoder.BindSet(setID, set); for (auto &[binding, ubo] : dynamicUBOS) { - encoder.SetOffset(setID, binding, 0, ubo->GetOffset()); + encoder.SetOffset(setID, binding, 0, static_cast(ubo->GetOffset())); } } diff --git a/render/core/src/resource/Shader.cpp b/runtime/render/core/src/resource/Shader.cpp similarity index 80% rename from render/core/src/resource/Shader.cpp rename to runtime/render/core/src/resource/Shader.cpp index 41ec9afe..94b7c0b4 100644 --- a/render/core/src/resource/Shader.cpp +++ b/runtime/render/core/src/resource/Shader.cpp @@ -71,7 +71,7 @@ namespace sky { } } - void Program::BuildPipelineLayout() + void Program::Build() { rhi::PipelineLayout::Descriptor plDesc = {}; std::vector layoutDesc; @@ -115,7 +115,7 @@ namespace sky { if (!rhiLayout) { return {}; } - auto layout = std::make_shared(); + auto *layout = new ResourceGroupLayout(); layout->SetRHILayout(rhiLayout); for (const auto &res : reflection->resources) { @@ -145,11 +145,11 @@ namespace sky { { // calculate signature std::stringstream ss; - uint32_t variantHash = option.preprocessor ? option.preprocessor->GetHash() : 0; + uint32_t variantHash = option.option ? option.option->GetHash() : 0; ss << name << '_' << entry << '_' << variantHash << '_' << static_cast(option.target); - auto cacheFolder = Renderer::Get()->GetCacheFolder() + "/shaderCache"; - std::string cachePath = cacheFolder + "/" + ss.str(); + auto cacheFolder = Renderer::Get()->GetCacheFolder() + "\\shaderCache"; + std::string cachePath = cacheFolder + "\\" + ss.str(); if (!std::filesystem::exists(cacheFolder)) { std::filesystem::create_directories(cacheFolder); @@ -160,7 +160,7 @@ namespace sky { { IFileArchive archive(cachePath); if (archive.IsOpen()) { - archive.Load(reinterpret_cast(&shaderHeader), sizeof(ShaderCacheHeader)); + archive.LoadRaw(reinterpret_cast(&shaderHeader), sizeof(ShaderCacheHeader)); if (shaderHeader.magic == ShaderCacheHeader::MAGIC && shaderHeader.version == hash) { needUpdateShader = false; @@ -210,40 +210,40 @@ namespace sky { return; } - MemoryArchive mArchive; - mArchive.Save(result.data); - - mArchive.Save(static_cast(result.reflection.resources.size())); - for (auto &res : result.reflection.resources) { - mArchive.Save(res.name); - mArchive.Save(res.type); - mArchive.Save(res.visibility.value); - mArchive.Save(res.set); - mArchive.Save(res.binding); - mArchive.Save(res.count); - mArchive.Save(res.size); - } - - mArchive.Save(static_cast(result.reflection.types.size())); - for (auto &type : result.reflection.types) { - mArchive.Save(type.name); - mArchive.Save(static_cast(type.variables.size())); - for (auto &var : type.variables) { - mArchive.Save(var.name); - mArchive.Save(var.set); - mArchive.Save(var.binding); - mArchive.Save(var.offset); - mArchive.Save(var.size); - } - } - - shaderHeader.version = hash; - shaderHeader.magic = ShaderCacheHeader::MAGIC; - shaderHeader.dataSize = static_cast(mArchive.GetData().size()); - - OFileArchive archive(cachePath); - archive.Save(reinterpret_cast(&shaderHeader), sizeof(ShaderCacheHeader)); - archive.Save(reinterpret_cast(mArchive.GetData().data()), shaderHeader.dataSize); +// MemoryArchive mArchive; +// mArchive.Save(result.data); +// +// mArchive.Save(static_cast(result.reflection.resources.size())); +// for (auto &res : result.reflection.resources) { +// mArchive.Save(res.name); +// mArchive.Save(res.type); +// mArchive.Save(res.visibility.value); +// mArchive.Save(res.set); +// mArchive.Save(res.binding); +// mArchive.Save(res.count); +// mArchive.Save(res.size); +// } +// +// mArchive.Save(static_cast(result.reflection.types.size())); +// for (auto &type : result.reflection.types) { +// mArchive.Save(type.name); +// mArchive.Save(static_cast(type.variables.size())); +// for (auto &var : type.variables) { +// mArchive.Save(var.name); +// mArchive.Save(var.set); +// mArchive.Save(var.binding); +// mArchive.Save(var.offset); +// mArchive.Save(var.size); +// } +// } +// +// shaderHeader.version = hash; +// shaderHeader.magic = ShaderCacheHeader::MAGIC; +// shaderHeader.dataSize = static_cast(mArchive.Size()); +// +// OFileArchive archive(cachePath); +// archive.SaveRaw(reinterpret_cast(&shaderHeader), sizeof(ShaderCacheHeader)); +// archive.SaveRaw(reinterpret_cast(mArchive.Data()), shaderHeader.dataSize); } } } // namespace sky \ No newline at end of file diff --git a/render/core/src/resource/Technique.cpp b/runtime/render/core/src/resource/Technique.cpp similarity index 79% rename from render/core/src/resource/Technique.cpp rename to runtime/render/core/src/resource/Technique.cpp index e3991984..c300cdc9 100644 --- a/render/core/src/resource/Technique.cpp +++ b/runtime/render/core/src/resource/Technique.cpp @@ -33,19 +33,29 @@ namespace sky { void Technique::SetShader(const ShaderRef &shader) { shaderData = shader; - RequestProgram(nullptr); } - RDProgramPtr Technique::RequestProgram(const ShaderPreprocessorPtr &preprocessor) + RDProgramPtr Technique::RequestProgram(const ShaderOptionPtr &shaderOption) { - auto program = std::make_shared(); + uint32_t hash = shaderOption ? shaderOption->GetHash() : 0; + auto iter = programCache.find(hash); + if (iter != programCache.end()) { + return iter->second; + } + + if (!shaderData.shaderCollection) { + return {}; + } + + auto *program = new Program(); program->SetName(shaderData.shaderCollection->GetName()); ShaderCompileOption option = {}; option.target = GetCompileTarget(); - option.preprocessor = preprocessor; + option.option = shaderOption; FillProgramInternal(*program, option); + programCache[hash] = program; return program; } @@ -69,10 +79,17 @@ namespace sky { rasterID = RenderNameHandle::Get()->GetOrRegisterName(tag); } - void GraphicsTechnique::SetVertexLayout(const std::string &key) + void GraphicsTechnique::Process(RenderVertexFlags flags, const ShaderOptionPtr &option) { - vertexDescKey = key; - vertexDesc = Renderer::Get()->GetVertexDescLibrary()->FindVertexDesc(key); + for (auto &val : preCompiledFlags) { + option->SetValue(val, true); + } + + for (auto &flag : vertexFlags) { + if (flags.TestBit(flag.first)) { + option->SetValue(flag.second, true); + } + } } void GraphicsTechnique::FillProgramInternal(Program &program, const ShaderCompileOption &option) @@ -106,7 +123,7 @@ namespace sky { program.AddShader(shader); program.MergeReflection(std::move(result.reflection)); } - program.BuildPipelineLayout(); + program.Build(); } void ComputeTechnique::FillProgramInternal(Program &program, const ShaderCompileOption &option) @@ -123,20 +140,21 @@ namespace sky { program.MergeReflection(std::move(result.reflection)); } - rhi::GraphicsPipelinePtr GraphicsTechnique::BuildPso(GraphicsTechnique &tech, + rhi::GraphicsPipelinePtr GraphicsTechnique::BuildPso(const RDProgramPtr &program, + const rhi::PipelineState &state, + const rhi::VertexInputPtr &vertexDesc, const rhi::RenderPassPtr &pass, uint32_t subPassID) { - auto program = tech.RequestProgram({}); const auto &shaders = program->GetShaders(); rhi::GraphicsPipeline::Descriptor descriptor = {}; - descriptor.state = tech.state; + descriptor.state = state; descriptor.state.multiSample.sampleCount = pass->GetSamplerCount(); descriptor.renderPass = pass; descriptor.subPassIndex = subPassID; descriptor.pipelineLayout = program->GetPipelineLayout(); - descriptor.vertexInput = tech.vertexDesc; + descriptor.vertexInput = vertexDesc; descriptor.vs = shaders[0]; descriptor.fs = shaders[1]; diff --git a/render/core/src/resource/Texture.cpp b/runtime/render/core/src/resource/Texture.cpp similarity index 79% rename from render/core/src/resource/Texture.cpp rename to runtime/render/core/src/resource/Texture.cpp index 03abda05..21de1a16 100644 --- a/render/core/src/resource/Texture.cpp +++ b/runtime/render/core/src/resource/Texture.cpp @@ -12,8 +12,7 @@ namespace sky { Texture::~Texture() { - imageView = nullptr; - Renderer::Get()->GetResourceGC()->CollectImage(image); + Renderer::Get()->GetResourceGC()->CollectImageViews(imageView); } Texture::Texture() @@ -21,31 +20,6 @@ namespace sky { device = RHI::Get()->GetDevice(); } - rhi::TransferTaskHandle Texture::Upload(const std::string &path, rhi::Queue &queue, uint32_t offset) - { - rhi::ImageUploadRequest request = {}; - request.source = std::make_shared(path, offset); - request.offset = 0; - request.mipLevel = 0; - request.layer = 0; - request.imageOffset = {0, 0, 0}; - request.imageExtent = imageDesc.extent; - return queue.UploadImage(image, request); - } - - rhi::TransferTaskHandle Texture::Upload(const uint8_t *ptr, uint64_t size, rhi::Queue &queue) - { - rhi::ImageUploadRequest request = {}; - request.source = std::make_shared(ptr); - request.offset = 0; - request.size = size; - request.mipLevel = 0; - request.layer = 0; - request.imageOffset = {0, 0, 0}; - request.imageExtent = imageDesc.extent; - return queue.UploadImage(image, request); - } - bool Texture::CheckExtent(uint32_t width, uint32_t height, uint32_t depth) const { return imageDesc.extent.width == width && imageDesc.extent.height == height && imageDesc.extent.depth == depth; @@ -131,4 +105,30 @@ namespace sky { return static_cast(imageView); } + void Texture::SetUploadStream(ImageData&& stream) + { + data = std::move(stream); + } + + void Texture::Upload(std::vector &&rawData, rhi::Queue *queue) + { + rhi::ImageUploadRequest request = {}; + request.size = static_cast(rawData.size()); + request.source = new rhi::RawBufferStream(std::move(rawData)); + request.imageExtent = imageDesc.extent; + + data.slices.emplace_back(request); + IStreamableResource::Upload(queue); + } + + uint64_t Texture::UploadImpl() + { + uint64_t size = 0; + for (auto &req : data.slices) { + size += req.size; + } + uploadHandle = uploadQueue->UploadImage(image, data.slices); + data.slices.clear(); + return size; + } } // namespace sky diff --git a/runtime/render/core/src/resource/TextureAtlas.cpp b/runtime/render/core/src/resource/TextureAtlas.cpp new file mode 100644 index 00000000..742e36c0 --- /dev/null +++ b/runtime/render/core/src/resource/TextureAtlas.cpp @@ -0,0 +1,65 @@ +// +// Created by blues on 2024/9/12. +// + +#include +#include + +namespace sky { + + Result TextureLinearAllocator::Allocate(uint32_t tw, uint32_t th) + { + uint32_t w = Align(tw + 1, 4u); + uint32_t h = Align(th + 1, 4u); + + if (currentX + w <= width && currentY + h <= height) { + Page ret = {currentX, currentY, tw, th}; + + currentX += w; + rowHeight = std::max(rowHeight, h); + + return {true, ret}; + } + + uint32_t nextY = currentY + rowHeight; + if (w <= width && nextY + h <= height) { + Page ret = {0, nextY, tw, th}; + + currentX = w; + currentY = nextY; + + rowHeight = h; + + return {true, ret}; + } + + return {false, {}}; + } + + bool Texture2DAtlas::Init(rhi::PixelFormat format, uint32_t width, uint32_t height) + { + allocator = std::make_unique(width, height); + return Texture2D::Init(format, width, height, 1); + } + + Result Texture2DAtlas::Allocate(uint32_t w, uint32_t h) + { + return allocator ? allocator->Allocate(w, h) : Result{false, {}}; + } + + void Texture2DAtlas::Upload(const Page &page, rhi::Queue &queue, std::vector &&data) + { + rhi::ImageUploadRequest request = {}; + request.offset = 0; + request.size = data.size(); + request.source = new rhi::RawBufferStream(std::move(data)); + request.mipLevel = 0; + request.layer = 0; + request.imageOffset = {static_cast(page.x), static_cast(page.y), 0}; + request.imageExtent = {page.w, page.h, 1}; + + uploadQueue = &queue; + uploadHandle = queue.UploadImage(image, request); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/skeleton/SkeletonMeshRenderer.cpp b/runtime/render/core/src/skeleton/SkeletonMeshRenderer.cpp new file mode 100644 index 00000000..7ecb7206 --- /dev/null +++ b/runtime/render/core/src/skeleton/SkeletonMeshRenderer.cpp @@ -0,0 +1,34 @@ +// +// Created by Zach Lee on 2023/9/9. +// + +#include +#include +#include + +namespace sky { + + SkeletonMeshRenderer::SkeletonMeshRenderer() + { + skin = new Skin(); + for (uint32_t i = 0; i < MAX_BONE_NUM; ++i) { + skin->boneMatrices[i] = Matrix4::Identity(); + } + } + + void SkeletonMeshRenderer::PrepareUBO() + { + MeshRenderer::PrepareUBO(); + + boneData = new DynamicUniformBuffer(); + boneData->Init(sizeof(Skin)); + boneData->WriteT(0, skin->boneMatrices.data()); + boneData->Upload(); + } + + RDResourceGroupPtr SkeletonMeshRenderer::RequestResourceGroup(MeshFeature *feature) + { + return feature->RequestSkinnedResourceGroup(); + } + +} // namespace sky diff --git a/runtime/render/core/src/text/Font.cpp b/runtime/render/core/src/text/Font.cpp new file mode 100644 index 00000000..3b808f8a --- /dev/null +++ b/runtime/render/core/src/text/Font.cpp @@ -0,0 +1,9 @@ +// +// Created by blues on 2024/9/11. +// + +#include + +namespace sky { + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/text/TextFeature.cpp b/runtime/render/core/src/text/TextFeature.cpp new file mode 100644 index 00000000..a8e99a01 --- /dev/null +++ b/runtime/render/core/src/text/TextFeature.cpp @@ -0,0 +1,58 @@ +// +// Created by blues on 2024/9/13. +// + +#include +#include +#include +#include + +namespace sky { + static constexpr uint32_t MAX_SET_PER_POOL = 4; + static std::vector SIZES = { + {rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC, MAX_SET_PER_POOL}, + {rhi::DescriptorType::SAMPLED_IMAGE, MAX_SET_PER_POOL}, + {rhi::DescriptorType::SAMPLER, MAX_SET_PER_POOL} + }; + + RDResourceGroupPtr TextFeature::RequestResourceGroup() + { + auto *rsg = new ResourceGroup(); + rsg->Init(batchLayout, *pool); + return rsg; + } + + void TextFeature::SetTechnique(const RDGfxTechPtr &tech) + { + technique = tech; + batchLayout = technique->RequestProgram()->RequestLayout(BATCH_SET); + } + + void TextFeature::Init() + { + Renderer::Get()->RegisterRenderFeature(); + auto *device = RHI::Get()->GetDevice(); + + { + rhi::DescriptorSetPool::Descriptor poolDesc = {}; + + poolDesc.maxSets = MAX_SET_PER_POOL; + poolDesc.sizeCount = static_cast(SIZES.size()); + poolDesc.sizeData = SIZES.data(); + pool = device->CreateDescriptorSetPool(poolDesc); + } + } + + Text* TextFeatureProcessor::CreateText(const FontPtr &font) + { + auto *text = TextRegistry::Get()->CreateText(font); + return texts.emplace_back(text).get(); + } + + void TextFeatureProcessor::RemoveText(Text *text) + { + texts.remove_if([text](const auto &val) { + return text == val.get(); + }); + } +} // namespace sky \ No newline at end of file diff --git a/runtime/render/core/src/text/TextRegistry.cpp b/runtime/render/core/src/text/TextRegistry.cpp new file mode 100644 index 00000000..c669792e --- /dev/null +++ b/runtime/render/core/src/text/TextRegistry.cpp @@ -0,0 +1,28 @@ +// +// Created by blues on 2024/9/13. +// + +#include + +namespace sky { + + FontPtr TextRegistry::LoadFont(const FileSystemPtr &fs, const std::string &name) + { + return factory ? factory->LoadFont(fs, name) : nullptr; + } + + Text* TextRegistry::CreateText(const FontPtr &font) + { + return factory ? factory->CreateText(font) : nullptr; + } + + void TextRegistry::Register(Impl* impl) + { + factory.reset(impl); + } + + void TextRegistry::UnRegister() + { + factory = nullptr; + } +} // namespace sky \ No newline at end of file diff --git a/render/imgui/CMakeLists.txt b/runtime/render/imgui/CMakeLists.txt similarity index 86% rename from render/imgui/CMakeLists.txt rename to runtime/render/imgui/CMakeLists.txt index 58e1dcc3..e1bb69fb 100644 --- a/render/imgui/CMakeLists.txt +++ b/runtime/render/imgui/CMakeLists.txt @@ -10,7 +10,8 @@ sky_add_library(TARGET ImGuiRender STATIC PUBLIC_INC include LINK_LIBS - SkyRenderCore + RenderCore Framework 3rdParty::imgui +# 3rdParty::implot ) \ No newline at end of file diff --git a/render/imgui/include/imgui/ImGuiFeature.h b/runtime/render/imgui/include/imgui/ImGuiFeature.h similarity index 82% rename from render/imgui/include/imgui/ImGuiFeature.h rename to runtime/render/imgui/include/imgui/ImGuiFeature.h index bc2e50cc..f1e458bf 100644 --- a/render/imgui/include/imgui/ImGuiFeature.h +++ b/runtime/render/imgui/include/imgui/ImGuiFeature.h @@ -8,15 +8,22 @@ #include #include #include +#include +#include namespace sky { + class ImGuiInstance; class ImGuiFeature : public Singleton { public: ImGuiFeature() = default; ~ImGuiFeature() override = default; - void Init(const RDGfxTechPtr &tech); + void Init(); + void Tick(float delta); + + void SetTechnique(const RDGfxTechPtr &tech); + RDResourceGroupPtr RequestResourceGroup(); const TechniqueInstance &GetDefaultTech() const { return instance; } diff --git a/render/imgui/include/imgui/ImGuiFeatureProcessor.h b/runtime/render/imgui/include/imgui/ImGuiFeatureProcessor.h similarity index 67% rename from render/imgui/include/imgui/ImGuiFeatureProcessor.h rename to runtime/render/imgui/include/imgui/ImGuiFeatureProcessor.h index e73acbd8..01f3d505 100644 --- a/render/imgui/include/imgui/ImGuiFeatureProcessor.h +++ b/runtime/render/imgui/include/imgui/ImGuiFeatureProcessor.h @@ -1,5 +1,5 @@ // -// Created by blues on 2023/9/20. +// Created by blues on 2024/7/31. // #pragma once @@ -17,11 +17,11 @@ namespace sky { void Tick(float time) override; void Render(rdg::RenderGraph &rdg) override; - ImGuiInstance *CreateGUIInstance(); - void RemoveGUIInstance(ImGuiInstance *mesh); + ImGuiInstance *CreateImGuiInstance(); + void RemoveImGuiInstance(ImGuiInstance *mesh); private: - std::list> guis; + std::list> guiInstances; }; -} // namespace sky +} // namespace sky \ No newline at end of file diff --git a/runtime/render/imgui/include/imgui/ImGuiInstance.h b/runtime/render/imgui/include/imgui/ImGuiInstance.h new file mode 100644 index 00000000..49071a7f --- /dev/null +++ b/runtime/render/imgui/include/imgui/ImGuiInstance.h @@ -0,0 +1,71 @@ +// +// Created by blues on 2023/9/20. +// + +#pragma once + +#include +//#include + +#include +#include +#include +#include +#include + +namespace sky { + namespace rdg { + struct RenderGraph; + } // namespace rdg + class RenderScene; + + class ImGuiInstance : public IWindowEvent, public IMouseEvent, public IKeyboardEvent { + public: + ImGuiInstance(); + ~ImGuiInstance() override; + + void AddWidget(ImWidget *widget); + + void Tick(float delta); + void Render(rdg::RenderGraph &rdg); + + void MakeCurrent(); + void BindNativeWindow(const NativeWindow *window); + + RenderPrimitive *GetPrimitive() const { return primitive.get(); } + private: + void CheckVertexBuffers(uint32_t vertexCount, uint32_t indexCount); + + void OnMouseButtonDown(const MouseButtonEvent &event) override; + void OnMouseButtonUp(const MouseButtonEvent &event) override; + void OnMouseMotion(const MouseMotionEvent &event) override; + void OnMouseWheel(const MouseWheelEvent &event) override; + + void OnKeyUp(const KeyboardEvent &event) override; + void OnKeyDown(const KeyboardEvent &event) override; + void OnTextInput(WindowID winID, const char *text) override; + + void OnFocusChanged(bool focus) override; + void OnWindowResize(uint32_t width, uint32_t height) override; + + EventBinder winBinder; + EventBinder keyBinder; + EventBinder mouseBinder; + + ImContext context; + + std::unique_ptr primitive; + RDDynamicBuffer vertexBuffer; + RDDynamicBuffer indexBuffer; + RDResourceGroupPtr globalSet; + + RDTexture2DPtr fontTexture; + RDDynamicUniformBufferPtr ubo; + uint64_t vertexSize = 0; + uint64_t indexSize = 0; + + ImDrawData* drawData = nullptr; + std::list widgets; + }; + +} // namespace sky diff --git a/runtime/render/imgui/include/imgui/ImWidget.h b/runtime/render/imgui/include/imgui/ImWidget.h new file mode 100644 index 00000000..bcbdd0ee --- /dev/null +++ b/runtime/render/imgui/include/imgui/ImWidget.h @@ -0,0 +1,50 @@ +// +// Created by blues on 2024/3/29. +// + +#pragma once + +#include +#include +#include +//#include + +namespace sky { + struct ImContext { + ImGuiContext *imContext = nullptr; +// ImPlotContext *plotContext = nullptr; + + void Init(); + void Destroy(); + + void MakeCurrent() const; + }; + + using UIFunc = std::function; + + class ImWidget { + public: + explicit ImWidget(const std::string &name_) : name(name_) {} + virtual ~ImWidget() = default; + + virtual void Execute(ImContext &context) = 0; + + inline const std::string &GetName() const { return name; } + + protected: + std::string name; + }; + + class LambdaWidget : public ImWidget { + public: + template + explicit LambdaWidget(const std::string &name, Func &&f) : ImWidget(name), fn(std::forward(f)) {} + ~LambdaWidget() override = default; + + void Execute(ImContext &context) override { fn(context); } + + private: + UIFunc fn; + }; + +} // namespace sky \ No newline at end of file diff --git a/render/imgui/src/ImGuiFeature.cpp b/runtime/render/imgui/src/ImGuiFeature.cpp similarity index 70% rename from render/imgui/src/ImGuiFeature.cpp rename to runtime/render/imgui/src/ImGuiFeature.cpp index cad24fcf..8961d091 100644 --- a/render/imgui/src/ImGuiFeature.cpp +++ b/runtime/render/imgui/src/ImGuiFeature.cpp @@ -3,23 +3,26 @@ // #include +#include #include #include -#include namespace sky { static constexpr uint32_t MAX_SET_PER_POOL = 1; static std::vector SIZES = { - {rhi::DescriptorType::SAMPLED_IMAGE, MAX_SET_PER_POOL}, - {rhi::DescriptorType::SAMPLER, MAX_SET_PER_POOL} + {rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC, MAX_SET_PER_POOL}, + {rhi::DescriptorType::SAMPLED_IMAGE, MAX_SET_PER_POOL}, + {rhi::DescriptorType::SAMPLER, MAX_SET_PER_POOL} }; + void ImGuiFeature::Tick(float delta) + { + } - void ImGuiFeature::Init(const RDGfxTechPtr &tech) + void ImGuiFeature::Init() { - instance.technique = tech; - resLayout = tech->RequestProgram()->RequestLayout(BATCH_SET); + Renderer::Get()->RegisterRenderFeature(); auto *device = RHI::Get()->GetDevice(); { @@ -31,13 +34,17 @@ namespace sky { pool = device->CreateDescriptorSetPool(poolDesc); } + } - Renderer::Get()->RegisterRenderFeature(); + void ImGuiFeature::SetTechnique(const RDGfxTechPtr &tech) + { + instance.technique = tech; + resLayout = tech->RequestProgram()->RequestLayout(BATCH_SET); } RDResourceGroupPtr ImGuiFeature::RequestResourceGroup() { - auto rsg = std::make_shared(); + auto *rsg = new ResourceGroup(); rsg->Init(resLayout, *pool); return rsg; } diff --git a/runtime/render/imgui/src/ImGuiFeatureProcessor.cpp b/runtime/render/imgui/src/ImGuiFeatureProcessor.cpp new file mode 100644 index 00000000..ffd1f00f --- /dev/null +++ b/runtime/render/imgui/src/ImGuiFeatureProcessor.cpp @@ -0,0 +1,35 @@ +// +// Created by blues on 2024/7/31. +// + +#include + +namespace sky { + + void ImGuiFeatureProcessor::Tick(float time) + { + for (auto &inst : guiInstances) { + inst->Tick(time); + } + } + + void ImGuiFeatureProcessor::Render(rdg::RenderGraph &rdg) + { + for (auto &inst : guiInstances) { + inst->Render(rdg); + } + } + + ImGuiInstance *ImGuiFeatureProcessor::CreateImGuiInstance() + { + return guiInstances.emplace_back(std::make_unique()).get(); + } + + void ImGuiFeatureProcessor::RemoveImGuiInstance(ImGuiInstance *inst) + { + guiInstances.remove_if([inst](const auto &val) { + return inst == val.get(); + }); + } + +} // namespace sky \ No newline at end of file diff --git a/runtime/render/imgui/src/ImGuiInstance.cpp b/runtime/render/imgui/src/ImGuiInstance.cpp new file mode 100644 index 00000000..ac8aa869 --- /dev/null +++ b/runtime/render/imgui/src/ImGuiInstance.cpp @@ -0,0 +1,362 @@ +// +// Created by blues on 2023/9/20. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace sky { + struct UITransform { + ImVec2 scale; + ImVec2 translate; + }; + + void ImContext::Init() + { + imContext = ImGui::CreateContext(); +// plotContext = ImPlot::CreateContext(); + } + + void ImContext::Destroy() + { + ImGui::DestroyContext(imContext); + imContext = nullptr; + +// ImPlot::DestroyContext(plotContext); +// plotContext = nullptr; + } + + void ImContext::MakeCurrent() const + { + ImGui::SetCurrentContext(imContext); +// ImPlot::SetCurrentContext(plotContext); + } + + ImGuiInstance::ImGuiInstance() + { + IMGUI_CHECKVERSION(); + context.Init(); + context.MakeCurrent(); + + ImGuiIO& io = ImGui::GetIO(); + + io.KeyMap[ImGuiKey_Tab] = static_cast(ScanCode::KEY_TAB); + io.KeyMap[ImGuiKey_LeftArrow] = static_cast(ScanCode::KEY_LEFT); + io.KeyMap[ImGuiKey_RightArrow] = static_cast(ScanCode::KEY_RIGHT); + io.KeyMap[ImGuiKey_UpArrow] = static_cast(ScanCode::KEY_UP); + io.KeyMap[ImGuiKey_DownArrow] = static_cast(ScanCode::KEY_DOWN); + io.KeyMap[ImGuiKey_PageUp] = static_cast(ScanCode::KEY_PAGEUP); + io.KeyMap[ImGuiKey_PageDown] = static_cast(ScanCode::KEY_PAGEDOWN); + io.KeyMap[ImGuiKey_Home] = static_cast(ScanCode::KEY_HOME); + io.KeyMap[ImGuiKey_End] = static_cast(ScanCode::KEY_END); + io.KeyMap[ImGuiKey_Insert] = static_cast(ScanCode::KEY_INSERT); + io.KeyMap[ImGuiKey_Delete] = static_cast(ScanCode::KEY_DELETE); + io.KeyMap[ImGuiKey_Backspace] = static_cast(ScanCode::KEY_BACKSPACE); + io.KeyMap[ImGuiKey_Space] = static_cast(ScanCode::KEY_SPACE); + io.KeyMap[ImGuiKey_Enter] = static_cast(ScanCode::KEY_RETURN); + io.KeyMap[ImGuiKey_Escape] = static_cast(ScanCode::KEY_ESCAPE); + io.KeyMap[ImGuiKey_KeypadEnter] = static_cast(ScanCode::KEY_KP_ENTER); + io.KeyMap[ImGuiKey_A] = static_cast(ScanCode::KEY_A); + io.KeyMap[ImGuiKey_C] = static_cast(ScanCode::KEY_C); + io.KeyMap[ImGuiKey_V] = static_cast(ScanCode::KEY_V); + io.KeyMap[ImGuiKey_X] = static_cast(ScanCode::KEY_X); + io.KeyMap[ImGuiKey_Y] = static_cast(ScanCode::KEY_Y); + io.KeyMap[ImGuiKey_Z] = static_cast(ScanCode::KEY_Z); + + + io.SetClipboardTextFn = [](void* user_data, const char* text){ + Platform::Get()->SetClipBoardText(text); + }; + io.GetClipboardTextFn = [](void* user_data)-> const char* { + auto &io = ImGui::GetIO(); + if (io.ClipboardUserData != nullptr) { + Platform::Get()->FreeClipBoardText(static_cast(io.ClipboardUserData)); + } + auto *text = Platform::Get()->GetClipBoardText(); + io.ClipboardUserData = static_cast(text); + return text; + }; + + unsigned char *pixels; + int width; + int height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + uint32_t uploadSize = width * height * 4 * sizeof(char); + std::vector rawData(uploadSize); + memcpy(rawData.data(), pixels, uploadSize); + + auto *queue = RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER); + fontTexture = new Texture2D(); + fontTexture->Init(rhi::PixelFormat::RGBA8_UNORM, width, height, 1); + fontTexture->Upload(std::move(rawData), queue); + + ubo = new DynamicUniformBuffer(); + ubo->Init(sizeof(UITransform)); + + io.Fonts->SetTexID((ImTextureID)(intptr_t)fontTexture->GetImageView().get()); + + auto *feature = ImGuiFeature::Get(); + primitive = std::make_unique(); + primitive->geometry = new RenderGeometry(); + primitive->geometry->AddVertexAttribute(VertexAttribute{VertexSemanticFlagBit::POSITION, 0, OFFSET_OF(ImDrawVert, pos), rhi::Format::F_RG32}); + primitive->geometry->AddVertexAttribute(VertexAttribute{VertexSemanticFlagBit::UV, 0, OFFSET_OF(ImDrawVert, uv), rhi::Format::F_RG32}); + primitive->geometry->AddVertexAttribute(VertexAttribute{VertexSemanticFlagBit::COLOR, 0, OFFSET_OF(ImDrawVert, col), rhi::Format::F_RGBA8}); + + primitive->techniques.emplace_back(feature->GetDefaultTech()); + + globalSet = feature->RequestResourceGroup(); + globalSet->BindTexture("FontTexture", fontTexture->GetImageView(), 0); + globalSet->BindDynamicUBO("Constants", ubo, 0); + globalSet->Update(); + + primitive->batchSet = globalSet; + } + + ImGuiInstance::~ImGuiInstance() + { + context.Destroy(); + + primitive = nullptr; + vertexBuffer = nullptr; + indexBuffer = nullptr; + ubo = nullptr; + globalSet = nullptr; + } + + void ImGuiInstance::AddWidget(ImWidget *widget) + { + widgets.emplace_back(widget); + } + + void ImGuiInstance::Tick(float delta) + { + MakeCurrent(); + + ImGuiIO& io = ImGui::GetIO(); + io.DeltaTime = delta; + + ImGui::NewFrame(); + + for (auto &widget : widgets) { + widget->Execute(context); + } + + ImGui::EndFrame(); + + ImGui::Render(); + } + + void ImGuiInstance::Render(rdg::RenderGraph &rdg) + { + if (!fontTexture->IsReady()) { + return; + } + + MakeCurrent(); + + drawData = ImGui::GetDrawData(); + UITransform transform; + transform.scale.x = 2.0f / drawData->DisplaySize.x; + transform.scale.y = 2.0f / drawData->DisplaySize.y; + transform.translate.x = -1.0f - drawData->DisplayPos.x * transform.scale.x; + transform.translate.y = -1.0f - drawData->DisplayPos.y * transform.scale.y; + ubo->WriteT(0, transform); + ubo->Upload(); + + float fbWidth = drawData->DisplaySize.x * drawData->FramebufferScale.x; + float fbHeight = drawData->DisplaySize.y * drawData->FramebufferScale.y; + + ImVec2 clipOff = drawData->DisplayPos; + ImVec2 clipScale = drawData->FramebufferScale; + + int globalVtxOffset = 0; + int globalIdxOffset = 0; + + if (drawData->TotalIdxCount == 0 || drawData->TotalVtxCount == 0) { + return; + } + + RenderCmdList package; + CheckVertexBuffers(drawData->TotalVtxCount, drawData->TotalIdxCount); + + vertexBuffer->SwapBuffer(); + auto *vtxDst = reinterpret_cast(vertexBuffer->GetMapped()); + + indexBuffer->SwapBuffer(); + auto *idxDst = reinterpret_cast(indexBuffer->GetMapped()); + + primitive->args.clear(); + for (int n = 0; n < drawData->CmdListsCount; n++) { + const ImDrawList *cmdList = drawData->CmdLists[n]; + // upload vertex buffers + memcpy(vtxDst, cmdList->VtxBuffer.Data, cmdList->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idxDst, cmdList->IdxBuffer.Data, cmdList->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtxDst += cmdList->VtxBuffer.Size; + idxDst += cmdList->IdxBuffer.Size; + + for (int i = 0; i < cmdList->CmdBuffer.Size; i++) { + const ImDrawCmd *pCmd = &cmdList->CmdBuffer[i]; + ImVec2 clipMin((pCmd->ClipRect.x - clipOff.x) * clipScale.x, (pCmd->ClipRect.y - clipOff.y) * clipScale.y); + ImVec2 clipMax((pCmd->ClipRect.z - clipOff.x) * clipScale.x, (pCmd->ClipRect.w - clipOff.y) * clipScale.y); + + if (clipMin.x < 0.0f) { clipMin.x = 0.0f; } + if (clipMin.y < 0.0f) { clipMin.y = 0.0f; } + if (clipMax.x > fbWidth) { clipMax.x = fbWidth; } + if (clipMax.y > fbHeight) { clipMax.y = fbHeight; } + if (clipMax.x < clipMin.x || clipMax.y < clipMin.y) { continue; } + + primitive->args.emplace_back(rhi::Rect2D{ + {static_cast((clipMin.x)), static_cast((clipMin.y))}, + {static_cast((clipMax.x - clipMin.x)), static_cast((clipMax.y - clipMin.y))} + }); + primitive->args.emplace_back(rhi::CmdDrawIndexed { + pCmd->ElemCount, + 1, + pCmd->IdxOffset + globalIdxOffset, + static_cast(pCmd->VtxOffset + globalVtxOffset), + 0 + }); + } + globalVtxOffset += cmdList->VtxBuffer.Size; + globalIdxOffset += cmdList->IdxBuffer.Size; + } + } + + void ImGuiInstance::MakeCurrent() + { + context.MakeCurrent(); + } + + void ImGuiInstance::BindNativeWindow(const NativeWindow *nativeWindow) + { + winBinder.Bind(this, nativeWindow); + mouseBinder.Bind(this); + keyBinder.Bind(this); + + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(static_cast(nativeWindow->GetWidth()), static_cast(nativeWindow->GetHeight())); + io.DisplayFramebufferScale = ImVec2(1.f, 1.f); + } + + int ConvertMouseButton(MouseButtonType type) + { + // 0=left, 1=right, 2=middle + switch (type) { + case MouseButtonType::LEFT: + return 0; + case MouseButtonType::RIGHT: + return 1; + case MouseButtonType::MIDDLE: + return 2; + default: + return 0; + } + } + + void ImGuiInstance::OnMouseButtonDown(const MouseButtonEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + io.MouseDown[ConvertMouseButton(event.button)] = true; + } + + void ImGuiInstance::OnMouseButtonUp(const MouseButtonEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + io.MouseDown[ConvertMouseButton(event.button)] = false; + } + + void ImGuiInstance::OnMouseMotion(const MouseMotionEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + io.MousePos = ImVec2(static_cast(event.x), static_cast(event.y)); + } + + void ImGuiInstance::OnMouseWheel(const MouseWheelEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + if (event.x > 0) { io.MouseWheelH += 1; } + if (event.x < 0) { io.MouseWheelH -= 1; } + if (event.y > 0) { io.MouseWheel += 1; } + if (event.y < 0) { io.MouseWheel -= 1; } + } + + void ImGuiInstance::OnFocusChanged(bool focus) + { + MakeCurrent(); + ImGuiIO& io = ImGui::GetIO(); + io.AddFocusEvent(focus); + } + + void ImGuiInstance::OnWindowResize(uint32_t width, uint32_t height) + { + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize = ImVec2(static_cast(width), static_cast(height)); + io.DisplayFramebufferScale = ImVec2(1.f, 1.f); + } + + void ImGuiInstance::OnKeyUp(const KeyboardEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[static_cast(event.scanCode)] = false; + io.KeyShift = static_cast(event.mod & KeyMod::SHIFT); + io.KeyCtrl = static_cast(event.mod & KeyMod::CTRL); + io.KeyAlt = static_cast(event.mod & KeyMod::ALT); + } + + void ImGuiInstance::OnKeyDown(const KeyboardEvent &event) + { + ImGuiIO& io = ImGui::GetIO(); + io.KeysDown[static_cast(event.scanCode)] = true; + io.KeyShift = static_cast(event.mod & KeyMod::SHIFT); + io.KeyCtrl = static_cast(event.mod & KeyMod::CTRL); + io.KeyAlt = static_cast(event.mod & KeyMod::ALT); + } + + void ImGuiInstance::OnTextInput(WindowID winID, const char *text) + { + ImGuiIO& io = ImGui::GetIO(); + io.AddInputCharactersUTF8(text); + } + + void ImGuiInstance::CheckVertexBuffers(uint32_t vertexCount, uint32_t indexCount) + { + bool rebuildGeometry = false; + auto vs = vertexCount * sizeof(ImDrawVert); + auto is = indexCount * sizeof(ImDrawIdx); + + if (vs > vertexSize) { + vertexSize = std::max(vertexSize * 2, static_cast(vs)); + vertexBuffer = new DynamicBuffer(); + vertexBuffer->Init(vertexSize, rhi::BufferUsageFlagBit::VERTEX); + rebuildGeometry = true; + } + + if (is > indexSize) { + indexSize = std::max(indexSize * 2, static_cast(is)); + indexBuffer = new DynamicBuffer(); + indexBuffer->Init(indexSize, rhi::BufferUsageFlagBit::INDEX); + rebuildGeometry = true; + } + + if (rebuildGeometry) { + primitive->geometry->Reset(); + primitive->geometry->vertexBuffers.emplace_back( + VertexBuffer{vertexBuffer, 0, vertexBuffer->GetSize(), static_cast(sizeof(ImDrawVert))} + ); + primitive->geometry->indexBuffer = + IndexBuffer{indexBuffer, 0, indexBuffer->GetSize(), sizeof(ImDrawIdx) == 2 ? rhi::IndexType::U16 : rhi::IndexType::U32}; // NOLINT + primitive->geometry->dynamicVB = true; + primitive->geometry->version++; + } + + primitive->isReady = true; + } +} // namespace sky diff --git a/render/shader/CMakeLists.txt b/runtime/render/shader/CMakeLists.txt similarity index 97% rename from render/shader/CMakeLists.txt rename to runtime/render/shader/CMakeLists.txt index ac9a21a8..4b19f992 100644 --- a/render/shader/CMakeLists.txt +++ b/runtime/render/shader/CMakeLists.txt @@ -38,4 +38,4 @@ sky_add_library(TARGET ShaderCompiler SHARED ShaderCompiler.Static ) -sky_add_dependency(TARGET ShaderCompiler DEPENDENCIES Launcher AssetBrowser Editor) +sky_add_dependency(TARGET ShaderCompiler DEPENDENCIES Launcher AssetBuilder Editor) diff --git a/render/shader/ShaderModule.cpp b/runtime/render/shader/ShaderModule.cpp similarity index 100% rename from render/shader/ShaderModule.cpp rename to runtime/render/shader/ShaderModule.cpp diff --git a/render/shader/include/shader/ShaderCompiler.h b/runtime/render/shader/include/shader/ShaderCompiler.h similarity index 77% rename from render/shader/include/shader/ShaderCompiler.h rename to runtime/render/shader/include/shader/ShaderCompiler.h index ab18387c..ae8704a9 100644 --- a/render/shader/include/shader/ShaderCompiler.h +++ b/runtime/render/shader/include/shader/ShaderCompiler.h @@ -12,12 +12,14 @@ #include #include #include +#include +#include #include namespace sky { struct ShaderIncludeContext { - std::vector &searchPaths; + std::vector &searchPaths; std::set visited; }; @@ -44,9 +46,17 @@ namespace sky { std::vector variables; }; + struct VertexStageAttribute { + std::string semantic; + uint32_t location; + uint32_t vecSize; + rhi::BaseType type; + }; + struct ShaderReflection { std::vector resources; std::vector types; + std::vector attributes; }; struct ShaderBuildResult { @@ -60,27 +70,26 @@ namespace sky { MSL }; - struct ShaderDef { bool enable; }; - using MacroValue = std::variant; + using MacroValue = std::variant; - class ShaderPreprocessor { + class ShaderOption : public RefObject { public: - ShaderPreprocessor() = default; - ~ShaderPreprocessor() = default; + ShaderOption() = default; + ~ShaderOption() override = default; void SetValue(const std::string &key, const MacroValue &val); void CalculateHash(); uint32_t GetHash() const { return hash; } - private: std::map values; + private: uint32_t hash = 0; }; - using ShaderPreprocessorPtr = std::shared_ptr; + using ShaderOptionPtr = CounterPtr; struct ShaderCompileOption { ShaderCompileTarget target; - ShaderPreprocessorPtr preprocessor; + ShaderOptionPtr option; }; struct ShaderSourceDesc { @@ -102,14 +111,14 @@ namespace sky { ShaderCompiler(); ~ShaderCompiler() override; - void AddSearchPath(const std::string &path) { searchPaths.emplace_back(path); } + void AddSearchPath(const FilePath &path) { searchPaths.emplace_back(path); } std::string LoadShader(const std::string &path); private: std::pair ProcessShaderSource(const std::string &path); std::pair ProcessHeaderFile(const std::string &path, ShaderIncludeContext &context, uint32_t depth); - std::vector searchPaths; + std::vector searchPaths; }; using ShaderCompileFunc = bool (*)(const ShaderSourceDesc &desc, const ShaderCompileOption &op, ShaderBuildResult &result); diff --git a/render/shader/include/shader/ShaderCompilerDXC.h b/runtime/render/shader/include/shader/ShaderCompilerDXC.h similarity index 100% rename from render/shader/include/shader/ShaderCompilerDXC.h rename to runtime/render/shader/include/shader/ShaderCompilerDXC.h diff --git a/render/shader/include/shader/ShaderCompilerGlsl.h b/runtime/render/shader/include/shader/ShaderCompilerGlsl.h similarity index 100% rename from render/shader/include/shader/ShaderCompilerGlsl.h rename to runtime/render/shader/include/shader/ShaderCompilerGlsl.h diff --git a/render/shader/include/shader/ShaderCross.h b/runtime/render/shader/include/shader/ShaderCross.h similarity index 100% rename from render/shader/include/shader/ShaderCross.h rename to runtime/render/shader/include/shader/ShaderCross.h diff --git a/render/shader/include/shader/ShaderLanguage.h b/runtime/render/shader/include/shader/ShaderLanguage.h similarity index 100% rename from render/shader/include/shader/ShaderLanguage.h rename to runtime/render/shader/include/shader/ShaderLanguage.h diff --git a/render/shader/src/ShaderCompiler.cpp b/runtime/render/shader/src/ShaderCompiler.cpp similarity index 95% rename from render/shader/src/ShaderCompiler.cpp rename to runtime/render/shader/src/ShaderCompiler.cpp index 097554fe..d5a8bd06 100644 --- a/render/shader/src/ShaderCompiler.cpp +++ b/runtime/render/shader/src/ShaderCompiler.cpp @@ -18,9 +18,9 @@ static const char* TAG = "ShaderCompiler"; namespace sky { - static std::pair GetShaderSource(const std::string &path) + static std::pair GetShaderSource(const FilePath &path) { - std::fstream f(path, std::ios::binary | std::ios::in); + std::fstream f = path.OpenFStream(std::ios::binary | std::ios::in); if (!f.is_open()) { return {false, ""}; } @@ -41,10 +41,10 @@ namespace sky { return count; } - std::pair GetSourceFromFile(const std::vector &searchPaths, const std::string &path) + std::pair GetSourceFromFile(const std::vector &searchPaths, const std::string &path) { for (const auto &searchPath : searchPaths) { - std::string loadPath = searchPath + path; + auto loadPath = searchPath / path; auto [rst, source] = GetShaderSource(loadPath); if (!rst) { continue; @@ -55,6 +55,9 @@ namespace sky { return {false, ""}; } + ShaderCompiler::ShaderCompiler() = default; + ShaderCompiler::~ShaderCompiler() = default; + std::pair ShaderCompiler::ProcessHeaderFile(const std::string &source, ShaderIncludeContext &context, uint32_t depth) { using LineTokenizer = boost::tokenizer>; @@ -78,14 +81,14 @@ namespace sky { auto begin = line.find_first_of('\"'); auto end = line.find_first_of('\"', begin + 1); - auto fileName = std::string("\\") + line.substr(begin + 1, (end - begin - 1)); + auto fileName = line.substr(begin + 1, (end - begin - 1)); auto [ret1, tmpHeader] = GetSourceFromFile(context.searchPaths, fileName); if (!ret1) { return {false, {}}; } - if (context.visited.count(fileName) != 0) { + if (context.visited.contains(fileName)) { continue; } @@ -122,27 +125,19 @@ namespace sky { return ProcessShaderSource(path).second; } - ShaderCompiler::ShaderCompiler() - { - } - - ShaderCompiler::~ShaderCompiler() - { - } - - void ShaderPreprocessor::SetValue(const std::string &key, const MacroValue &val) + void ShaderOption::SetValue(const std::string &key, const MacroValue &val) { values[key] = val; CalculateHash(); } - void ShaderPreprocessor::CalculateHash() + void ShaderOption::CalculateHash() { hash = 0; for (auto &[key, val] : values) { std::visit(Overloaded{ - [&](const ShaderDef &v) { - HashCombine32(hash, static_cast(v.enable)); + [&](const bool &v) { + HashCombine32(hash, static_cast(v)); }, [&](const auto &v){ HashCombine32(hash, Crc32::Cal(v)); diff --git a/render/shader/src/ShaderCompilerDXC.cpp b/runtime/render/shader/src/ShaderCompilerDXC.cpp similarity index 97% rename from render/shader/src/ShaderCompilerDXC.cpp rename to runtime/render/shader/src/ShaderCompilerDXC.cpp index d7a651c8..d8ca5e9f 100644 --- a/render/shader/src/ShaderCompilerDXC.cpp +++ b/runtime/render/shader/src/ShaderCompilerDXC.cpp @@ -53,11 +53,11 @@ namespace sky { // stage dxcArgStrings.emplace_back(L"-T"); if (desc.stage == rhi::ShaderStageFlagBit::VS) { - dxcArgStrings.emplace_back(L"vs_6_0"); + dxcArgStrings.emplace_back(L"vs_6_1"); } else if (desc.stage == rhi::ShaderStageFlagBit::FS) { - dxcArgStrings.emplace_back(L"ps_6_0"); + dxcArgStrings.emplace_back(L"ps_6_1"); } else if (desc.stage == rhi::ShaderStageFlagBit::CS) { - dxcArgStrings.emplace_back(L"cs_6_0"); + dxcArgStrings.emplace_back(L"cs_6_1"); } std::vector dxcArgs; diff --git a/render/shader/src/ShaderCompilerGlsl.cpp b/runtime/render/shader/src/ShaderCompilerGlsl.cpp similarity index 51% rename from render/shader/src/ShaderCompilerGlsl.cpp rename to runtime/render/shader/src/ShaderCompilerGlsl.cpp index 104a2712..c1619c34 100644 --- a/render/shader/src/ShaderCompilerGlsl.cpp +++ b/runtime/render/shader/src/ShaderCompilerGlsl.cpp @@ -5,11 +5,13 @@ #include #include #include +#include #include #include #include +#include "core/template/Overloaded.h" static const char* TAG = "ShaderCompilerGlsl"; namespace sky { @@ -38,11 +40,47 @@ namespace sky { return EShLangCount; } + static rhi::BaseType GetBaseType(const glslang::TType* type) + { + switch (type->getBasicType()) { + case glslang::EbtFloat: + return rhi::BaseType::FLOAT; + case glslang::EbtInt: + return rhi::BaseType::INT; + case glslang::EbtUint: + return rhi::BaseType::UINT; + default: + break; + } + return rhi::BaseType::UNDEFINED; + } + bool ShaderCompilerGlsl::CompileBinary(const ShaderSourceDesc &desc, const ShaderCompileOption &op, ShaderBuildResult &result) { const auto *ptr = desc.source.c_str(); + std::string finalSource; + auto language = GetLanguage(desc.stage); + if (op.option) { + static const std::string_view PREFIX = "#define "; + std::string preamble; + + for (auto &val: op.option->values) { + std::visit(Overloaded{ + [&](const bool &v) { + if (v) { + preamble += (std::string(PREFIX) + val.first + "\n"); + } + }, + [&](const auto &v) { + } + }, val.second); + } + finalSource = preamble + desc.source; + ptr = finalSource.c_str(); + } + glslang::TProgram program; glslang::TShader shader(language); shader.setStrings(&ptr, 1); @@ -50,16 +88,36 @@ namespace sky { shader.setEnvInput(glslang::EShSourceHlsl, language, glslang::EShClientVulkan, 130); shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3); shader.setEntryPoint(desc.entry.c_str()); - if (!shader.parse(GetDefaultResources(), 450, false, EShMsgAST)) { - LOG_E(TAG, "shader parse failed: path: %s\n", shader.getInfoLog()); + if (!shader.parse(GetDefaultResources(), 450, false, EShMessages(EShMsgAST | EShMsgReadHlsl))) { + LOG_E(TAG, "shader parse failed: %s\n", shader.getInfoLog()); return false; } + + shader.setAutoMapLocations(true); program.addShader(&shader); if (!program.link(EShMsgDefault)) { LOG_E(TAG, "link shader failed: %s\n", program.getInfoLog()); return false; } + program.buildReflection(); + + std::vector &attributes = result.reflection.attributes; + auto num = program.getNumPipeInputs(); + for (int i = 0; i < num && desc.stage == rhi::ShaderStageFlagBit::VS; ++i) { + const auto &refl = program.getPipeInput(i); + const auto *type = refl.getType(); + if (type->isBuiltIn()) { + continue; + } + + attributes.emplace_back(VertexStageAttribute{ + refl.getType()->getQualifier().semanticName, + refl.getType()->getQualifier().layoutLocation, + static_cast(type->getVectorSize()), + GetBaseType(type) + }); + } glslang::SpvOptions spvOptions = {}; // spvOptions.stripDebugInfo = false; @@ -71,4 +129,4 @@ namespace sky { return true; } -} // namespace sky \ No newline at end of file +} // namespace sky diff --git a/render/shader/src/ShaderCross.cpp b/runtime/render/shader/src/ShaderCross.cpp similarity index 100% rename from render/shader/src/ShaderCross.cpp rename to runtime/render/shader/src/ShaderCross.cpp diff --git a/render/shader/src/ShaderLanguage.cpp b/runtime/render/shader/src/ShaderLanguage.cpp similarity index 100% rename from render/shader/src/ShaderLanguage.cpp rename to runtime/render/shader/src/ShaderLanguage.cpp diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt deleted file mode 100644 index a7071698..00000000 --- a/sample/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -#add_subdirectory(RHISampleBase) -#add_subdirectory(RDSceneProject) diff --git a/sample/RDSceneProject/.gitignore b/sample/RDSceneProject/.gitignore deleted file mode 100644 index 70023560..00000000 --- a/sample/RDSceneProject/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/data -/assets/models/* -/assets.db -/cache -/products \ No newline at end of file diff --git a/sample/RDSceneProject/assets.txt b/sample/RDSceneProject/assets.txt deleted file mode 100644 index 9255d338..00000000 --- a/sample/RDSceneProject/assets.txt +++ /dev/null @@ -1,9 +0,0 @@ -skybox\output_iem.dds -skybox\output_pmrem.dds -skybox\output_skybox.dds -models\DamagedHelmet.glb -techniques\standard_forward.tech -techniques\post_processing.tech -techniques\brdf_lut.tech -techniques\skybox.tech -vertex\vertex_library.vtxlib \ No newline at end of file diff --git a/sample/RDSceneProject/assets/materials/floor.mati b/sample/RDSceneProject/assets/materials/floor.mati deleted file mode 100644 index 01750250..00000000 --- a/sample/RDSceneProject/assets/materials/floor.mati +++ /dev/null @@ -1,7 +0,0 @@ -{ - "material": "materials/StandardPBR.mat", - "properties": { - "baseColor": [1, 1, 1, 1], - "useBaseColorMap": true - } -} diff --git a/sample/RDSceneProject/assets/materials/volume_simple.mati b/sample/RDSceneProject/assets/materials/volume_simple.mati deleted file mode 100644 index 541674f5..00000000 --- a/sample/RDSceneProject/assets/materials/volume_simple.mati +++ /dev/null @@ -1,5 +0,0 @@ -{ - "material": "materials/volume_simple.mat", - "properties": { - } -} diff --git a/sample/RDSceneProject/assets/models/DamagedHelmet.glb b/sample/RDSceneProject/assets/models/DamagedHelmet.glb deleted file mode 100644 index 2cee76d7..00000000 Binary files a/sample/RDSceneProject/assets/models/DamagedHelmet.glb and /dev/null differ diff --git a/sample/RDSceneProject/assets/skybox/output_iem.dds b/sample/RDSceneProject/assets/skybox/output_iem.dds deleted file mode 100644 index 1ee23fd6..00000000 Binary files a/sample/RDSceneProject/assets/skybox/output_iem.dds and /dev/null differ diff --git a/sample/RDSceneProject/assets/skybox/output_pmrem.dds b/sample/RDSceneProject/assets/skybox/output_pmrem.dds deleted file mode 100644 index 32207486..00000000 Binary files a/sample/RDSceneProject/assets/skybox/output_pmrem.dds and /dev/null differ diff --git a/sample/RDSceneProject/assets/skybox/output_skybox.dds b/sample/RDSceneProject/assets/skybox/output_skybox.dds deleted file mode 100644 index fc33c1eb..00000000 Binary files a/sample/RDSceneProject/assets/skybox/output_skybox.dds and /dev/null differ diff --git a/sample/RDSceneProject/config/asset.json b/sample/RDSceneProject/config/asset.json deleted file mode 100644 index aa1ee231..00000000 --- a/sample/RDSceneProject/config/asset.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "shader": "shader_config.json" -} \ No newline at end of file diff --git a/sample/RDSceneProject/config/modules_game.json b/sample/RDSceneProject/config/modules_game.json deleted file mode 100644 index 273c8ad4..00000000 --- a/sample/RDSceneProject/config/modules_game.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "modules": [ - { - "name": "SkyRender", - "dependencies": [] - }, - { - "name": "ShaderCompiler", - "dependencies": [] - }, - { - "name": "RDSceneProject", - "dependencies": [ - "SkyRender", - "ShaderCompiler" - ] - } - ], - "game": { - "width": 1366, - "height": 768 - } -} \ No newline at end of file diff --git a/sample/RDSceneProject/config/modules_tool.json b/sample/RDSceneProject/config/modules_tool.json deleted file mode 100644 index f8d8363c..00000000 --- a/sample/RDSceneProject/config/modules_tool.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "modules": [ - { - "name": "ShaderCompiler", - "dependencies": [] - }, - { - "name": "RenderBuilder", - "dependencies": [] - } - ] -} \ No newline at end of file diff --git a/sample/RDSceneProject/config/shader_config.json b/sample/RDSceneProject/config/shader_config.json deleted file mode 100644 index c66e930d..00000000 --- a/sample/RDSceneProject/config/shader_config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "win32": { - "rhi": ["vk", "d3d"] - }, - "macos": { - "rhi": ["metal"] - }, - "ios": { - "rhi": ["metal"] - }, - "android": { - "rhi": ["vk", "gl"] - } -} \ No newline at end of file diff --git a/sample/RDSceneProject/engine_assets b/sample/RDSceneProject/engine_assets deleted file mode 120000 index 134bbd32..00000000 --- a/sample/RDSceneProject/engine_assets +++ /dev/null @@ -1 +0,0 @@ -D:/Code/Engine/SkyEngine/assets \ No newline at end of file diff --git a/sample/RDSceneProject/native/CMakeLists.txt b/sample/RDSceneProject/native/CMakeLists.txt deleted file mode 100644 index 6d1dea1e..00000000 --- a/sample/RDSceneProject/native/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -file(GLOB_RECURSE SRC_FILES src/*) -file(GLOB_RECURSE INC_FILES include/*) - -set(TARGET_NAME RDSceneProject) - -configure_file(ProjectRoot.h.in ${CMAKE_BINARY_DIR}/Gen/${TARGET_NAME}/ProjectRoot.h) -include_directories(${CMAKE_BINARY_DIR}/Gen) - -sky_add_library(TARGET ${TARGET_NAME} SHARED - SOURCES - ${SRC_FILES} - ${INC_FILES} - PRIVATE_INC - src - ${CMAKE_BINARY_DIR}/Gen/${TARGET_NAME} - PUBLIC_INC - include - LINK_LIBS - Framework - ImGuiRender - SkyRenderAdaptor - ) -add_custom_target(${TARGET_NAME}_RES - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/techniques/volumes/volume_simple.tech" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/techniques/geometry.tech" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/techniques/gui.tech" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/techniques/post_processing.tech" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/techniques/brdf_lut.tech" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/materials/skybox.mat" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "${CMAKE_SOURCE_DIR}/assets/vertex/vertex_library.vtxlib" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/models/DamagedHelmet.glb" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/materials/volume_simple.mati" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/materials/floor.mati" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/skybox/output_skybox.dds" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/skybox/output_iem.dds" - COMMAND AssetTool -e ${CMAKE_SOURCE_DIR} -p .. -o "../assets/skybox/output_pmrem.dds" - VERBATIM - ) - -sky_add_dependency(TARGET ${TARGET_NAME} DEPENDENCIES Launcher AssetTool) \ No newline at end of file diff --git a/sample/RDSceneProject/native/include/RDSceneProject.h b/sample/RDSceneProject/native/include/RDSceneProject.h deleted file mode 100644 index 94136f1d..00000000 --- a/sample/RDSceneProject/native/include/RDSceneProject.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Created by Zach Lee on 2022/8/13. -// - -#pragma once - -#include "SampleScene.h" -#include "framework/interface/IModule.h" -#include "framework/interface/ISystem.h" -#include "framework/interface/Interface.h" -#include "framework/window/IWindowEvent.h" -#include - -namespace sky { - class RenderScene; - class RenderWindow; - - class RDSceneProject : public IModule, public IWindowEvent { - public: - RDSceneProject() = default; - ~RDSceneProject() override = default; - - bool Init(const StartArguments &args) override; - void Shutdown() override; - void Start() override; - - void Tick(float delta) override; - - void OnWindowResize(uint32_t width, uint32_t height) override; - void OnKeyUp(KeyButtonType) override; - private: - void NextScene(); - - RenderWindow *window = nullptr; - SampleScene *currentScene = nullptr; - uint32_t sceneIndex = 0; - std::vector> sampleScenes; - }; - -} // namespace sky \ No newline at end of file diff --git a/sample/RDSceneProject/native/include/SampleScene.h b/sample/RDSceneProject/native/include/SampleScene.h deleted file mode 100644 index c0641aa9..00000000 --- a/sample/RDSceneProject/native/include/SampleScene.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by Zach Lee on 2023/9/2. -// - -#pragma once - -#include "framework/world/World.h" -#include -#include - -namespace sky { - class RenderScene; - class RenderWindow; - class World; - - class SampleScene { - public: - SampleScene() = default; - virtual ~SampleScene() = default; - - virtual bool Start(RenderWindow *window); - virtual void Shutdown(); - virtual void Resize(uint32_t width, uint32_t height) {} - - virtual void Tick(float time); - - protected: - std::unique_ptr world; - std::unique_ptr sceneProxy; - }; - -} // namespace sky diff --git a/sample/RDSceneProject/native/src/RDSceneProject.cpp b/sample/RDSceneProject/native/src/RDSceneProject.cpp deleted file mode 100644 index 280537eb..00000000 --- a/sample/RDSceneProject/native/src/RDSceneProject.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Created by Zach Lee on 2022/8/13. -// - -#include -#include - -#include "framework/asset/AssetManager.h" -#include "framework/serialization/CoreReflection.h" -#include "framework/window/NativeWindow.h" - -#include - -#include "scenes/SampleSceneCube.h" -#include "scenes/SampleMesh.h" - -namespace sky { - - bool RDSceneProject::Init(const StartArguments &args) - { - auto *renderer = Renderer::Get(); - const auto *nativeWindow = Interface::Get()->GetApi()->GetViewport(); - window = renderer->CreateRenderWindow(nativeWindow->GetNativeHandle(), nativeWindow->GetWidth(), nativeWindow->GetHeight(), false); - - Event::Connect(nativeWindow, this); - return true; - } - - void RDSceneProject::Start() - { - sampleScenes.emplace_back(new SampleMesh()); - // sampleScenes.emplace_back(new SampleSceneCube()); - sceneIndex = static_cast(sampleScenes.size()) - 1; - NextScene(); - } - - void RDSceneProject::OnWindowResize(uint32_t width, uint32_t height) - { - if (window != nullptr) { - window->Resize(width, height); - } - if (currentScene != nullptr) { - currentScene->Resize(width, height); - } - } - - void RDSceneProject::OnKeyUp(KeyButtonType type) - { - if (type == KeyButton::KEY_RIGHT) { - NextScene(); - } - } - - void RDSceneProject::NextScene() - { - if (currentScene != nullptr) { - currentScene->Shutdown(); - } - sceneIndex = (sceneIndex + 1) % sampleScenes.size(); - - currentScene = sampleScenes[sceneIndex].get(); - currentScene->Start(window); - } - - void RDSceneProject::Shutdown() - { - if (currentScene != nullptr) { - currentScene->Shutdown(); - } - sampleScenes.clear(); - - auto *renderer = Renderer::Get(); - renderer->DestroyRenderWindow(window); - - Event::DisConnect(this); - } - - void RDSceneProject::Tick(float delta) - { - if (currentScene != nullptr) { - currentScene->Tick(delta); - } - } - -} // namespace sky - -REGISTER_MODULE(sky::RDSceneProject) diff --git a/sample/RDSceneProject/native/src/SampleScene.cpp b/sample/RDSceneProject/native/src/SampleScene.cpp deleted file mode 100644 index eb37af08..00000000 --- a/sample/RDSceneProject/native/src/SampleScene.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// -// Created by Zach Lee on 2023/9/2. -// - -#include -#include -#include - -namespace sky { - - bool SampleScene::Start(RenderWindow *window) - { - world = std::make_unique(); - - sceneProxy = std::make_unique(); - auto *renderScene = sceneProxy->GetRenderScene(); - auto *ppl = new DefaultForward(); - ppl->SetOutput(window); - renderScene->SetPipeline(ppl); - - world->SetRenderScene(sceneProxy.get()); - return true; - } - - void SampleScene::Shutdown() - { - sceneProxy = nullptr; - world = nullptr; - } - - void SampleScene::Tick(float time) - { - world->Tick(time); - } - -} // namespace sky diff --git a/sample/RDSceneProject/native/src/scenes/SampleMesh.cpp b/sample/RDSceneProject/native/src/scenes/SampleMesh.cpp deleted file mode 100644 index e08cee72..00000000 --- a/sample/RDSceneProject/native/src/scenes/SampleMesh.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// -// Created by Zach Lee on 2023/9/16. -// - -#include "SampleMesh.h" -#include "core/file/FileIO.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "SimpleRotateComponent.h" - -#include - -namespace sky { - -//#define ENABLE_IBL - - RDTextureCubePtr LoadCubeMap(const std::string &path) - { - std::vector data; - ReadBin(PROJECT_ROOT + path, data); - - rhi::Image::Descriptor imageDesc = {}; - imageDesc.arrayLayers = 6; - - std::vector requests; - rhi::ProcessDDS(data.data(), data.size(), imageDesc, requests); - - auto tex = std::make_shared(); - auto *queue = RHI::Get()->GetDevice()->GetQueue(rhi::QueueType::TRANSFER); - tex->Init(imageDesc.format, imageDesc.extent.width, imageDesc.extent.height, imageDesc.mipLevels); - auto handle = queue->UploadImage(tex->GetImage(), requests); - queue->Wait(handle); - - return tex; - } - - class ForwardMSAAPass : public RenderPipeline { - public: - ForwardMSAAPass() = default; - ~ForwardMSAAPass() override = default; - - void SetOutput(RenderWindow *wnd, RenderScene *scene) - { - output = wnd; - if (!rdgContext->device->CheckFormatFeature(depthStencilFormat, rhi::PixelFormatFeatureFlagBit::DEPTH_STENCIL)) { - depthStencilFormat = rhi::PixelFormat::D32_S8; - } - - globalUbo = std::make_shared(); - globalUbo->Init(sizeof(ShaderPassInfo)); - - { - rhi::DescriptorSetLayout::Descriptor desc = {}; -// desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::UNIFORM_BUFFER, 1, 0, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS, "passInfo"}); - desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::UNIFORM_BUFFER, 1, 1, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS, "viewInfo"}); -// desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::SAMPLER, 1, 2, rhi::ShaderStageFlagBit::FS, "irradianceMap"}); -// desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::SAMPLER, 1, 3, rhi::ShaderStageFlagBit::FS, "radianceMap"}); -// desc.bindings.emplace_back(rhi::DescriptorSetLayout::SetBinding {rhi::DescriptorType::SAMPLER, 1, 4, rhi::ShaderStageFlagBit::FS, "brdfLutMap"}); - - forwardLayout = std::make_shared(); - forwardLayout->SetRHILayout(rdgContext->device->CreateDescriptorSetLayout(desc)); -// forwardLayout->AddNameHandler("passInfo", {0, sizeof(ShaderPassInfo)}); - forwardLayout->AddNameHandler("viewInfo", {1, sizeof(SceneViewInfo)}); -// forwardLayout->AddNameHandler("irradianceMap", {2, 0}); -// forwardLayout->AddNameHandler("radianceMap", {3, 0}); -// forwardLayout->AddNameHandler("brdfLutMap", {4, 0}); - } - - auto *am = AssetManager::Get(); - postTech = am->LoadAsset("techniques/post_processing.tech")->CreateInstanceAs(); - brdfLutTech = am->LoadAsset("techniques/brdf_lut.tech")->CreateInstanceAs(); - - irradiance = am->LoadAsset("skybox/output_iem.dds")->CreateInstanceAs(); - radiance = am->LoadAsset("skybox/output_pmrem.dds")->CreateInstanceAs(); - -// auto skyboxTex = LoadCubeMap("/assets/skybox/output_skybox.dds"); -// auto skyboxMat = AssetManager::Get()->LoadAsset("materials/skybox.mat")->CreateInstance(); -// auto skyboxMatInst = std::make_shared(); -// skyboxMatInst->SetMaterial(skyboxMat); -// skyboxMatInst->SetTexture("skybox", skyboxTex, 0); -// skyboxMatInst->Upload(); - -// skybox = std::make_unique(); -// skybox->SetUp(skyboxMatInst); -// skybox->AttachScene(scene); - } - - void OnSetup(rdg::RenderGraph &rdg) override - { - const auto &swapchain = output->GetSwaChain(); - const auto &ext = swapchain->GetExtent(); - const auto width = ext.width * 2; - const auto height = ext.height * 2; - - auto &rg = rdg.resourceGraph; - - const auto &views = rdg.scene->GetSceneViews(); - if (views.empty()) { - return; - } - auto *sceneView = views[0].get(); - const auto uboName = GetDefaultSceneViewUBOName(*sceneView); - const auto *const globalUboName = "globalUBO"; - - ShaderPassInfo passInfo = {}; - passInfo.viewport.x = 0; - passInfo.viewport.y = 0; - passInfo.viewport.z = static_cast(width); - passInfo.viewport.w = static_cast(height); - globalUbo->Write(0, passInfo); - - rg.ImportUBO(uboName.c_str(), sceneView->GetUBO()); - rg.ImportUBO(globalUboName, globalUbo); - - rhi::PixelFormat hdrFormat = rhi::PixelFormat::RGBA16_SFLOAT; - const uint32_t BRDFLutSize = 512; - - rg.ImportSwapChain("SwapChain", swapchain); - rg.ImportImage("Radiance", radiance->GetImage(), radiance->GetImageView()->GetViewDesc().viewType); - rg.ImportImage("Irradiance", irradiance->GetImage(), radiance->GetImageView()->GetViewDesc().viewType); - rg.AddImage("ForwardColor", rdg::GraphImage{{width, height, 1}, 1, 1, hdrFormat, rhi::ImageUsageFlagBit::RENDER_TARGET | rhi::ImageUsageFlagBit::SAMPLED, rhi::SampleCount::X1}); - rg.AddImage("ForwardColorMSAA", rdg::GraphImage{{width, height, 1}, 1, 1, hdrFormat, rhi::ImageUsageFlagBit::RENDER_TARGET, rhi::SampleCount::X2}); - rg.AddImage("ForwardDSMSAA", rdg::GraphImage{{width, height, 1}, 1, 1, depthStencilFormat, rhi::ImageUsageFlagBit::DEPTH_STENCIL, rhi::SampleCount::X2}); -#ifdef ENABLE_IBL - rg.AddImage("BRDF_LUT", rdg::GraphImage{{BRDFLutSize, BRDFLutSize, 1}, 1, 1, rhi::PixelFormat::RGBA16_SFLOAT, rhi::ImageUsageFlagBit::RENDER_TARGET | rhi::ImageUsageFlagBit::SAMPLED}); - - auto lut = rdg.AddRasterPass("BRDF_LUT_PASS", 512, 512) - .AddAttachment({"BRDF_LUT", rhi::LoadOp::DONT_CARE, rhi::StoreOp::STORE}, {}); - auto lutSub = lut.AddRasterSubPass("brdf_lut_sub0"); - lutSub.AddColor("BRDF_LUT", rdg::ResourceAccessBit::WRITE); - lutSub.AddFullScreen("brdf_lut") - .SetTechnique(brdfLutTech); -#endif - - auto forwardPass = rdg.AddRasterPass("forwardColor", width, height) - .AddAttachment({"ForwardColor", rhi::LoadOp::CLEAR, rhi::StoreOp::STORE}, rhi::ClearValue(0.2f, 0.2f, 0.2f, 1.f)) - .AddAttachment({"ForwardColorMSAA", rhi::LoadOp::CLEAR, rhi::StoreOp::STORE}, rhi::ClearValue(0.2f, 0.2f, 0.2f, 1.f)) - .AddAttachment({"ForwardDSMSAA", rhi::LoadOp::CLEAR, rhi::StoreOp::STORE}, rhi::ClearValue(1.f, 0)); - - auto subpass = forwardPass.AddRasterSubPass("color0_sub0"); - subpass.AddColor("ForwardColorMSAA", rdg::ResourceAccessBit::WRITE) - .AddDepthStencil("ForwardDSMSAA", rdg::ResourceAccessBit::WRITE) - .AddResolve("ForwardColor", rdg::ResourceAccessBit::WRITE) - .AddComputeView("Irradiance", {"irradianceMap", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS}) - .AddComputeView("Radiance", {"radianceMap", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS}) -#ifdef ENABLE_IBL - .AddComputeView("BRDF_LUT", {"brdfLutMap", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS}) -#endif - .AddComputeView(uboName, {"viewInfo", rdg::ComputeType::CBV, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS}) - .AddComputeView(globalUboName, {"passInfo", rdg::ComputeType::CBV, rhi::ShaderStageFlagBit::VS | rhi::ShaderStageFlagBit::FS}); - - subpass.AddQueue("queue1") - .SetRasterID("ForwardColor") - .SetView(sceneView) - .SetLayout(forwardLayout); - - subpass.AddQueue("queue2") - .SetRasterID("SkyBox") - .SetView(sceneView) - .SetLayout(forwardLayout); - - subpass.AddQueue("queue3") - .SetRasterID("ui"); - - auto pp = rdg.AddRasterPass("PostProcessing", ext.width, ext.height) - .AddAttachment({"SwapChain", rhi::LoadOp::DONT_CARE, rhi::StoreOp::STORE}, {}); - auto ppSub = pp.AddRasterSubPass("pp_sub0"); - ppSub.AddColor("SwapChain", rdg::ResourceAccessBit::WRITE) - .AddComputeView("ForwardColor", {"InColor", rdg::ComputeType::SRV, rhi::ShaderStageFlagBit::FS}); - ppSub.AddFullScreen("fullscreen") - .SetTechnique(postTech); - - rdg.AddPresentPass("present", "SwapChain"); - } - - private: - RenderWindow *output = nullptr; - rhi::PixelFormat depthStencilFormat = rhi::PixelFormat::D24_S8; - RDResourceLayoutPtr forwardLayout; - RDGfxTechPtr postTech; - RDGfxTechPtr brdfLutTech; - RDTextureCubePtr radiance; - RDTextureCubePtr irradiance; - - RDUniformBufferPtr globalUbo; - std::unique_ptr skybox; - }; - - bool SampleMesh::Start(sky::RenderWindow *window) - { - if (!SampleScene::Start(window)) { - return false; - } - - meshObj = world->CreateGameObject("Helmet"); - meshObj->GetComponent()->SetLocalRotation( - Quaternion(-30 / 180.f * 3.14f, VEC3_Y) * - Quaternion(90 / 180.f * 3.14f, VEC3_X)); - meshObj->AddComponent(); - - auto *mesh = meshObj->AddComponent(); - mesh->SetMesh(AssetManager::Get()->LoadAsset("models/DamagedHelmet.glb_node_damagedHelmet_-6514_mesh")); - -// auto mat = AssetManager::Get()->LoadAsset("materials/floor.mati")->CreateInstance(); -// auto floor = GridRenderer().SetUp({512}).BuildMesh(mat); -// mesh->SetMesh(floor); - - camera = world->CreateGameObject("MainCamera"); - auto *cc = camera->AddComponent(); - cc->Perspective(0.01f, 100.f, 45.f / 180.f * 3.14f); - cc->SetAspect(window->GetWidth(), window->GetHeight()); - camera->GetComponent()->SetWorldTranslation(Vector3(0, 0.5, 5)); - - auto *scene = GetRenderSceneFromGameObject(meshObj); - auto *pipeline = new ForwardMSAAPass(); - pipeline->SetOutput(window, GetRenderSceneFromGameObject(meshObj)); - - scene->SetPipeline(pipeline); - return true; - } - - void SampleMesh::Shutdown() - { - SampleScene::Shutdown(); - } - - void SampleMesh::Resize(uint32_t width, uint32_t height) - { - camera->GetComponent()->SetAspect(width, height); - } -} // namespace sky \ No newline at end of file diff --git a/sample/RDSceneProject/native/src/scenes/SampleMesh.h b/sample/RDSceneProject/native/src/scenes/SampleMesh.h deleted file mode 100644 index 78129788..00000000 --- a/sample/RDSceneProject/native/src/scenes/SampleMesh.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zach Lee on 2023/9/16. -// - -#pragma once - -#include "framework/world/GameObject.h" -#include "framework/world/World.h" -#include -#include - -namespace sky { - - class SampleMesh : public SampleScene { - public: - SampleMesh() = default; - ~SampleMesh() override = default; - - bool Start(RenderWindow *window) override; - void Shutdown() override; - void Resize(uint32_t width, uint32_t height) override; - - private: - GameObject *meshObj = nullptr; - GameObject *camera = nullptr; - }; - -} // namespace sky \ No newline at end of file diff --git a/sample/RDSceneProject/native/src/scenes/SampleSceneCube.cpp b/sample/RDSceneProject/native/src/scenes/SampleSceneCube.cpp deleted file mode 100644 index 00d847c8..00000000 --- a/sample/RDSceneProject/native/src/scenes/SampleSceneCube.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Created by Zach Lee on 2023/9/2. -// - -#include "SampleSceneCube.h" -#include -#include -#include -#include -#include - -#include "SimpleRotateComponent.h" - -namespace sky { - - class SimpleGeometryComponent : public Component { - public: - SimpleGeometryComponent() = default; - ~SimpleGeometryComponent() override = default; - - TYPE_RTTI_WITH_VT(SimpleGeometryComponent); - - void OnActive() override - { - geometry = std::make_unique(); - geometry->Init(); - geometry->DrawAABB(AABB{{-1.f, -1.f, -1.f}, {1.f, 1.f, 1.f}}); - geometry->Upload(); - - auto *scene = GetRenderSceneFromGameObject(object); - scene->AddPrimitive(geometry->GetPrimitive()); - } - - void OnTick(float time) override - { - auto *ts = object->GetComponent(); - geometry->UpdateTransform(ts->GetWorld().ToMatrix()); - } - - protected: - std::unique_ptr geometry; - }; - - bool SampleSceneCube::Start(sky::RenderWindow *window) - { - if (!SampleScene::Start(window)) { - return false; - } - - cube = world->CreateGameObject("Cube"); - cube->AddComponent(); - auto *sr = cube->AddComponent(); - sr->SetAxis(VEC3_ONE); - - camera = world->CreateGameObject("MainCamera"); - auto *cc = camera->AddComponent(); - cc->Perspective(0.01f, 100.f, 45.f / 180.f * 3.14f); - cc->SetAspect(window->GetWidth(), window->GetHeight()); - camera->GetComponent()->SetWorldTranslation(Vector3(0, 0, 5)); - return true; - } - - void SampleSceneCube::Shutdown() - { - SampleScene::Shutdown(); - } - - void SampleSceneCube::Resize(uint32_t width, uint32_t height) - { - camera->GetComponent()->SetAspect(width, height); - } -} // namespace sky diff --git a/sample/RDSceneProject/native/src/scenes/SampleSceneCube.h b/sample/RDSceneProject/native/src/scenes/SampleSceneCube.h deleted file mode 100644 index 556d52d3..00000000 --- a/sample/RDSceneProject/native/src/scenes/SampleSceneCube.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Zach Lee on 2023/9/2. -// - -#pragma once - -#include "framework/world/GameObject.h" -#include "framework/world/World.h" -#include -#include - -namespace sky { - - class SampleSceneCube : public SampleScene { - public: - SampleSceneCube() = default; - ~SampleSceneCube() override = default; - - bool Start(RenderWindow *window) override; - void Shutdown() override; - void Resize(uint32_t width, uint32_t height) override; - - private: - GameObject *cube = nullptr; - GameObject *camera = nullptr; - }; - -} // namespace sky diff --git a/sample/RDSceneProject/native/src/scenes/SimpleRotateComponent.h b/sample/RDSceneProject/native/src/scenes/SimpleRotateComponent.h deleted file mode 100644 index b6cab70c..00000000 --- a/sample/RDSceneProject/native/src/scenes/SimpleRotateComponent.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Created by Zach Lee on 2023/9/16. -// - -#pragma once - -#include "framework/world/TransformComponent.h" - -namespace sky { - - class SimpleRotateComponent : public Component { - public: - SimpleRotateComponent() = default; - ~SimpleRotateComponent() override = default; - - TYPE_RTTI_WITH_VT(SimpleRotateComponent) - - void OnTick(float time) override - { - auto *ts = object->GetComponent(); - ts->SetLocalRotation(Quaternion(angle, axis) * Quaternion(90 / 180.f * 3.14f, VEC3_X)); - angle += 0.5f * time; - } - - void SetAxis(const Vector3 &axis_) - { - axis = axis_; - } - - private: - float angle = 0.f; - Vector3 axis = {0, 1, 0}; - }; - -} // namespace sky \ No newline at end of file diff --git a/sample/RHISampleBase/CMakeLists.txt b/sample/RHISampleBase/CMakeLists.txt deleted file mode 100644 index 144af50d..00000000 --- a/sample/RHISampleBase/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -file(GLOB_RECURSE SRC_FILES src/*) -file(GLOB_RECURSE INC_FILES include/*) - -configure_file(ProjectRoot.h.in ${CMAKE_BINARY_DIR}/Gen/RHISample/ProjectRoot.h) -include_directories(${CMAKE_BINARY_DIR}/Gen) - -sky_add_library(TARGET RHISample SHARED - SOURCES - ${SRC_FILES} - ${INC_FILES} - PRIVATE_INC - src - PUBLIC_INC - include - LINK_LIBS - RHI - Framework - ShaderCompiler.Static - ) -sky_add_dependency(TARGET RHISample DEPENDENCIES Launcher) \ No newline at end of file diff --git a/sample/RHISampleBase/ProjectRoot.h.in b/sample/RHISampleBase/ProjectRoot.h.in deleted file mode 100644 index b9becc84..00000000 --- a/sample/RHISampleBase/ProjectRoot.h.in +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by Zach Lee on 2023/2/18. -// - -#pragma once - -#include - -namespace sky { - static std::string PROJECT_ROOT = "@CMAKE_CURRENT_SOURCE_DIR@"; -} // namespace sky \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/base_color_fs.glsl b/sample/RHISampleBase/assets/shaders/base_color_fs.glsl deleted file mode 100644 index 64457d06..00000000 --- a/sample/RHISampleBase/assets/shaders/base_color_fs.glsl +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 core - -layout(location = 0) in vec3 inPos; -layout(location = 1) in vec3 inNormal; - -layout(location = 0) out vec4 outColor; - -layout(set = 0, binding = 0) uniform CameraData { - mat4 viewProject; - vec4 position; -} cam; - -layout(set = 1, binding = 0) uniform Constant { - vec4 baseColor; -}; - -void main() -{ - vec3 L = normalize(vec3(5, 5, 5) - inPos); - vec3 V = normalize(cam.position.xyz - inPos); - vec3 N = normalize(inNormal); - - vec3 color = baseColor.xyz * dot(N, L); - outColor = vec4(vec3(dot(N, L)), baseColor.w); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/descriptor_fs.glsl b/sample/RHISampleBase/assets/shaders/descriptor_fs.glsl deleted file mode 100644 index 0dbef633..00000000 --- a/sample/RHISampleBase/assets/shaders/descriptor_fs.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 core - -layout(location = 0) in vec2 vUv; -layout(location = 0) out vec4 outColor; - -layout(set = 0, binding = 0) uniform sampler2D tex[2]; -layout(set = 1, binding = 0) buffer Storage1 { - vec4 data[]; -} storage1[2]; -layout(set = 1, binding = 1) uniform Matrix { - mat4 val; -} matrix[2]; -layout(set = 2, binding = 0) buffer Storage2 { - vec4 data[]; -} storage2[2]; - -void main() -{ - outColor = texture(tex[0], vUv) * texture(tex[1], vUv); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/full_screen_fs.glsl b/sample/RHISampleBase/assets/shaders/full_screen_fs.glsl deleted file mode 100644 index 438a20a7..00000000 --- a/sample/RHISampleBase/assets/shaders/full_screen_fs.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 - -layout(set = 0, binding = 0) uniform sampler2D colorImage; - -layout(location = 0) in vec2 uv; -layout(location = 0) out vec4 outColor; - -void main() -{ - outColor = texture(colorImage, uv); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/full_screen_fs_2.glsl b/sample/RHISampleBase/assets/shaders/full_screen_fs_2.glsl deleted file mode 100644 index 96b286b7..00000000 --- a/sample/RHISampleBase/assets/shaders/full_screen_fs_2.glsl +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout(set = 0, binding = 0) uniform sampler2D colorImage1; -layout(set = 0, binding = 1) uniform sampler2D colorImage2; - -layout(location = 0) in vec2 uv; -layout(location = 0) out vec4 outColor; - -void main() -{ - outColor = texture(colorImage1, uv) + texture(colorImage2, vec2(uv.x, 1 - uv.y)); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/full_screen_fs_tiled.glsl b/sample/RHISampleBase/assets/shaders/full_screen_fs_tiled.glsl deleted file mode 100644 index 839aa4f8..00000000 --- a/sample/RHISampleBase/assets/shaders/full_screen_fs_tiled.glsl +++ /dev/null @@ -1,12 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput colorImage; - -layout(location = 0) in vec2 uv; -layout(location = 0) out vec4 outColor; -layout(location = 1) out vec4 dummy1; - -void main() -{ - outColor = subpassLoad(colorImage); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/full_screen_vs.glsl b/sample/RHISampleBase/assets/shaders/full_screen_vs.glsl deleted file mode 100644 index 16263792..00000000 --- a/sample/RHISampleBase/assets/shaders/full_screen_vs.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) out vec2 outUv; - -vec2 positions[3] = vec2[]( - vec2(-1.0, 3.0), - vec2(-1.0, -1.0), - vec2( 3.0, -1.0) -); - -vec2 uv[3] = vec2[]( - vec2(0.0, 2.0), - vec2(0.0, 0.0), - vec2(2.0, 0.0) -); - -void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - outUv = uv[gl_VertexIndex]; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/pos_normal_vs.glsl b/sample/RHISampleBase/assets/shaders/pos_normal_vs.glsl deleted file mode 100644 index 0e018945..00000000 --- a/sample/RHISampleBase/assets/shaders/pos_normal_vs.glsl +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout(location = 0) in vec4 inPos; -layout(location = 1) in vec4 inNormal; - -layout(location = 0) out vec3 outPos; -layout(location = 1) out vec3 outNormal; - -layout(set = 0, binding = 0) uniform CameraData { - mat4 viewProject; - vec4 position; -} cam; - -layout(set = 2, binding = 0) uniform LocalData { - mat4 world; -} local; - -void main() { - vec4 pos = cam.viewProject * local.world * vec4(inPos.xyz, 1.0); - outNormal = mat3(local.world) * normalize(inNormal).xyz; - outPos = pos.xyz / pos.w; - gl_Position = pos; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/subpass/sub01_fs.glsl b/sample/RHISampleBase/assets/shaders/subpass/sub01_fs.glsl deleted file mode 100644 index 32b0f236..00000000 --- a/sample/RHISampleBase/assets/shaders/subpass/sub01_fs.glsl +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 uv; - -layout(location = 0) out vec4 color0; -layout(location = 1) out vec4 color1; -layout(location = 2) out vec4 color2; -layout(location = 3) out vec4 color3; - -void main() -{ - color0 = vec4(uv.x, 0, 0, 0.5); - color1 = vec4(0, uv.y, 0, 0.5); - color2 = vec4(1 - uv.x, 0, 0, 0.5); - color3 = vec4(0, 1 - uv.y, 0, 0.5); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/subpass/sub01_vs.glsl b/sample/RHISampleBase/assets/shaders/subpass/sub01_vs.glsl deleted file mode 100644 index 8e96108c..00000000 --- a/sample/RHISampleBase/assets/shaders/subpass/sub01_vs.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) out vec2 outUv; - -vec3 positions[3] = vec3[]( -vec3(-1.0, 3.0, 1), -vec3(-1.0, -1.0, 0), -vec3( 3.0, -1.0, 1) -); - -vec2 uv[3] = vec2[]( -vec2(0.0, 2.0), -vec2(0.0, 0.0), -vec2(2.0, 0.0) -); - -void main() { - gl_Position = vec4(positions[gl_VertexIndex], 1.0); - outUv = uv[gl_VertexIndex]; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/subpass/sub02_fs.glsl b/sample/RHISampleBase/assets/shaders/subpass/sub02_fs.glsl deleted file mode 100644 index b044b062..00000000 --- a/sample/RHISampleBase/assets/shaders/subpass/sub02_fs.glsl +++ /dev/null @@ -1,18 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inColor0; -layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput inColor1; - -layout (location = 0) out vec4 outColor; -layout (location = 1) out vec4 dummy1; -layout (location = 2) out vec4 dummy2; - -void main() -{ - vec4 v0 = subpassLoad(inColor0); - vec4 v1 = subpassLoad(inColor1); - - vec3 color1 = v0.rgb * v0.a; - vec3 color2 = v1.rgb * v1.a; - outColor = vec4(color1 + color2, v0.a + v1.a); -} diff --git a/sample/RHISampleBase/assets/shaders/subpass/sub03_fs.glsl b/sample/RHISampleBase/assets/shaders/subpass/sub03_fs.glsl deleted file mode 100644 index 731f738e..00000000 --- a/sample/RHISampleBase/assets/shaders/subpass/sub03_fs.glsl +++ /dev/null @@ -1,25 +0,0 @@ -#version 450 - -layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inColor0; -layout (input_attachment_index = 1, set = 0, binding = 1) uniform subpassInput inColor1; -layout (input_attachment_index = 2, set = 0, binding = 2) uniform subpassInput inColor2; -layout (input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput inDepth; -layout (input_attachment_index = 4, set = 0, binding = 4) uniform usubpassInput inStencil; - -layout (location = 0) out vec4 outColor; -layout (location = 1) out vec4 dummy1; -layout (location = 2) out vec4 dummy2; - -void main() -{ - vec4 v0 = subpassLoad(inColor0); - vec4 v1 = subpassLoad(inColor1); - vec4 v2 = subpassLoad(inColor2); - vec3 color1 = v0.rgb * v0.a; - vec3 color2 = v1.rgb * v1.a; - - float depth = subpassLoad(inDepth).x * 1.0; - float stencil = subpassLoad(inStencil).x / 256.0; - - outColor = v2 + vec4(color1 + color2, v0.a + v1.a); -} diff --git a/sample/RHISampleBase/assets/shaders/triangle_fs.glsl b/sample/RHISampleBase/assets/shaders/triangle_fs.glsl deleted file mode 100644 index f972a581..00000000 --- a/sample/RHISampleBase/assets/shaders/triangle_fs.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 core - -layout(location = 0) in vec4 inColor; -layout(location = 0) out vec4 outColor; - -void main() -{ - outColor = inColor; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/triangle_instanced_vs.glsl b/sample/RHISampleBase/assets/shaders/triangle_instanced_vs.glsl deleted file mode 100644 index 1bdd3dcf..00000000 --- a/sample/RHISampleBase/assets/shaders/triangle_instanced_vs.glsl +++ /dev/null @@ -1,23 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 offset; -layout(location = 1) in vec2 scale; - -layout(location = 0) out vec4 outColor; - -vec2 positions[3] = vec2[]( -vec2(-0.5, -0.5), -vec2( 0.5, -0.5), -vec2( 0.0, 0.5) -); - -vec4 color[3] = vec4[]( -vec4(1.0, 0.0, 0.0, 1.0), -vec4(0.0, 1.0, 0.0, 1.0), -vec4(0.0, 0.0, 1.0, 1.0) -); - -void main() { - gl_Position = vec4(positions[gl_VertexIndex] * scale + offset, 0.0, 1.0); - outColor = color[gl_VertexIndex]; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/triangle_msaa_fs.glsl b/sample/RHISampleBase/assets/shaders/triangle_msaa_fs.glsl deleted file mode 100644 index 8c42b030..00000000 --- a/sample/RHISampleBase/assets/shaders/triangle_msaa_fs.glsl +++ /dev/null @@ -1,11 +0,0 @@ -#version 450 core - -layout(location = 0) in vec4 inColor; -layout(location = 0) out vec4 outColor1; -layout(location = 1) out vec4 outColor2; - -void main() -{ - outColor1 = inColor; - outColor2 = vec4(vec3(1.0) - inColor.xyz, inColor.w); -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/triangle_msaa_vs.glsl b/sample/RHISampleBase/assets/shaders/triangle_msaa_vs.glsl deleted file mode 100644 index 6f9c7405..00000000 --- a/sample/RHISampleBase/assets/shaders/triangle_msaa_vs.glsl +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout(location = 0) out vec4 outColor; - -vec2 positions[3] = vec2[]( -vec2(-0.5, -1.0), -vec2( 0.5, -1.0), -vec2( 0.0, 1.0) -); - -vec4 color[3] = vec4[]( -vec4(1.0, 0.0, 0.0, 1.0), -vec4(0.0, 1.0, 0.0, 1.0), -vec4(0.0, 0.0, 1.0, 1.0) -); - -void main() { - vec2 pos = positions[gl_VertexIndex]; - gl_Position = vec4(pos, (pos.y + 1.0) / 2.0, 1.0); - outColor = color[gl_VertexIndex]; -} \ No newline at end of file diff --git a/sample/RHISampleBase/assets/shaders/triangle_vs.glsl b/sample/RHISampleBase/assets/shaders/triangle_vs.glsl deleted file mode 100644 index c77d40f7..00000000 --- a/sample/RHISampleBase/assets/shaders/triangle_vs.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#version 450 - -layout(location = 0) out vec4 outColor; - -vec2 positions[3] = vec2[]( -vec2(-0.5, -0.5), -vec2( 0.5, -0.5), -vec2( 0.0, 0.5) -); - -vec4 color[3] = vec4[]( -vec4(1.0, 0.0, 0.0, 1.0), -vec4(0.0, 1.0, 0.0, 1.0), -vec4(0.0, 0.0, 1.0, 1.0) -); - -void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - outColor = color[gl_VertexIndex]; -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/IRHI.h b/sample/RHISampleBase/include/IRHI.h deleted file mode 100644 index cb078d33..00000000 --- a/sample/RHISampleBase/include/IRHI.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include - -namespace sky::rhi { - class Device; - - struct IRHI { - virtual rhi::Device * GetDevice() const = 0; - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/RHIDrawIndirectSample.h b/sample/RHISampleBase/include/RHIDrawIndirectSample.h deleted file mode 100644 index bf9b7caa..00000000 --- a/sample/RHISampleBase/include/RHIDrawIndirectSample.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by Zach Lee on 2023/5/30. -// - -#pragma once - - -#include - -namespace sky::rhi { - - class RHIDrawIndirectSample : public RHISampleBase { - public: - RHIDrawIndirectSample() = default; - ~RHIDrawIndirectSample() = default; - - void SetupBase() override; - void OnTick(float delta) override; - void OnStop() override; - private: - void SetFeature() override; - - rhi::VertexInputPtr vi; - rhi::VertexAssemblyPtr va; - rhi::BufferViewPtr instanceBuffer; - rhi::BufferPtr indirectBuffer; - }; - -} // namespace sky::rhi \ No newline at end of file diff --git a/sample/RHISampleBase/include/RHIPassSample.h b/sample/RHISampleBase/include/RHIPassSample.h deleted file mode 100644 index 604a8dc3..00000000 --- a/sample/RHISampleBase/include/RHIPassSample.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include -#include - -namespace sky::rhi { - - class RHIPassSample : public RHISampleBase { - public: - RHIPassSample() = default; - ~RHIPassSample() override = default; - - void SetupBase() override; - void OnTick(float delta) override; - void OnStop() override; - private: - void SetupMaterial(); - void SetupMesh(); - void SetupCamera(); - void SetupLayout(); - void SetupScene(); - - void OnWindowResize(uint32_t width, uint32_t height) override; - - MaterialPtr material; - CameraPtr camera; - MeshPtr mesh; - std::shared_ptr scene; - - GFXTechniquePtr gfxTech; - DescriptorSetLayoutPtr globalLayout; - DescriptorSetLayoutPtr localLayout; - BufferPtr cameraBuffer; - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/RHISample.h b/sample/RHISampleBase/include/RHISample.h deleted file mode 100644 index 5462d894..00000000 --- a/sample/RHISampleBase/include/RHISample.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#pragma once - -#include "RHISampleBase.h" -#include -#include -#include -#include -#include -#include -#include - -namespace sky::rhi { - - class RHISample : public IModule, public IWindowEvent { - public: - RHISample() = default; - ~RHISample() = default; - - bool Init() override; - - void Start() override; - - void Stop() override; - - void Tick(float delta) override; - - template - void RegisterSample() - { - samples.emplace_back([this]() -> RHISampleBase* { - auto *sample = new T(); - sample->SetAPI(api); - sample->OnStart(); - return sample; - }); - } - - private: - bool StartSample(); - void NextSample(); - void PrevSample(); - - void RegisterPath(); - - void OnKeyUp(KeyButtonType) override; - std::vector> samples; - uint32_t currentIndex = 0; - std::unique_ptr currentSample; - API api = API::DEFAULT; - }; - -} diff --git a/sample/RHISampleBase/include/RHISampleBase.h b/sample/RHISampleBase/include/RHISampleBase.h deleted file mode 100644 index 00dd4b9d..00000000 --- a/sample/RHISampleBase/include/RHISampleBase.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky { - class NativeWindow; -} - -namespace sky::rhi { - - ShaderPtr CreateShader(API api, Device &device, ShaderStageFlagBit stage, const std::string &path); - - class RHISampleBase : public IWindowEvent, public IRHI { - public: - RHISampleBase() = default; - ~RHISampleBase() override = default; - - virtual void OnStart(); - virtual void OnStop(); - virtual void OnTick(float delta); - void SetAPI(API api) { rhi = api; } - - virtual void SetFeature() {} - bool CheckFeature() const; - protected: - void OnWindowResize(uint32_t width, uint32_t height) override; - - virtual void SetupBase(); - - void SetupPool(); - void SetupPass(); - void SetupTriangle(); - void SetupQueryPool(); - void ResetFramebuffer(); - rhi::Device * GetDevice() const override { return device; } - - rhi::Instance *instance = nullptr; - rhi::Device *device = nullptr; - - rhi::DescriptorSetPoolPtr pool; - rhi::SwapChainPtr swapChain; - rhi::RenderPassPtr renderPass; - std::vector colorViews; - std::vector frameBuffers; - rhi::FencePtr fence; - rhi::CommandBufferPtr commandBuffer; - rhi::GraphicsPipelinePtr pso; - rhi::PipelineLayoutPtr pipelineLayout; - rhi::VertexInputPtr emptyInput; - rhi::ImageViewPtr depthStencilImage; - std::vector clears; - const NativeWindow* window = nullptr; - - rhi::SemaphorePtr imageAvailable; - rhi::SemaphorePtr renderFinish; - rhi::DeviceFeature deviceFeature = {}; - - rhi::QueryPoolPtr psPool; - rhi::BufferPtr psResult; - uint32_t psResultStride = 0; - - rhi::QueryPoolPtr timeStampPool; - rhi::BufferPtr timeStampResult; - uint32_t timeStampResultStride = 0; - uint32_t timeStampCount = 4; - std::vector timeStampSysResult; - - uint32_t frameIndex = 0; - uint32_t maxFrameInflight = 2; - - API rhi = API::DEFAULT; -#if __APPLE__ - rhi::PixelFormat dsFormat = rhi::PixelFormat::D32_S8; -#else - rhi::PixelFormat dsFormat = rhi::PixelFormat::D24_S8; -#endif - }; -} diff --git a/sample/RHISampleBase/include/RHISubPassSample.h b/sample/RHISampleBase/include/RHISubPassSample.h deleted file mode 100644 index 8467b2b8..00000000 --- a/sample/RHISampleBase/include/RHISubPassSample.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include - -namespace sky::rhi { - - class RHISubPassSample : public RHISampleBase { - public: - RHISubPassSample() = default; - ~RHISubPassSample() = default; - - void SetupBase() override; - void OnTick(float delta) override; - void OnStop() override; - private: - rhi::RenderPassPtr tiedPass; - rhi::FrameBufferPtr fb; - std::vector subpassViews; - rhi::ImageViewPtr depthView; - rhi::ImageViewPtr stencilView; - std::vector fbClears; - - rhi::GraphicsPipelinePtr pso1; - rhi::GraphicsPipelinePtr pso2; - rhi::GraphicsPipelinePtr pso3; - rhi::GraphicsPipelinePtr fullScreen; - rhi::PipelineLayoutPtr fullScreenLayout; - rhi::PipelineLayoutPtr subpassLayout1; - rhi::PipelineLayoutPtr subpassLayout2; - rhi::DescriptorSetPtr fullScreenSet; - rhi::DescriptorSetPtr subpassSet1; - rhi::DescriptorSetPtr subpassSet2; - }; - -} // namespace sky::rhi \ No newline at end of file diff --git a/sample/RHISampleBase/include/RHISubpassMSAA.h b/sample/RHISampleBase/include/RHISubpassMSAA.h deleted file mode 100644 index b56ca73d..00000000 --- a/sample/RHISampleBase/include/RHISubpassMSAA.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by Zach Lee on 2023/6/14. -// - -#pragma once - -#include - -namespace sky::rhi { - - class RHISubPassMSAA : public RHISampleBase { - public: - RHISubPassMSAA() = default; - ~RHISubPassMSAA() = default; - - void SetupBase() override; - void OnTick(float delta) override; - void OnStop() override; - private: - rhi::RenderPassPtr tiedPass; - rhi::FrameBufferPtr fb; - - rhi::ImageViewPtr ms1; - rhi::ImageViewPtr resolve1; - rhi::ImageViewPtr ms2; - rhi::ImageViewPtr resolve2; - rhi::ImageViewPtr ds; - rhi::ImageViewPtr dsResolve; - - std::vector fbClears; - - rhi::GraphicsPipelinePtr pso1; - rhi::GraphicsPipelinePtr pso2; - rhi::PipelineLayoutPtr fullScreenLayout; - rhi::PipelineLayoutPtr emptyLayout; - rhi::DescriptorSetPtr set1; - }; - -} // namespace sky::rhi diff --git a/sample/RHISampleBase/include/scene_render/Camera.h b/sample/RHISampleBase/include/scene_render/Camera.h deleted file mode 100644 index 7bf212c7..00000000 --- a/sample/RHISampleBase/include/scene_render/Camera.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include - -namespace sky::rhi { - - struct CameraData { - Matrix4 vp; - Vector4 position; - }; - - class Camera { - public: - Camera() = default; - ~Camera() = default; - - void SetTransform(const Matrix4 &matrix); - void MakeProjective(float fov, float aspect, float near, float far); - void Update(); - const CameraData &GetData() const { return data; } - private: - Matrix4 project; - Matrix4 transform; - Matrix4 view; - CameraData data; - }; - using CameraPtr = std::shared_ptr; -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/Material.h b/sample/RHISampleBase/include/scene_render/Material.h deleted file mode 100644 index 13fe800d..00000000 --- a/sample/RHISampleBase/include/scene_render/Material.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace sky::rhi { - struct Texture { - ImageViewPtr view; - SamplerPtr sampler; - }; - - class Material { - public: - Material() = default; - ~Material() = default; - - struct Accessor { - uint32_t binding = 0; - uint32_t offset = 0; - }; - - struct Connection { - std::unordered_map accessors; - }; - - void SetLayout(const rhi::DescriptorSetLayoutPtr &l, const rhi::DescriptorSetPoolPtr &p, uint32_t size); - void AddConnection(const std::string &str, const Accessor &accessor); - - template - void SetValue(const std::string &key, const T &value) - { - SetValue(key, reinterpret_cast(&value), sizeof(T)); - } - void SetValue(const std::string &str, const uint8_t *data, uint32_t size); - void SetTexture(const std::string &key, const Texture &tex); - void Update(); - - const DescriptorSetLayoutPtr &GetLayout() const { return layout; } - const DescriptorSetPtr &GetSet() const { return batchSet; } - - private: - Accessor GetAccessor(const std::string &key) const; - using RawData = std::vector; - - DescriptorSetPtr batchSet; - DescriptorSetLayoutPtr layout; - DescriptorSetPoolPtr pool; - Connection connection; - - uint32_t bufferBinding = 0; - std::unordered_map textures; - std::unordered_map rawDatas; - std::unordered_map buffers; - - bool needUpdateSet = true; - }; - using MaterialPtr = std::shared_ptr; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/Mesh.h b/sample/RHISampleBase/include/scene_render/Mesh.h deleted file mode 100644 index df5fa29f..00000000 --- a/sample/RHISampleBase/include/scene_render/Mesh.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace sky::rhi { - - struct LocalData { - Matrix4 localData = Matrix4::Identity(); - }; - - struct SubMesh { - uint32_t firstIndex; - uint32_t indexCount; - MaterialPtr material; - GFXTechniquePtr tech; - }; - - struct Mesh { - void SetVA(const VertexAssemblyPtr &va) { vao = va; } - void AddSubMesh(const SubMesh &subMesh) { subMeshes.emplace_back(subMesh); } - void SetLocalSet(const DescriptorSetPtr &set); - void Update(); - - LocalData localData; - VertexAssemblyPtr vao; - DescriptorSetPtr descriptorSet; - BufferPtr localBuffer; - std::vector subMeshes; - }; - using MeshPtr = std::shared_ptr; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/Pipeline.h b/sample/RHISampleBase/include/scene_render/Pipeline.h deleted file mode 100644 index 58946b54..00000000 --- a/sample/RHISampleBase/include/scene_render/Pipeline.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -namespace sky::rhi { - - class Pipeline { - public: - Pipeline() = default; - ~Pipeline() = default; - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/Scene.h b/sample/RHISampleBase/include/scene_render/Scene.h deleted file mode 100644 index fd0d6c2d..00000000 --- a/sample/RHISampleBase/include/scene_render/Scene.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include -#include - -namespace sky::rhi { - - class Scene { - public: - Scene() = default; - ~Scene() = default; - - void SetGlobalSet(const DescriptorSetPtr &set) { globalSet = set; } - const DescriptorSetPtr &GetGlobalSet() const { return globalSet; } - - void AddMesh(const MeshPtr &mesh) { meshes.emplace_back(mesh); } - void AddCamera(const CameraPtr &cam) { cameras.emplace_back(cam); } - - void Tick() {} - - private: - DescriptorSetPtr globalSet; - - std::vector meshes; - std::vector cameras; - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/Technique.h b/sample/RHISampleBase/include/scene_render/Technique.h deleted file mode 100644 index 123dc93b..00000000 --- a/sample/RHISampleBase/include/scene_render/Technique.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include -#include -#include -#include - -namespace sky::rhi { - - struct GraphicsTechnique { - public: - GraphicsTechnique() = default; - ~GraphicsTechnique() = default; - - void SetPipelineLayout(const PipelineLayoutPtr &layout) { psoDesc.pipelineLayout = layout; } - void SetRenderPass(const RenderPassPtr &pass, uint32_t subPass = 0) { psoDesc.renderPass = pass; psoDesc.subPassIndex = subPass; } - void SetVertexInput(const VertexInputPtr &vi) { psoDesc.vertexInput = vi; } - void SetShader(const ShaderPtr &v, const ShaderPtr &f) { psoDesc.vs = v; psoDesc.fs = f; } - void BuildPso(); - - GraphicsPipeline::Descriptor psoDesc; - GraphicsPipelinePtr pso; - }; - using GFXTechniquePtr = std::shared_ptr; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/pass/ComputePass.h b/sample/RHISampleBase/include/scene_render/pass/ComputePass.h deleted file mode 100644 index 748865f7..00000000 --- a/sample/RHISampleBase/include/scene_render/pass/ComputePass.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include - -namespace sky::rhi { - - class ComputePass : public PassExecutor { - public: - ComputePass() = default; - ~ComputePass() = default; - - void Execute(const CommandBufferPtr &cmd) override {} - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/pass/PassExecutor.h b/sample/RHISampleBase/include/scene_render/pass/PassExecutor.h deleted file mode 100644 index 0877f3a4..00000000 --- a/sample/RHISampleBase/include/scene_render/pass/PassExecutor.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include - -namespace sky::rhi { - - class PassExecutor { - public: - PassExecutor() = default; - virtual ~PassExecutor() = default; - - virtual void Execute(const CommandBufferPtr &cmd) = 0; - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/include/scene_render/pass/RasterPass.h b/sample/RHISampleBase/include/scene_render/pass/RasterPass.h deleted file mode 100644 index 27436fd3..00000000 --- a/sample/RHISampleBase/include/scene_render/pass/RasterPass.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#pragma once - -#include - -namespace sky::rhi { - - class RasterPass : public PassExecutor { - public: - RasterPass() = default; - ~RasterPass() = default; - - void Execute(const CommandBufferPtr &cmd) override {} - }; - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/RHIDrawIndirectSample.cpp b/sample/RHISampleBase/src/RHIDrawIndirectSample.cpp deleted file mode 100644 index 70436a58..00000000 --- a/sample/RHISampleBase/src/RHIDrawIndirectSample.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// Created by Zach Lee on 2023/5/30. -// - -#include -#include -#include -#include -#include - -//#define ENABLE_MULTI_DRAW - -namespace sky::rhi { - - const uint32_t X_NUM = 8; - const uint32_t Y_NUM = 8; - const uint32_t TOTAL_NUM = X_NUM * Y_NUM; - - struct InstanceData { - Vector2 offset; - Vector2 scale; - }; - - struct IndirectCommand { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; - }; - - void RHIDrawIndirectSample::SetFeature() - { -#ifdef ENABLE_MULTI_DRAW - deviceFeature.multiDrawIndirect = true; -#else - deviceFeature.multiDrawIndirect = false; -#endif - } - - void RHIDrawIndirectSample::SetupBase() - { - SetupPass(); - SetupPool(); - - rhi::VertexInput::Descriptor viDesc = {}; - viDesc.attributes.emplace_back(VertexAttributeDesc {0, 0, 0, Format::F_RG32}); - viDesc.attributes.emplace_back(VertexAttributeDesc {1, 0, 8, Format::F_RG32}); - viDesc.bindings.emplace_back(VertexBindingDesc {0, sizeof(InstanceData), VertexInputRate::PER_INSTANCE}); - vi = device->CreateVertexInput(viDesc); - - auto path = Platform::Get()->GetInternalPath(); - builder::ShaderCompiler::CompileShader("shaders/triangle_instanced_vs.glsl", {path + "/shaders/RHISample/triangle_instanced_vs.shader", builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/triangle_fs.glsl", {path + "/shaders/RHISample/triangle_fs.shader", builder::ShaderType::FS}); - GraphicsPipeline::Descriptor psoDesc = {}; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/triangle_instanced_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/triangle_fs.shader"); - psoDesc.renderPass = renderPass; - psoDesc.pipelineLayout = pipelineLayout; - psoDesc.vertexInput = vi; - psoDesc.state.depthStencil.depthTest = true; - psoDesc.state.depthStencil.depthWrite = true; - psoDesc.state.blendStates.emplace_back(BlendState{}); - pso = device->CreateGraphicsPipeline(psoDesc); - - rhi::Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = sizeof(InstanceData) * TOTAL_NUM; - bufferDesc.usage = BufferUsageFlagBit::VERTEX; - bufferDesc.memory = MemoryType::CPU_TO_GPU; - auto buffer = device->CreateBuffer(bufferDesc); - instanceBuffer = buffer->CreateView({0, bufferDesc.size}); - - std::vector data(TOTAL_NUM); - for (uint32_t i = 0; i < X_NUM; ++i) { - for (uint32_t j = 0; j < Y_NUM; ++j) { - auto &dat = data[i * Y_NUM + j]; - dat.scale = Vector2{1 / static_cast(X_NUM), 1 / static_cast(Y_NUM)}; - dat.offset.x = i * 2 / static_cast(X_NUM) - 0.9f; - dat.offset.y = j * 2 / static_cast(Y_NUM) - 0.9f; - } - } - auto *ptr = buffer->Map(); - memcpy(ptr, data.data(), bufferDesc.size); - buffer->UnMap(); - - rhi::VertexAssembly::Descriptor vaDesc = {}; - vaDesc.vertexBuffers.emplace_back(instanceBuffer); - vaDesc.vertexInput = vi; - va = device->CreateVertexAssembly(vaDesc); - - std::vector indirect; - for (uint32_t i = 0; i < Y_NUM; ++i) { - indirect.emplace_back(IndirectCommand{3, 8, 0, i * X_NUM}); - } - bufferDesc.size = sizeof(IndirectCommand) * indirect.size(); - bufferDesc.usage = BufferUsageFlagBit::INDIRECT; - bufferDesc.memory = MemoryType::CPU_TO_GPU; - indirectBuffer = device->CreateBuffer(bufferDesc); - ptr = indirectBuffer->Map(); - memcpy(ptr, indirect.data(), bufferDesc.size); - indirectBuffer->UnMap(); - } - - void RHIDrawIndirectSample::OnTick(float delta) - { - auto *queue = device->GetQueue(QueueType::GRAPHICS); - uint32_t index = swapChain->AcquireNextImage(imageAvailable); - - SubmitInfo submitInfo = {}; - submitInfo.submitSignals.emplace_back(renderFinish); - submitInfo.waits.emplace_back(PipelineStageBit::COLOR_OUTPUT, imageAvailable); - submitInfo.fence = fence; - - fence->WaitAndReset(); - commandBuffer->Begin(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = depthStencilImage; - commandBuffer->QueueBarrier(barrier); - } - - commandBuffer->FlushBarriers(); - commandBuffer->EncodeGraphics()->BeginPass({frameBuffers[index], renderPass, 2, clears.data()}) - .BindPipeline(pso) - .BindAssembly(va) - .DrawIndirect(indirectBuffer, 0, X_NUM, sizeof(IndirectCommand)) - .EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::PRESENT; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - commandBuffer->FlushBarriers(); - } - - commandBuffer->End(); - commandBuffer->Submit(*queue, submitInfo); - - PresentInfo presentInfo = {}; - presentInfo.imageIndex = index; - presentInfo.semaphores.emplace_back(renderFinish); - swapChain->Present(*queue, presentInfo); - } - - void RHIDrawIndirectSample::OnStop() - { - device->WaitIdle(); - vi = nullptr; - va = nullptr; - instanceBuffer = nullptr; - indirectBuffer = nullptr; - RHISampleBase::OnStop(); - } -} // namespace sky::rhi \ No newline at end of file diff --git a/sample/RHISampleBase/src/RHIPassSample.cpp b/sample/RHISampleBase/src/RHIPassSample.cpp deleted file mode 100644 index ee334014..00000000 --- a/sample/RHISampleBase/src/RHIPassSample.cpp +++ /dev/null @@ -1,335 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - - -#include -#include -#include -#include -#include -#include -#include - -namespace sky::rhi { - - struct MaterialData { - Color baseColor; - }; - - struct MeshVertex { - Vector4 pos; - Vector4 normal; - }; - - template - struct VectorProvider : public IStream { - const uint8_t* GetData(uint64_t offset) override - { - return reinterpret_cast(data.data()) + offset; - } - - void ReadData(uint64_t offset, uint64_t size, uint8_t *out) override - { - const uint8_t *ptr = reinterpret_cast(data.data()) + offset; - memcpy(out, ptr, size); - } - - std::vector data; - }; - - void RHIPassSample::SetupMaterial() - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{ - DescriptorType::UNIFORM_BUFFER, 1, 0, ShaderStageFlagBit::FS, "Constant" - }); - auto layout = device->CreateDescriptorSetLayout(layoutDesc); - material = std::make_shared(); - material->SetLayout(layout, pool, sizeof(MaterialData)); - material->AddConnection("baseColor", {0, 0}); - material->SetValue("baseColor", Color{1.f, 1.f, 1.f, 1.f}); - material->Update(); - } - - void RHIPassSample::SetupMesh() - { - VertexInput::Descriptor viDesc = {}; - viDesc.attributes.emplace_back(VertexAttributeDesc{0, 0, 0, Format::F_RGBA32}); - viDesc.attributes.emplace_back(VertexAttributeDesc{1, 0, sizeof(Vector4), Format::F_RGBA32}); - viDesc.bindings.emplace_back(VertexBindingDesc{0, sizeof(MeshVertex)}); - auto vertexInput = device->CreateVertexInput(viDesc); - - std::vector vertices = { - {{-0.5f, -0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - {{ 0.5f, -0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - {{ 0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - {{ 0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - {{-0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - {{-0.5f, -0.5f, 0.5f, 1.f}, { 0.f, 0.f, 1.f, 1.f}}, - - {{ 0.5f, -0.5f, 0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - {{ 0.5f, -0.5f, -0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - {{ 0.5f, 0.5f, -0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - {{ 0.5f, 0.5f, -0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - {{ 0.5f, 0.5f, 0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - {{ 0.5f, -0.5f, 0.5f, 1.f}, { 1.f, 0.f, 0.f, 1.f}}, - - {{ 0.5f, -0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - {{-0.5f, -0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - {{-0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - {{-0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - {{ 0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - {{ 0.5f, -0.5f, -0.5f, 1.f}, { 0.f, 0.f, -1.f, 1.f}}, - - {{-0.5f, -0.5f, -0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - {{-0.5f, -0.5f, 0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, 0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, 0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, -0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - {{-0.5f, -0.5f, -0.5f, 1.f}, {-1.f, 0.f, 0.f, 1.f}}, - - {{ 0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - {{ 0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, -0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - {{-0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - {{ 0.5f, 0.5f, 0.5f, 1.f}, { 0.f, 1.f, 0.f, 1.f}}, - - {{ 0.5f, -0.5f, 0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - {{ 0.5f, -0.5f, -0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - {{-0.5f, -0.5f, -0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - {{-0.5f, -0.5f, -0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - {{-0.5f, -0.5f, 0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - {{ 0.5f, -0.5f, 0.5f, 1.f}, { 0.f, -1.f, 0.f, 1.f}}, - }; - std::vector indices = { - 0, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35 - }; - - uint64_t vertexSize = vertices.size() * sizeof(MeshVertex); - uint64_t indexSize = indices.size() * sizeof(uint16_t); - auto *queue = device->GetQueue(QueueType::TRANSFER); - - - Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = vertexSize; - bufferDesc.usage = BufferUsageFlagBit::TRANSFER_DST | BufferUsageFlagBit::VERTEX; - bufferDesc.memory = MemoryType::GPU_ONLY; - auto vb = device->CreateBuffer(bufferDesc); - auto vp = std::make_shared>(); - vp->data.swap(vertices); - auto vh = queue->UploadBuffer(vb, {vp, 0, vertexSize}); - - bufferDesc.size = indexSize; - bufferDesc.usage = BufferUsageFlagBit::TRANSFER_DST | BufferUsageFlagBit::INDEX; - auto ib = device->CreateBuffer(bufferDesc); - auto ip = std::make_shared>(); - ip->data.swap(indices); - auto ih = queue->UploadBuffer(ib, {ip, 0, indexSize}); - - queue->Wait(vh); - queue->Wait(ih); - - VertexAssembly::Descriptor vaDesc; - vaDesc.vertexInput = vertexInput; - vaDesc.vertexBuffers.emplace_back(vb->CreateView({0, vertexSize})); - auto va = device->CreateVertexAssembly(vaDesc); - auto localSet = pool->Allocate({localLayout}); - - PipelineLayout::Descriptor ppLayoutDesc = {{ - globalLayout, - material->GetLayout(), - localLayout, - }}; - auto pipelineLayout = device->CreatePipelineLayout(ppLayoutDesc); - - auto path = Platform::Get()->GetInternalPath(); - builder::ShaderCompiler::CompileShader("shaders/pos_normal_vs.glsl", {path + "/shaders/RHISample/pos_normal_vs.shader", builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/base_color_fs.glsl", {path + "/shaders/RHISample/base_color_fs.shader", builder::ShaderType::FS}); - - gfxTech = std::make_shared(); - gfxTech->SetShader(CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/pos_normal_vs.shader"), - CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/base_color_fs.shader")); - gfxTech->SetVertexInput(vertexInput); - gfxTech->SetPipelineLayout(pipelineLayout); - gfxTech->SetRenderPass(renderPass); - gfxTech->psoDesc.state.depthStencil.depthTest = true; - gfxTech->psoDesc.state.depthStencil.depthWrite = true; - gfxTech->psoDesc.state.blendStates.emplace_back(BlendState{}); - gfxTech->BuildPso(); - - mesh = std::make_shared(); - mesh->SetVA(va); - mesh->AddSubMesh({0, 36, material, gfxTech}); - mesh->SetLocalSet(localSet); - } - - void RHIPassSample::SetupCamera() - { - if (!camera) { - camera = std::make_shared(); - } - - const auto &ext = swapChain->GetExtent(); - camera->MakeProjective(60.f / 180.f * 3.14f, static_cast(ext.width) / static_cast(ext.height), 0.1f, 100.f); - - auto matrix = Matrix4::Identity(); - matrix[3][0] = 0.f; - matrix[3][1] = 1.0f; - matrix[3][2] = 5.f; - camera->SetTransform(matrix); - camera->Update(); - - if (!cameraBuffer) { - Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = sizeof(CameraData); - bufferDesc.usage = BufferUsageFlagBit::UNIFORM; - bufferDesc.memory = MemoryType::CPU_TO_GPU; - cameraBuffer = device->CreateBuffer(bufferDesc); - } - - uint8_t *ptr = cameraBuffer->Map(); - memcpy(ptr, &camera->GetData(), sizeof(CameraData)); - cameraBuffer->UnMap(); - } - - void RHIPassSample::SetupLayout() - { - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{ - DescriptorType::UNIFORM_BUFFER, 1, 0, ShaderStageFlagBit::VS | ShaderStageFlagBit::FS, "CameraData" - }); - globalLayout = device->CreateDescriptorSetLayout(layoutDesc); - } - - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{ - DescriptorType::UNIFORM_BUFFER, 1, 0, ShaderStageFlagBit::VS, "LocalData" - }); - localLayout = device->CreateDescriptorSetLayout(layoutDesc); - } - - { - auto set = pool->Allocate({globalLayout}); - set->BindBuffer(0, cameraBuffer->CreateView({0, sizeof(CameraData)}), 0); - set->Update(); - - scene = std::make_shared(); - scene->SetGlobalSet(set); - } - - } - - void RHIPassSample::SetupScene() - { - SetupCamera(); - SetupLayout(); - SetupPass(); - - SetupMaterial(); - SetupMesh(); - } - - void RHIPassSample::SetupBase() - { - SetupPass(); - SetupPool(); - SetupTriangle(); - - SetupScene(); - } - - void RHIPassSample::OnStop() - { - device->WaitIdle(); - material = nullptr; - camera = nullptr; - mesh = nullptr; - scene = nullptr; - - gfxTech = nullptr; - globalLayout = nullptr; - localLayout = nullptr; - cameraBuffer = nullptr; - - RHISampleBase::OnStop(); - } - - void RHIPassSample::OnTick(float delta) - { - auto *queue = device->GetQueue(QueueType::GRAPHICS); - uint32_t index = swapChain->AcquireNextImage(imageAvailable); - - SubmitInfo submitInfo = {}; - submitInfo.submitSignals.emplace_back(renderFinish); - submitInfo.waits.emplace_back( - PipelineStageBit::COLOR_OUTPUT, imageAvailable); - submitInfo.fence = fence; - - fence->WaitAndReset(); - commandBuffer->Begin(); - - auto encoder = commandBuffer->EncodeGraphics(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = depthStencilImage; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - encoder->BeginPass({frameBuffers[index], renderPass, 2, clears.data()}); - - for (auto &subMesh : mesh->subMeshes) { - encoder->BindPipeline(subMesh.tech->pso); - encoder->BindSet(0, scene->GetGlobalSet()); - encoder->BindSet(1, subMesh.material->GetSet()); - encoder->BindSet(2, mesh->descriptorSet); - encoder->BindAssembly(mesh->vao); - encoder->DrawLinear({36, 1, 0, 0}); - } - - encoder->EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::PRESENT; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - commandBuffer->End(); - commandBuffer->Submit(*queue, submitInfo); - - PresentInfo presentInfo = {}; - presentInfo.imageIndex = index; - presentInfo.semaphores.emplace_back(renderFinish); - swapChain->Present(*queue, presentInfo); - } - - void RHIPassSample::OnWindowResize(uint32_t width, uint32_t height) - { - RHISampleBase::OnWindowResize(width, height); - SetupCamera(); - } -} diff --git a/sample/RHISampleBase/src/RHISample.cpp b/sample/RHISampleBase/src/RHISample.cpp deleted file mode 100644 index aa6edf70..00000000 --- a/sample/RHISampleBase/src/RHISample.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#include "RHISample.h" -#include "RHISampleBase.h" -#include "RHIPassSample.h" -#include "RHISubPassSample.h" -#include "RHIDrawIndirectSample.h" -#include "RHISubpassMSAA.h" -#include -#include -#include -#include -#include -#include - -namespace sky::rhi { - - static const bool API_CHECK[] = { - true, - true, - true, - true, - true - }; - - bool RHISample::Init() - { - RegisterPath(); - - RegisterSample(); - RegisterSample(); - RegisterSample(); - RegisterSample(); - RegisterSample(); - - auto *systemApi = Interface::Get()->GetApi(); - auto &settings = systemApi->GetSettings(); - auto rhi = settings.VisitString("rhi"); - if (rhi == "gles") { - api = API::GLES; - } else if (rhi == "vulkan") { - api = API::VULKAN; - } else if (rhi == "dx12") { - api = API::DX12; - } else if (rhi == "metal") { - api = API::METAL; - } else { - api = API::VULKAN; - } - if (API_CHECK[static_cast(api)]) { - const auto *nativeWindow = systemApi->GetViewport(); - Event::Connect(nativeWindow, this); - return true; - } - return false; - } - - void RHISample::Start() - { - StartSample(); - } - - void RHISample::Stop() - { - if (currentSample) { - currentSample->OnStop(); - } - currentSample = nullptr; - Event::DisConnect(this); - } - - void RHISample::Tick(float delta) - { - if (currentSample) { - currentSample->OnTick(delta); - } - } - - bool RHISample::StartSample() - { - if (currentSample) { - currentSample->OnStop(); - } - currentSample.reset(samples[currentIndex]()); - return currentSample->CheckFeature(); - } - - void RHISample::NextSample() - { - currentIndex = (currentIndex + 1) % samples.size(); - } - - void RHISample::PrevSample() - { - currentIndex = (currentIndex + static_cast(samples.size()) - 1) % samples.size(); - } - - void RHISample::OnKeyUp(KeyButtonType button) - { - if (button == KeyButton::KEY_F2) { - NextSample(); - while (!StartSample()) { - NextSample(); - } - } else if (button == KeyButton::KEY_F3) { - PrevSample(); - StartSample(); - } - } - - void RHISample::RegisterPath() - { - AssetManager::Get()->RegisterSearchPath(ENGINE_ROOT + "/assets"); - AssetManager::Get()->RegisterSearchPath(PROJECT_ROOT + "/assets"); - - auto path = Platform::Get()->GetInternalPath(); - std::filesystem::create_directories(path + "/shaders/RHISample"); - } -} -REGISTER_MODULE(sky::rhi::RHISample) diff --git a/sample/RHISampleBase/src/RHISampleBase.cpp b/sample/RHISampleBase/src/RHISampleBase.cpp deleted file mode 100644 index 38e7e573..00000000 --- a/sample/RHISampleBase/src/RHISampleBase.cpp +++ /dev/null @@ -1,336 +0,0 @@ -// -// Created by Zach Lee on 2022/11/5. -// - -#include "RHISampleBase.h" -#include - -#include -#include - -#include - -#include - -namespace sky::rhi { - - ShaderPtr CreateShader(API api, Device &device, ShaderStageFlagBit stage, const std::string &path) - { - Shader::Descriptor shaderDesc = {}; - shaderDesc.stage = stage; - - std::string shaderPath = path; - if (api == API::VULKAN) { - shaderPath += ".spv"; - } else if (api == API::METAL) { - shaderPath += ".msl"; - } else if (api == API::GLES) { - shaderPath += ".gles"; - } - uint8_t *data = nullptr; - ReadBin(shaderPath, data, shaderDesc.size); - shaderDesc.data = data; - return device.CreateShader(shaderDesc); - } - - void RHISampleBase::OnStart() - { - SetFeature(); - instance = Instance::Create({"", "", true, rhi}); - device = instance->CreateDevice({deviceFeature}); - - auto *systemApi = Interface::Get()->GetApi(); - window = systemApi->GetViewport(); - Event::Connect(window, this); - SwapChain::Descriptor swcDesc = {}; - - swcDesc.window = window->GetNativeHandle(); - swcDesc.width = window->GetWidth(); - swcDesc.height = window->GetHeight(); - swapChain = device->CreateSwapChain(swcDesc); - - CommandBuffer::Descriptor cmdDesc = {}; - commandBuffer = device->CreateCommandBuffer(cmdDesc); - - Fence::Descriptor fenceDesc = {}; - fenceDesc.createSignaled = true; - fence = device->CreateFence(fenceDesc); - - imageAvailable = device->CreateSema({}); - renderFinish = device->CreateSema({}); - - Interface::Get()->Register(*this); - SetupBase(); - } - - void RHISampleBase::OnStop() - { - device->WaitIdle(); - - fence = nullptr; - commandBuffer = nullptr; - pipelineLayout = nullptr; - pso = nullptr; - swapChain = nullptr; - renderPass = nullptr; - renderFinish = nullptr; - imageAvailable = nullptr; - emptyInput = nullptr; - depthStencilImage = nullptr; - pool = nullptr; - psPool = nullptr; - psResult = nullptr; - timeStampPool = nullptr; - timeStampResult = nullptr; - colorViews.clear(); - frameBuffers.clear(); - - delete device; - device = nullptr; - - Instance::Destroy(instance); - instance = nullptr; - - Event::DisConnect(this); - Interface::Get()->UnRegister(); - } - - void RHISampleBase::OnTick(float delta) - { - auto *queue = device->GetQueue(QueueType::GRAPHICS); - uint32_t index = swapChain->AcquireNextImage(imageAvailable); - - SubmitInfo submitInfo = {}; - submitInfo.submitSignals.emplace_back(renderFinish); - submitInfo.waits.emplace_back( - PipelineStageBit::COLOR_OUTPUT, imageAvailable); - submitInfo.fence = fence; - - fence->WaitAndReset(); - - commandBuffer->Begin(); - commandBuffer->ResetQueryPool(psPool, 0, 1); - commandBuffer->ResetQueryPool(timeStampPool, 0, timeStampCount); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = depthStencilImage; - commandBuffer->QueueBarrier(barrier); - } - - commandBuffer->FlushBarriers(); - commandBuffer->EncodeGraphics()->BeginPass({frameBuffers[index], renderPass, 2, clears.data()}) - .BeginQuery(psPool, 0) - .WriteTimeStamp(timeStampPool, rhi::PipelineStageBit::VERTEX_INPUT, 0) - .WriteTimeStamp(timeStampPool, rhi::PipelineStageBit::VERTEX_SHADER, 1) - .BindPipeline(pso) - .DrawLinear({3, 1, 0, 0}) - .EndQuery(psPool, 0) - .WriteTimeStamp(timeStampPool, rhi::PipelineStageBit::FRAGMENT_SHADER, 2) - .WriteTimeStamp(timeStampPool, rhi::PipelineStageBit::COLOR_OUTPUT, 3) - .EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::PRESENT; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - commandBuffer->FlushBarriers(); - } - - commandBuffer->GetQueryResult(psPool, 0, 1, psResult, frameIndex * psResultStride, psResultStride); - commandBuffer->GetQueryResult(timeStampPool, 0, timeStampCount, timeStampResult, frameIndex * timeStampResultStride, sizeof(uint64_t)); - commandBuffer->End(); - commandBuffer->Submit(*queue, submitInfo); - - PresentInfo presentInfo = {}; - presentInfo.imageIndex = index; - presentInfo.semaphores.emplace_back(renderFinish); - swapChain->Present(*queue, presentInfo); - - uint32_t lastFrame = (frameIndex + maxFrameInflight - 1) % maxFrameInflight; - rhi::PipelineStatisticData data = {}; - psPool->ConvertPipelineStatisticData(psResult, lastFrame * psResultStride, psResultStride, data); - - { - uint8_t *ptr = timeStampResult->Map(); - memcpy(timeStampSysResult.data(), ptr + lastFrame * timeStampResultStride, timeStampResultStride); - timeStampResult->UnMap(); - } - - frameIndex = (frameIndex + 1 ) % maxFrameInflight; - } - - void RHISampleBase::SetupTriangle() - { - auto path = Platform::Get()->GetInternalPath(); - builder::ShaderCompiler::CompileShader("shaders/triangle_vs.glsl", {path + "/shaders/RHISample/triangle_vs.shader", builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/triangle_fs.glsl", {path + "/shaders/RHISample/triangle_fs.shader", builder::ShaderType::FS}); - GraphicsPipeline::Descriptor psoDesc = {}; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/triangle_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/triangle_fs.shader"); - psoDesc.renderPass = renderPass; - psoDesc.pipelineLayout = pipelineLayout; - psoDesc.vertexInput = emptyInput; - psoDesc.state.depthStencil.depthTest = true; - psoDesc.state.depthStencil.depthWrite = true; - psoDesc.state.blendStates.emplace_back(BlendState{}); - pso = device->CreateGraphicsPipeline(psoDesc); - } - - void RHISampleBase::SetupQueryPool() - { - { - rhi::QueryPool::Descriptor poolDesc = {}; - poolDesc.type = QueryType::PIPELINE_STATISTICS; - poolDesc.queryCount = 1; - poolDesc.pipelineStatisticFlags = rhi::PipelineStatisticFlagBits::ALL; - psPool = device->CreateQueryPool(poolDesc); - psResultStride = psPool->GetStride(); - - rhi::Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = psResultStride * maxFrameInflight; - bufferDesc.usage = rhi::BufferUsageFlagBit::TRANSFER_DST; - bufferDesc.memory = MemoryType::GPU_TO_CPU; - psResult = device->CreateBuffer(bufferDesc); - } - { - rhi::QueryPool::Descriptor poolDesc = {}; - poolDesc.type = QueryType::TIME_STAMP; - poolDesc.queryCount = timeStampCount; - - timeStampPool = device->CreateQueryPool(poolDesc); - timeStampResultStride = timeStampCount * sizeof(uint64_t); - - rhi::Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = timeStampResultStride * maxFrameInflight; - bufferDesc.usage = rhi::BufferUsageFlagBit::TRANSFER_DST; - bufferDesc.memory = MemoryType::GPU_TO_CPU; - timeStampResult = device->CreateBuffer(bufferDesc); - timeStampSysResult.resize(timeStampCount); - } - } - - void RHISampleBase::SetupBase() - { - SetupPass(); - SetupPool(); - SetupTriangle(); - SetupQueryPool(); - } - - void RHISampleBase::SetupPool() - { - std::vector sizes; - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::COMBINED_IMAGE_SAMPLER, 128}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::STORAGE_IMAGE, 32}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::UNIFORM_BUFFER, 128}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::UNIFORM_BUFFER_DYNAMIC, 128}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::STORAGE_BUFFER, 32}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::STORAGE_BUFFER_DYNAMIC, 32}); - sizes.emplace_back(DescriptorSetPool::PoolSize{DescriptorType::INPUT_ATTACHMENT, 32}); - - rhi::DescriptorSetPool::Descriptor poolDesc = {}; - poolDesc.maxSets = 16; - poolDesc.sizeData = sizes.data(); - poolDesc.sizeCount = static_cast(sizes.size()); - pool = device->CreateDescriptorSetPool(poolDesc); - } - - bool RHISampleBase::CheckFeature() const - { - const auto &feature = device->GetFeatures(); - return memcmp(&deviceFeature, &feature, sizeof(DeviceFeature)) == 0; - } - - void RHISampleBase::SetupPass() - { - auto format = swapChain->GetFormat(); - const auto &ext = swapChain->GetExtent(); - - RenderPass::Descriptor passDesc = {}; - passDesc.attachments.emplace_back(RenderPass::Attachment{ - format, - SampleCount::X1, - LoadOp::CLEAR, - StoreOp::STORE, - LoadOp::DONT_CARE, - StoreOp::DONT_CARE, - }); - passDesc.attachments.emplace_back(RenderPass::Attachment{ - dsFormat, - SampleCount::X1, - LoadOp::CLEAR, - StoreOp::DONT_CARE, - LoadOp::CLEAR, - StoreOp::DONT_CARE, - }); - passDesc.subPasses.emplace_back(RenderPass::SubPass { - { - {0, AccessFlagBit::COLOR_WRITE} - }, {}, {}, {}, - {1, AccessFlagBit::DEPTH_STENCIL_WRITE} - }); - renderPass = device->CreateRenderPass(passDesc); - - clears.resize(2); - clears[0].color.float32[0] = 0.f; - clears[0].color.float32[1] = 0.f; - clears[0].color.float32[2] = 0.f; - clears[0].color.float32[3] = 1.f; - - clears[1].depthStencil.depth = 1.f; - clears[1].depthStencil.stencil = 0; - - ResetFramebuffer(); - - rhi::PipelineLayout::Descriptor pLayoutDesc = {}; - pipelineLayout = device->CreatePipelineLayout(pLayoutDesc); - emptyInput = device->CreateVertexInput({}); - } - - void RHISampleBase::ResetFramebuffer() - { - const auto &ext = swapChain->GetExtent(); - uint32_t count = swapChain->GetImageCount(); - - rhi::Image::Descriptor imageDesc = {}; - imageDesc.format = dsFormat; - imageDesc.extent = {ext.width, ext.height, 1}; - imageDesc.usage = ImageUsageFlagBit::DEPTH_STENCIL; - auto image = device->CreateImage(imageDesc); - - rhi::ImageViewDesc viewDesc = {}; - viewDesc.subRange.aspectMask = rhi::AspectFlagBit::DEPTH_BIT | rhi::AspectFlagBit::STENCIL_BIT; - depthStencilImage = image->CreateView(viewDesc); - - frameBuffers.resize(count); - colorViews.resize(count); - for (uint32_t i = 0; i < count; ++i) { - FrameBuffer::Descriptor fbDesc = {}; - fbDesc.extent = ext; - fbDesc.pass = renderPass; - colorViews[i] = swapChain->GetImage(i)->CreateView({}); - fbDesc.views.emplace_back(colorViews[i]); - fbDesc.views.emplace_back(depthStencilImage); - frameBuffers[i] = device->CreateFrameBuffer(fbDesc); - } - } - - void RHISampleBase::OnWindowResize(uint32_t width, uint32_t height) - { - swapChain->Resize(width, height, window->GetNativeHandle()); - ResetFramebuffer(); - } -} diff --git a/sample/RHISampleBase/src/RHISubpassMSAA.cpp b/sample/RHISampleBase/src/RHISubpassMSAA.cpp deleted file mode 100644 index 8d585f37..00000000 --- a/sample/RHISampleBase/src/RHISubpassMSAA.cpp +++ /dev/null @@ -1,298 +0,0 @@ -// -// Created by Zach Lee on 2023/6/14. -// - -#include -#include "framework/platform/PlatformBase.h" -#include "builder/shader/ShaderCompiler.h" - -namespace sky::rhi { - - void RHISubPassMSAA::SetupBase() { - SetupPass(); - SetupPool(); - RenderPass::Descriptor passDesc = {}; - - auto sample1 = SampleCount::X4; - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM, sample1, LoadOp::CLEAR, StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM, SampleCount::X1, LoadOp::CLEAR, StoreOp::STORE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM, sample1, LoadOp::CLEAR, StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM, SampleCount::X1, LoadOp::CLEAR, StoreOp::STORE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{dsFormat, sample1, LoadOp::CLEAR, StoreOp::DONT_CARE, LoadOp::CLEAR, StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{dsFormat, SampleCount::X1, LoadOp::CLEAR, StoreOp::STORE, LoadOp::CLEAR, StoreOp::STORE}); - - passDesc.subPasses.emplace_back(RenderPass::SubPass{ - { - {0, AccessFlagBit::COLOR_WRITE}, - {2, AccessFlagBit::COLOR_WRITE}, - }, - { - {1, AccessFlagBit::COLOR_WRITE}, - {3, AccessFlagBit::COLOR_WRITE}, - }, - {}, - {}, - { 4, AccessFlagBit::DEPTH_STENCIL_WRITE}, - { 5, AccessFlagBit::DEPTH_STENCIL_WRITE}, - }); - - tiedPass = device->CreateRenderPass(passDesc); - - auto count = swapChain->GetImageCount(); - const auto &ext = swapChain->GetExtent(); - - rhi::Image::Descriptor desc = {}; - desc.imageType = ImageType::IMAGE_2D; - desc.format = PixelFormat::RGBA8_UNORM; - desc.extent = {ext.width, ext.height, 1}; - desc.mipLevels = 1; - desc.arrayLayers = 1; - desc.memory = MemoryType::GPU_ONLY; - - rhi::ImageViewDesc viewDesc = {}; - { - desc.samples = sample1; - desc.usage = ImageUsageFlagBit::RENDER_TARGET | ImageUsageFlagBit::TRANSIENT; - { - auto image = device->CreateImage(desc); - ms1 = image->CreateView(viewDesc); - } - { - auto image = device->CreateImage(desc); - ms2 = image->CreateView(viewDesc); - } - } - { - desc.samples = rhi::SampleCount::X1; - desc.usage = - ImageUsageFlagBit::RENDER_TARGET | ImageUsageFlagBit::INPUT_ATTACHMENT | ImageUsageFlagBit::SAMPLED; - { - auto image = device->CreateImage(desc); - resolve1 = image->CreateView(viewDesc); - } - { - auto image = device->CreateImage(desc); - resolve2 = image->CreateView(viewDesc); - } - } - { - desc.samples = sample1; - desc.format = dsFormat; - desc.usage = ImageUsageFlagBit::DEPTH_STENCIL | ImageUsageFlagBit::TRANSIENT; - - viewDesc.subRange.aspectMask = AspectFlagBit::DEPTH_BIT | AspectFlagBit::STENCIL_BIT; - { - auto image = device->CreateImage(desc); - ds = image->CreateView(viewDesc); - } - - desc.usage = ImageUsageFlagBit::DEPTH_STENCIL | ImageUsageFlagBit::SAMPLED; - { - desc.samples = rhi::SampleCount::X1; - auto image = device->CreateImage(desc); - dsResolve = image->CreateView(viewDesc); - } - } - - rhi::FrameBuffer::Descriptor fbDesc = {}; - fbDesc.extent = ext; - fbDesc.pass = tiedPass; - fbDesc.views.resize(6); - fbDesc.views[0] = ms1; - fbDesc.views[1] = resolve1; - fbDesc.views[2] = ms2; - fbDesc.views[3] = resolve2; - fbDesc.views[4] = ds; - fbDesc.views[5] = dsResolve; - fb = device->CreateFrameBuffer(fbDesc); - - fbClears.resize(6, ClearValue(0, 0, 0, 0)); - fbClears[4] = ClearValue(1.0, 0); - fbClears[5] = ClearValue(1.0, 0); - - // pipeline layouts - { - PipelineLayout::Descriptor pLayoutDesc = {}; - emptyLayout = device->CreatePipelineLayout(pLayoutDesc); - } - - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back( - DescriptorSetLayout::SetBinding{DescriptorType::COMBINED_IMAGE_SAMPLER, 1, 0, ShaderStageFlagBit::FS, "colorImage1"}); - layoutDesc.bindings.emplace_back( - DescriptorSetLayout::SetBinding{DescriptorType::COMBINED_IMAGE_SAMPLER, 1, 1, ShaderStageFlagBit::FS, "colorImage2"}); - auto passlayout = device->CreateDescriptorSetLayout(layoutDesc); - PipelineLayout::Descriptor pLayoutDesc = {}; - pLayoutDesc.layouts.emplace_back(passlayout); - DescriptorSet::Descriptor setDesc = {passlayout}; - set1 = pool->Allocate(setDesc); - set1->BindImageView(0, resolve1, 0); - set1->BindImageView(1, resolve2, 0); - set1->Update(); - fullScreenLayout = device->CreatePipelineLayout(pLayoutDesc); - } - - - auto path = Platform::Get()->GetInternalPath(); - builder::ShaderCompiler::CompileShader("shaders/full_screen_vs.glsl", - {path + "/shaders/RHISample/full_screen_vs.shader", - builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/full_screen_fs_2.glsl", - {path + "/shaders/RHISample/full_screen_fs_2.shader", - builder::ShaderType::FS}); - builder::ShaderCompiler::CompileShader("shaders/triangle_msaa_vs.glsl", - {path + "/shaders/RHISample/triangle_msaa_vs.shader", - builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/triangle_msaa_fs.glsl", - {path + "/shaders/RHISample/triangle_msaa_fs.shader", - builder::ShaderType::FS}); - - rhi::GraphicsPipeline::Descriptor psoDesc = {}; - psoDesc.state.rasterState.cullMode = rhi::CullModeFlagBits::NONE; - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.state.multiSample.sampleCount = rhi::SampleCount::X1; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, - path + "/shaders/RHISample/full_screen_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, - path + "/shaders/RHISample/full_screen_fs_2.shader"); - psoDesc.renderPass = renderPass; - psoDesc.pipelineLayout = fullScreenLayout; - psoDesc.vertexInput = emptyInput; - psoDesc.subPassIndex = 0; - pso2 = device->CreateGraphicsPipeline(psoDesc); - - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.state.multiSample.sampleCount = sample1; - psoDesc.state.depthStencil.depthWrite = true; - psoDesc.state.depthStencil.depthTest = true; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, - path + "/shaders/RHISample/triangle_msaa_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, - path + "/shaders/RHISample/triangle_msaa_fs.shader"); - psoDesc.renderPass = tiedPass; - psoDesc.pipelineLayout = emptyLayout; - psoDesc.vertexInput = emptyInput; - psoDesc.subPassIndex = 0; - pso1 = device->CreateGraphicsPipeline(psoDesc); - } - - void RHISubPassMSAA::OnTick(float delta) - { - auto *queue = device->GetQueue(QueueType::GRAPHICS); - uint32_t index = swapChain->AcquireNextImage(imageAvailable); - - SubmitInfo submitInfo = {}; - submitInfo.submitSignals.emplace_back(renderFinish); - submitInfo.waits.emplace_back( - PipelineStageBit::COLOR_OUTPUT, imageAvailable); - submitInfo.fence = fence; - - fence->WaitAndReset(); - commandBuffer->Begin(); - - auto encoder = commandBuffer->EncodeGraphics(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = ms1; - commandBuffer->QueueBarrier(barrier); - barrier.view = ms2; - commandBuffer->QueueBarrier(barrier); - barrier.view = resolve1; - commandBuffer->QueueBarrier(barrier); - barrier.view = resolve2; - commandBuffer->QueueBarrier(barrier); - } - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = ds; - commandBuffer->QueueBarrier(barrier); - barrier.view = dsResolve; - commandBuffer->QueueBarrier(barrier); - } - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = depthStencilImage; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - encoder->BeginPass({fb, tiedPass, static_cast(fbClears.size()), fbClears.data()}); - - encoder->BindPipeline(pso1); - encoder->DrawLinear({3, 1, 0, 0}); - - encoder->EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::FRAGMENT_SRV; - barrier.view = resolve1; - commandBuffer->QueueBarrier(barrier); - barrier.view = resolve2; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - commandBuffer->EncodeGraphics()->BeginPass({frameBuffers[index], renderPass, 2, clears.data()}); - encoder->BindPipeline(pso2); - encoder->BindSet(0, set1); - encoder->DrawLinear({3, 1, 0, 0}); - encoder->EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::PRESENT; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - commandBuffer->FlushBarriers(); - } - - commandBuffer->End(); - commandBuffer->Submit(*queue, submitInfo); - - PresentInfo presentInfo = {}; - presentInfo.imageIndex = index; - presentInfo.semaphores.emplace_back(renderFinish); - swapChain->Present(*queue, presentInfo); - } - - void RHISubPassMSAA::OnStop() - { - device->WaitIdle(); - tiedPass = nullptr; - fb = nullptr; - fbClears.clear(); - - ms1 = nullptr; - ms2 = nullptr; - resolve1 = nullptr; - resolve2 = nullptr; - ds = nullptr; - dsResolve = nullptr; - pso1 = nullptr; - pso2 = nullptr; - fullScreenLayout = nullptr; - emptyLayout = nullptr; - set1 = nullptr; - RHISampleBase::OnStop(); - } - - -} // namespace sky::rhi diff --git a/sample/RHISampleBase/src/RHISubpassSample.cpp b/sample/RHISampleBase/src/RHISubpassSample.cpp deleted file mode 100644 index 227459b9..00000000 --- a/sample/RHISampleBase/src/RHISubpassSample.cpp +++ /dev/null @@ -1,345 +0,0 @@ - -#include "RHISubPassSample.h" -#include "framework/platform/PlatformBase.h" -#include "builder/shader/ShaderCompiler.h" - -namespace sky::rhi { - - void RHISubPassSample::SetupBase() - { - SetupPass(); - SetupPool(); - RenderPass::Descriptor passDesc = {}; - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM,SampleCount::X1,LoadOp::CLEAR,StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM,SampleCount::X1,LoadOp::CLEAR,StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM,SampleCount::X1,LoadOp::CLEAR,StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM,SampleCount::X1,LoadOp::CLEAR,StoreOp::DONT_CARE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{PixelFormat::RGBA8_UNORM,SampleCount::X1,LoadOp::CLEAR,StoreOp::STORE}); - passDesc.attachments.emplace_back(RenderPass::Attachment{dsFormat,SampleCount::X1,LoadOp::CLEAR,StoreOp::DONT_CARE}); - - passDesc.subPasses.emplace_back(RenderPass::SubPass { - { - {0, AccessFlagBit::COLOR_WRITE}, - {1, AccessFlagBit::COLOR_WRITE}, - {2, AccessFlagBit::COLOR_WRITE}, - {3, AccessFlagBit::COLOR_WRITE}, - }, {}, {}, {}, - {5, AccessFlagBit::DEPTH_STENCIL_WRITE}, - }); - passDesc.subPasses.emplace_back(RenderPass::SubPass { - { - {4, AccessFlagBit::COLOR_WRITE} - }, - {}, - { - {0, AccessFlagBit::COLOR_INPUT}, - {1, AccessFlagBit::COLOR_INPUT}, - }, - { 2, 3 }, - }); - passDesc.subPasses.emplace_back(RenderPass::SubPass { - { - {4, AccessFlagBit::COLOR_INOUT_WRITE} - }, - {}, - { - {2, AccessFlagBit::COLOR_INPUT}, - {3, AccessFlagBit::COLOR_INPUT}, - {4, AccessFlagBit::COLOR_INOUT_WRITE}, - {5, AccessFlagBit::DEPTH_STENCIL_INPUT, rhi::AspectFlagBit::DEPTH_BIT}, - {5, AccessFlagBit::DEPTH_STENCIL_INPUT, rhi::AspectFlagBit::STENCIL_BIT}, - }, - }); - - passDesc.dependencies.emplace_back(RenderPass::Dependency{0, 1, - AccessFlagBit::COLOR_WRITE, - AccessFlagBit::COLOR_INPUT}); - passDesc.dependencies.emplace_back(RenderPass::Dependency{0, 2, - AccessFlagBit::COLOR_WRITE, - AccessFlagBit::COLOR_INPUT}); - passDesc.dependencies.emplace_back(RenderPass::Dependency{1, 2, - AccessFlagBit::COLOR_WRITE, - AccessFlagBit::COLOR_INOUT_WRITE}); - tiedPass = device->CreateRenderPass(passDesc); - - const auto &ext = swapChain->GetExtent(); - rhi::Image::Descriptor imageDesc = {}; - imageDesc.format = PixelFormat::RGBA8_UNORM; - imageDesc.extent = {ext.width, ext.height, 1}; - rhi::FrameBuffer::Descriptor fbDesc = {}; - fbDesc.extent = ext; - fbDesc.pass = tiedPass; - - for (uint32_t i = 0; i < 6; ++i) - { - rhi::ImageViewDesc viewDesc = {}; - if (i == 5) { - viewDesc.subRange.aspectMask = rhi::AspectFlagBit::DEPTH_BIT | rhi::AspectFlagBit::STENCIL_BIT; - imageDesc.format = dsFormat; - imageDesc.usage = ImageUsageFlagBit::DEPTH_STENCIL | ImageUsageFlagBit::INPUT_ATTACHMENT | ImageUsageFlagBit::TRANSIENT; - fbClears.emplace_back(rhi::ClearValue(1, 0)); - } else if (i == 4) { - imageDesc.usage = ImageUsageFlagBit::RENDER_TARGET | ImageUsageFlagBit::INPUT_ATTACHMENT | ImageUsageFlagBit::SAMPLED; - fbClears.emplace_back(rhi::ClearValue(0, 0, 0, 1)); - } else { - imageDesc.usage = ImageUsageFlagBit::RENDER_TARGET | ImageUsageFlagBit::INPUT_ATTACHMENT | ImageUsageFlagBit::TRANSIENT; - fbClears.emplace_back(rhi::ClearValue(0, 0, 0, 1)); - } - - auto image = device->CreateImage(imageDesc); - auto view = image->CreateView(viewDesc); - fbDesc.views.emplace_back(view); - subpassViews.emplace_back(view); - - if (i == 5) { - rhi::ImageViewDesc dsViewDesc = {}; - dsViewDesc.subRange.aspectMask = AspectFlagBit::DEPTH_BIT; - depthView = image->CreateView(dsViewDesc); - dsViewDesc.subRange.aspectMask = AspectFlagBit::STENCIL_BIT; - stencilView = image->CreateView(dsViewDesc); - } - } - - fb = device->CreateFrameBuffer(fbDesc); - - // pipeline layouts - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{ - DescriptorType::COMBINED_IMAGE_SAMPLER, 1, 0, ShaderStageFlagBit::FS, "colorOut" - }); - auto localLayout = device->CreateDescriptorSetLayout(layoutDesc); - PipelineLayout::Descriptor pLayoutDesc = {}; - pLayoutDesc.layouts.emplace_back(localLayout); - - DescriptorSet::Descriptor setDesc = { localLayout }; - fullScreenSet = pool->Allocate(setDesc); - fullScreenSet->BindImageView(0, fbDesc.views[4], 0); - fullScreenSet->Update(); - - fullScreenLayout = device->CreatePipelineLayout(pLayoutDesc); - } - - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 0, ShaderStageFlagBit::FS,"inColor0"}); - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 1, ShaderStageFlagBit::FS,"inColor1"}); - auto passlayout = device->CreateDescriptorSetLayout(layoutDesc); - PipelineLayout::Descriptor pLayoutDesc = {}; - pLayoutDesc.layouts.emplace_back(passlayout); - DescriptorSet::Descriptor setDesc = {passlayout}; - subpassSet1 = pool->Allocate(setDesc); - subpassSet1->BindImageView(0, fbDesc.views[0], 0); - subpassSet1->BindImageView(1, fbDesc.views[1], 0); - subpassSet1->Update(); - subpassLayout1 = device->CreatePipelineLayout(pLayoutDesc); - } - - { - DescriptorSetLayout::Descriptor layoutDesc = {}; - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 0, ShaderStageFlagBit::FS,"inColor0"}); - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 1, ShaderStageFlagBit::FS,"inColor1"}); - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 2, ShaderStageFlagBit::FS,"inColor2"}); - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 3, ShaderStageFlagBit::FS,"inDepth"}); - layoutDesc.bindings.emplace_back(DescriptorSetLayout::SetBinding{DescriptorType::INPUT_ATTACHMENT, 1, 4, ShaderStageFlagBit::FS,"inStencil"}); - auto passlayout = device->CreateDescriptorSetLayout(layoutDesc); - PipelineLayout::Descriptor pLayoutDesc = {}; - pLayoutDesc.layouts.emplace_back(passlayout); - DescriptorSet::Descriptor setDesc = {passlayout}; - subpassSet2 = pool->Allocate(setDesc); - subpassSet2->BindImageView(0, fbDesc.views[2], 0); - subpassSet2->BindImageView(1, fbDesc.views[3], 0); - subpassSet2->BindImageView(2, fbDesc.views[4], 0, DescriptorBindFlagBit::FEEDBACK_LOOP); - subpassSet2->BindImageView(3, depthView, 0); - subpassSet2->BindImageView(4, stencilView, 0); - subpassSet2->Update(); - subpassLayout2 = device->CreatePipelineLayout(pLayoutDesc); - } - - // shaders - auto path = Platform::Get()->GetInternalPath(); - builder::ShaderCompiler::CompileShader("shaders/full_screen_vs.glsl", {path + "/shaders/RHISample/full_screen_vs.shader", builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/full_screen_fs.glsl", {path + "/shaders/RHISample/full_screen_fs.shader", builder::ShaderType::FS}); - builder::ShaderCompiler::CompileShader("shaders/subpass/sub01_vs.glsl", {path + "/shaders/RHISample/sub01_vs.shader", builder::ShaderType::VS}); - builder::ShaderCompiler::CompileShader("shaders/subpass/sub01_fs.glsl", {path + "/shaders/RHISample/sub01_fs.shader", builder::ShaderType::FS, tiedPass->GetInputMap(0), tiedPass->GetOutputMap(0)}); - builder::ShaderCompiler::CompileShader("shaders/subpass/sub02_fs.glsl", {path + "/shaders/RHISample/sub02_fs.shader", builder::ShaderType::FS, tiedPass->GetInputMap(1), tiedPass->GetOutputMap(1)}); - builder::ShaderCompiler::CompileShader("shaders/subpass/sub03_fs.glsl", {path + "/shaders/RHISample/sub03_fs.shader", builder::ShaderType::FS, tiedPass->GetInputMap(2), tiedPass->GetOutputMap(2)}); - - rhi::GraphicsPipeline::Descriptor psoDesc = {}; - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/full_screen_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/full_screen_fs.shader"); - psoDesc.renderPass = renderPass; - psoDesc.pipelineLayout = fullScreenLayout; - psoDesc.vertexInput = emptyInput; - psoDesc.subPassIndex = 0; - fullScreen = device->CreateGraphicsPipeline(psoDesc); - - psoDesc.renderPass = tiedPass; - psoDesc.pipelineLayout = subpassLayout1; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/full_screen_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/sub02_fs.shader"); - psoDesc.subPassIndex = 1; - - pso2 = device->CreateGraphicsPipeline(psoDesc); - - psoDesc.pipelineLayout = subpassLayout2; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/full_screen_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/sub03_fs.shader"); - psoDesc.subPassIndex = 2; - - pso3 = device->CreateGraphicsPipeline(psoDesc); - - - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.state.blendStates.emplace_back(BlendState{}); - psoDesc.state.depthStencil.depthWrite = true; - psoDesc.state.depthStencil.depthTest = true; - psoDesc.state.depthStencil.stencilTest = true; - psoDesc.state.depthStencil.front.reference = 0x80; - psoDesc.state.depthStencil.front.writeMask = 0xFF; - psoDesc.state.depthStencil.front.compareMask = 0xFF; - psoDesc.state.depthStencil.front.passOp = StencilOp::REPLACE; - psoDesc.state.depthStencil.front.compareOp = CompareOp::ALWAYS; - psoDesc.state.depthStencil.back = psoDesc.state.depthStencil.front; - - psoDesc.pipelineLayout = pipelineLayout; - psoDesc.vs = CreateShader(rhi, *device, ShaderStageFlagBit::VS, path + "/shaders/RHISample/sub01_vs.shader"); - psoDesc.fs = CreateShader(rhi, *device, ShaderStageFlagBit::FS, path + "/shaders/RHISample/sub01_fs.shader"); - psoDesc.subPassIndex = 0; - pso1 = device->CreateGraphicsPipeline(psoDesc); - } - - void RHISubPassSample::OnTick(float delta) - { - auto *queue = device->GetQueue(QueueType::GRAPHICS); - uint32_t index = swapChain->AcquireNextImage(imageAvailable); - - SubmitInfo submitInfo = {}; - submitInfo.submitSignals.emplace_back(renderFinish); - submitInfo.waits.emplace_back(PipelineStageBit::COLOR_OUTPUT, imageAvailable); - submitInfo.fence = fence; - - fence->WaitAndReset(); - commandBuffer->Begin(); - - auto encoder = commandBuffer->EncodeGraphics(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = subpassViews[0]; - commandBuffer->QueueBarrier(barrier); - barrier.view = subpassViews[1]; - commandBuffer->QueueBarrier(barrier); - barrier.view = subpassViews[2]; - commandBuffer->QueueBarrier(barrier); - barrier.view = subpassViews[3]; - commandBuffer->QueueBarrier(barrier); - barrier.view = subpassViews[4]; - commandBuffer->QueueBarrier(barrier); - } - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = subpassViews[5]; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - encoder->BeginPass({fb, tiedPass, static_cast(fbClears.size()), fbClears.data()}); - - encoder->BindPipeline(pso1); - encoder->DrawLinear({3, 1, 0, 0}); - - encoder->NextSubPass(); - - encoder->BindPipeline(pso2); - encoder->BindSet(0, subpassSet1); - encoder->DrawLinear({3, 1, 0, 0}); - - encoder->NextSubPass(); - - encoder->BindPipeline(pso3); - encoder->BindSet(0, subpassSet2); - encoder->DrawLinear({3, 1, 0, 0}); - - encoder->EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_INOUT_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::FRAGMENT_SRV; - barrier.view = subpassViews[4]; - commandBuffer->QueueBarrier(barrier); - } - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - } - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::NONE; - barrier.dstFlags = rhi::AccessFlagBit::DEPTH_STENCIL_WRITE; - barrier.view = depthStencilImage; - commandBuffer->QueueBarrier(barrier); - } - commandBuffer->FlushBarriers(); - - encoder->BeginPass({frameBuffers[index], renderPass, static_cast(clears.size()), clears.data()}); - - encoder->BindPipeline(fullScreen); - encoder->BindSet(0, fullScreenSet); - encoder->DrawLinear({3, 1, 0, 0}); - - encoder->EndPass(); - - { - ImageBarrier barrier = {}; - barrier.srcFlags = rhi::AccessFlagBit::COLOR_WRITE; - barrier.dstFlags = rhi::AccessFlagBit::PRESENT; - barrier.view = colorViews[index]; - commandBuffer->QueueBarrier(barrier); - commandBuffer->FlushBarriers(); - } - - commandBuffer->End(); - commandBuffer->Submit(*queue, submitInfo); - - PresentInfo presentInfo = {}; - presentInfo.imageIndex = index; - presentInfo.semaphores.emplace_back(renderFinish); - swapChain->Present(*queue, presentInfo); - } - - void RHISubPassSample::OnStop() - { - device->WaitIdle(); - tiedPass = nullptr; - fb = nullptr; - pso1 = nullptr; - pso2 = nullptr; - pso3 = nullptr; - subpassSet1 = nullptr; - subpassSet2 = nullptr; - subpassLayout1 = nullptr; - subpassLayout2 = nullptr; - subpassViews.clear(); - depthView = nullptr; - stencilView = nullptr; - - fullScreen = nullptr; - fullScreenLayout = nullptr; - fullScreenSet = nullptr; - RHISampleBase::OnStop(); - } - -} // namespace sky::rhi diff --git a/sample/RHISampleBase/src/scene_render/Camera.cpp b/sample/RHISampleBase/src/scene_render/Camera.cpp deleted file mode 100644 index 2d22ecea..00000000 --- a/sample/RHISampleBase/src/scene_render/Camera.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include -#include - -namespace sky::rhi { - - void Camera::SetTransform(const Matrix4 &matrix) - { - transform = matrix; - view = transform.Inverse(); - data.position.x = transform[3][0]; - data.position.y = transform[3][1]; - data.position.z = transform[3][2]; - } - - void Camera::MakeProjective(float fov, float aspect, float near, float far) - { - project = MakePerspective(fov, aspect, near, far); - } - - void Camera::Update() - { - data.vp = project * view; - } - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/Material.cpp b/sample/RHISampleBase/src/scene_render/Material.cpp deleted file mode 100644 index b18bd739..00000000 --- a/sample/RHISampleBase/src/scene_render/Material.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include -#include -#include -#include -#include - -namespace sky::rhi { - - void Material::SetLayout(const rhi::DescriptorSetLayoutPtr &l, const rhi::DescriptorSetPoolPtr &p, uint32_t size) - { - auto *device = Interface::Get()->GetApi()->GetDevice(); - - layout = l; - pool = p; - auto &bindings = layout->GetBindings(); - for (auto &binding : bindings) { - if (binding.type == rhi::DescriptorType::UNIFORM_BUFFER || - binding.type == rhi::DescriptorType::UNIFORM_BUFFER_DYNAMIC) { - bufferBinding = binding.binding; - - rhi::Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = size; - bufferDesc.usage = rhi::BufferUsageFlagBit::UNIFORM; - bufferDesc.memory = rhi::MemoryType::CPU_TO_GPU; - auto buffer = device->CreateBuffer(bufferDesc); - buffers.emplace(binding.binding, buffer); - rawDatas.emplace(binding.binding, RawData(size)); - break; - } - } - batchSet = pool->Allocate({layout}); - } - - void Material::AddConnection(const std::string &str, const Accessor &accessor) - { - connection.accessors.emplace(str, accessor); - } - - Material::Accessor Material::GetAccessor(const std::string &key) const - { - auto iter = connection.accessors.find(key); - return iter != connection.accessors.end() ? iter->second : Accessor{~(0U)}; - } - - void Material::SetValue(const std::string &key, const uint8_t *data, uint32_t size) - { - auto accessor = GetAccessor(key); - SKY_ASSERT(accessor.binding != ~(0U)) - SKY_ASSERT(buffers.count(accessor.binding)); - SKY_ASSERT(rawDatas.count(accessor.binding)); - - auto &rawData = rawDatas.at(accessor.binding); - SKY_ASSERT(accessor.offset + size <= rawData.size()); - memcpy(rawData.data() + accessor.offset, data, size); - } - - void Material::SetTexture(const std::string &key, const Texture &tex) - { - auto accessor = GetAccessor(key); - SKY_ASSERT(accessor.binding != ~(0U)) - - textures[accessor.binding] = tex; - - needUpdateSet = true; - } - - void Material::Update() - { - for (auto &[binding, buffer] : buffers) { - auto &rawData = rawDatas[binding]; - memcpy(buffer->Map(), rawData.data(), rawData.size()); - } - - if (!needUpdateSet) { - return; - } - for (auto &[binding, tex] : textures) { - batchSet->BindImageView(binding, tex.view, 0); - batchSet->BindSampler(binding, tex.sampler, 0); - } - rhi::BufferViewDesc viewDesc = {}; - for (auto &[binding, buffer] : buffers) { - viewDesc.range = buffer->GetBufferDesc().size; - batchSet->BindBuffer(bufferBinding, buffer->CreateView(viewDesc)); - } - - batchSet->Update(); - needUpdateSet = false; - } -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/Mesh.cpp b/sample/RHISampleBase/src/scene_render/Mesh.cpp deleted file mode 100644 index bfcd41cd..00000000 --- a/sample/RHISampleBase/src/scene_render/Mesh.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include -#include -#include - -namespace sky::rhi { - void Mesh::SetLocalSet(const DescriptorSetPtr &set) - { - descriptorSet = set; - Buffer::Descriptor bufferDesc = {}; - bufferDesc.size = sizeof(LocalData); - bufferDesc.usage = BufferUsageFlagBit::UNIFORM; - bufferDesc.memory = MemoryType::CPU_TO_GPU; - - localBuffer = Interface::Get()->GetApi()->GetDevice()->CreateBuffer(bufferDesc); - Update(); - - descriptorSet->BindBuffer(0, localBuffer->CreateView({0, sizeof(LocalData)})); - descriptorSet->Update(); - } - - void Mesh::Update() - { - auto *ptr = localBuffer->Map(); - memcpy(ptr, &localData, sizeof(LocalData)); - localBuffer->UnMap(); - } -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/Pipeline.cpp b/sample/RHISampleBase/src/scene_render/Pipeline.cpp deleted file mode 100644 index bacea165..00000000 --- a/sample/RHISampleBase/src/scene_render/Pipeline.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include - -namespace sky::rhi { - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/Scene.cpp b/sample/RHISampleBase/src/scene_render/Scene.cpp deleted file mode 100644 index 25e34aba..00000000 --- a/sample/RHISampleBase/src/scene_render/Scene.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include - -namespace sky::rhi { - - - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/Technique.cpp b/sample/RHISampleBase/src/scene_render/Technique.cpp deleted file mode 100644 index 4d89f5d7..00000000 --- a/sample/RHISampleBase/src/scene_render/Technique.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include -#include -#include - -namespace sky::rhi { - - void GraphicsTechnique::BuildPso() - { - pso = Interface::Get()->GetApi()->GetDevice()->CreateGraphicsPipeline(psoDesc); - } - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/pass/ComputePass.cpp b/sample/RHISampleBase/src/scene_render/pass/ComputePass.cpp deleted file mode 100644 index 08bd7725..00000000 --- a/sample/RHISampleBase/src/scene_render/pass/ComputePass.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include - -namespace sky::rhi { - -} \ No newline at end of file diff --git a/sample/RHISampleBase/src/scene_render/pass/RasterPass.cpp b/sample/RHISampleBase/src/scene_render/pass/RasterPass.cpp deleted file mode 100644 index a7bb44cb..00000000 --- a/sample/RHISampleBase/src/scene_render/pass/RasterPass.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by Zach Lee on 2023/4/7. -// - -#include - -namespace sky::rhi { - -} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8085122c..ea846f93 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,8 @@ +configure_file(EngineRoot.h.in ${CMAKE_BINARY_DIR}/Gen/test/EngineRoot.h) +include_directories(${CMAKE_BINARY_DIR}/Gen) add_subdirectory(core) add_subdirectory(framework) -add_subdirectory(engine) add_subdirectory(vulkan) add_subdirectory(render) \ No newline at end of file diff --git a/sample/RDSceneProject/native/ProjectRoot.h.in b/test/EngineRoot.h.in similarity index 59% rename from sample/RDSceneProject/native/ProjectRoot.h.in rename to test/EngineRoot.h.in index 5738a5b8..c34bb3b8 100644 --- a/sample/RDSceneProject/native/ProjectRoot.h.in +++ b/test/EngineRoot.h.in @@ -1,5 +1,5 @@ // -// Created by Zach Lee on 2022/1/16. +// Created by Zach Lee on 2023/2/18. // #pragma once @@ -7,6 +7,6 @@ #include namespace sky { - static std::string ENGINE_ROOT = "@ENGINE_ROOT@"; + static std::string ENGINE_ROOT = "@CMAKE_SOURCE_DIR@"; static std::string PROJECT_ROOT = "@CMAKE_CURRENT_SOURCE_DIR@"; } // namespace sky \ No newline at end of file diff --git a/test/assets/framework/data/test_asset.t1 b/test/assets/framework/data/test_asset.t1 new file mode 100644 index 00000000..61da7808 --- /dev/null +++ b/test/assets/framework/data/test_asset.t1 @@ -0,0 +1,3 @@ +{ + "val": 1 +} \ No newline at end of file diff --git a/test/assets/framework/data/test_asset.t2 b/test/assets/framework/data/test_asset.t2 new file mode 100644 index 00000000..608501f4 --- /dev/null +++ b/test/assets/framework/data/test_asset.t2 @@ -0,0 +1,3 @@ +{ + "val": 2.0 +} \ No newline at end of file diff --git a/test/assets/framework/data/test_asset.t3 b/test/assets/framework/data/test_asset.t3 new file mode 100644 index 00000000..267ab40d --- /dev/null +++ b/test/assets/framework/data/test_asset.t3 @@ -0,0 +1,4 @@ +{ + "v1": "framework/data/test_asset.t1", + "v2": "framework/data/test_asset.t2" +} \ No newline at end of file diff --git a/test/configs/asset_build_presets.json b/test/configs/asset_build_presets.json new file mode 100644 index 00000000..1f1113ec --- /dev/null +++ b/test/configs/asset_build_presets.json @@ -0,0 +1,11 @@ +{ + "bundles": [ + "common", + "config1", + "config2" + ], + "presets": { + "windows": ["common", "config1"], + "macos": ["common", "config2"] + } +} \ No newline at end of file diff --git a/test/configs/asset_cfg_t2.json b/test/configs/asset_cfg_t2.json new file mode 100644 index 00000000..0640b4d6 --- /dev/null +++ b/test/configs/asset_cfg_t2.json @@ -0,0 +1,14 @@ +{ + "t2": { + "config1": { + "extVal": 3 + }, + "config2": { + "extVal": 4 + } + }, + "defaultBundles": { + "Windows": "config1", + "MacOS": "config2" + } +} \ No newline at end of file diff --git a/test/core/ArchiveTest.cpp b/test/core/ArchiveTest.cpp index 6d1cb7ff..4ca3f358 100644 --- a/test/core/ArchiveTest.cpp +++ b/test/core/ArchiveTest.cpp @@ -3,6 +3,7 @@ // #include +#include #include #include #include @@ -76,4 +77,35 @@ TEST(StreamArchiveTest, SStreamArchiveTestInOut) ASSERT_EQ(t.d, 4); ASSERT_EQ(t.e, 5); } +} + +TEST(StreamArchiveTest, MemoryArchive) +{ + std::string t("test memory archive"); + + MemoryArchive archive; + { + archive << 1; // 4 + archive << 0.f; // 4 + archive << 3.0; // 8 + archive << t; // 4 + 4 + } + + { + int a; + archive >> a; + float b; + archive >> b; + double c; + archive >> c; + std::string d; + archive >> d; + + ASSERT_EQ(a, 1); + ASSERT_EQ(b, 0.f); + ASSERT_EQ(c, 3.0); + ASSERT_EQ(d, t); + } + + ASSERT_EQ(archive.Size(), (4 + 4 + 8 + (4 + t.size()))); } \ No newline at end of file diff --git a/test/core/FileSystemTest.cpp b/test/core/FileSystemTest.cpp new file mode 100644 index 00000000..583ec4ee --- /dev/null +++ b/test/core/FileSystemTest.cpp @@ -0,0 +1,33 @@ +// +// Created by blues on 2024/6/16. +// + +#include +#include +#include +#include +using namespace sky; + +TEST(FileSystemTest, FileTest) +{ +#ifdef SKY_FS_USE_WCHAR + FilePath path("中文测试.txt"); +#else + FilePath path("test.txt"); +#endif + + NativeFileSystem fs(""); + { + auto file = fs.CreateOrOpenFile(path); + auto archive = file->WriteAsArchive(); + archive->Save(0xFFFF0000); + } + + { + auto file = fs.OpenFile(path); + auto archive = file->ReadAsArchive(); + uint32_t val = 0; + archive->Load(val); + ASSERT_EQ(val, 0xFFFF0000); + } +} \ No newline at end of file diff --git a/test/core/JobSystemTest.cpp b/test/core/JobSystemTest.cpp deleted file mode 100644 index b78fd769..00000000 --- a/test/core/JobSystemTest.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// -// Created by Zach Lee on 2022/3/6. -// - -#include "core/jobsystem/JobSystem.h" -#include "core/logger/Logger.h" -#include -#include - -using namespace sky; - -TEST(JobSystemTest, TaskFlowTest) -{ - auto js = JobSystem::Get(); - - int a = 0; - tf::Taskflow flow; - auto t1 = flow.emplace([&a]() { a = 1; }); - auto t2 = flow.emplace([&a]() { a++; }); - t2.succeed(t1); - - js->RunAndWait(flow); - ASSERT_EQ(a, 2); - - JobSystem::Destroy(); -} - -TEST(JobSystemTest, TaskHandleTest) -{ - auto js = JobSystem::Get(); - - tf::Taskflow flow1; - - int a = 0; - int b = 0; - - flow1.emplace([&a]() { - std::this_thread::sleep_for(std::chrono::duration(50)); - a++; - }); - auto future = js->Run(flow1); - - tf::Taskflow flow2; - flow1.emplace([&a, &b, &future]() { - b = a; - future.wait(); - }); - js->RunAndWait(flow1); - - ASSERT_EQ(b, 1); - - JobSystem::Destroy(); -} \ No newline at end of file diff --git a/test/core/ReferenceObjectTest.cpp b/test/core/ReferenceObjectTest.cpp index f268aa82..73e2609b 100644 --- a/test/core/ReferenceObjectTest.cpp +++ b/test/core/ReferenceObjectTest.cpp @@ -8,51 +8,41 @@ using namespace sky; static uint32_t g_count = 0; -struct TestRef : public RefObject { +class TestRef : public RefObject { public: - TestRef() - { - } + TestRef() = default; - ~TestRef() + ~TestRef() override { g_count++; } - - TestRef(const TestRef &) - { - } - - TestRef &operator=(const TestRef &) - { - return *this; - } - - void OnExpire() override - { - delete this; - } }; -struct TestRefDev : public TestRef { +class TestRefDev : public TestRef { public: TestRefDev() = default; - ~TestRefDev() = default; + ~TestRefDev() override = default; }; TEST(ReferenceObjectTest, ConstructTest) { - auto ptr = new TestRefDev(); - { - CounterPtr cPtr1(ptr); + auto *ptr = new TestRefDev(); + + CounterPtr cPtr1(ptr); ASSERT_EQ(ptr->GetRef(), 1); - CounterPtr cPtr2(ptr); + CounterPtr cPtr2(cPtr1); ASSERT_EQ(ptr->GetRef(), 2); - CounterPtr cPtr3 = cPtr2; - ASSERT_EQ(ptr->GetRef(), 3); + CounterPtr cPtr3(std::move(cPtr2)); + ASSERT_EQ(ptr->GetRef(), 2); } ASSERT_EQ(g_count, 1); + + { + CounterPtr ptr = new TestRef(); + ptr = new TestRef(); + } + ASSERT_EQ(g_count, 3); } \ No newline at end of file diff --git a/test/core/TaskTest.cpp b/test/core/TaskTest.cpp new file mode 100644 index 00000000..5f8249d4 --- /dev/null +++ b/test/core/TaskTest.cpp @@ -0,0 +1,39 @@ +// +// Created by blues on 2024/9/6. +// + +#include +#include + +using namespace sky; + +class TestTask : public Task { +public: + explicit TestTask(uint32_t &v) : id(v) {} + ~TestTask() override = default; + + bool DoWork() override + { + std::this_thread::sleep_for(std::chrono::duration(10)); + return true; + } + + void OnComplete(bool result) override + { + id = 20; + } + +private: + uint32_t& id; +}; + +TEST(TaskTest, TaskTestBase) +{ + uint32_t id = 0; + + auto *tf = TaskExecutor::Get(); + tf->ExecuteTask(new TestTask(id)); + tf->WaitForAll(); + + ASSERT_EQ(id, 20); +} \ No newline at end of file diff --git a/test/core/TypeTest.cpp b/test/core/TypeTest.cpp new file mode 100644 index 00000000..92ceb2f2 --- /dev/null +++ b/test/core/TypeTest.cpp @@ -0,0 +1,21 @@ +// +// Created by blues on 2024/4/22. +// + +#include +#include +#include +#include + +using namespace sky; + +struct FuncTypeTest { + void f1() const {} + void f2() {} +}; + +TEST(TypeTest, FuncTypeTest01) +{ + ASSERT_EQ(FuncTraits::CONST, true); + ASSERT_EQ(FuncTraits::CONST, false); +} \ No newline at end of file diff --git a/test/core/UtilTest.cpp b/test/core/UtilTest.cpp index 93b8ff04..c8dc571c 100644 --- a/test/core/UtilTest.cpp +++ b/test/core/UtilTest.cpp @@ -70,4 +70,12 @@ TEST(UtilTest, ArrayBitTest) bit.ResetBit(ArrayBitTestE::VAL33); ASSERT_EQ(bit.CheckBit(ArrayBitTestE::VAL33), false); +} + +struct MemoryBuf { + std::vector data; +}; + +TEST(UtilTest, MemoryStreamTest) +{ } \ No newline at end of file diff --git a/test/engine/CMakeLists.txt b/test/engine/CMakeLists.txt deleted file mode 100644 index 4d710d67..00000000 --- a/test/engine/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -file(GLOB_RECURSE TEST_SRC ./*) - -sky_add_test(TARGET EngineTest - SOURCES - ${TEST_SRC} - LIBS - SkyEngine - 3rdParty::googletest - ) \ No newline at end of file diff --git a/test/engine/ReflectionTest.cpp b/test/engine/ReflectionTest.cpp deleted file mode 100644 index d3e34fd3..00000000 --- a/test/engine/ReflectionTest.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// Created by Zach Lee on 2021/12/15. -// - -#include -#include -#include -#include -#include -#include - -using namespace sky; - -static const char *TAG = "EngineReflection"; - -TEST(EngineReflect, TestBasic) -{ - SkyEngine::Reflect(); - - std::string output; - { - Any transform(Transform{}); - ASSERT_EQ(!!transform, true); - } - - Component *comp = new TransformComponent(); - const TypeInfoRT *info = comp->GetTypeInfo(); - - auto node = GetTypeMember("local", info->typeId); - ASSERT_NE(node, nullptr); - - auto local = node->getterFn(comp); - auto rotation = GetValue(local, node->info->typeId, "rotation"); - auto pos = GetValue(local, node->info->typeId, "translation"); - auto scale = GetValue(local, node->info->typeId, "scale"); - - ASSERT_EQ(*static_cast(GetValue(pos, TypeInfo::Hash(), "x")), 0.f); - ASSERT_EQ(*static_cast(GetValue(pos, TypeInfo::Hash(), "y")), 0.f); - ASSERT_EQ(*static_cast(GetValue(pos, TypeInfo::Hash(), "z")), 0.f); - - ASSERT_EQ(*static_cast(GetValue(scale, TypeInfo::Hash(), "x")), 1.f); - ASSERT_EQ(*static_cast(GetValue(scale, TypeInfo::Hash(), "y")), 1.f); - ASSERT_EQ(*static_cast(GetValue(scale, TypeInfo::Hash(), "z")), 1.f); - - ASSERT_EQ(*static_cast(GetValue(rotation, TypeInfo::Hash(), "x")), 0.f); - ASSERT_EQ(*static_cast(GetValue(rotation, TypeInfo::Hash(), "y")), 0.f); - ASSERT_EQ(*static_cast(GetValue(rotation, TypeInfo::Hash(), "z")), 0.f); - ASSERT_EQ(*static_cast(GetValue(rotation, TypeInfo::Hash(), "w")), 1.f); - - struct Test { - int a; - int b; - }; - - auto va = &Test::a; - Test p = {1, 2}; - std::invoke(va, p) = 3; - - Test *q = &p; - ASSERT_EQ(p.a, 3); - std::invoke(va, q) = 4; - ASSERT_EQ(p.a, 4); -} - -TEST(GlobalVairableTest, ValueBasic) -{ - const std::string VALUE1("Test1 value"); - const int VALUE2 = 1; - const float VALUE3 = 2; - - auto gv = GlobalVariable::Get(); - gv->Register("VALUE1", VALUE1); - gv->Register("VALUE2", VALUE2); - gv->Register("VALUE3", VALUE3); - - ASSERT_EQ(gv->Find("VALUE1"), nullptr); - ASSERT_EQ(*gv->Find("VALUE1"), VALUE1); - ASSERT_EQ(*gv->Find("VALUE2"), VALUE2); - ASSERT_EQ(*gv->Find("VALUE3"), VALUE3); -} \ No newline at end of file diff --git a/test/engine/main.cpp b/test/engine/main.cpp deleted file mode 100644 index b3afefe8..00000000 --- a/test/engine/main.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "gtest/gtest.h" - -int main(int argc, char *argv[]) -{ - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/test/core/AnyTest.cpp b/test/framework/AnyTest.cpp similarity index 92% rename from test/core/AnyTest.cpp rename to test/framework/AnyTest.cpp index 61514515..f9ce91db 100644 --- a/test/core/AnyTest.cpp +++ b/test/framework/AnyTest.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include using namespace sky; @@ -89,20 +89,18 @@ struct AnyCopy1 { { } - AnyCopy1(uint32_t v) : a(v) + explicit AnyCopy1(uint32_t v) : a(v) { } - ~AnyCopy1() - { - } + ~AnyCopy1() = default; AnyCopy1(const AnyCopy1 &any) { a = any.a; } - AnyCopy1(AnyCopy1 &&any) + AnyCopy1(AnyCopy1 &&any) noexcept { a = any.a; } @@ -116,7 +114,7 @@ struct AnyCopy2 { { } - AnyCopy2(uint32_t v) : a(v) + explicit AnyCopy2(uint32_t v) : a(v) { } @@ -130,7 +128,7 @@ struct AnyCopy2 { a = any.a; } - AnyCopy2(AnyCopy2 &&any) + AnyCopy2(AnyCopy2 &&any) noexcept { a = any.a; } diff --git a/test/framework/AssetManagerTest.cpp b/test/framework/AssetManagerTest.cpp new file mode 100644 index 00000000..6fe9ac88 --- /dev/null +++ b/test/framework/AssetManagerTest.cpp @@ -0,0 +1,268 @@ +// +// Created by blues on 2024/6/21. +// + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace sky; + +struct T1Data { + int v; +}; + +struct T2Data { + float v; + int extVal; +}; + +template <> +struct AssetTraits { + using DataType = T1Data; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; + + static constexpr std::string_view ASSET_TYPE = "T1"; +}; + +template <> +struct AssetTraits { + using DataType = T2Data; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; + + static constexpr std::string_view ASSET_TYPE = "T2"; +}; + +struct T3Data { + Uuid t1; + Uuid t2; +}; + +template <> +struct AssetTraits { + using DataType = T3Data; + static constexpr SerializeType SERIALIZE_TYPE = SerializeType::BIN; + + static constexpr std::string_view ASSET_TYPE = "T3"; +}; + +class TestBuilder1 : public AssetBuilder { +public: + TestBuilder1() = default; + ~TestBuilder1() override = default; + + struct Config { + int extVal = 0; + }; + + const std::vector &GetExtensions() const override + { + static std::vector ext = {".t1", ".t2"}; + return ext; + } + + std::string GetDefaultBundle() const + { +#if WIN32 + auto type = PlatformType::Windows; +#else + auto type = PlatformType::MacOS; +#endif + auto iter = defaultBundles.find(type); + SKY_ASSERT(iter != defaultBundles.end()); + return iter->second; + } + + void LoadConfig(const FileSystemPtr &cfg) override + { + auto archive = cfg->OpenFile("asset_cfg_t2.json")->ReadAsArchive(); + JsonInputArchive json(*archive); + + json.Start("t2"); + + json.ForEachMember([this, &json](const std::string &key) { + auto &cfg = configs[key]; + json.Start(key); + + json.Start("extVal"); + cfg.extVal = json.LoadInt(); + json.End(); + + json.End(); + }); + + json.End(); + + json.Start("defaultBundles"); + + json.ForEachMember([&json, this](const std::string &key) { + json.Start(key); + auto platformType = Platform::GetPlatformTypeByName(key); + if (platformType != PlatformType::UNDEFINED) { + defaultBundles[platformType] = json.LoadString(); + } + json.End(); + }); + + json.End(); + } + + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override + { + auto archive = request.file->ReadAsArchive(); + JsonInputArchive json(*archive); + + auto *am = AssetManager::Get(); + if (request.assetInfo->category == AssetTraits::ASSET_TYPE) { + auto asset = std::static_pointer_cast>(am->FindOrCreateAsset(request.assetInfo->uuid, "T1")); + + T1Data &data = asset->Data(); + json.Start("val"); + data.v = json.LoadInt(); + + am->SaveAsset(asset, "common"); + } else { + auto asset = std::static_pointer_cast>(am->FindOrCreateAsset(request.assetInfo->uuid, "T2")); + + T2Data &data = asset->Data(); + json.Start("val"); + data.v = static_cast(json.LoadDouble()); + + auto target = request.target.empty() ? GetDefaultBundle() : request.target; + + auto iter = configs.find(target); + if (iter != configs.end()) { + data.extVal = iter->second.extVal; + am->SaveAsset(asset, target); + } + } + } + + std::string_view QueryType(const std::string &ext) const override + { + return ext == ".t1" ? AssetTraits::ASSET_TYPE : AssetTraits::ASSET_TYPE; + } + +private: + std::unordered_map configs; + std::unordered_map defaultBundles; +}; + +class TestBuilder2 : public AssetBuilder { +public: + TestBuilder2() = default; + ~TestBuilder2() override = default; + + void Request(const AssetBuildRequest &request, AssetBuildResult &result) override + { + auto archive = request.file->ReadAsArchive(); + JsonInputArchive json(*archive); + + json.Start("v1"); + std::string p1 = json.LoadString(); + json.End(); + + json.Start("v2"); + std::string p2 = json.LoadString(); + json.End(); + + auto *am = AssetManager::Get(); + auto asset = std::static_pointer_cast>(am->FindOrCreateAsset(request.assetInfo->uuid, "T3")); + + auto p1Asset = AssetDataBase::Get()->RegisterAsset(p1); + auto p2Asset = AssetDataBase::Get()->RegisterAsset(p2); + ASSERT_NE(p1Asset, nullptr); + ASSERT_NE(p2Asset, nullptr); + + request.assetInfo->dependencies.emplace_back(p1Asset->uuid); + request.assetInfo->dependencies.emplace_back(p2Asset->uuid); + + auto &data = asset->Data(); + data.t1 = p1Asset->uuid; + data.t2 = p2Asset->uuid; + + asset->AddDependencies(p1Asset->uuid); + asset->AddDependencies(p2Asset->uuid); + + am->SaveAsset(asset, "common"); + result.retCode = AssetBuildRetCode::SUCCESS; + } + + const std::vector &GetExtensions() const override + { + static std::vector ext = {".t3"}; + return ext; + } + + std::string_view QueryType(const std::string &ext) const override { return AssetTraits::ASSET_TYPE; } +}; + +class AssetManagerTest : public ::testing::Test { +public: + static void SetUpTestSuite() + { + auto *context = SerializationContext::Get(); + + context->Register("T1Data") + .Member<&T1Data::v>("v"); + + context->Register("T2Data") + .Member<&T2Data::v>("v") + .Member<&T2Data::extVal>("extVal"); + + context->Register("T3Data") + .Member<&T3Data::t1>("t1") + .Member<&T3Data::t2>("t2"); + + NativeFileSystemPtr projectFs = new NativeFileSystem(PROJECT_ROOT); + AssetDataBase::Get()->SetEngineFs(new NativeFileSystem(ENGINE_ROOT)); + AssetDataBase::Get()->SetWorkSpaceFs(projectFs); + + AssetBuilderManager::Get()->RegisterBuilder(new TestBuilder1()); + AssetBuilderManager::Get()->RegisterBuilder(new TestBuilder2()); + + AssetBuilderManager::Get()->LoadBuildConfigs(projectFs->CreateSubSystem("configs", false)); + + AssetManager::Get()->RegisterAssetHandler(); + AssetManager::Get()->RegisterAssetHandler(); + AssetManager::Get()->RegisterAssetHandler(); + } + + static void TearDownTestSuite() + { + } +}; + +TEST_F(AssetManagerTest, BuilderTest) +{ + auto *db = AssetDataBase::Get(); + db->Load(); + auto src = db->RegisterAsset("framework/data/test_asset.t3"); + db->Save(); + db->Dump(std::cout); + + auto asset = AssetManager::Get()->LoadAsset(src->uuid); + ASSERT_NE(asset, nullptr); + asset->BlockUntilLoaded(); + + auto &data = asset->Data(); + auto t1 = AssetManager::Get()->FindAsset(data.t1); + auto t2 = AssetManager::Get()->FindAsset(data.t2); + + + ASSERT_EQ(t1->Data().v, 1); + ASSERT_EQ(t2->Data().v, 2.f); +#if WIN32 + ASSERT_EQ(t2->Data().extVal, 3); +#else + ASSERT_EQ(t2->Data().extVal, 4); +#endif +} \ No newline at end of file diff --git a/test/framework/AssetTest.cpp b/test/framework/AssetTest.cpp deleted file mode 100644 index 60c331e7..00000000 --- a/test/framework/AssetTest.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// Created by Zach Lee on 2022/8/11. -// - -#include -#include -#include -#include -#include - -struct Test1Data { - int a; - float b; - std::string c; - - template - void serialize(Archive &ar) - { - ar(a, b, c); - } -}; - -struct Test1 { - Test1Data value; -}; - -namespace sky { - template <> - struct AssetTraits { - using DataType = Test1Data; - static constexpr Uuid ASSET_TYPE = Uuid::CreateFromString("5F34BBB0-3E06-4197-B1A9-069C18D5D3C5"); - static constexpr SerializeType SERIALIZE_TYPE = SerializeType::JSON; - - static std::shared_ptr CreateFromData(const DataType &data) - { - auto res = std::make_shared(); - res->value = data; - return res; - } - }; -} // namespace sky - -class AssetTest : public ::testing::Test { -public: - static void SetUpTestSuite() - { - sky::DBManager::Get()->Init(); - } - - static void TearDownTestSuite() - { - sky::AssetManager::Destroy(); - sky::DBManager::Destroy(); - } - - void SetUp() override - { - } - - void TearDown() override - { - } -}; - -TEST_F(AssetTest, DataTest) -{ - const char *CREATE = "CREATE TABLE IF NOT EXISTS data(" - "key TEXT PRIMARY KEY," - "value TEXT);"; - const char *UPDATE = "REPLACE INTO data(key, value) VALUES (?,?);"; - const char *SELECT = "SELECT value FROM data WHERE key=?;"; - - { - sky::DataBase dataBase; - dataBase.Init("test.db"); - - { - std::unique_ptr tableStmt(dataBase.CreateStatement(CREATE)); - tableStmt->Step(); - tableStmt->Finalize(); - } - - { - std::unique_ptr addStmt(dataBase.CreateStatement(UPDATE)); - addStmt->BindText(1, "key"); - addStmt->BindText(2, "value"); - addStmt->Step(); - addStmt->Finalize(); - } - - dataBase.Shutdown(); - } - - { - sky::DataBase dataBase; - dataBase.Init("test.db"); - - std::unique_ptr selectStmt(dataBase.CreateStatement(SELECT)); - selectStmt->BindText(1, "key"); - selectStmt->Step(); - std::string val = selectStmt->GetText(0); - ASSERT_EQ(val, "value"); - } - -} diff --git a/test/framework/ComponentTest.cpp b/test/framework/ComponentTest.cpp new file mode 100644 index 00000000..1c538d9d --- /dev/null +++ b/test/framework/ComponentTest.cpp @@ -0,0 +1,185 @@ +// +// Created by blues on 2024/5/14. +// + +#include +#include +#include +#include +#include +#include + +using namespace sky; + +struct TestComponentData { + int a; + float b; +}; + +class TestComponent : public ComponentAdaptor { +public: + TestComponent() = default; + ~TestComponent() override = default; + + COMPONENT_RUNTIME_INFO(TestComponent) + + static void Reflect(SerializationContext *context) + { + context->Register("TestComponentData") + .Member<&TestComponentData::a>("a") + .Member<&TestComponentData::b>("b"); + + + REGISTER_BEGIN(TestComponent, context) + REGISTER_MEMBER(a, SetA, GetA) + REGISTER_MEMBER(b, SetB, GetB); + } + + void SetA(int a) { data.a = a; } + int GetA() const { return data.a; } + + void SetB(float b) { data.b = b; } + float GetB() const { return data.b; } +}; + +class ComponentTest : public ::testing::Test { +public: + static void SetUpTestSuite() + { + auto *context = SerializationContext::Get(); + TestComponent::Reflect(context); + TransformComponent::Reflect(context); + } + + static void TearDownTestSuite() + { + } +}; + +TEST_F(ComponentTest, ActorTest) +{ + std::unique_ptr pWorld(World::CreateWorld()); + auto &world = *pWorld; + + auto id = Uuid::CreateWithSeed(0); + ActorPtr actor = world.CreateActor(id); + + { + auto* comp = actor->AddComponent(); + comp->SetA(1); + comp->SetB(2.f); + + ASSERT_EQ(comp->GetA(), 1); + ASSERT_EQ(comp->GetB(), 2.f); + } + + { + auto* comp = actor->GetComponent(); + comp->SetA(1); + comp->SetB(2.f); + + ASSERT_EQ(comp->GetA(), 1); + ASSERT_EQ(comp->GetB(), 2.f); + } + + { + auto *comp = actor->GetComponent(); + comp->SetLocalRotationEuler(VEC3_ZERO); + comp->SetLocalTranslation(Vector3(1.f, 2.f, 3.f)); + comp->SetLocalScale(Vector3(4.f, 5.f, 6.f)); + } + + { + std::ofstream stream("ActorTest.json"); + OStreamArchive streamArchive(stream); + JsonOutputArchive archive(streamArchive); + + world.SaveJson(archive); + } + + { + actor->RemoveComponent(); + auto* comp = actor->GetComponent(); + ASSERT_EQ(comp, nullptr); + + actor->RemoveComponent(Uuid{}); + + world.DetachFromWorld(actor); + } + + { + std::ifstream stream("ActorTest.json"); + IStreamArchive streamArchive(stream); + JsonInputArchive archive(streamArchive); + + world.LoadJson(archive); + + auto tActor = world.GetActorByUuid(id); + ASSERT_NE(tActor, nullptr); + + auto* comp = tActor->GetComponent(); + ASSERT_NE(tActor, nullptr); + ASSERT_EQ(comp->GetA(), 1); + ASSERT_EQ(comp->GetB(), 2.f); + } +} + +//TEST_F(ComponentTest, ActorHierarchy) +//{ +// { +// std::unique_ptr world(World::CreateWorld()); +// +// auto *actor1 = world->CreateActor(); +// auto *actor2 = world->CreateActor(); +// auto *actor3 = world->CreateActor(); +// +// actor3->SetParent(actor1); +// ASSERT_EQ(actor1->GetChildren()[0], actor3); +// ASSERT_EQ(actor2->GetChildren().size(), 0); +// ASSERT_EQ(actor3->GetParent(), actor1); +// +// actor3->SetParent(actor2); +// ASSERT_EQ(actor1->GetChildren().size(), 0); +// ASSERT_EQ(actor2->GetChildren()[0], actor3); +// ASSERT_EQ(actor3->GetParent(), actor2); +// } +// +// { +// std::unique_ptr world(World::CreateWorld()); +// +// auto *actor1 = world->CreateActor(); +// auto *actor2 = world->CreateActor(); +// auto *actor3 = world->CreateActor(); +// +// actor2->SetParent(actor1); +// actor3->SetParent(actor2); +// +// world->DestroyActor(actor1); +// ASSERT_EQ(actor2->GetChildren()[0], actor3); +// ASSERT_EQ(actor2->GetParent(), world->GetRoot()); +// ASSERT_EQ(actor3->GetParent(), actor2); +// } +// +//} + +TEST_F(ComponentTest, TransformComponentTest) +{ + TransformComponent transformComponent; + SetValue(transformComponent, "scale", Vector3(1, 1, 1)); + SetValue(transformComponent, "rotation", Vector3(0, 0, 0)); + SetValue(transformComponent, "translation", Vector3(1, 2, 3)); + + const auto &data = transformComponent.GetData(); + ASSERT_EQ(data.local.scale.x, 1.f); + ASSERT_EQ(data.local.scale.y, 1.f); + ASSERT_EQ(data.local.scale.z, 1.f); + + ASSERT_EQ(data.local.rotation.x, 0.f); + ASSERT_EQ(data.local.rotation.y, 0.f); + ASSERT_EQ(data.local.rotation.z, 0.f); + ASSERT_EQ(data.local.rotation.w, 1.f); + + ASSERT_EQ(data.local.translation.x, 1.f); + ASSERT_EQ(data.local.translation.y, 2.f); + ASSERT_EQ(data.local.translation.z, 3.f); +} \ No newline at end of file diff --git a/test/framework/EventTest.cpp b/test/framework/EventTest.cpp index 9b8aa38a..813a2e60 100644 --- a/test/framework/EventTest.cpp +++ b/test/framework/EventTest.cpp @@ -1,7 +1,7 @@ // // Created by Zach Lee on 2022/6/22. // -#include "framework/event/Event.h" +#include "core/event/Event.h" #include #include diff --git a/test/framework/GameObjectTest.cpp b/test/framework/GameObjectTest.cpp deleted file mode 100644 index 9876ea33..00000000 --- a/test/framework/GameObjectTest.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// Created by Zach Lee on 2021/12/3. -// - -#include -#include -#include -#include - -class TestComponent : public sky::Component { -public: - TestComponent() = default; - ~TestComponent() = default; - - TYPE_RTTI_WITH_VT(TestComponent) -}; - -using namespace sky; -TEST(EngineTest, GameObjectTest) -{ - World world; - - auto go = world.CreateGameObject("test"); - ASSERT_NE(go, nullptr); - - auto test1 = go->AddComponent(); - auto test2 = go->GetComponent(); - ASSERT_EQ(test1, test2); -} - -TEST(EngineTest, TransformComponentTest) -{ - World world; - - auto go1 = world.CreateGameObject("t1"); - auto t1 = go1->GetComponent(); - - auto go2 = world.CreateGameObject("t2"); - auto t2 = go2->GetComponent(); - t2->SetParent(t1); - ASSERT_EQ(t2->GetParent(), t1); - - auto go3 = world.CreateGameObject("t3"); - auto t3 = go3->GetComponent(); - t3->SetParent(t1); - ASSERT_EQ(t3->GetParent(), t1); - - auto go4 = world.CreateGameObject("t4"); - auto t4 = go4->GetComponent(); - t4->SetParent(t2); - ASSERT_EQ(t4->GetParent(), t2); - ASSERT_EQ(t2->GetChildren().size(), 1); - - t4->SetParent(t1); - ASSERT_EQ(t4->GetParent(), t1); - ASSERT_EQ(t2->GetChildren().size(), 0); - - t3->SetParent(t2); - t4->SetParent(t3); - ASSERT_EQ(t4->GetParent(), t3); - ASSERT_EQ(t3->GetParent(), t2); - ASSERT_EQ(t2->GetParent(), t1); - - ASSERT_EQ(world.GetGameObjects().size(), size_t(5)); -} - -struct TestSystem : public IComponentListener { - TestSystem(int &val) : p(val) - { - ComponentFactory::Get()->RegisterListener(this); - } - - ~TestSystem() - { - ComponentFactory::Get()->UnRegisterListener(this); - } - void OnAddComponent(GameObject *go, Component *comp) - { - p += 10; - } - void OnRemoveComponent(GameObject *go, Component *comp) - { - p += 20; - } - int &p; -}; - -TEST(EngineTest, ListenerTest) -{ - int val = 0; - TestSystem system(val); - -// World world; -// auto go = world.CreateGameObject("test"); - -// go->AddComponent(); -// ASSERT_EQ(val, 10); -// -// go->AddComponent(); -// ASSERT_EQ(val, 10); -// -// go->RemoveComponent(); -// ASSERT_EQ(val, 30); -// -// go->RemoveComponent(); -// ASSERT_EQ(val, 30); -} - -TEST(EngineTest, TransformComponentWorldLocalTest) -{ - World world; - - auto go1 = world.CreateGameObject("t1"); - auto t1 = go1->GetComponent(); - t1->SetWorldTranslation(Vector3{1.f, 0.f, 0.f}); - { - auto &local = t1->GetLocal(); - ASSERT_FLOAT_EQ(local.translation.x, 1.f); - ASSERT_FLOAT_EQ(local.translation.y, 0.f); - ASSERT_FLOAT_EQ(local.translation.z, 0.f); - auto &world = t1->GetWorld(); - ASSERT_FLOAT_EQ(world.translation.x, 1.f); - ASSERT_FLOAT_EQ(world.translation.y, 0.f); - ASSERT_FLOAT_EQ(world.translation.z, 0.f); - } - - auto go2 = world.CreateGameObject("t2"); - auto t2 = go2->GetComponent(); - t2->SetWorldTranslation(Vector3{2.f, 0.f, 0.f}); - { - auto &local = t2->GetLocal(); - ASSERT_FLOAT_EQ(local.translation.x, 2.f); - ASSERT_FLOAT_EQ(local.translation.y, 0.f); - ASSERT_FLOAT_EQ(local.translation.z, 0.f); - auto &world = t2->GetWorld(); - ASSERT_FLOAT_EQ(world.translation.x, 2.f); - ASSERT_FLOAT_EQ(world.translation.y, 0.f); - ASSERT_FLOAT_EQ(world.translation.z, 0.f); - } - - t2->SetParent(t1); - ASSERT_EQ(t2->GetParent(), t1); - { - auto &local = t2->GetLocal(); - ASSERT_FLOAT_EQ(local.translation.x, 1.f); - ASSERT_FLOAT_EQ(local.translation.y, 0.f); - ASSERT_FLOAT_EQ(local.translation.z, 0.f); - auto &world = t2->GetWorld(); - ASSERT_FLOAT_EQ(world.translation.x, 2.f); - ASSERT_FLOAT_EQ(world.translation.y, 0.f); - ASSERT_FLOAT_EQ(world.translation.z, 0.f); - } - - t1->SetWorldTranslation(Vector3{2.f, 0.f, 0.f}); - { - auto &local = t1->GetLocal(); - ASSERT_FLOAT_EQ(local.translation.x, 2.f); - ASSERT_FLOAT_EQ(local.translation.y, 0.f); - ASSERT_FLOAT_EQ(local.translation.z, 0.f); - auto &world = t1->GetWorld(); - ASSERT_FLOAT_EQ(world.translation.x, 2.f); - ASSERT_FLOAT_EQ(world.translation.y, 0.f); - ASSERT_FLOAT_EQ(world.translation.z, 0.f); - } - - { - auto &local = t2->GetLocal(); - ASSERT_FLOAT_EQ(local.translation.x, 1.f); - ASSERT_FLOAT_EQ(local.translation.y, 0.f); - ASSERT_FLOAT_EQ(local.translation.z, 0.f); - auto &world = t2->GetWorld(); - ASSERT_FLOAT_EQ(world.translation.x, 3.f); - ASSERT_FLOAT_EQ(world.translation.y, 0.f); - ASSERT_FLOAT_EQ(world.translation.z, 0.f); - } -} \ No newline at end of file diff --git a/test/framework/ModuleTest.cpp b/test/framework/ModuleTest.cpp index 629219b1..cecf0ce8 100644 --- a/test/framework/ModuleTest.cpp +++ b/test/framework/ModuleTest.cpp @@ -17,7 +17,7 @@ TEST(ModuleManagerTest, ModuleSortTest) manager.RegisterModule({"Test4", {"Test5"}}); manager.TopoSort(); - manager.WalkModules([](const std::string &module) { - printf("%s\n", module.c_str()); - }); +// manager.WalkModules([](const std::string &module) { +// printf("%s\n", module.c_str()); +// }); } \ No newline at end of file diff --git a/test/framework/SerializationTest.cpp b/test/framework/SerializationTest.cpp index 3ef495d8..8f34a13e 100644 --- a/test/framework/SerializationTest.cpp +++ b/test/framework/SerializationTest.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -50,23 +51,13 @@ TEST(SerializationTest, TypeTest) auto testReflect = context->FindType("TestReflect"); ASSERT_NE(testReflect, nullptr); ASSERT_EQ(testReflect->members.size(), 7); - LOG_I(TAG, "name %s", testReflect->info->markedName.data()); auto testMember = context->FindType("TestMember"); ASSERT_NE(testMember, nullptr); ASSERT_EQ(testMember->members.size(), 2); - LOG_I(TAG, "name %s", testMember->info->markedName.data()); - - for (auto &member : testReflect->members) { - auto &memberNode = member.second; - LOG_I(TAG, "name %s, type %s, isFundamental %u, isStatic %u, isConst %u", member.first.data(), memberNode.info->markedName.data(), - memberNode.info->isFundamental, memberNode.isStatic, memberNode.isConst); - } - - LOG_I(TAG, "%u, %u, %u, %u", std::is_trivial_v, std::is_trivial_v, std::is_trivial_v, std::is_trivial_v); TestReflect v = {}; - uint32_t typeId = TypeInfo::Hash(); + auto typeId = TypeInfo::RegisteredId(); uint32_t *ptr = nullptr; ASSERT_EQ(SetValue(v, "a", 5u), true); ASSERT_EQ(SetValue(v, "b", 6.f), true); @@ -78,17 +69,12 @@ TEST(SerializationTest, TypeTest) ASSERT_EQ(v.b, 6.f); ASSERT_EQ(v.c, nullptr); - void *va = GetValue(reinterpret_cast(&v), typeId, "a"); - ASSERT_NE(va, nullptr); - ASSERT_EQ(*static_cast(va), 5U); + ASSERT_EQ(*GetValueRaw(reinterpret_cast(&v), typeId, "a").GetAs(), 5U); + ASSERT_EQ(*GetValueRaw(reinterpret_cast(&v), typeId, "b").GetAs(), 6.f); - void *vb = GetValue(reinterpret_cast(&v), typeId, "b"); - ASSERT_NE(vb, nullptr); - ASSERT_EQ(*static_cast(vb), 6.f); - - void *vc = GetValue(reinterpret_cast(&v), typeId, "c"); + uint32_t **vc = GetValueRaw(reinterpret_cast(&v), typeId, "c").GetAs(); ASSERT_NE(vc, nullptr); - ASSERT_EQ(*static_cast(vc), nullptr); + ASSERT_EQ(*vc, nullptr); } struct Ctor1 { @@ -114,7 +100,7 @@ struct Ctor2 { TEST(SerializationTest, ConstructorTest) { - auto context = SerializationContext::Get(); + auto *context = SerializationContext::Get(); context->Register("Ctor1") .Member<&Ctor1::a>("a") @@ -141,7 +127,7 @@ TEST(SerializationTest, ConstructorTest) } { - Any any1 = MakeAny(TypeInfo::Hash(), 1, 2.f, 3.0, true); + Any any1 = MakeAny(TypeInfo::RegisteredId(), 1, 2.f, 3.0, true); Ctor1 *ptr = any1.GetAs(); ASSERT_NE(ptr, nullptr); ASSERT_EQ(ptr->a, 1); @@ -151,7 +137,7 @@ TEST(SerializationTest, ConstructorTest) } { - Any any1 = MakeAny(TypeInfo::Hash(), 1, 2.f, 3.0, 4.0); + Any any1 = MakeAny(TypeInfo::RegisteredId(), 1, 2.f, 3.0, 4.0); ASSERT_EQ(!any1, true); } @@ -170,6 +156,95 @@ TEST(SerializationTest, ConstructorTest) } } +struct GetterSetterTestData { + int a; + float b; + std::string c; + double d; +}; + +class GetterSetterTestController { +public: + explicit GetterSetterTestController(GetterSetterTestData &dt) : data(dt) {} + ~GetterSetterTestController() = default; + + using MY_CLASS = GetterSetterTestController; + static void Reflect(SerializationContext* context) + { + REGISTER_BEGIN(GetterSetterTestController, context) + REGISTER_MEMBER(a, SetA, GetA) + REGISTER_MEMBER(b, SetB, GetB) + REGISTER_MEMBER(c, SetC, GetC) + REGISTER_MEMBER(d, SetD, GetD); + } + + + void SetA(const int &v) { data.a = v; } + const int &GetA() const { return data.a; } + + void SetB(const float &v) { data.b = v; } + const float &GetB() const { return data.b; } + + void SetC(const std::string &name) { data.c = name; } + const std::string &GetC() const { return data.c; } + + void SetD(const double &v) { data.d = v; } + double GetD() const { return data.d; } + +private: + GetterSetterTestData &data; +}; + +TEST(SerializationTest, GetterSetterTest) +{ + auto *context = SerializationContext::Get(); + GetterSetterTestController::Reflect(context); + + { + GetterSetterTestData data { 1, 2.f }; + GetterSetterTestController controller(data); + + SetValue(controller, "a", 2); + SetValue(controller, "b", 3.f); + SetValue(controller, "c", std::string("test")); + SetValue(controller, "d", 4.0); + ASSERT_EQ(data.a, 2); + ASSERT_EQ(data.b, 3.f); + ASSERT_EQ(data.c, "test"); + ASSERT_EQ(data.d, 4.0); + + int a = *GetValueConst(controller, "a").GetAsConst(); + float b = *GetValueConst(controller, "b").GetAsConst(); + + ASSERT_EQ(a, 2); + ASSERT_EQ(b, 3.f); + + { + std::ofstream stream("GetterSetterTest.json"); + OStreamArchive streamArchive(stream); + JsonOutputArchive archive(streamArchive); + + archive.SaveValueObject(controller); + } + + { + std::ifstream stream("GetterSetterTest.json"); + IStreamArchive streamArchive(stream); + JsonInputArchive archive(streamArchive); + + GetterSetterTestData data2 {}; + GetterSetterTestController controller2(data2); + + archive.LoadValueObject(controller2); + + ASSERT_EQ(data2.a, 2); + ASSERT_EQ(data2.b, 3.f); + ASSERT_EQ(data2.c, "test"); + ASSERT_EQ(data2.d, 4.0); + } + } +} + struct TestObject { uint64_t uv1 = 1; uint32_t uv2 = 2; @@ -212,7 +287,8 @@ TEST(ArchiveTest, JsonArchiveTest) { std::ofstream stream("test.json"); - JsonOutputArchive archive(stream); + OStreamArchive streamArchive(stream); + JsonOutputArchive archive(streamArchive); TestStruct obj; obj.t1.uv1 += 10; @@ -234,7 +310,8 @@ TEST(ArchiveTest, JsonArchiveTest) { std::ifstream stream("test.json"); - JsonInputArchive archive(stream); + IStreamArchive streamArchive(stream); + JsonInputArchive archive(streamArchive); TestStruct obj; archive.LoadValueObject(obj); @@ -342,28 +419,28 @@ TEST(ArchiveTest, JsonArchiveRegisterTest) test.c[i].v3 = i * 3 + 2; } std::ofstream file("json-serialization-test.json", std::ios::binary); - JsonOutputArchive archive(file); + OStreamArchive streamArchive(file); + JsonOutputArchive archive(streamArchive); TestSerFunc &f = test; - archive.SaveValueObject(&f, TypeInfo::Hash()); + archive.SaveValueObject(&f, TypeInfo::RegisteredId()); } { TestSerFuncDerv test; std::ifstream file("json-serialization-test.json", std::ios::binary); - JsonInputArchive archive(file); + IStreamArchive streamArchive(file); + JsonInputArchive archive(streamArchive); TestSerFunc &f = test; - archive.LoadValueById(&f, TypeInfo::Hash()); - - std::cout << test.a << std::endl; + archive.LoadValueById(&f, TypeInfo::RegisteredId()); } } TEST(ArchiveTest, BinaryArchiveRegister_FundamentalTest) { { - std::ofstream file("binary-fundamental-test.bin", std::ios::binary); + OFileArchive file("binary-fundamental-test.bin", std::ios::binary); BinaryOutputArchive archive(file); archive.SaveValue(-1); archive.SaveValue(2U); @@ -374,7 +451,7 @@ TEST(ArchiveTest, BinaryArchiveRegister_FundamentalTest) } { - std::ifstream file("binary-fundamental-test.bin", std::ios::binary); + IFileArchive file("binary-fundamental-test.bin", std::ios::binary); BinaryInputArchive archive(file); { int value = 0; @@ -442,17 +519,17 @@ TEST(ArchiveTest, BinaryArchiveRegister_ClassTest) { TestBinArchive test = {{1, 2.f}, {3, 4.0}}; - std::ofstream file("binary-class-test.bin", std::ios::binary); + OFileArchive file("binary-class-test.bin", std::ios::binary); BinaryOutputArchive archive(file); - archive.SaveObject(&test, TypeInfo::Hash()); + archive.SaveObject(&test, TypeInfo::RegisteredId()); } { - std::ifstream file("binary-class-test.bin", std::ios::binary); + IFileArchive file("binary-class-test.bin", std::ios::binary); BinaryInputArchive archive(file); TestBinArchive test = {}; - archive.LoadObject(&test, TypeInfo::Hash()); + archive.LoadObject(&test, TypeInfo::RegisteredId()); ASSERT_EQ(test.b1.a, 1); ASSERT_EQ(test.b1.b, 2.f); diff --git a/test/framework/SettingRegistryTest.cpp b/test/framework/SettingRegistryTest.cpp deleted file mode 100644 index eb624321..00000000 --- a/test/framework/SettingRegistryTest.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by Zach Lee on 2022/3/13. -// - -#include -#include - -using namespace sky; - -TEST(SettingRegistryTest, BasicTest) -{ - SettingRegistry registry; - registry.SetValue("/test1", 1); - registry.SetValue("/test2", 2u); - registry.SetValue("/test3", uint8_t(3)); - registry.SetValue("/test4", int8_t(4)); - registry.SetValue("/test5", uint16_t(5)); - registry.SetValue("/test6", int16_t(6)); - registry.SetValue("/test7", uint64_t(7)); - registry.SetValue("/test8", int64_t(8)); - registry.SetValue("/test9", 9.0); - registry.SetValue("/test10", 10.f); - registry.SetValue("/test11", true); - registry.SetValue("/test12", std::string_view("v1")); - - registry.SetValue("/test1/v1", 3); - - std::string out; - registry.Save(out); - - std::cout << out << std::endl; -} \ No newline at end of file diff --git a/test/render/CMakeLists.txt b/test/render/CMakeLists.txt index bf27b371..1d71c013 100644 --- a/test/render/CMakeLists.txt +++ b/test/render/CMakeLists.txt @@ -4,6 +4,6 @@ sky_add_test(TARGET RenderTest SOURCES ${TEST_SRC} LIBS - SkyRenderCore + RenderCore 3rdParty::googletest ) \ No newline at end of file diff --git a/test/render/RenderGraphNodeTest.cpp b/test/render/RenderGraphNodeTest.cpp index 4eacfd7b..488e0d4c 100644 --- a/test/render/RenderGraphNodeTest.cpp +++ b/test/render/RenderGraphNodeTest.cpp @@ -32,7 +32,7 @@ TEST(RenderGraphTest, NodeGraphTest01) context.commandBuffers.resize(1); context.commandBuffers[0] = context.device->CreateCommandBuffer({}); - RenderGraph rdg(&context, nullptr); + RenderGraph rdg(&context); auto &rg = rdg.resourceGraph; diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index f359daaf..c41526a8 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,5 +1,5 @@ if (SKY_BUILD_TOOL) - add_subdirectory(asset_browser) +# add_subdirectory(asset_builder) endif () #add_subdirectory(assettools) #add_subdirectory(noise) diff --git a/tools/asset_browser/CMakeLists.txt b/tools/asset_builder/CMakeLists.txt similarity index 56% rename from tools/asset_browser/CMakeLists.txt rename to tools/asset_builder/CMakeLists.txt index cfba24ee..788210ec 100644 --- a/tools/asset_browser/CMakeLists.txt +++ b/tools/asset_builder/CMakeLists.txt @@ -1,4 +1,4 @@ -sky_add_exe(TARGET AssetBrowser +sky_add_exe(TARGET AssetBuilder SOURCES main.cpp INCS @@ -7,4 +7,4 @@ sky_add_exe(TARGET AssetBrowser 3rdParty::cxxopts ) -sky_set_dependency(TARGET AssetBrowser) \ No newline at end of file +sky_set_dependency(TARGET AssetBuilder) \ No newline at end of file diff --git a/tools/asset_browser/main.cpp b/tools/asset_builder/main.cpp similarity index 96% rename from tools/asset_browser/main.cpp rename to tools/asset_builder/main.cpp index 2ee51c7c..f609c8c3 100644 --- a/tools/asset_browser/main.cpp +++ b/tools/asset_builder/main.cpp @@ -9,7 +9,7 @@ using namespace sky; int main(int argc, char *argv[]) { - cxxopts::Options options("AssetBrowser", "SkyEngine AssetBrowser"); + cxxopts::Options options("AssetBuilder", "SkyEngine AssetBuilder"); options.add_options()("e,engine", "Engine Directory", cxxopts::value()) ("p,project", "Project Directory", cxxopts::value()) ("i,import", "Import Source Asset", cxxopts::value>()) diff --git a/tools/noise/CMakeLists.txt b/tools/noise/CMakeLists.txt index 9bff99aa..3f8f9cef 100644 --- a/tools/noise/CMakeLists.txt +++ b/tools/noise/CMakeLists.txt @@ -16,7 +16,7 @@ sky_add_library(TARGET ${TARGET_NAME} SHARED LINK_LIBS Framework ImGuiRender - SkyRenderAdaptor + RenderAdaptor 3rdParty::PerlinNoise ) diff --git a/tools/noise/NoiseToolModule.cpp b/tools/noise/NoiseToolModule.cpp index a5274f53..774f2e67 100644 --- a/tools/noise/NoiseToolModule.cpp +++ b/tools/noise/NoiseToolModule.cpp @@ -10,14 +10,14 @@ #include #include #include -#include +#include #include #include #include #include #include -#include +#include #include #include #include diff --git a/tools/perf/include/perf/gui/Gui.h b/tools/perf/include/perf/gui/Gui.h index 01c977fc..eb8a9dd5 100644 --- a/tools/perf/include/perf/gui/Gui.h +++ b/tools/perf/include/perf/gui/Gui.h @@ -41,7 +41,7 @@ namespace sky::perf { bool CreateOrResize(vk::BufferPtr &buffer, size_t size, bool vtx); void OnMouseWheel(int32_t wheelX, int32_t wheelY) override; - void OnMouseMove(int32_t x, int32_t y) override; + void OnMouseMove(int32_t x, int32_t y, int32_t relX, int32_t relY) override; void OnMouseButtonDown(MouseButtonType button) override; void OnMouseButtonUp(MouseButtonType button) override; void OnKeyUp(KeyButtonType) override; diff --git a/tools/perf/src/gui/Gui.cpp b/tools/perf/src/gui/Gui.cpp index b7bb7048..5ebd4026 100644 --- a/tools/perf/src/gui/Gui.cpp +++ b/tools/perf/src/gui/Gui.cpp @@ -394,7 +394,7 @@ namespace sky::perf { if (wheelY < 0) io.MouseWheel -= 1; } - void Gui::OnMouseMove(int32_t x, int32_t y) + void Gui::OnMouseMove(int32_t x, int32_t y, int32_t relX, int32_t relY) { ImGuiIO& io = ImGui::GetIO(); io.MousePos = ImVec2(static_cast(x), static_cast(y));